ESP-NOW and WiFi Client/Station (Thingspeak) Simultaneously
Posted: Tue Sep 01, 2020 4:16 am
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:
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:
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:
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);*/
}
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.");
}
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;
}