This is the code for ESPNow two way controller. It reads some data from Serial and beams it to a slave which in turn sends some other by return. Code based on this discussion : ESP8266 with ESP-NOW as an alternative to nRF24L01+ - Exhibition / Gallery - Arduino Forum
This is the Error I am getting in Serial monitor :
19:56:10.510 -> --------------- CUT HERE FOR EXCEPTION DECODER ---------------
19:56:10.544 ->
19:56:10.544 -> ets Jan 8 2013,rst cause:2, boot mode:(3,6)
19:56:10.544 ->
19:56:10.544 -> load 0x4010f000, len 3584, room 16
19:56:10.544 -> tail 0
19:56:10.544 -> chksum 0xb0
19:56:10.544 -> csum 0xb0
19:56:10.544 -> v2843a5ac
19:56:10.544 -> ~ld
19:56:10.786 -> 0,0,0,0,0
19:56:10.786 ->
19:56:10.786 -> User exception (panic/abort/assert)
19:56:10.786 -> --------------- CUT HERE FOR EXCEPTION DECODER ---------------
19:56:10.786 ->
19:56:10.786 -> Panic core_esp8266_main.cpp:133 __yield
19:56:10.786 ->
19:56:10.786 -> >>>stack>>>
19:56:10.786 ->
19:56:10.786 -> ctx: sys
19:56:10.786 -> sp: 3fffed80 end: 3fffffb0 offset: 0000
19:56:10.786 -> 3fffed80: 00000000 00000000 00000020 40100154
19:56:10.821 -> 3fffed90: 000000fe 00000000 00000000 00000000
19:56:10.821 -> 3fffeda0: 00000000 00000000 00000000 3ffee630
Any reason why this is resetting ?
The full code is below :
#include <ESP8266WiFi.h>
#include <espnow.h>
#include "SSD1306Wire.h"
// This is the MAC Address of the connected slave
uint8_t remoteMac[] = {0x36, 0x33, 0x33, 0x33, 0x33, 0x33};
#define WIFI_CHANNEL 4
const byte numChars = 100; // Adjust based on max number of char + null
char receivedChars[numChars]; // Holder for incoming data
bool started = false; //True: Message is started
bool ended = false; //True: Message is finished
bool newData = false;
char incomingByte ; //Variable to store the incoming byte
byte charIndex ; //Index of received array
uint16_t txMsgCount ;
unsigned long serTimeOutMs = millis();
unsigned long serTimeOutIntvl = 2000;
struct DataStruct { // The controller will send DI and AI data
uint16_t DIState;
uint16_t AIVal[16];
};
struct RDataStruct { // The Controller will receive DO and AO data
uint16_t DOState;
uint16_t AOVal[4];
};
DataStruct sendingData; // Data to Slave
RDataStruct receivedData; // Data from slave
unsigned long lastSentMillis;
unsigned long sendIntervalMillis = 500; // This decides how often the data is sent. The Slave will folow this ...
unsigned long lastBlinkMillis;
unsigned long fastBlinkMillis = 100;
unsigned long slowBlinkMillis = 1000;
unsigned long blinkIntervalMillis = slowBlinkMillis;
byte ledPin = 14;
// Initialize the OLED display using Wire library
SSD1306Wire display(0x3c, D1, D2); // SDA = D1 and SCL = D2
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
display.init();
display.flipScreenVertically();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
if (esp_now_init() != 0) {
display.drawString(0, 10, "ESP-NOW INIT");
display.drawString(0, 35, "FAILED...");
display.display();
while (true) {};
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
esp_now_add_peer(remoteMac, ESP_NOW_ROLE_COMBO, WIFI_CHANNEL, NULL, 0);
esp_now_register_send_cb(sendCallBackFunction);
esp_now_register_recv_cb(receiveCallBackFunction);
waitingForHostMsg();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void loop() {
readSerial();
if ( millis() - serTimeOutMs > serTimeOutIntvl ) {
waitingForHostMsg();
txMsgCount = 0;
}
blinkLed();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//READ DI AND AI VALUES FROM MASTER SCREEN
void readSerial() // Read from the LabVIEW code via Serial and prepare to Send it to Controller
{
while (Serial.available() > 0) // Is there any data in Serial buffer ??
{
incomingByte = Serial.read(); // Read the incoming byte .. this removes it from Serial buffer
if (incomingByte == '<') // Wait for the start marker..
{
started = true; // Got the start marker. Set receive boolean to true..
charIndex = 0;
receivedChars[charIndex] = '\0'; // Throw away any incomplete characters
}
else if (incomingByte == '>') // Wait for the end marker
{
ended = true; // Got the end marker ...
break; // Stop reading - exit from while loop!
}
else // Read the message from the Serial buffer !
{
if (charIndex < numChars) // Make sure there is room
{
receivedChars[charIndex] = incomingByte; // Add char to array
charIndex++;
receivedChars[charIndex] = '\0'; // Add NULL to end.. keep on adding
}
}
}
if (started && ended) // All data read from the Serial buffer... process it.
{
receivedChars[charIndex] = '\0';
parseData(); // Read and store the Voltage info in variables.
charIndex = 0;
started = false;
ended = false;
serTimeOutMs = millis();
}
}
//**********************************
// PARSE THE DI AND AI VALUES & SEND TO SLAVE
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(receivedChars, ","); // get the first part - the string
sendingData.DIState = atoi(strtokIndx);
for ( byte count = 0; count < 16; count++) {
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
sendingData.AIVal[count] = atoi(strtokIndx); // convert this part to an integer
}
sendDI_AIData();
}
//**********************************
// SEND THE DI AND AI VALUES TO SLAVE VIA WIFI
void sendDI_AIData() { // Send the DI and AI values got via Serial to the Slave
uint8_t byteArray[sizeof(sendingData)];
memcpy(byteArray, &sendingData, sizeof(sendingData));
esp_now_send(NULL, byteArray, sizeof(sendingData)); // NULL means send to all peers
delay(2); // A small delay for the Slave response to reach back
}
//**********************************
// GET THE DO AND AO VALUES FROM SLAVE VIA WIFI
// AND THEN PRINT IT TO THE MASTER SCREEN
void receiveCallBackFunction(uint8_t *senderMac, uint8_t *incomingData, uint8_t len) {
memcpy(&receivedData, incomingData, sizeof(receivedData));
// This data will be processed inside Send call back function..
}
//**********************************
//
void sendCallBackFunction(uint8_t* mac, uint8_t sendStatus) {
char receiveBuffer[50]; // Buffer for the DO and AO state from controller
if (sendStatus == 0) {
blinkIntervalMillis = fastBlinkMillis;
sprintf(receiveBuffer, "%u,%u,%u,%u,%u", receivedData.DOState, receivedData.AOVal[0], receivedData.AOVal[1], receivedData.AOVal[2], receivedData.AOVal[3]);
Serial.println(receiveBuffer); // Update the Master with DO and AO values..
char msg[10];
display.clear();
txMsgCount++ ;
if (txMsgCount > 1000 ) txMsgCount = 0;
sprintf(msg, "MsgCount : %5u", txMsgCount);
display.drawString(0, 20, msg );
display.display();
}
else {
blinkIntervalMillis = slowBlinkMillis;
sprintf(receiveBuffer, "%u,%u,%u,%u,%u", 0,0,0,0,0);
Serial.println(receiveBuffer); // Update the Master with Zero for DO and AO values as Slave not on line..
display.drawString(0, 20, "Link Fail." );
display.display();
}
}
//**********************************
// BLINK LED FAST IF SEND IS SUCCESS ELSE SLOW
void blinkLed() {
if (millis() - lastBlinkMillis >= blinkIntervalMillis) {
lastBlinkMillis += blinkIntervalMillis;
digitalWrite(ledPin, ! digitalRead(ledPin));
}
}
//**********************************
// HOST SERIAL IS OFF MESSAGE
void waitingForHostMsg() {
display.clear();
display.drawString(0, 10, "WAITING FOR");
display.drawString(0, 35, "SERIAL HOST.");
display.display();
}