Can not get Arduino code with ESP board to work

I am not C++ coder.
I have this complex code that reads MAX3485 output and should foward it with help of MQTT. I was hoping to get it work with ESP board, first with ESP8266 and then, deciding that maybe the board recourses are not enough I did try switch to ESP32. Every time the result was same. I could have some MQTT connectivity or I could read sensors output in serial monitor. When I try to forward any actual data to mqtt everything broke immediately. Finally I was so desperate that I did try it several days with help of AI . It turns out that AI I was able to talk is really stupid so no point doing that.
Maybe someone knows about ESP boards and MQTT or has access to smarter AI then I. I put here ESP8266 version I tested unsuccessfully.
Thanks

#include <ESP8266WiFi.h>   // Library to handle Wi-Fi connections
#include <PubSubClient.h>  // Library for MQTT communication
#include <Ticker.h>        // Library for non-blocking delays and watchdog timer

// Wi-Fi credentials
const char* ssid = "";             // Replace with your Wi-Fi SSID
const char* password = "";     // Replace with your Wi-Fi password

// MQTT broker information
const char* mqtt_server = "";   // Replace with your MQTT broker IP
const int mqtt_port = 1883;                        // Default MQTT port
const char* mqtt_user = "";      // Replace with your MQTT broker username
const char* mqtt_password = "";  // Replace with your MQTT broker password



// User setting for date format
enum DateFormat {
  DDMMYYYY, // Date in DD.MM.YYYY format
  YYYYMMDD  // Date in YYYY-MM-DD format
};

DateFormat dateFormat = DDMMYYYY;  // Default format is DD.MM.YYYY

// Device and MQTT settings
const char* device_name = "Hewalex_Solar";
const char* mqtt_topic_base = "homeassistant/sensor/hewalex_solar";
const char* node_id = "hewalex_solar";  // Node ID for MQTT discovery

WiFiClient espClient;
PubSubClient client(espClient);  // Declare the client as a global variable

// Watchdog timer settings
Ticker hardwareWatchdog;         // Define a Ticker object for the hardware watchdog
const int watchdogTimeout = 5000; // Watchdog timeout in milliseconds

// Array to store sensor readings
float Temp[4];            // Using 4 elements for Temp array
float Flow = 0.0;         // Flow rate in liters per minute
float TotalEnergy = 0.0;  // Total energy in kWh
float CollectorPower = 0.0; // Collector Power in watts
float Consumption = 0.0;    // Consumption in watts
int CollectorPumpSpeed = 0; // Collector Pump Speed (0-15)
bool CollectorActive = false; // Collector Active status

// Strings to store controller date and time
String ControllerDate = "";
String ControllerTime = "";

// Wi-Fi Setup
void setup_wifi() {
  delay(10);
  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());
}

// MQTT Callback (not used here)
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  // Handle incoming MQTT messages
}

