Tag Archives: hardware

Wemos with Keypad, led and 7 segment display using MQTT

Warning, read the notes!

There are several caveats.

  • I was needing ALL GPIO pins, even RX/TX ( see trick below)
    When doing so, you can’t use serialprint.
    Do NOT enable, your sketch won’t work!
  • Don’t use pullup on D8, you can’t upload to the wemos if you do that
  • Due to library conflicts in keypad.h, DON’T change the order in the source. You will end up with compile errors!
  • The keypad has a weird pinout, but there are similar keypads with alternative layouts. Measure this using a multimeter.
  • The pull-up resistors will help fighting ghost key presses!
  • I2C needs D1/D2

To use RX/TX as GPIO pins you need to do the following:

//Define pins
  int led = 1; //tx
  int col = 3; //rx

// Change to function mode 3
// see https://www.esp8266.com/wiki/doku.php?id=esp8266_gpio_pin_allocations
  pinMode(1, FUNCTION_3);
  pinMode(3, FUNCTION_3);
 
// Revert to normal mode
// pinMode(1, FUNCTION0);

// Define mode input/output
// i'm using led to control the led so thats an output
// I'm using col for the keypad column scanner, that's an input
  pinMode(led, OUTPUT);
  pinMode(col, INPUT);

Complete code

The (*) clears input
The (#) sends the pin code using MQTT

Sending a 0 or 1 to escape/keypadin topic will toggle the led

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
// Do not change order!
#include "Keypad.h"
#include <TM1637Display.h>
#include <Ethernet.h>

#define wifi_ssid "SSID"
#define wifi_password "SSIDPASS"
#define mqtt_server "MQTTSERVER"
#define mqtt_port 1883

#define MSG_BUFFER_SIZE  (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;

const byte ROWS = 4; //four rows
const byte COLS = 3; //four columns

int led = 1; //tx
int col = 3; //rx

#define CLK D1
#define DIO D2
#define TEST_DELAY   2000
TM1637Display display(CLK, DIO);

char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {D3, D5 , D6 , D7 };
byte colPins[COLS] = {D4 , col, D8 };

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
int keyNum = 0;
WiFiClient espClient;
EthernetClient ethClient;

PubSubClient mqtt(espClient);

void setup_wifi() {
  delay(10);
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}


void setup() {
  setup_wifi();
  mqtt.setServer(mqtt_server, mqtt_port);
  mqtt.setCallback(callback);
  
  pinMode(1, FUNCTION_3);
  pinMode(3, FUNCTION_3);
  pinMode(led, OUTPUT);
  pinMode(col, INPUT);
  // using above? .. then disable serial!
  // Serial.begin(9600);
display.showNumberDec(0, true);
delay(TEST_DELAY);
WiFiClient espClient;
PubSubClient mqtt(espClient);

 mqtt.setClient(espClient);
 mqtt.setServer(mqtt_server, 1883);
    
mqtt.setCallback(callback);
mqtt.subscribe("escape/keypadin");

}

void callback(char* topic, byte* payload, unsigned int length) {
    //  digitalWrite(led, HIGH);

    String topicStr = topic;
      byte value = atoi((char*)payload);
       if (value == 1){
    digitalWrite(led, HIGH);

 }else if (value == 0){
    digitalWrite(led, LOW);
 }
    

}

void reconnect() {
  while (!mqtt.connected()) {
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    if (mqtt.connect(clientId.c_str())) {
      mqtt.publish("outTopic", "hello world");
      mqtt.subscribe("escape/keypadin");
    } else {
      delay(5000);
    }
  }
}



void loop() {

  if (!mqtt.connected()) {
    reconnect();
  }
    mqtt.loop();

  // put your main code here, to run repeatedly:
  char key = keypad.getKey();

  if (key) {

    if(key=='*'){
      keyNum = 0;
    } else if (key=='#'){
         ++value;
  snprintf (msg, MSG_BUFFER_SIZE, "#%1d", keyNum);
        mqtt.publish("escape/keypad", msg);
    }
    
       else{
      if(keyNum<=999){
        keyNum = (keyNum*10) + (int(key)-48);
      }
    }
    
    //  Serial.println(key);
    display.setBrightness(0x0f);

    uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 };
    display.setSegments(data);

    display.setSegments(data);
    display.showNumberDec(keyNum);

  }

}

