Search code examples
arduinouartnodemcu

Receiving all zeros in payload sent from nodemcu to Arduino UNO over UART using SerialTransfer library


I have a nodemcu master streaming sensor values to Arduino Uno slave over UART using SerialTransfer.h. I have set up an additional serial port on Arduino digital pins 2, 3 for Rx, Tx using SoftwareSerial.h. I have wired the Tx on nodemcu to Rx on Uno and Rx on nodemcu to Tx on the Uno. I have a level-shifter to adjust for 3.3 V nodemcu and 5 V Arduino. I have made sure to provide a common ground.

I transmit a struct from nodemcu with sensor values (bool and int types, hard-coded for demo) but receive only zero values at the Arduino, as seen with Serial monitor. My code is below. I'd appreciate any inputs.

I have tried the following with no difference.

  1. With and without an extra serial port on Uno created using SoftwareSerial.h
  2. Reversing the set up with Arduino Uno master and nodemcu slave
  3. With and without level-shifter on nodemcu Tx and Arduino Uno Rx

Here is the code for nodemcu master.

#include <Wire.h>
#include <SerialTransfer.h>

SerialTransfer masterMCU;

struct PAYMASTER {
  /*
  water: instruction to switch pump on or off. Note the float sensor in pump's circuit will prevent overflow.
  fan: instruction to control fan speed - LO, MED, HIGH. Note PC fan requires an int between 0 and 255.
  led: instruction to control LED brightness. Note that the FastLED library requires an int between 0 and 255.
  */
  bool water;
  int fan; 
  int led;
} instructions = {
  true,
  201,
  60
};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  delay(999);
  masterMCU.begin(Serial);
  delay(999);
}

void debug() {
  Serial.print("MASTER: ");
  Serial.print(millis());
  Serial.print("   Water: ");
  Serial.print(instructions.water);
  Serial.print(", Fan: ");
  Serial.print(instructions.fan);
  Serial.print(", LED: ");
  Serial.println(instructions.led);
}

void loop() {
  // put your main code here, to run repeatedly:
  masterMCU.txObj(instructions, sizeof(instructions));
  masterMCU.sendData(sizeof(instructions));
  debug();
  delay(999);

}

Here is the code for Arduino Uno slave.

#include <Wire.h>
#include <SerialTransfer.h>
#include <SoftwareSerial.h>

SerialTransfer slaveMCU;
SoftwareSerial extra(2, 3); // Rx 2, Tx 3

struct PAYMASTER {
  /*
  water: instruction to switch pump on or off. Note the float sensor in pump's circuit will prevent overflow.
  fan: instruction to control fan speed - LO, MED, HIGH. Note PC fan requires an int between 0 and 255.
  led: instruction to control LED brightness. Note that the FastLED library requires an int between 0 and 255.
  */
  bool water;
  int fan; 
  int led;
} instructions;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  delay(201);
  extra.begin(9600);
  delay(201);
  slaveMCU.begin(extra);
  delay(201);
}

void debug() {
  Serial.print("SLAVE: ");
  Serial.print(millis());
  Serial.print("   Water: ");
  Serial.print((bool)instructions.water);
  Serial.print(", Fan: ");
  Serial.print(instructions.fan);
  Serial.print(", LED: ");
  Serial.println(instructions.led);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (slaveMCU.available()) {
    slaveMCU.rxObj(instructions, sizeof(instructions));
    debug();
  } else if (slaveMCU.status < 0) {
    Serial.print("ERROR: ");

    if(slaveMCU.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(slaveMCU.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(slaveMCU.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
  delay(999);
}

Solution

  • I made a few changes and data are received with correct values now.

    Data Received!

    1. I replaced delay() with millis() in master.
    2. I replaced SerialTransfer::sendData() with SerialTransfer::sendDatum() in master. The former is for streaming multiple objects whereas the latter is for streaming a single object.
    3. I replaced int types with uint8_t in the struct that is sent over wires in both master and slave.

    The values are received correctly at Arduino Uno now. None of the changes made any difference until 3. above. I have retained the other changes as they also appear important to the result. Here is the final code that works for correct transmission and reception of objects from nodemcu master to Arduino Uno slave.

    nodemcu master:

    #include <Wire.h>
    #include <SerialTransfer.h>
    
    SerialTransfer masterMCU;
    unsigned long tic = millis();
    unsigned long toc = tic;
    
    #define DELTA 1000
    
    struct PAYMASTER {
      /*
      water: instruction to switch pump on or off. Note the float sensor in pump's circuit will prevent overflow.
      fan: instruction to control fan speed - LO, MED, HIGH. Note PC fan requires an int between 0 and 255.
      led: instruction to control LED brightness. Note that the FastLED library requires an int between 0 and 255.
      */
      bool water;
      uint8_t fan; 
      uint8_t led;
    } instructions = {
      true,
      201,
      60
    };
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      delay(999);
      masterMCU.begin(Serial);
      delay(999);
    }
    
    void debug() {
      Serial.print("MASTER: ");
      Serial.print(millis());
      Serial.print("   Water: ");
      Serial.print(instructions.water);
      Serial.print(", Fan: ");
      Serial.print(instructions.fan);
      Serial.print(", LED: ");
      Serial.println(instructions.led);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      toc = millis();
      if ((toc - tic) > DELTA) {
        masterMCU.txObj(instructions, sizeof(instructions));
        masterMCU.sendDatum(instructions), sizeof(instructions);
        debug();
        tic = toc;
      }
    
    }
    

    Arduino Uno slave:

    #include <Wire.h>
    #include <SerialTransfer.h>
    #include <SoftwareSerial.h>
    
    SerialTransfer slaveMCU;
    SoftwareSerial Extra(2, 3); // Rx: 2, Tx: 3
    unsigned long tic = millis();
    unsigned long toc = tic;
    
    struct PAYMASTER {
      /*
      water: instruction to switch pump on or off. Note the float sensor in pump's circuit will prevent overflow.
      fan: instruction to control fan speed - LO, MED, HIGH. Note PC fan requires an int between 0 and 255.
      led: instruction to control LED brightness. Note that the FastLED library requires an int between 0 and 255.
      */
      bool water;
      uint8_t fan; 
      uint8_t led;
    } instructions;
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      delay(201);
      Extra.begin(9600);
      delay(201);
      slaveMCU.begin(Extra);
      delay(201);
    }
    
    void debug() {
      Serial.print("SLAVE: ");
      Serial.print(millis());
      Serial.print("   Water: ");
      Serial.print((bool)instructions.water);
      Serial.print(", Fan: ");
      Serial.print(instructions.fan);
      Serial.print(", LED: ");
      Serial.println(instructions.led);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      if (slaveMCU.available()) {
        slaveMCU.rxObj(instructions);
        debug();
      } else if (slaveMCU.status < 0) {
        Serial.print("ERROR: ");
    
        if(slaveMCU.status == -1)
          Serial.println(F("CRC_ERROR"));
        else if(slaveMCU.status == -2)
          Serial.println(F("PAYLOAD_ERROR"));
        else if(slaveMCU.status == -3)
          Serial.println(F("STOP_BYTE_ERROR"));
      }
    }