// Reconnect to MQTT broker
void reconnect() {
  // Loop until reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(device_name, mqtt_user, mqtt_password)) {
      Serial.println("connected");

      // Publish MQTT discovery messages for Home Assistant
      publishDiscoveryMessages();
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

// Publish discovery messages for Home Assistant
void publishDiscoveryMessages() {
  // Device information for grouping
  String deviceInfo =
    "{\"identifiers\": [\"hewalex_solar_device\"],"
    "\"name\": \"Hewalex Solar System\","
    "\"model\": \"Hewalex Model X\","
    "\"manufacturer\": \"Hewalex\","
    "\"sw_version\": \"1.0\","
    "\"support_url\": \"https://hewalex.com/support\"}";

  // Discovery topics for each sensor
  String discoveryTopics[] = {
    String("homeassistant/sensor/") + node_id + "/collector_temp/config", // Collector Temp
    String("homeassistant/sensor/") + node_id + "/buffer_temp/config",    // Buffer Temp
    String("homeassistant/sensor/") + node_id + "/backflow_temp/config",  // T3 Backflow Temp
    String("homeassistant/sensor/") + node_id + "/flow/config",           // Flow
    String("homeassistant/sensor/") + node_id + "/total_energy/config",   // Total Energy
    String("homeassistant/sensor/") + node_id + "/controller_date/config", // Controller Date
    String("homeassistant/sensor/") + node_id + "/controller_time/config", // Controller Time
    String("homeassistant/sensor/") + node_id + "/collector_power/config", // Collector Power
    String("homeassistant/sensor/") + node_id + "/consumption/config",    // Consumption
    String("homeassistant/sensor/") + node_id + "/collector_pump_speed/config", // Collector Pump Speed
    String("homeassistant/sensor/") + node_id + "/collector_active/config" // Collector Active
  };

  // Sensor names
  String sensorNames[] = {
    "Hewalex Solar Collector Temp", // Collector Temp
    "Hewalex Solar Buffer Temp",    // Buffer Temp
    "Hewalex Solar T3 Backflow Temp", // T3 Backflow Temp
    "Hewalex Solar Flow",           // Flow
    "Hewalex Total Energy",         // Total Energy
    "Hewalex Controller Date",      // Controller Date
    "Hewalex Controller Time",      // Controller Time
    "Hewalex Solar Collector Power",// Collector Power
    "Hewalex Solar Consumption",    // Consumption
    "Hewalex Solar Collector Pump Speed", // Collector Pump Speed
    "Hewalex Solar Collector Active" // Collector Active
  };

  // Units of measurement
  String units[] = {
    "°C", "°C", "°C", "L/min", "kWh", "", "", "W", "W", "", ""
  };

  // JSON keys
  String jsonKeys[] = {
    "collector", "buffer", "backflow", "flow",
    "total_energy", "controller_date", "controller_time", "collector_power",
    "consumption", "collector_pump_speed", "collector_active"
  };

  // Unique IDs
  String uniqueIds[] = {
    "hewalex_collector_temp", // Unique ID for Collector Temp
    "hewalex_buffer_temp",    // Unique ID for Buffer Temp
    "hewalex_backflow_temp",  // Unique ID for T3 Backflow Temp
    "hewalex_flow",           // Unique ID for Flow
    "hewalex_total_energy",   // Unique ID for Total Energy
    "hewalex_controller_date", // Unique ID for Controller Date
    "hewalex_controller_time", // Unique ID for Controller Time
    "hewalex_collector_power", // Unique ID for Collector Power
    "hewalex_consumption",    // Unique ID for Consumption
    "hewalex_collector_pump_speed", // Unique ID for Collector Pump Speed
    "hewalex_collector_active" // Unique ID for Collector Active
  };

  // Publish discovery messages
  for (int i = 0; i < 11; i++) {
    String discoveryPayload = String("{") +
                              "\"disc\": true," + // Add disc flag
                              "\"name\": \"" + sensorNames[i] + "\"," +
                              "\"state_topic\": \"" + mqtt_topic_base + "\"," +
                              "\"unit_of_measurement\": \"" + units[i] + "\"," +
                              "\"value_template\": \"{{ value_json." + jsonKeys[i] + " }}\"," +
                              "\"device\": " + deviceInfo + "," +
                              "\"unique_id\": \"" + uniqueIds[i] + "\"" +
                              "}";

    client.publish(discoveryTopics[i].c_str(), discoveryPayload.c_str(), true); // Set retain flag
    Serial.print("Published discovery message for ");
    Serial.println(sensorNames[i]);
  }
}

// Function to reset the hardware watchdog
void resetWatchdog() {
  ESP.wdtFeed(); // Reset the hardware watchdog timer
}

void setup() {
  // Initialize Serial Monitor for debugging
  Serial.begin(38400);  // Set the baud rate for Serial Monitor and RS485

  // Initialize Wi-Fi
  setup_wifi();

  // Initialize MQTT client
  client.setServer(mqtt_server, mqtt_port); // Set MQTT broker with port
  client.setCallback(mqttCallback);
  client.setKeepAlive(120); // Increase keep-alive to 120 seconds

  // Initialize the hardware watchdog
  hardwareWatchdog.attach_ms(watchdogTimeout, resetWatchdog);

  // Print a startup message
  Serial.println("ESP8266 Initialized with Watchdog Timer");
}

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

  // Reset the watchdog periodically
  resetWatchdog(); // Feed the watchdog timer to prevent reset

  char messageread[1000]; // Buffer to store incoming data
  int pos = 0;            // Position index for message buffer

  // Define the message to be sent via RS485
  byte message[] = {0x69, 0x02, 0x01, 0x84, 0x00, 0x00, 0x0C, 0xF6, 0x02, 0x00, 0x01, 0x00, 0x40, 0x80, 0x00, 0x32, 0x64, 0x00, 0xBD, 0xB2};

  // Send the message via RS485
  Serial.write(message, sizeof(message));  // Send the message via RS485

  // Delay to allow message transmission
  delay(10);

  // Read the data coming in from RS485
  while (Serial.available() > 0) {
    messageread[pos] = Serial.read();
    pos++;
  }

  // Check the first byte to ensure the correct message was received
  if (messageread[0] == 0x69) {
    int fncID = messageread[12];  // Extract function ID

    // Process message if function ID matches expected value
    if (fncID == 0x50) {
      int startReg = messageread[16];  // Extract starting register
      for (int i = 0; i < messageread[15]; i++) {
        if (i % 2 == 0) {
          int iReg = i + startReg;  // Calculate register index

          // Process readings based on register index (ascending order)
          if (iReg == 120) {  // Controller Date
            // Extract raw values
            byte yearByte = messageread[18 + i];
            byte monthByte = messageread[19 + i];
            byte dayByte = messageread[20 + i];  // Using 20th index for day

            Serial.print("Raw Year: ");
            Serial.println(yearByte, HEX);  // Print as hexadecimal

            Serial.print("Raw Month: ");
            Serial.println(monthByte, HEX);  // Print as hexadecimal

            Serial.print("Raw Day: ");
            Serial.println(dayByte, HEX);  // Print as hexadecimal

            // Format date based on selected date format
            int year = 2000 + yearByte;  // Extract year
            int month = monthByte;       // Extract month
            int day = dayByte;           // Extract day

            if (dateFormat == DDMMYYYY) {
              // Format as DD.MM.YYYY
              ControllerDate = (day < 10 ? "0" : "") + String(day) + "." +
                               (month < 10 ? "0" : "") + String(month) + "." +
                               String(year);
            } else {
              // Format as YYYY-MM-DD
              ControllerDate = String(year) + "-" +
                               (month < 10 ? "0" : "") + String(month) + "-" +
                               (day < 10 ? "0" : "") + String(day);
            }

            Serial.print("Formatted Date: ");
            Serial.println(ControllerDate);
          }

          if (iReg == 124) {  // Controller Time
            // Extract raw values
            byte rawHour = messageread[18 + i];
            byte rawMinute = messageread[19 + i];

            // Print unformatted raw values
            Serial.print("Raw Hour: ");
            Serial.println(rawHour);  // Print as integer

            Serial.print("Raw Minute: ");
            Serial.println(rawMinute);  // Print as integer

            // Show formatted time as HH:MM with leading zeros
            ControllerTime = (rawHour < 10 ? "0" : "") + String(rawHour) + ":" + (rawMinute < 10 ? "0" : "") + String(rawMinute);

            Serial.print("Formatted Time: ");
            Serial.println(ControllerTime);
          }

          if (iReg == 128) {  // Collector Temp
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            if (w & 0x8000) {
              w = w - 0x10000;
            }
            Temp[0] = (w / 10.0) * 10.0; // Convert to °C
          }

          if (iReg == 130) {  // Buffer Temp
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            if (w & 0x8000) {
              w = w - 0x10000;
            }
            Temp[1] = (w / 10.0) * 10.0; // Convert to °C
          }

          if (iReg == 132) {  // T3 Backflow Temp
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            if (w & 0x8000) {
              w = w - 0x10000;
            }
            Temp[2] = (w / 10.0) * 10.0; // Convert to °C
          }

          if (iReg == 144) {  // Collector Power
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            if (w & 0x8000) {
              w = w - 0x10000;
            }
            CollectorPower = w; // Use Collector Power directly in watts
          }

          if (iReg == 148) {  // Consumption
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            if (w & 0x8000) {
              w = w - 0x10000;
            }
            Consumption = w; // Use Consumption directly in watts
          }

          if (iReg == 150) {  // Collector Active
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            CollectorActive = (w != 0); // Set Collector Active status
          }

          if (iReg == 152) {  // Flow
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            if (w & 0x8000) {
              w = w - 0x10000;
            }
            Flow = w / 10.0;  // Convert to liters per minute
          }

          if (iReg == 156) {  // Collector Pump Speed
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            CollectorPumpSpeed = w; // Values are 0-15
          }

          if (iReg == 166) {  // Total Energy
            byte hexstr[] = {messageread[19 + i], messageread[18 + i]};
            int w = hexstr[0] << 8 | hexstr[1];
            if (w & 0x8000) {
              w = w - 0x10000;
            }
            TotalEnergy = w / 100.0;  // Convert to kWh
          }
        }
      }
    }
  }

  // Send temperature data and other metrics to MQTT
  char mqttPayload[512]; // Increased buffer size to accommodate new parameters
  snprintf(mqttPayload, sizeof(mqttPayload),
           "{\"collector\": %.1f, \"buffer\": %.1f, \"backflow\": %.1f, \"collector_power\": %.0f, \"consumption\": %.0f, \"collector_pump_speed\": %d, \"collector_active\": %s, \"flow\": %.1f, \"total_energy\": %.1f, \"controller_date\": \"%s\", \"controller_time\": \"%s\"}",
           Temp[0], Temp[1], Temp[2], CollectorPower, Consumption, CollectorPumpSpeed, CollectorActive ? "true" : "false", Flow, TotalEnergy, ControllerDate.c_str(), ControllerTime.c_str());
  client.publish(mqtt_topic_base, mqttPayload, true); // Set QoS to 2 for reliable message delivery

  // Print readings to Serial Monitor
  Serial.print("Collector Temp = ");
  Serial.print(Temp[0]);
  Serial.println(" °C");

  Serial.print("Buffer Temp = ");
  Serial.print(Temp[1]);
  Serial.println(" °C");

  Serial.print("T3 Backflow Temp = ");
  Serial.print(Temp[2]);
  Serial.println(" °C");

  Serial.print("Collector Power = ");
  Serial.print(CollectorPower);
  Serial.println(" W");

  Serial.print("Consumption = ");
  Serial.print(Consumption);
  Serial.println(" W");

  Serial.print("Collector Pump Speed = ");
  Serial.print(CollectorPumpSpeed);
  Serial.println("");

  Serial.print("Collector Active = ");
  Serial.println(CollectorActive ? "true" : "false");

  Serial.print("Flow = ");
  Serial.print(Flow);
  Serial.println(" L/min");

  Serial.print("Total Energy = ");
  Serial.print(TotalEnergy);
  Serial.println(" kWh");

  Serial.print("Controller Date = ");
  Serial.println(ControllerDate);

  Serial.print("Controller Time = ");
  Serial.println(ControllerTime);

  // Wait for 2 seconds before repeating
  delay(2000);
}