Shelly Devices

I love shellies, easy to implement and hacker friendly.

MQTT out of the box.
Curl in and out – you can switch it on/off using curl, but it can send a http command also.
I’ve used this with Domoticz and Home Assistant.
It has a webinterface, with timers, and there is also a client for Android/Iphone
You’ve got some own gpio pins to your disposal and the unit is flash-able!

curl -X POST https://shellydevice/device/relay/control -d "channel=IDHERE&turn=on&id=ID&auth_key=AUTH"

The device is not isolated from the mains. To flash it, the mains must be disconnected.

SHELLY 1

I use this for simple on/off switches around the house.
Using it with a physical switch and MQTT (Nodered)

SHELLY 2 PM

Same as above but this one has a build in power meter

SHELLY DIMMER

Generic dimmer

Dimmer with low voltage rotary encoder!
https://www.instructables.com/Shelly-Dimmer-Wall-Switch-With-Rotary-Knob-and-Hom/

SHELLY RGBW2

A RGBW / 4 Channel controller
You can connect RGB strips, but also dimmable white strips in 4 channels. 12V or 24V.
NOTE! : There is a common 12V connection, and GND will be controlled!

SHELLY PLUG S

I love these small wall plugs, i’ve used these also to find power consuming devices around the house.

For example, i made a nodered flow, to see if the washing machines are running or not.

SHELLY BUTTON

This became my all purpose alarm thinghy

SHELLY DOORSENSOR

A door sensor WITH temperature and light sensor build in!

Home Assistant example

SHELLY WATER SENSOR

This one lays below our washing machine

SHELLY SMOKE ALARM

(Preordered)

SHELLY PM4

A four channel power measure/switch for your fuse box


GENERIC SHELLY STUFF
A smart doorbell schematic i found

https://www.thingiverse.com/thing:5756154
Very nice .. printable cases for your shellies!

Mobile Raspberry Access Point with Mqtt and a display

UPDATE: 20230214 / 20230224

Install Bullseye on a SDCard

Enable wifi country code using raspi-conf
(While you at it, enable I2C for the display)

Install and configure an Access Point

# As root
apt update
apt upgrade
apt install hostapd
apt install dnsmasq
systemctl stop hostapd
systemctl stop dnsmasq

cat <<EOF > /etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
ssid=escape
hw_mode=g
channel=6
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=mysecretpass
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
EOF

cat <<EOF >> /etc/dnsmasq.conf
interface=wlan0
bind-dynamic
domain-needed
bogus-priv
dhcp-range=192.168.50.150,192.168.50.200,255.255.255.0,12h
EOF

cat <<EOF >> /etc/dhcpcd.conf
interface wlan0
nohook wpa_supplicant
static ip_address=192.168.50.10/24
static routers=192.168.50.1
static domain_name_servers=8.8.8.8
EOF

sed -i s/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g /etc/sysctl.conf


mkdir /etc/nftables
cat <<EOF > /etc/nftables/nft-stat-ap.nft
flush ruleset

table inet ap {
        chain routethrough {
                type nat hook postrouting priority filter; policy accept;
                oifname "eth0" masquerade
        }

        chain fward {
                type filter hook forward priority filter; policy accept;
                iifname "eth0" oifname "wlan0" ct state established,related accept
                iifname "wlan0" oifname "eth0" accept
        }
}
EOF

chmod +x /etc/nftables/nft-stat-ap.nft
cat /etc/nftables.conf | grep nft-stat-ap.nft || echo 'include "/etc/nftables/nft-stat-ap.nft"' >> /etc/nftables.conf

systemctl unmask hostapd
systemctl enable hostapd
systemctl enable nftables

reboot

UPDATE: 20230214

Now in its case, added two buttons and one led.

UPDATE : 20230224 mqtt config

apt-get install mosquitto mosquitto-clients

