Code Monkey home page Code Monkey logo

esp-now-sensor-system-with-wifi's Issues

Thoughts on further optimizing sleep power.

Your write-up and code are some of the best examples I have seen in either the Arduino or ESP ecosystem.

I have been working on my own power optimized designs. I didn't have a CPU module with low enough power consumption even with deep sleep so I used some other tricks. If you combine what I did with what you did it could provide even longer battery life.

Added a low-side mosfet switch to disconnect sensor power when sensors are not being actively used. Found this necessary for greedy sensors like magnetic field sensors and MPU6050. The CPU powers up the sensors by setting a IO pin HIGH to energize the gate on the N-channel mosfet. I use a 1 meg resistor gate to ground to force sensors off when the CPU is booting. As soon as I finish taking readings I turn of the sensors while the CPU may run a bit longer transmitting the data.

Added a DS3231 clock chip that includes alarm functionality that I use to facilitate power conservation. I wanted it for accurate multi-year time keeping but found that it added some features that make managing the CPU a lot easier like low-voltage reset. It is ultra low power and can run for years on a coin cell.

  • Add a low side n-channel mosfet switch that cuts ground connection between charger module and CPU module reducing power consumption down to the leakage value of the transistor. Call the Gate on this mosfet CPWR
  • The clock chip includes alarms that can be programmed to fire every second, every minute or every hour. When they fire they activate it's INT/SQW pin.
  • When the alarm fires it generates a pulse which energizes CPWR gate on the mosfet that restores power to the CPU. I use a capacitor to hold the CPWR HIGH long enough to allow the CPU to set a PIN to HIGH that keeps CPWR high until the CPU finishes working.
  • The clock can be connected to run direct from the TP4056 but I also used a coin backup because I don't want to loose time and date when the 18650 battery needs to be replaced. No need for a separate regulator for the clock chip because it is 5.5V tolerant.
  • Once the CPU finishes it's work, it sets that pin to LOW which drives CPWR low turning off the mosfet completely disconnecting the CPU until the clock pulse fires again.
  • A manual wake-up button energizes the CPWR mosfet gate to turn the CPU on but I can not always tell if the wake-up was because the button was pressed versus the alarm firing unless the user keeps their finger on the button long enough to boot and take a reading.
  • The clock chip must be in circuit between TP4056 and CPU power mosfet. Otherwise it's alarm pulse can not be used to energize the CPWR mosfet gate.

My sensors are not always in WiFi range so I write data to SPIFFS and send in batch once they can connect again. I extended this so I have a transmit interval that may be longer than my measure interval. Since it takes a little time with CPU active to negotiate the connection this can save a bit more power.

One downside of this approach is that any data you want to retain between wakeup events must be stored in SPIFFS because the CPU can not retain RTC variable storage when completely powered off. I read there is some NVM on this CPU but have not tried using it.

Code?

I see references to existing code, but I see no code in Repo?

Tp4056 is necessary?

Why using a TP4056 when using a solar panel?

Wemos D1 mini pro v 2 includes a battery charger. Won't it be possible to connect the solar panel directly to the D1 mini pro?

espnow_sensor.ino - ESPNOW: Peer interface is invalid

I realize that this may be caused updated ArduinoIDE packages and what not, but I'm not sure how to get around it.

Hardware: ESP32 (WROOM32) (Gateway set up with WROOM32 as well)

Code as tested:
NOTE: I've *undefined the sensors and comment out their uses, and simplified the data struct to modify the code as little as possible.

#define SKETCH_NAME     "ESP-Now Sensor"
#define SKETCH_VERSION  "2021-12-31"
#define SKETCH_ABOUT    "Temp sensor, Deep Sleep, ESP-Now, ESP8266 and ESP32."