not clear (to me) what works and what doesn't. Usually best to isolate the problem

did you try generating an MQTT request using data entered thru the Serial monitor? are you sure WiFi is connected, that the MQTT is connected? of course none of this requires the max3485

Please post the original, working code you had, and tell us what Arduino it worked on, so we might surmise where you've gone wrong.

1 Like

I have used the library that sends output to both serial and mqtt. It was all new to me, but it was fairly easy to implement. I always start with a sample from the library I am using that is the closest match to what I want to do.

It is basically code for using ESP8266 to get device data to serial output but is, as it is completely useless. GitHub - Alexgrosy/hewalex-geco-protocol-for-esp8266-esp32-Arduino-IDE: Very simple communication of the Hewalex geco with esp8266 or esp32 @ Arduino IDE
So I attempted to make from it for me something useful and added wifi and mqtt. Ultimate goal was to have it as single device in HA

What my code does:
It still puts device readings to serial
It connects to Mosquitto with no problem
It does not publish any data as device or sensor

I replaced 8266 with an ESP32 which is much more capable so it's definitely not a hardware issue. It connects, so it is definitely not a connection issue.
Ultimately, it is too much to ask but I think anybody who has esp8266 or esp32 laying around can try it out. I think there is no actual data to serial needed, it would just display zeros.

Did you try the basic MQTT examples that come with the PubSubClient library? Did they work for you with the Mosquitto broker?

1 Like

Without code, error log if any, and wiring diagram, only mind readers can help.

code is right there

Sorry, going blind.

Part 1 of 3 done, part 2 is any error logs in code tags, then a wiring diagram. Is it working with 8266? If so, it's relatively trivial to get the code working with the esp32.
Ideally if you can clearly describe what the code SHOULD do then describe what it DOES do it mnakes things easier for the volunteers.

do you see a log msg from the Mosquitto server?

I did fix it myself. I discovered ArduinoHA library and this helped a lot!