ESP8266 esp-now Garage Door Status sensor

Hello Dear Reader,

New to Arduino/ESP8266, but some minor mechatronics coding back in school, so heavy on the mechanics, weak on networking syntax. I've done lots of homework on this, and have semi functioning code, but II can't seem to identify the syntax or timing (state?) issue in my code.

I have two ESP8266 boards (one master one slave), and I'm trying to create an esp-now exchange between two sensors on a part of my farm that doesn't have wifi or power.

To simulate the door states, I have two buttons, Green Button for Small Door, Red Button for the large door. Eventually these will be magnetic reed switches.

On the transmitter side with the buttons, I am getting correct real-time status updates to the serial monitor, as well as a successful notification that packets were received.

On the receiver side, I am getting a successful esp-now pairing with the transmitter, able to read the incoming MAC address, the size of the packet, and print those two items to the serial monitor.

However the bool values for the states of the two garage doors, are just reading consistent "0"/false/low.

Is this a syntax issue of how I am pushing the values to serial print here

  Serial.println(myData.largeDoorState);
   Serial.println(myData.smallDoorState);

or perhaps how the data is being decoded here:

void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData));

Credit to the syntax found on random nerd tutorials for the inspiration
ESP-NOW: Receive Data from Multiple ESP8266 Boards (many-to-one) | Random Nerd Tutorials)

Full code for the Door/Sensor+ Transmitter as well as the receiver code

Door Sensor and Transmitter code

#include <ESP8266WiFi.h>
#include <espnow.h>

// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x40, 0x91,0x51, 0x4F, 0x0F, 0xE8};

byte red_button = D3;
byte green_button = D2;
bool largeDoorState;
bool smallDoorState;
bool prevREDstate = LOW;
bool prevGREENstate = LOW;
bool currentGREENstate = HIGH;
bool currentREDstate = HIGH;
unsigned long lastTime = 0;
unsigned long timerDelay = 3000;

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
    bool largeDoorState;
    bool smallDoorState;
    
} struct_message;


struct_message myData;// Create a struct_message called test to store variables to be sent

// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("\r\nLast Packet Send Status: ");
  if (sendStatus == 0){
    Serial.println("Delivery success");
  }
  else{
    Serial.println("Delivery fail");
  }
}

void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  Serial.begin(115200);  Serial.println();
   Serial.println("Serial Communication Initalized");
 pinMode(red_button,INPUT_PULLUP);
 pinMode(green_button,INPUT_PULLUP);


  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  } 
  // Set ESP-NOW role
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);

  // Once ESPNow is successfully init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

}

void checkRedDoor () {
  int currentREDstate = digitalRead(red_button);  
   if(prevREDstate != currentREDstate){
    if(currentREDstate == LOW){
     largeDoorState = false;
        Serial.println("The Large Garage Door is Closed");
        }
        else if(currentREDstate == HIGH){
           largeDoorState = true;
             Serial.println("The Large Garage Door is Open");}


                 } 
                 prevREDstate = currentREDstate;
                 }

void checkGreenDoor () { 
  int currentGREENstate = digitalRead(green_button);
  if(prevGREENstate != currentGREENstate){
    if(currentGREENstate == LOW){
     smallDoorState = false;
        Serial.println("The Small Garage Door is Closed");
        }
        else if(currentGREENstate == HIGH){
           smallDoorState = true;
             Serial.println("The Small Garage Door is Open");}


                 } 
                  prevGREENstate = currentGREENstate;
                  }

void loop() {
   checkRedDoor ();
   checkGreenDoor();
   
  if ((millis() - lastTime) > timerDelay) {
    // Set values to send
    myData.smallDoorState;
    myData.largeDoorState;
     
    // Send message via ESP-NOW
    esp_now_send(0, (uint8_t *) &myData, sizeof(myData));
    lastTime = millis();
  }

      }

Receiver/Monitor Code

#include <ESP8266WiFi.h>
#include <espnow.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>

byte red_LED = D3;
byte green_LED = D2;

typedef struct struct_message {
    bool largeDoorState;
    bool smallDoorState;
    
} struct_message;

struct_message myData;

void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Recieved:%u bytes\n", len);
   Serial.println(myData.largeDoorState);
   Serial.println(myData.smallDoorState);
  Serial.println();
}

void setup() {
  // put your setup code here, to run once:
   pinMode(red_LED,OUTPUT);
   pinMode(green_LED,OUTPUT);
Serial.begin(115200);
Serial.println();

// Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  
  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
 // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  //esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  // put your main code here, to run repeatedly:
esp_now_register_recv_cb(OnDataRecv);
}```

So smallDoorState = false; is where the door state is held but

    myData.smallDoorState;
    myData.largeDoorState;

is the data that is sent.

Would it be better to just update the structure variable that is being sent instead of the variable being updated but not being sent?

    myData.smallDoorState= true;

and then send that data?

1 Like

Thanks a Million @Idahowalker! I had built the code in MVP stages and had flagged the bool variable to notify the local serial output before adding in the coms with the second board, and it didn't occur to me to update the structure variable. I was just staring at the code too closely and missed the forest for the trees.

Again, many, many thanks. :+1: :+1:

1 Like

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