Ice Maker - Controlling onboard PCB

Hi,

Let me start off by saying I am pretty new to this.

Some important information:

  • ESP8266
  • Injecting myself between the main board of the ice machine and the control board (led lights, power on/off, etc)
  • 6 wires between those 2 boards.

I followed this guide: Smart Ice Maker
Note: I don't have the same ice machine but it seems to be pretty much the same thing.

My issue:
It seems that when connecting the red wire directly to ground for a second or so, the machine turns on, or turns off.

I cannot seem to be able to figure out how to approach this using an ESP8266 in order to be able to send it signals (basically put that wire to ground). Currently using the same as in the article, Wemos D1 Mini and have the wire as an output pin. The code seems to send LOW signal then high.

Seems to not work at all. I am unsure what to do in order to be about to control it .

The schematic:

Any ideas?
Thanks

Never mind. Looking at where you got the diagram I thought you drew.

Welvome to the forum.

Draw diagram showing you between two things, There shoukd be three things, with you in between.

Do you mean to say the red wire, when grounded, turns the machine off if it was on, and vice versa?

a7

Post the code you are running.

Use the <CODE/> button in the message composition window toolbar and

paste the code here like is says

a7

Correct, the red wire when touching ground turns on the machine and vice versa.

  if (!strncmp((char*)payload, "ON", length) || (!strncmp((char*)payload, "OFF", length))) {
    digitalWrite(button, LOW);
    delay(200);
    digitalWrite(button, HIGH);
  }

Their code can be found on that url,

but here's the whole thing if needed

Note: I have modified their If statement and removed the state variable to ease troubleshooting and debugging. The state var was populated properly either way, but just FYI.

/*
    SmartHomeGeeks.io Smart Ice Maker
    https://smarthomegeeks.io/smart-icemaker
*/

#ifdef ESP32
#include <WiFi.h>             // WIFI for ESP32
#else
#include <ESP8266WiFi.h>      // WIFI for ESP8266
#include <ESP8266mDNS.h>
#endif

#include <PubSubClient.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ArduinoJson.h>
#include <arduino_secrets.h>

// Device configuration
const String deviceName = "Ice Maker";

const int sensor1 = 15; // blue wire (empty / small)
const int sensor2 = 12; // yellow wire (full)
const int sensor3 = 14; // orange wire (large / small)
const int sensor4 = 2;  // green wire (power)
const int button = 13;  // red wire

// WiFi configuration
const char* ssid = SECRET_SSID;
const char* password =  SECRET_PASS;

// MQTT configuration
const String mqttClient = "ice_maker";                          // MQTT client name
const String mqttPowerTopic = mqttClient + "/power";            // MQTT power state topic
const String mqttStateTopic = mqttClient + "/state";            // MQTT state topic
const String mqttCmdTopic = mqttClient + "/command";            // MQTT command topic
const String mqttAvlTopic = mqttClient + "/availability";       // MQTT availability topic
const char* mqttServer = SECRET_MQTT_BROKER;                    // MQTT broker IP
const char* mqttUser = SECRET_MQTT_USERNAME;                    // MQTT username
const char* mqttPassword = SECRET_MQTT_PASSWORD;                // MQTT password
const int mqttPort = 1883;                                      // MQTT port (default: 1883)

char sensorState[5];
char sensorPrevState[5];
char charPayload[50];
unsigned long lastMQTTconnect = 0;
String state;

WiFiClient espClient;
PubSubClient client(espClient); //lib required for mqtt

