Doel is om op afstand een koffie apparaat aan te zetten, een Schaerer Siena 2.
Stap 1
Om te beginnen google we naar "schaerer siena service manual", dan vinden we meteen de layout van de machine (https://coffeemachinesmanual.files.wordpress.com/2011/02/c2a7-062760_smsi-02-v03.pdf). Hierin staat hoe je hem open moet maken.
Om te beginnen zoeken we de knop die hem aan en uit zet, die zit op de printplaat bij het LCD scherm. na wat meten zien we dat bij een pin koppelt aan ground en hiermee de machine aan en uit zet. Om dit eenvoudig aan het netwerk te koppelen hebben we een qubino relay gebruikt (Flush 1D Relay). Zwave netwerk gaat via een Razberry en homebridge. Zo kunnen we hem eenvoudig koppelen aan homekit.
Stap 2
Nu we toch bezig zijn met de PCB met het LCD scherm willen we een stap verder gaan, kunnen we de status uitlezen? Na wat googlen op de IC's zien we dat er 4 schift registers opzitten die de knoppen en de lampjes aansturen. De lampjes zitten vast aan twee 74HC165N IC's, geen idee wat we hiermee kunnen dus weer googlen...

http://www.ti.com/lit/ds/symlink/sn74hc595.pdf
En de setup lijkt verdacht veel op:

Met dank aan: https://aherrero.github.io/atmega328/shifting/2018/11/12/MultiplexingAndAtmega.html
Na veel meten hier onze tekening:

Nu solderen en de pinnen uitlezen, de koffie machine ziet er nu zo uit:

We gaan een esp32 boardje gebruiken om te kijken of we de signalen af kunnen vangen, op de pinnen: Data, Latch en Clock.
We zoeken 16 bits met de regelmaat van de klok en dat elke latch:
attachInterrupt(clockPin, getData, FALLING);
attachInterrupt(latchPin, processData, FALLING);
Als de Latch valt lezen we bij het vallen van de klokpin de data uit de IC:
void getData() {
//Serial.println("getData");
pins |= digitalRead(dataPin) << count;
count++;
}
Na heel veel uren proberen en studeren zijn we op de volgende code uit gekomen. (Arduino - lolin D32)
#include <WiFi.h>
#include <MQTT.h>
#define clockPin 5
#define dataPin 4
#define latchPin 16
uint32_t ledsTimer[16] = {0};
uint32_t ledsState[16] = {0};
uint32_t sendState[16] = {0};
volatile int count = 0;
volatile int countPD = 0;
volatile int state = 0;
volatile bool checkStateTwo = false;
volatile uint32_t pins = 0;
volatile uint32_t diff = 0;
volatile uint32_t pinsCheck1 = 0;
volatile uint32_t lastSent = 0;
void ICACHE_RAM_ATTR getData();
void ICACHE_RAM_ATTR processData();
const char ssid[] = "SSID";
const char pass[] = "PASSWORD";
WiFiClient net;
MQTTClient MQTTc;
void processData() {
if(count == 16) {
if(pinsCheck1 == pins && countPD < 100) {
if(checkStateTwo) countPD++;
} else {
if(countPD > 99) {
char countString[32];
//sprintf(countString, "%d", countPD);
//MQTTc.publish("Check",countString);
//Serial.println("Check 20 ");
}
countPD = 0;
diff = pins ^ pinsCheck1;
uint32_t currentTime = millis();
checkStateTwo = false;
for(int i=0; i<16; i++) {
state = ledsState[i];
if(diff & (1 << i)) {
getState(i);
if(ledsTimer[i] > 0 ) {
if((currentTime - ledsTimer[i]) < 1000) {
state = 2;
ledsTimer[i] = currentTime;
}
}
} else if(ledsState[i] == 2 && ((currentTime - ledsTimer[i]) > 1000)) {
getState(i);
}
if(state == 2) checkStateTwo = true;
if(ledsState[i] != state) {
ledsTimer[i] = currentTime;
ledsState[i] = state;
}
}
pinsCheck1 = pins;
}
}
pins = 0;
count = 0;
}
void getData() {
//Serial.println("getData");
pins |= digitalRead(dataPin) << count;
count++;
}
void getState(int i) {
if((i>=0 && i<=3) || (i>=8 && i<=11)) {
state = 1;
if(pins & (1 << i)) state = 0;
} else {
state = 0;
if(pins & (1 << i)) state = 1;
}
}
void setup() {
Serial.begin(115200);
Serial.println();
delay(1000);
Serial.setDebugOutput(true);
WiFi.begin(ssid, pass);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
MQTTc.begin("xxx.xxx.xxx.xxx", net);
attachInterrupt(clockPin, getData, FALLING);
attachInterrupt(latchPin, processData, FALLING);
}
void reconnectMQTT() {
detachInterrupt(clockPin);
detachInterrupt(latchPin);
//long randomNR = random(1, 9999);
while (!MQTTc.connected()) {
//ESP.wdtFeed();
if(WiFi.status() != WL_CONNECTED) {
Serial.print("Connecting");
WiFi.disconnect();
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
}
Serial.print("Attempting MQTT connection...");
//Serial.print(randomNR);
// Attempt to connect
// If you do not want to use a username and password, change next line to
// if (client.connect("ESP8266Client")) {
if (MQTTc.connect("Siena")) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
//Serial.print(MQTTc.state());
Serial.println(" try again in 1 seconds");
// Wait 1 seconds before retrying
delay(1000);
}
}
attachInterrupt((clockPin), getData, FALLING);
attachInterrupt((latchPin), processData, FALLING);
}
void loop() {
if (!MQTTc.connected()) {
reconnectMQTT();
MQTTc.publish("Alive","Yes");
Serial.println("MQTT keep alive ....");
}
for(int i=0; i<16; i++) {
if(ledsState[i] != sendState[i]) {
Serial.print("Led ");
Serial.print(i+1);
Serial.print(": ");
Serial.println(state);
char ledString[32];
sprintf(ledString, "/koffie/led/%d", (i+1));
MQTTc.publish(ledString, ledsState[i] == 2 ? "BLINK" : (ledsState[i] == 1 ? "ON" : "OFF"));
Serial.println(ledString);
sendState[i] = ledsState[i];
}
}
}
De led status wordt via MQTT verstuurd naar de Dominica server.