vi /etc/mosquitto/conf.d/remotemqtt.conf
per_listener_settings true
# internal mqtt
listener 1883
allow_anonymous true
# connection over the internet
connection bridge-01
address remoteserver:8883
bridge_cafile /etc/mosquitto/certs/ca.crt
bridge_keyfile /etc/mosquitto/certs/remoteaccesspoint.key
bridge_certfile /etc/mosquitto/certs/remoteaccesspoint.crt
topic escape/# both 0
remote_username remoteuser
remote_password remotepass

########## remote server config

cd /etc/mosquitto
mosquitto_passwd passwords remoteuser

cd /etc/mosquitto/certs
./generate-CA.sh client remoteaccesspoint

copy ca.crt remoteaccesspoint.key and remoteaccesspoint.crt to accesspoint

mosquitto.conf
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
#per_listener_settings true
# Plain MQTT protocol
listener 1883
allow_anonymous true
# End of plain MQTT configuration
# MQTT over TLS/SSL
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/webserver.fash.lab.crt
keyfile /etc/mosquitto/certs/webserver.fash.lab.key
allow_anonymous false
password_file /etc/mosquitto/passwords
# End of MQTT over TLS/SLL configuration
listener 9001
protocol websockets
# End of plain Websockets configuration
# WebSockets over TLS/SSL
listener 9883
protocol websockets
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/webserver.fash.lab.crt
keyfile /etc/mosquitto/certs/webserver.fash.lab.key
log_dest file /var/log/mosquitto/mosquitto.log
include_dir /etc/mosquitto/conf.d
connection bridge-01
address extramqttserver:1883
topic lscspm1/# both 0
topic owntracks/# both 0
topic escape/# both 0

log_type all


Controlling Display and MQTT messages examples

apt-get install python3-smbus

python3 printline.py -1 "line 1" -2 "line 2"

wget https://github.com/emcniece/rpi-lcd/blob/master/RPi_I2C_driver.py

cat printline.py
# requires RPi_I2C_driver.py
import RPi_I2C_driver
from time import *
import sys, getopt

#python3 fix
unichr = chr 

mylcd = RPi_I2C_driver.lcd()
# test 2                  1234567812345678


def main(argv):
   line1 = ''
   line2 = ''
   try:
      opts, args = getopt.getopt(argv,"h1:2:",["txt1=","txt2="])
   except getopt.GetoptError:
      print ('printline.py -1 <line1> -2 <line2>')
      sys.exit(2)
   for opt, arg in opts:
      if opt == '-h':
         print ('printline.py -1 <line1> -2 <line2>')
         sys.exit()
      elif opt in ("-1", "--txt1"):
         line1 = arg
      elif opt in ("-2", "--txt2"):
         line2 = arg

   mylcd.lcd_display_string(line1, 1)
   mylcd.lcd_display_string(line2, 2)
if __name__ == "__main__":
   main(sys.argv[1:])

Print internal and external ip

myip=$(/usr/sbin/ifconfig eth0 | grep "inet " | awk '{ print $2 }')
extip=$(curl -s http://whatismyip.akamai.com/)
python3 printline.py -1 "i $myip" -2 "e $extip"

mosquitto health tester

timeout 1 mosquitto_sub -t '$SYS/#' -C 1 | grep -v Error || exit 1

Button press shutdown

raspi-gpio get 27  | grep level=0 >/dev/null 
if [ $? == 0 ] ; then

python3 printline.py -1 "shutting" -2 "down"
/usr/sbin/halt -p
fi

Cleaned-up minimal mqtt poster

#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid = "ssidname";
const char* password = "ssidpass";
const char* mqttServer = "192.168.50.10";

WiFiClient espClient;
PubSubClient client(espClient);


void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
}


void setup() {
Serial.begin(115200);
initWiFi();
  Serial.print("RRSI: ");
  Serial.println(WiFi.RSSI());
    client.setClient(espClient);
    client.setServer(mqttServer,1883);
 if (client.connect("testmodule")) {

      Serial.println("connected");
 client.publish("escape/testclient", "connected");
    } else {
            Serial.println("Mqtt not connected");
    }

}

void loop() {
        }

}

ARDUINO CONCERTINA – POC 2