//
//  This is a template code for an ESP-Now sensor for ESP8266 and ESP32. It Assumes Arduino IDE.
//
//  Note. ESP8266 and ESP32 use different WiFi implementations why you must set the appropriate
//  #define USE_ESP8266 or USE_ESP32. Please remember to also set the appropriate BOARD in the 
//  ARDUINO IDE to find the correct include files.
//
//  The ESP-Now sensor sends messages on ESP-Now to a MAC address of a Gateway which is 
//  connected to WiFi and Internet.
//
//  A sensor unit consists of; ESP8266 board, a Temp Sensor and a LiPo/Li-Ion battery cell. 
//  An optional Solar panel and Solar panel manager/Battery charger can be connected.
//
//  The ESP8266 operates in deep sleep mode and wakes every 5 mins, takes a sensor reading, 
//  transmits the data using ESP-Now to an ESP-Now Gateway and then returns to deep sleep.
//  The design is aimed for Battery Cell and/or Solar Panel powered units with as low power 
//  consumption as possible, using standard ESP8266 boards. No special, or modified, ultra low 
//  power ESP8266 boards are required.
//
//  ESP-Now is much faster than ordinary WiFi (TCP/IP), reducing the "sending energy" dramatically. 
//  The drawback is that ESP-Now is a proprietary protocol of Espressif and is only implemented 
//  (what i know) for ESP MCU's.
//
//  The wakeup time of the MCU is heavily dependent on the temp sensor used. Some temp sensors 
//  will return sensor data within 100 ms or shorter, some requires 500 ms or more. This varies 
//  with sensor type/manufacturer (spec) and samples. Specs often claim a wake-up or stabilization
//  time of upto 2 secs, but most sensors can return a stable (?) measurement in 200-500 ms typically.
//
//  (Generally, SHT30 and DS18B20 temp sensors perform well and decently fast. DHT11/21/22 are slower 
//  and less reliant in my testes. I dont use them in real life.)
//
//  AUTHOR:
//  Jonas Byström, https://github.com/jonasbystrom
//
//  CREDITS:
//  This code is based on code from:
//  - Anthony Elder @ https://github.com/HarringayMakerSpace/ESP-Now/blob/master/espnow-sensor-bme280/espnow-sensor-bme280.ino
//  With important info from:
//  - Erik Bakke @ https://www.bakke.online/index.php/2017/05/21/reducing-wifi-power-consumption-on-esp8266-part-2/
//  And great info from:
//  - ArduinoDIY @ https://arduinodiy.wordpress.com/2020/01/18/very-deepsleep-and-energy-saving-on-esp8266/

//  HARDWARE:
//  - D1 Mini Pro v2.0 (or, D1 Mini v3.1.0), or
//  - Any ESP32 board
//  - SHT30 or DS18B20 temp sensor
//  - 3.7V LiPo/Li-Ion battery with JST connector. Flat 1200mAh, 18650 2200mAh or similar.
//  - Optional: Solar panel and solar panel charger board
//
//  CONNECTIONS:
//
//  D1 Mini Pro V2.0.0:
//  ===================
//  BAT --- A0          (solder/short the "BAT-A0" pad for battery level measurement)
//  RST --- D0/GPIO16   (solder/short the "SLEEP" pad)
//
//
//  D1 Mini SHT30 (If using WEMOS/LOLIN boards, just plug them together.)
//  ======= =====
//  GND     GND
//  3V3     VCC
//  D1/SCL  SCK
//  D2/SDA  SDA
//
//  or, if using a DS18B20
//
//  D1 Mini - DS18B20 (with an internal resistor)
//  =======   =======
//  GND       G (GND)
//  3V        V (VCC)
//  D3
//  D4        S (DATA)
//
//
//  HISTORY:
//  ========
//  2021-12-30  Cleaned for public publish on GitHub.
//  2021-12-31  Support for ESP32 added.
//

// ------------------------------------------------------------------------------------------
// ESP CONFIGS
// ------------------------------------------------------------------------------------------
//
// IMPORTANT. Select ESP8266 or ESP32. - Remember to also set the appropriate ESP8266 or ESP32 board in the ARDUINO IDE !
#define USE_ESP32               // Select (uncomment) one of ESP8266 or ESP32. (And set BOARD in ARDUINO IDE.) 
//#define USE_ESP8266  
      
// Different Wifi and ESP-Now implementations for ESP8266 and ESP32
#ifdef USE_ESP8266
#include <ESP8266WiFi.h>
#include <espnow.h>
#endif

#ifdef USE_ESP32
#include <WiFi.h>
#include <esp_now.h>
#endif


