Page 1 of 1

ESP-NOW and WiFi Client/Station (Thingspeak) Simultaneously

Posted: Tue Sep 01, 2020 4:16 am
by Darkextratoasty
I seem to be unable to have an ESP32 receive data via ESP-NOW and send that data over WiFi to Thingspeak.com, even though this should, I believe, be a very simple thing to do. My basic setup is this; ESP32 number 1 reads a temperature sensor and sends the data over to ESP32 number 2 via ESP-NOW. ESP32 number 2 receives the data and throws it over to Thingspeak.com via an internet connection over regular WiFi. ESP32 number 1 is working flawlessly, no issues there. On ESP32 number 2, I can get it to either receive the temperature data via ESP-NOW, or send data to Thingspeak.com via WiFi, but not both.
This is the code for ESP32 number 2:

Code: Select all

#include <esp_now.h>
#include <WiFi.h>
#include "ThingSpeak.h"
#include "secrets.h" //this contains network SSID & password and Thingspeak channel ID & APIKEY

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
  float voltage;
  float temperature;
  byte yr,mt,dy,hr,mn,sc;
} struct_message;

// Create a struct_message called myData
struct_message myData;

char ssid[] = SECRET_SSID;   // your network SSID (name) 
char pass[] = SECRET_PASS;   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
WiFiClient  client;

unsigned long myChannelNumber = SECRET_CH_ID;
const char * myWriteAPIKey = SECRET_WRITE_APIKEY;

// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.println("Battery Voltage: " + String(myData.voltage));
  Serial.print(myData.temperature, 4); Serial.println("*F.");
  Serial.print("RTC DateTime: ");
  Serial.print(myData.yr);
  Serial.print('/');
  Serial.print(myData.mt);
  Serial.print('/');
  Serial.print(myData.dy);
  Serial.print(' ');
  Serial.print(myData.hr);
  Serial.print(':');
  Serial.print(myData.mn);
  Serial.print(':');
  Serial.println(myData.sc);
  Serial.println();
/*
  ThingSpeak.setField(1, myData.temperature);
  ThingSpeak.setField(2, myData.voltage);
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  if(x == 200){
    Serial.println("Channel update successful.");
  }
  else{
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }*/
}
 
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

/*
  ThingSpeak.begin(client);  // Initialize ThingSpeak

  if(WiFi.status() != WL_CONNECTED){
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while(WiFi.status() != WL_CONNECTED){
      WiFi.begin(ssid, pass);  // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print(".");
      delay(5000);     
    } 
    Serial.println("\nConnected.");
  }
*/
  
  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  else {
    Serial.println("ESP-NOW initialized successfully");
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to get recv packer info
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {
 /* ThingSpeak.setField(1, random(0,10));
  ThingSpeak.setField(2, random(20,50));
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  if(x == 200){
    Serial.println("Channel update successful.");
  }
  else{
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
  delay(60000);*/
}
If I comment out the Thingspeak portions (the parts currently commented out), then I can receive the temperature data from ESP32 number 1 without any issues. If I uncomment those portions, I can connect to Thingspeak.com and successfully send my dummy data without any issues, but I never receive anything from ESP32 number 1. The problem seems to come from this portion here:

Code: Select all

 if(WiFi.status() != WL_CONNECTED){
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while(WiFi.status() != WL_CONNECTED){
      WiFi.begin(ssid, pass);  // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print(".");
      delay(5000);     
    } 
    Serial.println("\nConnected.");
  }
as I can uncomment just that portion and ESP32 number 2 stops receiving temperature data via ESP-NOW. As far as I'm aware, the ESP32 is perfectly capable of sustaining both an ESP-NOW and WiFi networks at the same time. I've actually seen multiple tutorials on having it run as an ESP-NOW station and a WiFi access point simultaneously. Unfortunately I've not been able to find any on how to get it to operate as an ESP-NOW station and a WiFi station/client simultaneously, which is what I'm trying to do.
Any ideas on why this isn't working? Any suggestions on resources I could look at? Anything I'm doing blatantly wrong because I'm an idiot?

If it's worth anything, here's the code running on ESP32 number 1 that reads a temperature sensor and sends the data via ESP-NOW:

Code: Select all

/*
 * Sparkfun ESP32 Thing Plus MAC address: BC:DD:C2:D2:A6:F8
 * TinyPico ESP32 MAC address: 50:02:91:86:89:A8
 */
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
#include "Adafruit_MCP9808.h"
#include "uRTCLib.h"
#include <TinyPICO.h>
TinyPICO tp = TinyPICO();

#define TIME_TO_SLEEP  2        /* Time ESP32 will go to sleep (in seconds) */

Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();

uRTCLib rtc;
bool timeSet = false;

uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //use to openly broadcast to everyone

typedef struct struct_message {
  float voltage;
  float temperature;
  byte yr,mt,dy,hr,mn,sc;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
 
void setup() {
  tp.DotStar_SetPower(false);
  // Init Serial Monitor
  Serial.begin(115200);

 if (!tempsensor.begin(0x18)) {
    Serial.println("Couldn't find MCP9808! Check your connections and verify the address is correct.");
    while (1);
  }
  tempsensor.setResolution(3); // sets the resolution mode of reading, the modes are defined in the table bellow:

  rtcSetup();

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

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // 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_peer_info_t peerInfo;
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }

  myData.voltage = tp.GetBatteryVoltage();
  Serial.println("Battery Voltage: " + String(myData.voltage));
  
  tempsensor.wake();   // wake up, ready to read!
  myData.temperature = tempsensor.readTempF();
  Serial.print(myData.temperature, 4); Serial.println("*F.");
  tempsensor.shutdown_wake(1); // shutdown MSP9808 - power consumption ~0.1 mikro Ampere, stops temperature sampling

  rtc.refresh();
  myData.yr = rtc.year();
  myData.mt = rtc.month();
  myData.dy = rtc.day();
  myData.hr = rtc.hour();
  myData.mn = rtc.minute();
  myData.sc = rtc.second();
  /*Serial.print("RTC DateTime: ");
  Serial.print(myData.yr);
  Serial.print('/');
  Serial.print(myData.mt);
  Serial.print('/');
  Serial.print(myData.dy);
  Serial.print(' ');
  Serial.print(myData.hr);
  Serial.print(':');
  Serial.print(myData.mn);
  Serial.print(':');
  Serial.print(myData.sc);
  Serial.println();*/

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }

  //Serial.println("Time elapsed: " + String(millis()));

  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * 1000000);
  esp_deep_sleep_start();
}
 