See also

Potmeter needs some tweaking

New code

#include <Keypad.h>
int buzzer=9;
int lastsensorread;
int prevkey;
int push=450;
int pull=550;

const byte ROWS = 8; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'#','0','*'},
  {'A','B','C'},
  {'D','E','F'},
  {'G','H','I'},
  {'J','K','L'}
};
byte rowPins[ROWS] = {5, 6, 7, 8, 10, 11, 12, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {2, 3, 4 }; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
  pinMode(buzzer,OUTPUT);

}
  
void loop(){
  char key = keypad.getKey();
//  if (key == NO_KEY){
 //   key = prevkey;
   //   }
      
  
 // if (key != NO_KEY){
    int freq = 0;
    int sensorValue = analogRead(A0);
    //sensorValue = ((sensorValue+4)/5)*5;



    
    if (sensorValue > push && sensorValue < pull   ) {
    // Serial.println("No pull or push");
    noTone(buzzer);
    }
    else if (key == NO_KEY){
      switch (keypad.getState()){
            case RELEASED:
             noTone(buzzer);
      }
    }
    else 
    {
    if (key == '1' && sensorValue < push ) { tone(buzzer,415); }; // G push
    if (key == '1' && sensorValue > pull ) { tone(buzzer,466); }; // A pull
    if (key == '2' && sensorValue < push ) { tone(buzzer,392); }; // G push
    if (key == '2' && sensorValue > pull ) { tone(buzzer,440); }; // A pull
    if (key == '3' && sensorValue < push ) { tone(buzzer,587); }; // G push
    if (key == '3' && sensorValue > pull ) { tone(buzzer,659); }; // A pull
    
    if (key == '4' && sensorValue < push ) { tone(buzzer,440); };
    if (key == '4' && sensorValue > pull ) { tone(buzzer,392); };
    if (key == '5' && sensorValue < push ) { tone(buzzer,329); };
    if (key == '5' && sensorValue > pull ) { tone(buzzer,349); };
    if (key == '6' && sensorValue < push ) { tone(buzzer,493); };
    if (key == '6' && sensorValue > pull ) { tone(buzzer,523); };
      //8l f/e
    if (key == '8' && sensorValue < push ) { tone(buzzer,261); };
    if (key == '8' && sensorValue > pull ) { tone(buzzer,587); };

    if (key == 'A' && sensorValue < push ) { tone(buzzer,783); };
    if (key == 'A' && sensorValue > pull ) { tone(buzzer,739); };
    if (key == 'B' && sensorValue < push ) { tone(buzzer,523); };
    if (key == 'B' && sensorValue > pull ) { tone(buzzer,493); };

    if (key == 'D' && sensorValue < push ) { tone(buzzer,987); };
    if (key == 'D' && sensorValue > pull ) { tone(buzzer,880); };
    if (key == 'E' && sensorValue < push ) { tone(buzzer,659); };
    if (key == 'E' && sensorValue > pull ) { tone(buzzer,587); };

    if (key == 'H' && sensorValue < push ) { tone(buzzer,783); };
    if (key == 'H' && sensorValue > pull ) { tone(buzzer,698); };
    //tone(buzzer,freq);
    }
    Serial.println(sensorValue);
    Serial.println(key);
    Serial.println(freq);
 //   lastsensorread = sensorValue;
    prevkey = key;
      
 // }
}

Wanted to make a mini Sid Player, and failed

UPDATE: https://www.henriaanstoot.nl/2024/05/30/c64-mobile-sid-player-using-raspberry/

I’ve got an old Speaker Phat, and a Raspberry Zero

An audio add-on board for Raspberry ( same size as the Zero )
Connections

My initial idea was to have the “High Voltage Sid Collection” (Downloaded the 55000 pack)
On a mini device, battery operated and with a little keypad.

On the keypad i can select the Sidtune to play, or pressing
A and a number the Sids from a certain artist.

The display gives you information about the tune being played.
( The display has an I2C hat to convert 8bits to I2C )

See pinout phat above.
I’ve got three choices for I2C connection (green/blue to the Phat)

  • Direct connect and use different addresses
  • Use a I2C hub and different addresses
  • Define a secondary I2C on the raspberry