void setup_wifi() {
  delay(1000);

  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.print(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.hostname(mqttClient);
  WiFi.begin(ssid, password);

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

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

void autoDiscovery() {
  Serial.println("Publishing Home Assistant Autodiscovery...");

  char buffer[512];

  DynamicJsonDocument deviceData(512);
  deviceData["name"] = deviceName;
  deviceData["mdl"] = "Icemaker 400475";
  deviceData["ids"] = mqttClient;
  deviceData["mf"] = "SmartHomeGeeks.io for Tectake";
  deviceData["sw"] = "2023.08";
  
  // Switch
  DynamicJsonDocument root(512);
  root["name"] = nullptr;
  root["obj_id"] = mqttClient + "_power";
  root["ic"] = "mdi:snowflake";
  root["uniq_id"] = "switch." + mqttClient;
  root["stat_t"] = mqttPowerTopic;
  root["cmd_t"] = mqttClient + "/command";
  root["avty_t"] = mqttAvlTopic;
  for (JsonPair kv : deviceData.as<JsonObject>()) root["dev"][kv.key()] = kv.value();
  serializeJson(root, buffer);
  client.publish(("homeassistant/switch/" + mqttClient + "/config").c_str(), buffer, true);
  root.clear();

  // sensors
  root["name"] = nullptr;
  root["obj_id"] = mqttClient + "_state";
  root["ic"] = "mdi:snowflake";
  root["stat_t"] = mqttClient + "/state";
  root["uniq_id"] = "sensor." + mqttClient;
  root["avty_t"] = mqttAvlTopic;
  for (JsonPair kv : deviceData.as<JsonObject>()) root["dev"][kv.key()] = kv.value();
  serializeJson(root, buffer);
  client.publish(("homeassistant/sensor/" + mqttClient + "/config").c_str(), buffer, true);
  root.clear();

  root["name"] = "RSSI";
  root["obj_id"] = mqttClient + "_rssi";
  root["stat_t"] = mqttClient + "/rssi";
  root["unit_of_meas"] = "dBm";
  root["ic"] = "mdi:access-point";
  root["uniq_id"] = "sensor." + mqttClient + "_rssi";
  root["avty_t"] = mqttAvlTopic;
  root["ent_cat"] = "diagnostic";
  for (JsonPair kv : deviceData.as<JsonObject>()) root["dev"][kv.key()] = kv.value();
  serializeJson(root, buffer);
  client.publish(("homeassistant/sensor/" + mqttClient + "/rssi/config").c_str(), buffer, true);
  root.clear();

  // IP
  root["name"] = "IP";
  root["obj_id"] = mqttClient + "_ip";
  root["stat_t"] = mqttClient + "/ip";
  root["ic"] = "mdi:ip-network";
  root["uniq_id"] = "sensor." + mqttClient + "_ip";
  root["avty_t"] = mqttClient + "/availability";
  root["ent_cat"] = "diagnostic";
  for (JsonPair kv : deviceData.as<JsonObject>()) root["dev"][kv.key()] = kv.value();
  serializeJson(root, buffer);
  client.publish(("homeassistant/sensor/" + mqttClient + "/ip/config").c_str(), buffer, true);
  root.clear();
}

void connectmqtt() {
  // prevent constant reconnect
  if (millis() - lastMQTTconnect < 5000) return;
  lastMQTTconnect = millis();

  if (client.connect(mqttClient.c_str(), mqttUser, mqttPassword, mqttAvlTopic.c_str(), 1, true, "offline")) {
    Serial.println("connected to MQTT");
    client.setBufferSize(512);
    autoDiscovery();

    client.subscribe(mqttCmdTopic.c_str());
    client.publish(mqttAvlTopic.c_str(), "online", true);
    client.publish((mqttClient + "/ip").c_str(),  WiFi.localIP().toString().c_str(), true);

  } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
  }
}

void setup() {
  Serial.begin(115200);
  digitalWrite(button, HIGH);
  pinMode(button, OUTPUT);
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(sensor3, INPUT);
  pinMode(sensor4, INPUT);


  // Setup WiFi  
  setup_wifi();

  // Configure OTA
  ArduinoOTA.setHostname(mqttClient.c_str());
  ArduinoOTA.setPassword(SECRET_OTA_PASSWORD);
  ArduinoOTA.begin(); 

  //Connect MQTT
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  connectmqtt();
}

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

  if ((!strncmp((char*)payload, "ON", length) && state == "Off") || (!strncmp((char*)payload, "OFF", length) && state != "Off")) {
    digitalWrite(button, LOW);
    delay(200);
    digitalWrite(button, HIGH);
  }
}