void loop() {}

void rtcSetup() {
  rtc.set_rtc_address(0x68);
  rtc.set_model(URTCLIB_MODEL_DS3231);
  Serial.print("Lost power status: ");
  if (rtc.lostPower()) {
    Serial.print("POWER FAILED. Clearing flag...");
    rtc.lostPowerClear();
    Serial.println(" done.");
    setRTC();
    timeSet = true;
  } else {
    Serial.println("POWER OK");
  }
  rtc.sqwgSetMode(URTCLIB_SQWG_OFF_0);
  rtc.alarmClearFlag(URTCLIB_ALARM_1);
  rtc.alarmClearFlag(URTCLIB_ALARM_2);
}

void setRTC() {
  String tmstr = __TIME__;
  String dstr = __DATE__;
  byte hr = tmstr.substring(0, 2).toInt();
  byte mn = tmstr.substring(3, 5).toInt();
  byte sc = tmstr.substring(6, 8).toInt();
  byte day = dstr.substring(dstr.indexOf(' ') + 1, dstr.lastIndexOf(' ')).toInt();
  byte mth = monthDecode(dstr.substring(0, dstr.indexOf(' ')));
  byte yr = dstr.substring(dstr.lastIndexOf(' ') + 3).toInt();
  rtc.set(sc, mn, hr, 0, day, mth, yr);
  //  RTCLib::set(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
}

byte monthDecode(String m) {
//  Serial.println();
//  Serial.println(m);
//  Serial.println();
  if (m == "January") return 1;
  if (m == "February") return 2;
  if (m == "March") return 3;
  if (m == "April") return 4;
  if (m == "May") return 5;
  if (m == "June") return 6;
  if (m == "July") return 7;
  if (m == "August") return 8;
  if (m == "September") return 9;
  if (m == "October") return 10;
  if (m == "November") return 11;
  if (m == "December") return 12;
  return 255;
}

Re: ESP-NOW and WiFi Client/Station (Thingspeak) Simultaneously

Posted: Tue Nov 10, 2020 9:36 pm
by mike.loney@gmail.com
I have the same issue. The only solution I have found so far is to do an ESP.Reset() after sending your data to ThingSpeak. This will reset the ESP-NOW comms until the next send to ThingSpeak. Not an ideal solution. :? I love to get a better one.