So I made the first test setup …

Underrun occurred .. So back to the drawingboard.
I probably need a better Audio Hat.
First to try .. Zero fast enough for sidplay2?
Maybe audio over hdmi works??

Computer cards i’ve owned / used

Only cards worth mentioning.
I will add more information to this page

Graphics:

Hercules ???? – Did a lot of machinecode on this one. (Which?)
CGA/EGA Card ??? – Machinecode hacking
VGA .. first card also machine code hacking
Matrox
Some cards i knew a lot about, i did some manipulations using assembly that were very interesting, but only worked on that specific brand.

16 Bit ISA VGA card that is compatibe with 8bits slots for my XT.
see https://www.henriaanstoot.nl/2022/11/16/hercules-to-vga/

Sound:

I’ve bought a lot of Crystal Soundcards, there were breeze to install and use under linux, way back when it was hard to get supported hardware.



Firewire card (for Studio equipment):

Our old trusty mixer

Videocapture:

Video blaster – Which i used to record video (Like ‘Sepp en fash vervelen zich nooit’) and my DIY controllable webcam.

Video Blaster


Pinnacle PCTV- Brooktree Bt848

I used the firewire connection to get the footage of my Canon Video Camera

Firewire cable
Not my card but comparable


Hauppauge WinTV PVR 350


Basetech BR116 (Current) – RCA

Not really a “card”


Camlink 4K (Current) – hdmi

Other:

Stallion RS-232 card for connecting multiple serial terminals.
(Icecrew chat server on Lan Parties)

insmod istallion board0=brumby,0x350,0xcc000
/usr/lib/stallion/stlload -i 2681.sys


Wyse Multiport Serial Card

Ramvantage 16bits ISA memory expansion

PC Hardware diagnostics card

Could not find any information on this card

Catweasel

The Catweasel is a family of enhanced floppy-disk controllers from German company Individual Computers. These controllers are designed to allow more recent computers, such as PCs, to access a wide variety of older or non-native disk formats using standard floppy drives.

You could connect joysticks and there is a socket for a SID chip on the card.

Servo’s Rotary encoders, Node-red and Mqtt

Multiple rotary encoders are controlling a servo based lock. 3 players have to work together to open the lock.

Secure MQTT rotary encoder (Can be used over the internet)
Servo based lock
Lock Mockup
Node red test logic

Arduino Rotary button (mqtt)

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <time.h>
#include <PubSubClient.h>

#define encoderCLK 5   //D1
#define encoderDT 4    //D2
int servoAngle = 0;
int crntCLK;
int prvsCLK;
String myString;
char ang[50];

#ifndef SECRET
const char ssid[] = "MYSSID";
const char pass[] = "MSSIDPASS";

#define HOSTNAME "rotary1"

const char MQTT_HOST[] = "securemqttserver";
const int MQTT_PORT = 8883;
const char MQTT_USER[] = "user"; // leave blank if no credentials used
const char MQTT_PASS[] = "pass"; // leave blank if no credentials used

const char MQTT_SUB_TOPIC[] = "escape/" HOSTNAME "/in";
const char MQTT_PUB_TOPIC[] = "escape/" HOSTNAME "/out";
const char MQTT_PUB_TOPIC_angle[] = "escape/" HOSTNAME "/angle";

#ifdef CHECK_CA_ROOT
static const char digicert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIUXEEQRLHhYox8a95YiAYX/wQ/XeMwDQYJKoZIhvcNAQEN
----8< snip snap
CyLjTT2rtllw==
-----END CERTIFICATE-----
)EOF";
    #endif

    #ifdef CHECK_PUB_KEY
    // Extracted by: openssl x509 -pubkey -noout -in ca.crt
    static const char pubkey[] PROGMEM = R"KEY(
    -----BEGIN PUBLIC KEY-----
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxx
    -----END PUBLIC KEY-----
    )KEY";
    #endif

    #ifdef CHECK_FINGERPRINT
	// Extracted by: openssl x509 -fingerprint -in ca.crt
    static const char fp[] PROGMEM = "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD";
    #endif
