1

I have a program that communicate between a esp8266 and a atmega328 using Serial, the esp8266 will connect to a MQTT server running on local network, and publish/subscribe to some topics. In the callback function for the subscribing, it will send an instruction to atmega chip to toggle the LED (pin 13). I am using XC4411 board which is an integrated 2-in-1 board with both esp and atmega.

The code looks like this: On esp side:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "credentials.h" // this is where I define the wifi ssid, psw, mqtt username/psw etc.
#include <Arduino.h>

#define SERIAL_BAUD 115200 //make sure this is the same in atmega code, serial communication with atmega chip
#define ESP8266_LED 1

WiFiClient espWifiClient;
PubSubClient espMQTTClient(espWifiClient);
const char* test_topic = "/test/msg01";
void reconnect();
void callback(char *topic, uint8_t *payload, unsigned int length);


void setup_wifi() {
    delay(10);
    WiFi.begin(MY_SSID, MY_WIFIPSW);
    while (WiFi.status() != WL_CONNECTED) delay(500);
}


void setup_mqtt() {
    espMQTTClient.setServer(MY_MQTT_SERVER_ADDRESS, MY_MQTT_SERVER_PORT);
    reconnect();
    espMQTTClient.subscribe(test_topic);
    espMQTTClient.setCallback(callback);
    
}


void reconnect() {
    while(! espMQTTClient.connected()) {
        if (espMQTTClient.connect(MY_MQTT_CLIENT_ID, MY_MQTT_USER, MY_MQTT_PSW)) {
            espMQTTClient.subscribe(test_topic);
        }
        else delay(500);
    }
}


void callback(char *topic, uint8_t *payload, unsigned int length) {
    
    digitalWrite(ESP8266_LED, !digitalRead(ESP8266_LED));
    Serial.println("[toggle]");
    
    // espMQTTClient.publish("/test/esp8266", topic, length);
    espMQTTClient.publish("/test/esp8266", payload, length);
   
    if (strcmp(topic, test_topic) == 0) {
        if (length >= 0 && (char) payload[0] == '1') {
            espMQTTClient.publish("/test/esp8266", "get payload 1");
        } else if (length >= 0 && (char) payload[0] == '0') {
            espMQTTClient.publish("/test/esp8266", "get payload 0");
        } else {
            espMQTTClient.publish("/test/esp8266", "unknown payload for topic /test/msg01");
        }
            
    }
}


void setup() {
    Serial.begin(SERIAL_BAUD);
    setup_wifi();
    setup_mqtt();
    pinMode(ESP8266_LED, OUTPUT);
}

String data_from_arduino = "";

void loop() {
    if (! espMQTTClient.connected()) reconnect();
    espMQTTClient.loop();
    while (Serial.available()) {
        char x = Serial.read();
        if (x == '\r')
            continue;
        data_from_arduino += x;
    }
    if (data_from_arduino != "") {
        espMQTTClient.publish("/test/arduino", data_from_arduino.c_str());
        data_from_arduino = "";
    }
    // espMQTTClient.publish("/test/esp8266", "hello from esp"); // this line works fine, so there is no connection problem
}

On atmega side:

#include <Arduino.h>

#define SERIAL_BAUD 115200

#define LED_PIN 13

String receivedCommand = "";
bool dataIn = false;

void setup()
{

    Serial.begin(SERIAL_BAUD); //same as ESP baud
    pinMode(LED_PIN, OUTPUT);
}

String msg_from_esp8266 = "";
bool start_receiving_msg = false;

void loop()
{
    while (Serial.available())
    {
        char c = Serial.read(); 

        if (c == '[')
        {
            start_receiving_msg = true;
            msg_from_esp8266 = "";
        } else if (start_receiving_msg && c != ']') {
            msg_from_esp8266 += c;
        } else if (start_receiving_msg && c == ']') {
            start_receiving_msg = false;
            if (msg_from_esp8266 == "toggle") {
                digitalWrite(LED_PIN, !digitalRead(LED_PIN));
                Serial.println("arduino toggle led");
            }
        }
        
    }
    delay(10);
}

Basically when you publish anything to topic /test/msg01 manually, it will try to toggle the esp8266's built in led. then esp8266 will publish a message to /test/esp8266 with the exact payload you publish to /test/msg01. Also, esp8266 will also send a serial message "[toggle]" to atmega. On the atmega side, it will check if it receives the "[toggle]" and toggle its built in LED, then it will send a message through serial. on the esp side, in the loop, it will receive that message from atmega and publish it to topic /test/arduino. This program is to test the communication between other mqtt client devices and the esp8266, as well as (communication between other mqtt client devices) and the atmega through esp8266 via serial. The code in if (strcmp(topic, test_topic) == 0) is just some other additional test code.

Generally, you should expect the behaviour like this: once you publish any message to topic /test/msg01, you will see the same message being relayed to topic /test/esp8266. both esp8266 and atmega will toggle their LED on and off. And the message "arduino toggle led" will be published to topic /test/arduino.

However, neither LED toggles. And there is no message from /test/arduino. in topic /test/esp8266 I saw some garbage text instead of my original message.

I have already troubleshooted the connection, the board configuration and checked if the lED is broken. They are all good, and I am pretty sure that the problem is to do within the "callback" function.

Here are some screenshot with the mqtt message:

What I have published to /test/msg01: enter image description here

What I get from /test/esp8266 enter image description here enter image description here

And, there is no problem with the message in /test/msg01 as I was also subscribing to the topic and get the same message as I published. enter image description here enter image description here

I didn't receive any message from topic "/test/arduino", so seems like the Serial message didn't get to atmega.

And again no problem with XC4411 board configuration as I turn the button 1, 2 on after I done flashing the two chips, and the code compiled and was uploaded to both chip successfully.

Looks like the callback function just corrupted my message, and also just somehow skipped and ignored the line that sends the toggle message to arduino and the line that toggle esp8266's LED.

I am very new to these topic discussed in the question in general, so maybe there are some mechanism that I am not aware of. Thank you the answers in advance.

1 Answer 1

2

From the PubSubClient library documentation:

Internally, the client uses the same buffer for both inbound and outbound messages. After the callback function returns, or if a call to either publish or subscribe is made from within the callback function, the topic and payload values passed to the function will be overwritten

2
  • Hi, that make sense. Thanks. Any ideas on why the LED isn't turn on and off? Apr 25, 2023 at 12:07
  • I'm not familiar with the XC4411 board but suspect the ESP8266 LED isn't on GPIO 1 and anyway it may not be possible to use serial and the built in LED at the same time
    – Bra1n
    Apr 25, 2023 at 15:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.