// ------------------------------------------------------------------------------------------
// ESP-NOW SYSTEM CONFIGS
// ------------------------------------------------------------------------------------------
#define WIFI_CHANNEL        1      // Must be 1. (!IMPORTANT)
                                  // ESP-Now can work on other channels, but the receiving ESP Gateway must operate on
                                  // channel 1 in order to also work for TCP/IP WiFi.
                                  // It has been reported to work also for other Channels, but I have only succeeded on ch 1.

//uint8_t Gateway_Mac[] = {0x02, 0x10, 0x11, 0x12, 0x13, 0x14};
uint8_t Gateway_Mac[] = {0xC8, 0x2B, 0x96, 0xA1, 0x93, 0x78};
                                  // MAC Address of the remote ESP Gateway we send to.
                                  // This is the "system address" all Sensors send to and the Gateway listens on.
                                  // (The ESP Gateway will set this "soft" MAC address in its HW. See Gateway code for info.)

typedef struct sensor_data_t {    // Sensor data format for sending on ESP-Now to Gateway
  int           id;               // Unit no to identy which sensor is sending
  int           on_delay;
  bool          active;
  //char          confg[30]; // Meh
  unsigned long updated;            // Epoch time when received by Gateway. Set by gateway/receiver. (Not used by sensor, but part of struct for convenience reasons.)
} sensor_data_t;


// -----------------------------------------------------------------------------------------
// ESP SENSOR CONFIGS
// -----------------------------------------------------------------------------------------
#define UNIT                1       // Sensor unit ID to identify THIS unit for the receiving gateway. Recommended to use [1 -20]

//#define USE_SHT30                   // Select (uncomment) the temp sensor type in use
//#define USE_DS18B20

#define DEBUG_LOG                   // Enable (uncomment) to print debug info. Disabling (comment) debug output saves some 4-5 ms ...

//ADC_MODE(ADC_VCC);                // Uncomment to Enable reading Vcc (if board cannot read VBAT).

#define SLEEP_SECS        5*60-8    // [sec] Sleep time between wake up and readings. Will be 5 mins +/- 8 secs. Varying to avoid transmit collusions.
#define MAX_WAKETIME_MS   1000      // [ms]  Timeout until forced gotosleep if no sending success 



#ifdef USE_SHT30
// -----------------------------------------------------------------------------------------
//  WEMOS SHT30 Temp and Humidity sensor
// -----------------------------------------------------------------------------------------
#include "Wire.h"
#define ADDR              0x45      // I2C address of SHT30.
#endif


#ifdef USE_DS18B20
// -----------------------------------------------------------------------------------------
// DS18B20 - TEMP SENSOR
// -----------------------------------------------------------------------------------------
// Temp probe is connected with onewire interface.
//
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port D3 & D4 on the ESP8266
#define ONE_WIRE_BUS            D4                // Change to other port if wanted/needed
#define TEMPERATURE_PRECISION   12                // [9-12]. 12 => resolution of 0.0625 C
                      /*  12-bit precision:
                          1-bit for sign, 7-bit for integer part, and 4-bit for fractional part (4-digit after decimal point)
                          Temperature range: xxx.0000 C to xxx.9375 C in 0.0625 C discrete step.
                      */        
OneWire oneWire (ONE_WIRE_BUS);                   // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature tempSensor(&oneWire);           // Pass our oneWire reference to Dallas Temperature.
DeviceAddress tempDeviceAddress;                  // We'll use this variable to store a found device address

#endif


// -----------------------------------------------------------------------------------------
//  BATTERY LEVEL CALIBRATION
// -----------------------------------------------------------------------------------------
#define CALIBRATION         4.21 / 4.35                       // Measured V by multimeter / reported (raw) V 
                                                              // (Set to 1 if no calibration is needed/wanted)
#define VOLTAGE_DIVIDER     (130+220+100)/100 * CALIBRATION   // D1 Mini Pro voltage divider to A0. 
                                                              // May be different for other boards.


// -----------------------------------------------------------------------------------------
// GLOBALS
// -----------------------------------------------------------------------------------------
sensor_data_t sensorData;
volatile boolean messageSent;     // flag to tell when message is sent out and we can safely goto sleep