#endif

//////////////////////////////////////////////////////

#if (defined(CHECK_PUB_KEY) and defined(CHECK_CA_ROOT)) or (defined(CHECK_PUB_KEY) and defined(CHECK_FINGERPRINT)) or (defined(CHECK_FINGERPRINT) and defined(CHECK_CA_ROOT)) or (defined(CHECK_PUB_KEY) and defined(CHECK_CA_ROOT) and defined(CHECK_FINGERPRINT))
  #error "cant have both CHECK_CA_ROOT and CHECK_PUB_KEY enabled"
#endif

BearSSL::WiFiClientSecure net;
PubSubClient client(net);

time_t now;
unsigned long lastMillis = 0;

void mqtt_connect()
{
  while (!client.connected()) {
    Serial.print("Time: ");
    Serial.print(ctime(&now));
    Serial.print("MQTT connecting ... ");
    if (client.connect(HOSTNAME, MQTT_USER, MQTT_PASS)) {
      Serial.println("connected.");
      client.subscribe(MQTT_SUB_TOPIC);
    } else {
      Serial.print("failed, status code =");
      Serial.print(client.state());
      Serial.println(". Try again in 5 seconds.");
      /* Wait 5 seconds before retrying */
      delay(5000);
    }
  }
}

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Received [");
  Serial.print(topic);
  Serial.print("]: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
}

void setup()
{
  pinMode (encoderCLK,INPUT_PULLUP);
  pinMode (encoderDT,INPUT_PULLUP);
  prvsCLK = digitalRead(encoderCLK);
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  Serial.print("Attempting to connect to SSID: ");
  Serial.print(ssid);
  WiFi.hostname(HOSTNAME);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("connected!");

  Serial.print("Setting time using SNTP");
  configTime(1 * 3600, 0, "pool.ntp.org", "time.nist.gov");
  now = time(nullptr);
  while (now < 1510592825) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("done!");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));

  #ifdef CHECK_CA_ROOT
    BearSSL::X509List cert(digicert);
    net.setTrustAnchors(&cert);
  #endif
  #ifdef CHECK_PUB_KEY
    BearSSL::PublicKey key(pubkey);
    net.setKnownKey(&key);
  #endif
  #ifdef CHECK_FINGERPRINT
    net.setFingerprint(fp);
  #endif
  #if (!defined(CHECK_PUB_KEY) and !defined(CHECK_CA_ROOT) and !defined(CHECK_FINGERPRINT))
    net.setInsecure();
  #endif

  client.setServer(MQTT_HOST, MQTT_PORT);
  client.setCallback(receivedCallback);
  mqtt_connect();
}

void loop()
{
   crntCLK = digitalRead(encoderCLK);

 if (crntCLK != prvsCLK){
      // If the encoderDT state is different than the encoderCLK state then the rotary encoder is rotating counterclockwise
        if (digitalRead(encoderDT) != crntCLK) {
          servoAngle ++;

        }
        else {
          servoAngle --;
         }
         Serial.println(servoAngle);
          String myString = String(servoAngle);
          myString.toCharArray(ang, myString.length() + 1);
          client.publish(MQTT_PUB_TOPIC_angle, ang, false);
 }
  prvsCLK = crntCLK; 
  
  now = time(nullptr);
  if (WiFi.status() != WL_CONNECTED)
  {
    Serial.print("Checking wifi");
    while (WiFi.waitForConnectResult() != WL_CONNECTED)
    {
      WiFi.begin(ssid, pass);
      Serial.print(".");
      delay(10);
    }
    Serial.println("connected");
  }
  else
  {
    if (!client.connected())
    {
      mqtt_connect();
    }
    else
    {
      client.loop();
    }
  }

  if (millis() - lastMillis > 5000) {
    lastMillis = millis();
    client.publish(MQTT_PUB_TOPIC, ctime(&now), false);
  }
}

Arduino 3 servos using mqtt

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Servo.h> 
Servo lock1; 
Servo lock2;
Servo lock3;