void loop() {
  if (!client.connected()) {
    connectmqtt();
  }

  sprintf(sensorState, "%d%d%d%d", digitalRead(sensor1), digitalRead(sensor2), digitalRead(sensor3), digitalRead(sensor4));

  // if sensorState is differen than sensorPrevState and power is not blinking
  if (strcmp(sensorState, sensorPrevState) != 0 && atoi(sensorState) != 1) {
    client.publish((mqttClient + "/sensors").c_str(), sensorState, true);
    Serial.println(sensorState);

    switch (atoi(sensorState)) {
      case 1111:
        state = "Empty";
        break;
      case 101:
        state = "Full";
        break;
      case 11:
        state = "On";
        break;
      case 0:
        state = "Off";
        break;
    }

    Serial.println("Publish " + state);
    client.publish(mqttStateTopic.c_str(), state.c_str(), true);
    client.publish(mqttPowerTopic.c_str(), (state == "Off" ? "OFF" : "ON") , true);
    client.publish((mqttClient + "/rssi").c_str(),  String(WiFi.RSSI()).c_str(), true);

    strcpy(sensorPrevState, sensorState);
  }

  // Delay is necessary for accurate readout 
  delay(200);

  ArduinoOTA.handle();

  client.loop();
}

I can't slog through the code from where I am just now, but this

  digitalWrite(button, HIGH);
  pinMode(button, OUTPUT);

makes it seem like in the original, the red wire was connected to pin 13 and the software could turn on and off the machine by delivering a fake button press, just write LOW, wait a bit then return it to HIGH.

It might be that your machine is different and whatever the code you are borrowing did just isn't something your machine responds to.

If it was routed to a pushbutton on the machine, a relay could be placed with switch contacts in parallel with that and run by the same pin 13 signal.

You'd need an inexpensive relay module, or a plain relay and a few parts. Modules make it fooler proof.

Did you say it doesn't turn on and off when you follow the entire project detail for detail?

And is the code posted the original, or after your mods?

a7

What is the voltage between the brown and other wires?

Did you say it doesn't turn on and off when you follow the entire project detail for detail?

Correct, it does not.

And is the code posted the original, or after your mods?

Code posted is original. I only changed values (users, pass, mqtt stuff). I did change that if statement to make it easier to troubleshoot while sending ON / OFF via mqtt, which I can see in the serial monitor, getting those values just fine.

@JCA34F, Between brown and red = 5v (brown is ground). The rest are ~ 1.5 volt with machine "off" but w/ power.

OK, just peeping into the code, I see exactly what I expected

  if ((!strncmp((char*)payload, "ON", length) && state == "Off") || (!strncmp((char*)payload, "OFF", length) && state != "Off")) {
    digitalWrite(button, LOW);
    delay(200);
    digitalWrite(button, HIGH);
  }
}

A brief LOW going pulse delivered to pin 13, and therefor to the red wire.

Since manually connecting the red wire to ground turns the device on and off, we would expect the pin 13 output to do the same, that is what the original depends on and exploits.

Maybe you could measure the voltage between the red wire and ground, with the red wire hooked up as the original has it, and see if the voltage goes to zero for the pulse when the code turns the drive on and off.

Also, put a print statement right on in there to be sure the flow of the program is correct and it is actually trying, and lengthen the time the "button" is "pressed", viz:

  if ((!strncmp((char*)payload, "ON", length) && state == "Off") || (!strncmp((char*)payload, "OFF", length) && state != "Off")) {

Serial.println("                   toggling power"); 

    digitalWrite(button, LOW);
    delay(1000);
    digitalWrite(button, HIGH);
  }
}

if 200 milliseconds didn't break anything, 1000 probably won't either. You could bump it up 200 milliseconds at a time from 200 and take the measurement and observe the behaviour if you wanna be conservative. Several experiments.

If that does not work, and it is being execute, you will have to fall back to using a relay module to stand in parallel with the existing button.

But TBH it makes me worry that there are other differences...

You could test further by watching for the print message I suggest adding, leaving the red wire disconnected and acting yourself on behalf of commands printed by the code to press the button when it tells you it is doing. Just give the real button a good press when it says.

Or just leave the read wire unconnected and the device on - the code neither knows or cares if the device is on, off or being switched.

a7

Increased delay to no avail, but here are some findings:

Red wire to ground = 5v

Pin 13 (where red is) to ground only ~3.2v. I saw online maybe the ESP8266 can only output 3v. Can be powered by 5v but that's it. Thoughts?

I do see the pulse going near 0 when sending the ON / OFF command.

Didn't notice you were on a 3.3 volt board, so maybe when connected the pin never seems HIGH to the device.

But isn't that the board the original used? I'm out of an idea and can only offer the relay advice and without combing through the software say that if that button doesn't work, neither might any of the other signals the Arduino board generates.

There are solutions less clunky than relays.

Didja try being the power switch master to see if the rest of the signals do plausible things when injected as they are by the Arduino board?

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.