#ifdef USE_SHT30
// -----------------------------------------------------------------------------------------
byte sht30_get(float &temp, float &humid)
// -----------------------------------------------------------------------------------------
// Read the SHT30 temp/humid sensor.
// Code is from WEMOS_sht3x.cpp - modified by reducing delays and adjusting types.
{
  unsigned int data[6];

  temp = NAN;
  humid = NAN;

  Wire.beginTransmission(ADDR);           // Start I2C Transmission
  Wire.write(0x2C);                       // Send measurement command
  Wire.write(0x06);
  if (Wire.endTransmission() != 0)        // Stop I2C transmission
    return 1;

  delay(100);         // 100 ms sensor stabilization time. Shorter than spec, but works OK.  Can be tweaked if needed.
                      // (I have seen Tasmota code to read SHT30 a bit different and as it seems even faster - would be interesting to try ...)

  Wire.requestFrom(ADDR, 6);              // Read the 6 data bytes
  for (int i = 0; i < 6; i++) {
    data[i] = Wire.read();
  };

  delay(50);                              // Let it stabilize. Can be tweaked
  if (Wire.available() != 0)
    return 2;
  // Convert the data
  temp = ((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45;
  //fahrenheit version: temp = (temp * 1.8) + 32;
  humid = ((((data[3] * 256.0) + data[4]) * 100) / 65535.0);

  return 0;
}
#endif


// -----------------------------------------------------------------------------------------
void setup()
// -----------------------------------------------------------------------------------------
{
  // Disable WiFi until we shall use it, to save energy
  WiFi.persistent( false );         // Dont save WiFi info to Flash - to save time
  #ifdef USE_ESP8266
  WiFi.mode( WIFI_OFF );            // Wifi OFF - during sensor reading - to save current/power
  WiFi.forceSleepBegin();
  delay( 1 );                       // Necessary for the OFF to work. (!IMPORTANT)
  #endif
  
  #ifdef USE_SHT30
  Wire.begin();                     // Prepare the I2C communication
  #endif

  #ifdef DEBUG_LOG
  Serial.begin(115200);
  while (!Serial) {};
  Serial.println("\n\nStart");
  #endif

  #ifdef USE_DS18B20
  // Init sensor/bus
  //pinMode(ONE_WIRE_BUS, OUTPUT);     // use this if using PARASITE mode of DS18B20 (vcc from data line, and probably a pull up resistor ...)
  tempSensor.begin();
  tempSensor.getAddress(tempDeviceAddress, 0);
  tempSensor.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);
  tempSensor.requestTemperatures();
  #endif

  // read battery voltage
  //int raw = analogRead(A0);
  //sensorData.Vbat = raw * VOLTAGE_DIVIDER / 1023.0;
          // Alternative. If cannot read Battery level on your board, Read Vcc instead
          // const float calVal = 0.001108;     // 3.27/2950=0.001108. Vcc 3.27 on Multimeter, 2950 from getVcc()
          // sensorData.Vbat = ESP.getVcc()/1023; // * calVal;
 
  #ifdef DEBUG_LOG
  //Serial.print("Battery voltage:"); Serial.print(sensorData.Vbat); Serial.println(" V");
  #endif

  // compile message to send
  //strcpy (sensorData.ID, SKETCH_NAME);
  //strcat (sensorData.ID, " - ");
  //strcat (sensorData.ID, SKETCH_VERSION);
  sensorData.id = 1;
  //sensorData.unit = UNIT;

  // Read the temp sensor
  #ifdef USE_SHT30
  if (sht30_get(sensorData.temp, sensorData.humidity) == 0) {
    // reading ok   
  } else {
    // SHT30 reading error, use -999 as "invalid data". (Maybe it is better to use NAN instead (?))
    sensorData.temp = -999;
    sensorData.humidity = -999;
  }
  #elif defined USE_DS18B20
  sensorData.temp     = tempSensor.getTempC(tempDeviceAddress);
  #endif

#ifdef USE_8266
  // WiFi ON                    (This step seems not to be necessary, but anyway ...)
  WiFi.forceSleepWake();
  delay( 1 );
#endif

  // Set up ESP-Now link ---------------------------
  WiFi.mode(WIFI_STA);          // Station mode for esp-now sensor node
  WiFi.disconnect();
  #ifdef DEBUG_LOG
  Serial.printf("My HW mac: %s", WiFi.macAddress().c_str());
  Serial.println("");
  Serial.printf("Sending to MAC: %02x:%02x:%02x:%02x:%02x:%02x", Gateway_Mac[0], Gateway_Mac[1], Gateway_Mac[2], Gateway_Mac[3], Gateway_Mac[4], Gateway_Mac[5]);
  Serial.printf(", on channel: %i\n", WIFI_CHANNEL);
  #endif

  // Initialize ESP-now ----------------------------
  if (esp_now_init() != 0) {
    #ifdef DEBUG_LOG
    Serial.println("*** ESP_Now init failed. Going to sleep");
    #endif
    delay(100);
    gotoSleep();
  }

  #ifdef USE_ESP8266
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_add_peer(Gateway_Mac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULL, 0);
  #endif
  #ifdef USE_ESP32
  esp_now_peer_info_t gateway;
  memcpy(gateway.peer_addr, Gateway_Mac, 6);
  gateway.channel = WIFI_CHANNEL;
  gateway.encrypt = false;            // no encryption
  //esp_now_add_peer(&gateway);  
  if (esp_now_add_peer(&gateway) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  } else {
    Serial.println("Added peer");
  }
  #endif

  #ifdef USE_ESP8266
  esp_now_register_send_cb([](uint8_t* mac, uint8_t sendStatus) {
  #endif
  #ifdef USE_ESP32
  esp_now_register_send_cb([](const uint8_t* mac, esp_now_send_status_t sendStatus) {
  #endif
    // callback for message sent out
    messageSent = true;         // flag message is sent out - we can now safely go to sleep ...
    #ifdef DEBUG_LOG
    Serial.printf("Message sent out, sendStatus = %i\n", sendStatus);
    #endif
  });

  messageSent = false;
  sensorData.id = 1;
  sensorData.on_delay = 12;
  sensorData.active = false;
  sensorData.updated = 16151;
  // Send message -----------------------------------
  #ifdef DEBUG_LOG
  Serial.println("Message Data: " + \
                  String(sensorData.id));// + ", Unit:" + \
                  //String(sensorData.unit) + ", Temp:" + \
                  //String(sensorData.temp) + "C, Hum: " + \
                  //String(sensorData.humidity) + "%, Lux: " + \
                  //String(sensorData.lux) + ", Vbat:" + \
                  //String(sensorData.Vbat) \
                );
  #endif
  
  uint8_t sendBuf[sizeof(sensorData)];          // create a send buffer for sending sensor data (safer)
  //sensorData.wakeTimeMS = millis();             // set wake time until now
  memcpy(sendBuf, &sensorData, sizeof(sensorData));
  #ifdef USE_ESP8266
  uint16_t result = esp_now_send(NULL, sendBuf, sizeof(sensorData));
  #endif
  #ifdef USE_ESP32
  const uint8_t *peer_addr = gateway.peer_addr;
  esp_err_t result=esp_now_send(peer_addr, (uint8_t *) &sensorData, sizeof(sensorData)); 
  #endif
  
  #ifdef DEBUG_LOG
  //Serial.print("Wake: "); Serial.print(sensorData.wakeTimeMS); Serial.println(" ms");
  Serial.print("Sending result: "); Serial.println(result);
  #endif
}

// -----------------------------------------------------------------------------------------
void loop()
// -----------------------------------------------------------------------------------------
{
  // Wait until ESP-Now message is sent, or timeout, then goto sleep
  if (messageSent || (millis() > MAX_WAKETIME_MS)) {
    //gotoSleep();
  }
}


// -----------------------------------------------------------------------------------------
void gotoSleep()
// -----------------------------------------------------------------------------------------
{
  int sleepSecs;

  #ifdef USE_ESP8266
  sleepSecs = SLEEP_SECS + ((uint8_t)RANDOM_REG32 / 16);  // add random time to avoid traffic jam collisions
  #ifdef DEBUG_LOG
  Serial.printf("Up for %i ms, going to deep sleep for %i secs ...\n", millis(), sleepSecs);
  #endif

  ESP.deepSleep(sleepSecs * 1000000, RF_NO_CAL);
  delay (10);                                             // good convention with delay after call to deep sleep.

  // Never return here - ESP will be reset after deep sleep
  #endif

  #ifdef USE_ESP32
  sleepSecs = SLEEP_SECS + ((uint8_t)esp_random()/16);      // add random time to avoid traffic jam collisions
  #ifdef DEBUG_SENSOR      
    Serial.printf("Up for %i ms, going to sleep for %i secs...\n", millis(), sleepSecs); 
  #endif

  esp_sleep_enable_timer_wakeup(sleepSecs * 1000000);
  //esp_sleep_enable_ext0_wakeup((gpio_num_t)BUTTON_PIN, LOW);
  esp_deep_sleep_start(); 

  // Never return here - ESP will be reset after deep sleep  
  #endif
}

The code complies and uploads, but the serial output shows :
15:43:53.886 -> Sending to MAC: c8:2b:96:a1:93:78, on channel: 1 15:43:53.886 -> E (156) ESPNOW: Peer interface is invalid 15:43:53.886 -> Failed to add peer
"Failed to add peer" was added by me to check response code of esp_now_add_peer(&gateway)

ANy help would be greatly appreciated!

cannot convert 'esp_interface_t' to 'wifi_interface_t'

Your Code that I edit for ESP32 only and I try Verify ..
and it will error at this line
"esp_wifi_set_mac(ESP_IF_WIFI_AP, &GatewayMac[0]);"

`
#define SKETCH_NAME "ESP-NOW GATEWAY"
#define SKETCH_VERSION "2022-01-01"
#define SKETCH_ABOUT "ESP-Now Gateway template code and demonstrator of simultaneous ESP-Now and WiFi."

/*

  • This is a template code for an ESP-Now Gateway for ESP8266 and ESP32. It assumes Arduino IDE.
  • Note. ESP8266 and ESP32 use different WiFi implementations why you must set the appropriate
  • #define USE_ESP8266 or USE_ESP32. Please remember to also set the appropriate BOARD in the
  • ARDUINO IDE to find the correct include files.
  • The Gateway receives messages on the Espressif proprietary protocol ESP-Now. It also provides a simple WEB server
  • displaying the received temperature data from all sensors. This is to demonstrate a single ESP8266 is capable of
  • communicating on ESP-Now and 2.4 GHz Wifi simoultaneously. One restriction apply, this only works on WiFi channel 1
  • and you must therefore set the router to "fixed" channel 1.
  • In order to perform the demonstration you will need:
    • 1x ESP8266 or ESP32 programmed with this sketch, acting as Gateway (to the WiFi/internet), and
    • 1-20x ESP8266 or ESP32 programmed with the espnow_sensor sketch and equipped with a temperature sensor
  • (or anything else you connect and modify the code for).
  • This is a simple demo sketch but fully working. It demostrates simultaneous WiFi and ESP-Now on ESP8266 and ESP32.
  • You can add other Internet services like MQTT, Blynk, ThingSpeak etc. (I have been running this for 1.5+ years with
  • those services.)
  • AUTHOR:
  • Jonas Byström, https://github.com/jonasbystrom
  • CREDITS:
  • Code related to ESP-Now is partly based on code from:
  • With important info from:
  • And great info from:

#include <esp_now.h>
#include <esp_wifi.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WebServer.h>

#ifndef LED_BUILTIN
#define LED_BUILTIN 5 // Set this to the built-in LED number of your ESP32 board
#endif

// ------------------------------------------------------------------------------------------
// ESP-NOW SYSTEM CONFIGS
// ------------------------------------------------------------------------------------------
//
// This is the MAC address to be installed (sensors shall then send to this MAC address)
uint8_t GatewayMac[] = {0x02, 0x10, 0x11, 0x12, 0x13, 0x14};

/*  Note, the Gateway listens on this MAC address. All sensors shall send to this MAC address.
 *  You can set any MAC address of your choice according to this table of "free-to-use local MAC addresses":
 *    {0x02, any, any, any, any, any}
 *    {0x06, any, ...}
 *    {0x0A, any, ...}
 *    {0x0E, any, ...}
 *  
 *  Further, it would be possible to use the built-in HW-MAC address of the ESP8266. But, in case you would need to  
 *  change the ESP (for any reasons) you would then need to update ALL sensors to the same new MAC address. 
 *  It is therefore better to use a soft MAC defined by code. This will be installed in any new ESP HW you may use.
 *  Just remeber to set a new MAC address for every new system (gateway+sensors) you install in paralell. *  
 */

// ESP-Now message format. Sensor data is transmitted using this struct.
typedef struct sensor_data_t {
int unit; // Unit no to identy which sensor is sending
float temp; // Temperature (C)
float humidity; // Humidity (%)
float baro_pressure; // Barometric pressure (hPa)
int lux; // Light sensor data (lux)
float Vbat; // Battery voltage level (V)
char ID[80]; // Any clear text to identify the unit
int wakeTimeMS; // Sensor wake time until sending data
unsigned long updated; // Epoch time when received by Gateway. Set by gateway/receiver. (Not used by sensor, but part of struct for convenience reasons.)
} sensor_data_t;

// ------------------------------------------------------------------------------------------
// ESP-NOW GATEWAY CONFIGS
// ------------------------------------------------------------------------------------------
// Router WiFi Credentials (runnning on 2.4GHz and Channel=1)
#define SOFTAP_SSID "...YOUR SSID Network Name..."
#define SOFTAP_PASS "...YOUR Network Password ..."

#define UNITS 20 // No of esp-now sensor units supported to receive from. ESP-Now has a maximum of 20

// ------------------------------------------------------------------------------------------
// GLOBALS
// ------------------------------------------------------------------------------------------
WiFiMulti wifiMulti;

sensor_data_t bufSensorData; // buffer for incoming data
sensor_data_t sensorData[UNITS+1]; // buffer for all sensor data

// ------------------------------------------------------------------------------------------
// ESP-NOW functions
// ------------------------------------------------------------------------------------------
//
// This is a callback function from ESP (?), anyway (!IMPORTANT)
//
// (Note. I noted now, 1 1/2 years later, when i clean this up and retest a gateway with ESP32 - this initVariant
// seems not to be called by ESP routines anymore. I have as a fix called this routine manually in the setup.
// This could of course (?) be done also for ESP8266. But i dont want to touch that code since it has been working
// for 1.5 years now.)
//
void initVariant()
{

WiFi.mode(WIFI_AP);
esp_wifi_set_mac(ESP_IF_WIFI_AP, &GatewayMac[0]); //ESP32 code
}

// Callback when data is received from any Sender
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len)
{
digitalWrite (LED_BUILTIN, !HIGH); // Led ON

char macStr[24];
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.print("\nData received from: "); Serial.println(macStr);
memcpy(&bufSensorData, data, sizeof(bufSensorData));

// Print data
Serial.print ("ID: ");
Serial.print (bufSensorData.ID);
Serial.println ("");
Serial.print ("Unit: ");
Serial.print (bufSensorData.unit);
Serial.print (" Temp: ");
Serial.print (bufSensorData.temp);
Serial.print (" Humidity: ");
Serial.print (bufSensorData.humidity);
Serial.print (" Baro: ");
Serial.print (bufSensorData.baro_pressure);
Serial.print (" Lux: ");
Serial.print (bufSensorData.lux);
Serial.println ("");
Serial.print ("Vbat: ");
Serial.print (bufSensorData.Vbat);
Serial.print (" Wake: ");
Serial.print (bufSensorData.wakeTimeMS);
Serial.println ("");

// Store data
int i = bufSensorData.unit;
if ( (i >= 1) && (i <= UNITS) ) {
memcpy(&sensorData[i], data, sizeof(bufSensorData));
};

digitalWrite (LED_BUILTIN, !LOW); // Led OFF}
}

// ------------------------------------------------------------------------------------
// WEB server functions
// ------------------------------------------------------------------------------------
WebServer server(80);

void handleRoot() {
digitalWrite (LED_BUILTIN, !HIGH); // Led ON

// Create a (very) simple response, just to demonstrate
String msg;
msg = "ESP-Now Gateway \n";
for (int i=1; i<=UNITS; i++) {
String str2 = (i<10)?("0"+String(i)):(String(i)); // Make i to 2 pos string
msg += String("Unit: "+str2+" Temp: "+String(sensorData[i].temp)+" C\n");
}
server.send(200, "text/plain", msg );
Serial.println ("Web server call:" + msg);

digitalWrite (LED_BUILTIN, !LOW); // Led OFF}
}

void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}

// ------------------------------------------------------------------------------------
void setup()
// ------------------------------------------------------------------------------------
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite (LED_BUILTIN, !HIGH); // Led ON (Most often not working on ESP32)

// Init Serial
Serial.begin(115200);
while (!Serial) {};
delay(100); // Needed for some boards
Serial.println("\n\n");

// Print sketch intro ---------------------------
Serial.println();
Serial.println("===========================================");
Serial.println(SKETCH_NAME);
Serial.println(SKETCH_VERSION);
Serial.println(SKETCH_ABOUT);
Serial.println("===========================================");

// initVariant() seems (?) not to be called anymore for ESP32. It used to ...? Anyway, just call it from here.
// (And of course, we could maybe just move all the code here, also for ESP8266. Some other day ...)
initVariant();

// Connect to WiFi ------------------------------
Serial.print("Connecting to WiFi ");

// Set device in AP mode to begin with
WiFi.mode(WIFI_AP_STA); // AP and STA is required (!IMPORTANT)

wifiMulti.addAP(SOFTAP_SSID, SOFTAP_PASS); // I use wifiMulti ... just by habit, i guess ....
while (wifiMulti.run() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

// Come here - we are connected
Serial.println(" Done");

// Print WiFi data
Serial.println("Set as AP_STA station.");
Serial.print ("SSID: "); Serial.println(WiFi.SSID());
Serial.print ("Channel: "); Serial.println(WiFi.channel());
Serial.print ("IP address: "); Serial.println(WiFi.localIP());
delay(1000);

// Initialize ESP-Now ---------------------------

// Config gateway AP - set SSID and channel
int channel = WiFi.channel();
if (WiFi.softAP(SOFTAP_SSID, SOFTAP_PASS, channel, 1)) {
Serial.println("AP Config Success. AP SSID: " + String(SOFTAP_SSID));
} else {
Serial.println("AP Config failed.");
}

// Print MAC addresses
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());

// Init ESP-Now
#define ESPNOW_SUCCESS ESP_OK

if (esp_now_init() == ESPNOW_SUCCESS) {
Serial.println("ESP - Now Init Success");
} else {
Serial.println("ESP - Now Init Failed");
ESP.restart(); // just restart if we cant init ESP-Now
}

// ESP-Now is now initialized. Register a callback fcn for when data is received
esp_now_register_recv_cb(OnDataRecv);

// Set web server callback functions
server.on("/", handleRoot);
server.onNotFound(handleNotFound);

// Start web server
server.begin();
Serial.print("WEB server started on SSID: "); Serial.print (WiFi.SSID()); Serial.print (" with IP: "); Serial.println(WiFi.localIP());

digitalWrite (LED_BUILTIN, !LOW); // Led OFF
}

// ------------------------------------------------------------------------------------
void loop()
// ------------------------------------------------------------------------------------
{
server.handleClient();
}
`

When I compiled it has error below

Error

Arduino: 1.8.19 (Windows Store 1.8.57.0) (Windows 10), Board: "NodeMCU-32S, 80MHz, 921600, None"

C:\Users\NECGEN~1\AppData\Local\Temp\arduino_modified_sketch_785761\sketch_aug11d.ino: In function 'void initVariant()':

sketch_aug11d:138:50: error: cannot convert 'esp_interface_t' to 'wifi_interface_t'

esp_wifi_set_mac(ESP_IF_WIFI_AP, &GatewayMac[0]); //ESP32 code

                                              ^

In file included from C:\Users\NECGEN~1\AppData\Local\Temp\arduino_modified_sketch_785761\sketch_aug11d.ino:59:

C:\Users\NECgen4UEFI\Documents\ArduinoData\packages\esp32\hardware\esp32\2.0.4/tools/sdk/esp32/include/esp_wifi/include/esp_wifi.h:659:45: note: initializing argument 1 of 'esp_err_t esp_wifi_set_mac(wifi_interface_t, const uint8_t*)'

esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, const uint8_t mac[6]);

                        ~~~~~~~~~~~~~~~~~^~~

Multiple libraries were found for "WiFi.h"

Used: C:\Users\NECgen4UEFI\Documents\ArduinoData\packages\esp32\hardware\esp32\2.0.4\libraries\WiFi

Not used: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.57.0_x86__mdqgnx93n4wtt\libraries\WiFi

exit status 1

cannot convert 'esp_interface_t' to 'wifi_interface_t'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
...
I found some fix this issue, but I dont' know how to use this fix to edit with sketch. please help me,thank you.

I am a newbe to learn about esp-now

--

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.