const char* ssid = "MYSSID";                // WiFi SSID
const char* password = "MYSSIDPASS";        // WiFi Password
const char* mqtt_server = "MQTTSERVER";  // IP Broker MQTT
const char* topic_lock1 = "escape/servo/lock1";
const char* topic_lock2 = "escape/servo/lock2";
const char* topic_lock3 = "escape/servo/lock3";
 
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup() {

  Serial.begin(115200);
  lock1.attach(D1);
  lock2.attach(D2);
  lock3.attach(D3);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
 String string;
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 for (int i = 0; i < length; i++) {
 string+=((char)payload[i]); 
 }
 Serial.print(string);
 Serial.print(" toInt ");
 int pos = string.toInt(); 
 Serial.println(pos);

 
 if ( strcmp(topic, topic_lock1) == 0 ) {
 Serial.print("lock1 ");
 Serial.println(pos);
 lock1.write(pos); 
 }
 if ( strcmp(topic, topic_lock2) == 0 ) {
 Serial.print("lock2 ");
 Serial.println(pos);
 lock2.write(pos); 
 }
 if ( strcmp(topic, topic_lock3) == 0 ) {
 Serial.print("lock3 ");
 Serial.println(pos);
 lock3.write(pos); 
 }
 
 delay(15); 
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266servolocks")) {
      Serial.println("connected");
      client.subscribe(topic_lock1); 
      client.subscribe(topic_lock2); 
      client.subscribe(topic_lock3); 
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
void loop() {   
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  delay(100);
}

Connect the wires puzzle

As part of my internet based escape room.

I took the idea from the Keep-talking-and-nobody-explodes game.

When starting up, is gets the configuration from a Mqtt Topic.
So i can create a different setup over the internet.

The result is also send back via MQTT.

(example play, all players are on different locations)

  • Player 1 figures out the wires.
  • Player 2 connects the wires.
  • Player 3 sees the result (correct or not) and next puzzle opens up for Player 3

I used a wire with a line. Multiple colors for jacks and sockets.
It’s also possible to connect a jack to a jack.
Loads of possibilities.

Todo:

Wifi and Mqtt part
Debounce software or hardware

Arduino Concertina

Lets try to make a Electronic Concertina

UPDATE:
https://www.henriaanstoot.nl/2023/01/10/arduino-concertina-poc/
https://www.henriaanstoot.nl/2023/01/17/arduino-concertina-poc-2/

First design

So we need some pushbuttons … at least 14 .. for the most simple tunes.
A sensor for push and pull.
A buzzer or better yet .. a jack for earphones.
Arduino with enough pins to connect a keyboard matrix.
When using a keyboard matrix only single keypresses are detected.
So we cant do chords!

Raspberry Zero with display

I’ve installed a headless Raspbian on a Pi Zero with a 2×16 Chars lcd display. As part of the Escape Room over the internet

Using the raspberry imager:
I’ve set the username/password and ssh access in this tool.
For wifi access i’ve placed below file on the SDcard in /boot
(You can do this in the tool, but i want to make this dynamic when connected at a remote site.)
file: wpa_supplicant.conf

country=NL
update_config=1
ctrl_interface=/var/run/wpa_supplicant

network={
 scan_ssid=1
 ssid="MYSSID"
 psk="MYSSIDPASS"
}

ssh into the RPi

sudo raspi-config
Interface options and enable I2C

sudo apt-get install python3-smbus

wget https://gist.githubusercontent.com/DenisFromHR/cc863375a6e19dce359d/raw/36b82e787450d127f5019a40e0a55b08bd43435a/RPi_I2C_driver.py
and 
wget https://gist.githubusercontent.com/DenisFromHR/cc863375a6e19dce359d/raw/36b82e787450d127f5019a40e0a55b08bd43435a/examples.py

For python3 edit the example and put at the top

# requires RPi_I2C_driver.py
import RPi_I2C_driver
from time import *
unichr = chr

Run with 
python3 examples.py
lcd display with i2c backpack
I2C backpack

Below is a mockup session.

Next todo:

  • Add more hardware (like buttons) to the RPI
  • Configure an Accesspoint on this Rpi for other devices to connect to
  • Install a local Mqtt broker, which connects secure to my internet facing broker
Setup example