Trying to understand ESP32 OTA over the GSM code - arduino

I am performing ESP32 OTA over the GSM. I have found some example code online, modified it slightly based on my board connections and was able to sucesfully perform a firmware update.
I use lilygo ESP32 GSM development board.
However, it frustrates me that I am not capable of understanding what really happens in the code at the low level. I really want to understand before I go any further with my project.
Full code for my OTA update:
#include <Update.h>
#define TINY_GSM_MODEM_SIM800
// Increase RX buffer
#define TINY_GSM_RX_BUFFER 1030
const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";
#define MODEM_RST 5
#define MODEM_PWRKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define LED_GPIO 13
#define LED_ON HIGH
#define LED_OFF LOW
#define SerialAT Serial1
#include <TinyGsmClient.h>
#include <CRC32.h>
#include "FS.h"
#include "SPIFFS.h"
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file
uint32_t knownCRC32 = 0x6f50d767;
uint32_t knownFileSize = 1024; // In case server does not send it
void setup()
{
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
// Set console baud rate
Serial.begin(115200);
setupModem();
delay(10);
if (!SPIFFS.begin(true))
{
Serial.println("SPIFFS Mount Failed");
return;
}
SPIFFS.format();
listDir(SPIFFS, "/", 0);
// Set GSM module baud rate
delay(3000);
// Restart takes quite some time
// To skip it, call init() instead of restart()
Serial.println("Initializing modem...");
modem.restart();
String modemInfo = modem.getModemInfo();
Serial.print("Modem: ");
Serial.println(modemInfo);
// Unlock your SIM card with a PIN
//modem.simUnlock("1234");
}
void loop()
{
Serial.print("Waiting for network...");
if (!modem.waitForNetwork())
{
Serial.println(" fail");
delay(10000);
return;
}
Serial.println(" OK");
Serial.print("Connecting to ");
Serial.print(apn);
if (!modem.gprsConnect(apn, user, pass))
{
Serial.println(" fail");
delay(10000);
return;
}
Serial.println(" OK");
Serial.print("Connecting to ");
Serial.print(server);
// if you get a connection, report back via serial:
if (!client.connect(server, port))
{
Serial.println(" fail");
delay(10000);
return;
}
Serial.println(" OK");
// Make a HTTP request:
client.print(String("GET ") + resource + " HTTP/1.0\r\n");
client.print(String("Host: ") + server + "\r\n");
client.print("Connection: close\r\n\r\n");
long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 5000L)
{
Serial.println(">>> Client Timeout !");
client.stop();
delay(10000L);
return;
}
}
Serial.println("Reading header");
uint32_t contentLength = knownFileSize;
File file = SPIFFS.open("/update.bin", FILE_APPEND);
while (client.available())
{
String line = client.readStringUntil('\n');
line.trim();
//Serial.println(line); // Uncomment this to show response header
line.toLowerCase();
if (line.startsWith("content-length:"))
{
contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();
}
else if (line.length() == 0)
{
break;
}
}
timeout = millis();
uint32_t readLength = 0;
CRC32 crc;
unsigned long timeElapsed = millis();
printPercent(readLength, contentLength);
while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
{
int i = 0;
while (client.available())
{
// read file data to spiffs
if (!file.print(char(client.read())))
{
Serial.println("Appending file");
}
//Serial.print((char)c); // Uncomment this to show data
//crc.update(c);
readLength++;
if (readLength % (contentLength / 13) == 0)
{
printPercent(readLength, contentLength);
}
timeout = millis();
}
}
file.close();
printPercent(readLength, contentLength);
timeElapsed = millis() - timeElapsed;
Serial.println();
client.stop();
Serial.println("stop client");
modem.gprsDisconnect();
Serial.println("gprs disconnect");
Serial.println();
float duration = float(timeElapsed) / 1000;
/*
Serial.print("Tamaño de Archivo: ");
Serial.println(contentLength);
Serial.print("Leido: ");
Serial.println(readLength);
Serial.print("Calculado. CRC32: 0x");
Serial.println(crc.finalize(), HEX);
Serial.print("Conocido CRC32: 0x");
Serial.println(knownCRC32, HEX);
Serial.print("Bajado en: ");
Serial.print(duration);
Serial.println("s");
Serial.println("Se genera una espera de 3 segundos");
for (int i = 0; i < 3; i++)
{
Serial.print(String(i) + "...");
delay(1000);
}
*/
//readFile(SPIFFS, "/update.bin");
updateFromFS();
// Do nothing forevermore
while (true)
{
delay(1000);
}
}
void appendFile(fs::FS &fs, const char *path, const char *message)
{
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if (!file)
{
Serial.println("Failed to open file for appending");
return;
}
if (file.print(message))
{
Serial.println("APOK");
}
else
{
Serial.println("APX");
}
}
void readFile(fs::FS &fs, const char *path)
{
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if (!file || file.isDirectory())
{
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while (file.available())
{
Serial.write(file.read());
delayMicroseconds(100);
}
}
void writeFile(fs::FS &fs, const char *path, const char *message)
{
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if (!file)
{
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message))
{
Serial.println("File written");
}
else
{
Serial.println("Write failed");
}
}
void listDir(fs::FS &fs, const char *dirname, uint8_t levels)
{
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if (!root)
{
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory())
{
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while (file)
{
if (file.isDirectory())
{
Serial.print(" DIR : ");
Serial.println(file.name());
if (levels)
{
listDir(fs, file.name(), levels - 1);
}
}
else
{
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void deleteFile(fs::FS &fs, const char *path)
{
Serial.printf("Deleting file: %s\n", path);
if (fs.remove(path))
{
Serial.println("File deleted");
}
else
{
Serial.println("Delete failed");
}
}
void updateFromFS()
{
File updateBin = SPIFFS.open("/update.bin");
if (updateBin)
{
if (updateBin.isDirectory())
{
Serial.println("Directory error");
updateBin.close();
return;
}
size_t updateSize = updateBin.size();
if (updateSize > 0)
{
Serial.println("Starting update");
performUpdate(updateBin, updateSize);
}
else
{
Serial.println("Error, archivo vacío");
}
updateBin.close();
// whe finished remove the binary from sd card to indicate end of the process
//fs.remove("/update.bin");
}
else
{
Serial.println("no such binary");
}
}
void performUpdate(Stream &updateSource, size_t updateSize)
{
if (Update.begin(updateSize))
{
size_t written = Update.writeStream(updateSource);
if (written == updateSize)
{
Serial.println("Writes : " + String(written) + " successfully");
}
else
{
Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
}
if (Update.end())
{
Serial.println("OTA finished!");
if (Update.isFinished())
{
Serial.println("Restart ESP device!");
ESP.restart();
}
else
{
Serial.println("OTA not fiished");
}
}
else
{
Serial.println("Error occured #: " + String(Update.getError()));
}
}
else
{
Serial.println("Cannot beggin update");
}
}
void printPercent(uint32_t readLength, uint32_t contentLength)
{
// If we know the total length
if (contentLength != -1)
{
Serial.print("\r ");
Serial.print((100.0 * readLength) / contentLength);
Serial.print('%');
}
else
{
Serial.println(readLength);
}
}
void setupModem()
{
#ifdef MODEM_RST
// Keep reset high
pinMode(MODEM_RST, OUTPUT);
digitalWrite(MODEM_RST, HIGH);
#endif
pinMode(MODEM_PWRKEY, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
// Turn on the Modem power first
digitalWrite(MODEM_POWER_ON, HIGH);
// Pull down PWRKEY for more than 1 second according to manual requirements
digitalWrite(MODEM_PWRKEY, HIGH);
delay(100);
digitalWrite(MODEM_PWRKEY, LOW);
delay(1000);
digitalWrite(MODEM_PWRKEY, HIGH);
// Initialize the indicator as an output
pinMode(LED_GPIO, OUTPUT);
digitalWrite(LED_GPIO, LED_OFF);
}
From what I understand, the following part of the code reads my binary file that is stored in the server and read it into SPIFFS memory:
while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
{
int i = 0;
while (client.available())
{
// read file data to spiffs
if (!file.print(char(client.read())))
{
Serial.println("Appending file");
}
//Serial.print((char)c); // Uncomment this to show data
//crc.update(c);
readLength++;
if (readLength % (contentLength / 13) == 0)
{
printPercent(readLength, contentLength);
}
timeout = millis();
}
}
Then the updateFromFS() function is executed, which checks whether the binary is all good and then calls another function performUpdate(updateBin, updateSize);
void updateFromFS()
{
File updateBin = SPIFFS.open("/update.bin");
if (updateBin)
{
if (updateBin.isDirectory())
{
Serial.println("Directory error");
updateBin.close();
return;
}
size_t updateSize = updateBin.size();
if (updateSize > 0)
{
Serial.println("Starting update");
performUpdate(updateBin, updateSize);
}
else
{
Serial.println("Error, archivo vacío");
}
updateBin.close();
// whe finished remove the binary from sd card to indicate end of the process
//fs.remove("/update.bin");
}
else
{
Serial.println("no such binary");
}
}
in the performUpdate(updateBin, updateSize), 2 functions from Arduino Update Library are being called ( Update.begin(updateSize) and Update.writeStream(updateSource) ) and that is where I cant follow anymore...
void performUpdate(Stream &updateSource, size_t updateSize)
{
if (Update.begin(updateSize))
{
size_t written = Update.writeStream(updateSource);
if (written == updateSize)
{
Serial.println("Writes : " + String(written) + " successfully");
}
else
{
Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
}
if (Update.end())
{
Serial.println("OTA finished!");
if (Update.isFinished())
{
Serial.println("Restart ESP device!");
ESP.restart();
}
else
{
Serial.println("OTA not fiished");
}
}
else
{
Serial.println("Error occured #: " + String(Update.getError()));
}
}
else
{
Serial.println("Cannot beggin update");
}
}
I have found this Update library source code :
https://github.com/espressif/arduino-esp32/blob/master/libraries/Update/src/Updater.cpp
But it seems that this is beyond my knowledge to understand what really is going on in this code.
First of all, we pass only 1 variable to .begin method, but the function prototype requires more than that:
bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn, const char *label)
And then I am trying to understand what happens in function Update.writeStream(updateSource) but cant..
If anyone could shed some light here I would appreciate a lot! Thanks in advance...

The algorithm downloads the new firmware (.bin) from the cloud to the device's local memory and makes the firmware change with the UpdateClass library
(I see the texts in Spanish if you want we speak in Spanish)
Check the .h (only one argument required)
https://github.com/espressif/arduino-esp32/blob/master/libraries/Update/src/Update.h
/*
Call this to check the space needed for the update
Will return false if there is not enough space
*/
bool begin(size_t size=UPDATE_SIZE_UNKNOWN, int command = U_FLASH, int ledPin = -1, uint8_t ledOn = LOW, const char *label = NULL);

You could use the OTAdrive library and use it for OTA updates.
Check here for the esp32 gsm modem OTA example.

Related

Problem transferring data to firebase using Sim7600CE, http

I am using ESP32 integrated Sim7600CE module to transfer data to Firebase Realtime database using http and got 400 Bad Request, please help me to solve this.
13:36:48.693 -> Status code: 400
13:36:48.833 -> Response: <html>
13:36:48.833 -> <head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
13:36:48.833 -> <body>
13:36:48.833 -> <center><h1>400 Bad Request</h1></center>
#define TINY_GSM_MODEM_SIM7600
#define TINY_GSM_RX_BUFFER 650
#include <ArduinoJson.h>
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h> //https://github.com/arduino-libraries/ArduinoHttpClient
#include "TinyGsmClient.h"
#define SIM_RESET_PIN 15
#define SIM_AT_BAUDRATE 115200
#define GSM_PIN ""
#define SIM_TX 17
#define SIM_RX 16
const char FIREBASE_HOST[] = "smartgrid1-930b0-default-rtdb.firebaseio.com";
const String FIREBASE_AUTH = "zezoyo69fX9eqPDpjaom6CJAyXhnW081GlJ4ah5c";
const String FIREBASE_PATH = "/";
const int SSL_PORT = 443;
char APN[] = "v-internet"; //
char USER[] = "";
char PASS[] = "";
TinyGsm modem(Serial2);
TinyGsmClient gsm_client_secure_modem(modem);
HttpClient http_client = HttpClient(gsm_client_secure_modem, FIREBASE_HOST, SSL_PORT);
unsigned long previousMillis = 0;
// Hàm dùng để thiết lập modem SIM tạo kết nối GPRS
bool connectToGPRS() {
// Unlock SIM (nếu có)
if (GSM_PIN && modem.getSimStatus() != 3)
modem.simUnlock(GSM_PIN);
Serial.println("Ket noi toi nha mang...");
while (!modem.waitForNetwork(60000L)) {
Serial.println("._.");
delay(5000);
}
// Nếu không thấy sóng từ nhà mạng thì thoát hàm
if (!modem.isNetworkConnected())
return false;
Serial.println("Ket noi GPRS");
if (!modem.gprsConnect(APN)) {// Hàm kết nối tới gprs trả về true/false cho biết có kết nối được hay chưa
Serial.print("Khong the ket noi GPRS - ");
Serial.println(APN);
return false;
}
// Kiểm tra lại lần nữa để chắc cú
if (modem.isGprsConnected()){
Serial.println("Da ket noi duoc GPRS!");
return true;
}
return false;
}
// Hàm khởi động module SIM
bool initModemSIM() {
Serial.println("Bat dau khoi dong module SIM");
// Đặt chân reset của module xuống LOW để chạy
pinMode(SIM_RESET_PIN, OUTPUT);
digitalWrite(SIM_RESET_PIN, LOW);
delay(5000);
Serial2.begin(SIM_AT_BAUDRATE);// Module SIM giao tiếp với ESP qua cổng Serial2 bằng AT cmds
if (!modem.restart()) {
Serial.println("Khong the khoi dong lai module SIM => Co loi");
return false;
}
return true;
}
void setup() {
Serial.begin(115200);
if (initModemSIM()){
while(!connectToGPRS()) delay(100);
}
if (modem.isGprsConnected()) {
Serial.print(F("Connecting to "));
Serial.println(APN);
if (!modem.gprsConnect(APN, USER, PASS))
{
Serial.println(" fail");
delay(1000);
return;
}
}
if (initModemSIM()){
while(!connectToGPRS()) delay(100);
}
modem.restart();
String modemInfo = modem.getModemInfo();
Serial.print("Modem: ");
Serial.println(modemInfo);
http_client.setHttpResponseTimeout(10 * 1000); //^0 secs timeout
}
void loop() {
Serial.print(F("Connecting to "));
Serial.println(APN);
if (!modem.gprsConnect(APN, USER, PASS))
{
Serial.println(" fail");
delay(1000);
return;
}
Serial.println(" OK");
http_client.connect(FIREBASE_HOST, SSL_PORT);
while (true) {
if (!http_client.connected())
{
Serial.println();
http_client.stop();// Shutdown
Serial.println("HTTP not connect");
break;
}
else
{
dht_loop();
}
}
}
void PostToFirebase(const char* method, const String & path , const String & data, HttpClient* http)
{
String response;
int statusCode = 0;
http->connectionKeepAlive(); // Currently, this is needed for HTTPS
String url;
if (path[0] != '/')
{
url = "/";
}
url += path + ".json";
url += "?auth=" + FIREBASE_AUTH;
Serial.print("POST:");
Serial.println(url);
Serial.print("Data:");
Serial.println(data);
String contentType = "application/json";
http->put(url, contentType, data);
statusCode = http->responseStatusCode();
Serial.print("Status code: ");
Serial.println(statusCode);
response = http->responseBody();
Serial.print("Response: ");
Serial.println(response);
// if (!http->connected())
// {
// Serial.println();
// http->stop();// Shutdown
// Serial.println("HTTP POST disconnected");
// }
}
void dht_loop()
{
String h = String(random(1,100));
delay(100);
Serial.print("h = ");
Serial.println(h);
String Data = "{";
Data += "\"Sim\":" + h + "";
Data += "}";
PostToFirebase("PATCH", FIREBASE_PATH, Data, &http_client);
}

Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed) error shows when i use ESP now protocol

This error shows in my serial monitor see the code below for ESP32
and please help me to solve
Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached
memory region accessed) Core 1 register dump: PC : 0x400d1580 PS
: 0x00060034 A0 : 0x400847fc A1 : 0x3ffbe7b0 A2 :
0x00000001 A3 : 0x00000002 A4 : 0x000000ff A5 :
0x4008b368 A6 : 0x00000000 A7 : 0x00000001 A8 :
0x80081348 A9 : 0x3ff5f024 A10 : 0x3ffbebfc A11 :
0x20000000 A12 : 0x00000400 A13 : 0x3ffb1b10 A14 :
0x00000026 A15 : 0x3ffc4598 SAR : 0x00000020 EXCCAUSE:
0x00000007 EXCVADDR: 0x00000000 LBEG : 0x40001609 LEND :
0x4000160d LCOUNT : 0x00000000 Core 1 was running in ISR context:
EPC1 : 0x40087157 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4
: 0x400d1580
Backtrace: 0x400d1580:0x3ffbe7b0 0x400847f9:0x3ffbe7d0
0x40087154:0x3ffb1b50 0x400e2aa9:0x3ffb1bc0 0x400e1379:0x3ffb1be0
0x400e17c7:0x3ffb1c00 0x400e015d:0x3ffb1c70 0x400e0c5f:0x3ffb1cc0
0x400df715:0x3ffb1d20 0x400dfc8d:0x3ffb1d60 0x4012d7e6:0x3ffb1d80
0x4012d9da:0x3ffb1dd0 0x4012da2d:0x3ffb1e00 0x400e2f57:0x3ffb1e20
0x400e30aa:0x3ffb1e40 0x400d70dd:0x3ffb1e60 0x400d2da9:0x3ffb1e80
0x400d1392:0x3ffb1f80 0x400d468b:0x3ffb1fb0 0x40088c05:0x3ffb1fd0
#include <esp_now.h>
#include <WiFi.h>
#include <IRremote.h>
int IR_Recv = 4;
#define CHANNEL 3
#define NUM_SLAVES 20 // ESP-Now can handle a maximum of 20 slaves
#define PRINTSCANRESULTS 0
IRrecv irrecv(IR_Recv);
decode_results results;
int slaveCount = 0; // Keeps count of no. of slaves with the defined prefix
esp_now_peer_info_t slaves[NUM_SLAVES]; // Stores the information of each of the slave that is added as a peer
void initESPNow();
void manageSlaves();
void scanForSlaves();
void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status);
void onDataRecv(const uint8_t *mac_add, const uint8_t *data, int data_len);
void sendData(uint8_t data);
void setup()
{
Serial.begin(115200);
irrecv.enableIRIn();
WiFi.mode(WIFI_MODE_STA);
initESPNow();
esp_now_register_send_cb(onDataSent);
esp_now_register_recv_cb(onDataRecv);
scanForSlaves();
manageSlaves();
}
void loop()
{
//Serial.println("Digital Read: " + String(digitalRead(IR_PIN)));
if(slaveCount > 0)
{
if (irrecv.decode(&results)){
long int decCode = results.value;
Serial.println(results.value);
switch (results.value){
case 2921: //when you press the 1 button
sendData(0);
break;
case 873: //when you press the 4 button
sendData(512);
break;
case 874: //when you press the 2 button
sendData(100);
break;
case 2922: //when you press the 5 button
sendData(300);
break;
default:
Serial.println('nothing to send');
break;
}
irrecv.resume(); // Receives the next value from the button you press
}
}
delay(3000);
}
// Init ESP Now with fallback
void initESPNow()
{
WiFi.disconnect();
if (esp_now_init() == ESP_OK)
{
Serial.println("ESPNow Init Success");
}
else
{
Serial.println("ESPNow Init Failed");
ESP.restart();
}
}
// Scan for slaves in AP mode
void scanForSlaves()
{
int8_t scanResults = WiFi.scanNetworks();
//reset slaves
memset(slaves, 0, sizeof(slaves));
slaveCount = 0;
Serial.println("");
if (scanResults == 0)
{
Serial.println("No WiFi devices in AP Mode found");
}
else
{
Serial.print("Found ");
Serial.print(scanResults);
Serial.println(" devices ");
for (int i = 0; i < scanResults; i++)
{
// Print SSID and RSSI for each device found
String SSID = WiFi.SSID(i);
int32_t RSSI = WiFi.RSSI(i);
String BSSIDstr = WiFi.BSSIDstr(i);
if (PRINTSCANRESULTS)
{
Serial.print(i + 1);
Serial.print(": ");
Serial.print(SSID);
Serial.print(" [");
Serial.print(BSSIDstr);
Serial.print("]");
Serial.print(" (");
Serial.print(RSSI);
Serial.print(")");
Serial.println("");
}
delay(10);
// Check if the current device starts with `Slave`
if (SSID.indexOf("Slave") == 0)
{
// SSID of interest
Serial.print(i + 1);
Serial.print(": ");
Serial.print(SSID);
Serial.print(" [");
Serial.print(BSSIDstr);
Serial.print("]");
Serial.print(" (");
Serial.print(RSSI);
Serial.print(")");
Serial.println("");
// Get BSSID => Mac Address of the Slave
int mac[6];
if(6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]))
{
for(int j = 0; j < 6; j++)
{
slaves[slaveCount].peer_addr[j] = (uint8_t)mac[j];
}
}
slaves[slaveCount].channel = CHANNEL; // pick a channel
slaves[slaveCount].encrypt = 0; // no encryption
slaveCount++;
}
}
}
if(slaveCount > 0)
{
Serial.print(slaveCount); Serial.println(" Slave(s) found, processing..");
}
else
{
Serial.println("No Slave Found, trying again.");
}
// clean up ram
WiFi.scanDelete();
}
// Check if the slave is already paired with the master.
// If not, pair the slave with master
void manageSlaves()
{
if(slaveCount > 0)
{
for(int i = 0; i < slaveCount; i++)
{
const esp_now_peer_info_t *peer = &slaves[i];
const uint8_t *peer_addr = slaves[i].peer_addr;
Serial.print("Processing: ");
for(int j = 0; j < 6; j++)
{
Serial.print((uint8_t) slaves[i].peer_addr[j], HEX);
if (j != 5)
{
Serial.print(":");
}
}
Serial.print(" Status: ");
// check if the peer exists
bool exists = esp_now_is_peer_exist(peer_addr);
if(exists)
{
// Slave already paired.
Serial.println("Already Paired");
}
else
{
// Slave not paired, attempt pair
esp_err_t addStatus = esp_now_add_peer(peer);
if(addStatus == ESP_OK)
{
// Pair success
Serial.println("Pair success");
}
else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT)
{
// How did we get so far!!
Serial.println("ESPNOW Not Init");
}
else if (addStatus == ESP_ERR_ESPNOW_ARG)
{
Serial.println("Add Peer - Invalid Argument");
}
else if (addStatus == ESP_ERR_ESPNOW_FULL)
{
Serial.println("Peer list full");
}
else if (addStatus == ESP_ERR_ESPNOW_NO_MEM)
{
Serial.println("Out of memory");
}
else if (addStatus == ESP_ERR_ESPNOW_EXIST)
{
Serial.println("Peer Exists");
}
else
{
Serial.println("Not sure what happened");
}
delay(1000);
}
}
}
else
{
// No slave found to process
Serial.println("No Slave found to process");
}
}
// send data
void sendData(uint8_t data)
{
for(int i = 0; i < slaveCount; i++)
{
const uint8_t *peer_addr = slaves[i].peer_addr;
if (i == 0)
{
// print only for first slave
Serial.print("Sending: ");
Serial.println(data);
}
esp_err_t result = esp_now_send(peer_addr, &data, sizeof(data));
Serial.print("Send Status: ");
if (result == ESP_OK) {
Serial.println("Success");
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW not Init.");
} else if (result == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (result == ESP_ERR_ESPNOW_INTERNAL) {
Serial.println("Internal Error");
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
} else {
Serial.println("Not sure what happened");
}
delay(100);
}
}
// callback when data is sent from Master to Slave
void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
{
char macStr[18];
// sendTime = millis();
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("Last Packet Sent to: ");
Serial.println(macStr);
Serial.print("Last Packet Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
// callback when data is received from Slave to Master
void onDataRecv(const uint8_t *mac_add, const uint8_t *data, int data_len)
{
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]);
Serial.print("Last Packet Recv from: ");
Serial.println(macStr);
Serial.print("Last Packet Recv Data: ");
Serial.println(*data);
Serial.println("");
}```
Out of curiosity I tried your code and I can reproduced what you are facing. But I noticed that if I swap the line irrecv.enableIRIn(); with WiFi.mode(WIFI_MODE_STA); in setup(), the crash stop.
This will cause the sketch to crash
#include <WiFi.h>
#include <IRremote.h>
int IR_Recv = 4;
IRrecv irRecv(IR_Recv);
decode_results results;
void setup()
{
Serial.begin(115200);
irRecv.enableIRIn();
WiFi.mode(WIFI_MODE_STA);
}
void loop() {
}
This will work perfectly without crash
#include <WiFi.h>
#include <IRremote.h>
int IR_Recv = 4;
IRrecv irRecv(IR_Recv);
decode_results results;
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_MODE_STA);
irRecv.enableIRIn();
}
void loop() {
}
I couldn't explain why, what irrecv.enableIRIn() does is to setup the interrupt and reset the timer2, but I couldn't see how this affect the WiFi.mode(WIFI_MODE_STA), maybe others could explain why this happen.

Error using thingspeak talk back to control arduino led

The error I'm facing is about using talkback function of thingspeak to control my Arduino LED. it cannot execute the talkback command to off the led. The error is in my void get talkback. Please help me
#include "ThingSpeak.h"
#include <Ethernet.h>
#define redLED 8
byte mac[] = {0x90, 0xA2, 0xDA, 0x10, 0x40, 0x4F};
const String channelsAPIKey = "";
const String talkBackAPIKey = "";
const String talkBackID = "";
const String talkCommandID = "";
const unsigned int getTalkBackInterval = 10 * 1000;
const unsigned int updateChannelsInterval = 15 * 1000;
String talkBackCommand;
long lastConnectionTimeChannels = 0;
boolean lastConnectedChannels = false;
int failedCounterChannels = 0;
long lastConnectionTimeTalkBack = 0;
boolean lastConnectedTalkBack = false;
int failedCounterTalkBack = 0;
char charIn;
// Arduino Ethernet Client is initialized
EthernetClient client;
void setup()
{
Ethernet.init(10); // Most Arduino Ethernet hardware
Serial.begin(9600); //Initialize serial
// start the Ethernet connection:
pinMode(redLED, OUTPUT);
digitalWrite(redLED, HIGH);
}
void loop()
{
getTalkBack();
}
void getTalkBack()
{
String tsData;
tsData = talkBackID + "/commands/execute?api_key=" + talkBackAPIKey;
if ((!client.connected() && (millis() - lastConnectionTimeTalkBack > getTalkBackInterval)))
{
if (client.connect("api.thingspeak.com", 80))
{
client.println("GET /talkbacks/" + tsData + " HTTP/1.0");
client.println();
lastConnectionTimeTalkBack = millis();
if (client.connected())
{
Serial.println("---------------------------------------");
Serial.println("GET TalkBack command");
Serial.println();
Serial.println("Connecting to ThingSpeak");
Serial.println();
Serial.println();
Serial.println("Server response");
Serial.println();
failedCounterTalkBack = 0;
while (client.connected() && !client.available()) delay(2000); //waits for data
while (client.connected() || client.available())
{
charIn = client.read();
talkBackCommand += charIn;
Serial.print(charIn);
if (talkBackCommand == "LED_ON")
{
digitalWrite(redLED, HIGH);
}
if (talkBackCommand == "LED_OFF")
{
digitalWrite(redLED, LOW);
}
}
if (talkBackCommand = talkBackCommand.substring(talkBackCommand.indexOf("_CMD_") + 5));
{
Serial.println();
Serial.println();
Serial.println("Disconnected");
Serial.println();
Serial.println("--------");
Serial.println();
Serial.println("talkback command was");
Serial.println();
Serial.println("--------");
Serial.println();
Serial.println(talkBackCommand);
Serial.println("--------");
Serial.println();
}
}
else
{
failedCounterTalkBack++;
Serial.println("Connection to ThingSpeak failed (" + String(failedCounterTalkBack, DEC) + ")");
Serial.println();
lastConnectionTimeChannels = millis();
}
}
}
if (failedCounterTalkBack > 3 )
{
startEthernet();
}
client.stop();
Serial.flush();
}
The below is a image from my serial monitor. It shows that I can capture the command but couldn't execute it.
Looks like you are reading and appending all the received bytes to talkBackCommand. So, talkBackCommand is "HTTP/1.1 200 OK Date...." and if (talkBackCommand == "LED_ON") would never be true.
I think you wanted to see if the received data contain your commands LED_ON or LED_OFF. You can do something like this:
if (talkBackCommand.indexOf("LED_ON") != -1)
indexOf() locates a String in a String and returns index or -1 if not found.
See more info about indexOf() here: https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/indexof/

Send Mirf values with ethercard

I have project where I'm getting data over nRF24L01 and using Mirf to that. Now I'm working for Hub which need to send data to my webservice. For ethernet my choice was ENC28j60 with ethercard library.
Question : How I can wait data from Mirf and just send data forward with Ethercard browseUrl? I can send data without Mirf but there's some loop which I'm not understand.
My code :
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <EtherCard.h>
// Set network settings
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
byte Ethernet::buffer[700];
static uint32_t timer;
// My webservice
const char website[] PROGMEM = "my.webservice.com";
// Mirf variables
int tmpVal1;
// Local components
const int Yellow = 6;
const int Blue = 5;
void setup() {
Serial.begin(57600);
// Setup leds
pinMode(Yellow, OUTPUT);
digitalWrite(Yellow, LOW);
pinMode(Blue, OUTPUT);
digitalWrite(Blue, LOW);
setupMirf();
setupEthernet();
}
void loop() {
// Waiting to get date from Mirf
while (!Mirf.dataReady()) {
//ether.packetLoop(ether.packetReceive());
}
Mirf.getData((byte *)&tmpVal1);
Serial.print(tmpVal1);
Serial.println(F(" C"));
// Receive responses
ether.packetLoop(ether.packetReceive());
if (millis() > timer) {
timer = millis() + 5000;
//Serial.println();
Serial.println("Sending data to webservice : ");
ether.browseUrl(PSTR("/sendingdata.asmx/sendingdata?"), "Device=100&DeviceValue=80", website, my_callback);
}
//ShowLedNotification();
}
// called when the client request is complete
static void my_callback (byte status, word off, word len) {
Serial.println(">>>");
Ethernet::buffer[off+300] = 0;
Serial.print((const char*) Ethernet::buffer + off);
Serial.println("...");
digitalWrite(Blue,HIGH);
delay(200);
digitalWrite(Blue,LOW);
}
void ShowLedNotification() {
if (tmpVal1 > 0 ) {
digitalWrite(Yellow, HIGH);
delay(1000);
digitalWrite(Yellow, LOW);
}
else
{
digitalWrite(Blue, HIGH);
delay(1000);
digitalWrite(Blue, LOW);
}
}
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}
//Setting up network and getting DHCP IP
void setupEthernet() {
Serial.println(F("Setting up network and DHCP"));
Serial.print(F("MAC: "));
for (byte i = 0; i < 6; ++i) {
Serial.print(mymac[i], HEX);
if (i < 5)
Serial.print(':');
}
Serial.println();
if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
Serial.println(F("Failed to access Ethernet controller"));
Serial.println(F("Setting up DHCP"));
if (!ether.dhcpSetup())
Serial.println(F("DHCP failed"));
ether.printIp("My IP: ", ether.myip);
ether.printIp("Netmask: ", ether.netmask);
ether.printIp("GW IP: ", ether.gwip);
ether.printIp("DNS IP: ", ether.dnsip);
// Check network connection
if (!ether.dnsLookup(website))
Serial.println("DNS failed");
ether.printIp("SRV: ", ether.hisip);
}
void setupMirf() {
//Initialize nRF24
Serial.println(F("Initializing Mirf"));
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.setRADDR((byte *)"serv1");
Mirf.payload = sizeof(tmpVal1);
// we use channel 90 as it is outside of WLAN bands
// or channels used by wireless surveillance cameras
Mirf.channel = 90;
Mirf.config();
}
Did get that work. Now using if clause not while Mirf.dataReady()
void loop() {
if (Mirf.dataReady()) {
Mirf.getData((byte *)&tmpVal1);
Serial.print(tmpVal1);
Serial.println(F(" C"));
ShowLedNotification();
// Send data to webservice
if (millis() > timer) {
timer = millis() + 5000;
Serial.println("Sending data to webservice");
String myVarsStr = "Device=";
myVarsStr += myDeviceID;
myVarsStr += "&DeviceValue=";
myVarsStr += tmpVal1;
char myVarsCh[40];
myVarsStr.toCharArray(myVarsCh, 40);
ether.browseUrl(PSTR("/receivedata.asmx/ReceiveData?"), myVarsCh, website, my_callback);
}
}
else
{
word pos = ether.packetReceive();
word len = ether.packetLoop(pos);
delay(200);
}
}

DELAY is crashing board if delay duration is greater than 30 seconds?

I have this variable, DELAY_INTERVAL, which I set to measure how long my arduino mega board will delay before submitting a request to my server again.
I've found that when this variable is set to 30 seconds my board runs fine but as soon as I set it to 45 seconds my board crashes.
I've inserted a bunch of printlns for debugging purposes:
void loop() {
Serial.print("Free RAM: ");
Serial.println(getFreeRam(), DEC);
Serial.println(1);
getEC();
Serial.println(2);
getPH();
Serial.println(3);
createPoint(ecSensorString, phSensorString);
Serial.println(4);
delay(DELAY_INTERVAL*1000);
Serial.println(5);
}
Note that this runs indefinitely for 30s but not 45s.
This is what the console outputs on 45s:
Free RAM: 6551
1
getEC:*OK
2
getPH:
3
a
postPointToServer:ec=*OK&ph=&interval=45s
b
c
d
e
f
g
h
4
<output monitor just stalls>
So I have identified that delay is the culprit here. But why and how can I solve this?
The rest of my code if anyone is interested.
void setup() {
//initRGB();
Serial.begin(9600);
ecSensorString.reserve(30);
phSensorString.reserve(30);
initSensors();
initWireless();
Serial.println("Setup Complete");
}
void loop() {
Serial.print("Free RAM: ");
Serial.println(getFreeRam(), DEC);
Serial.println(1);
getEC();
Serial.println(2);
getPH();
Serial.println(3);
createPoint(ecSensorString, phSensorString);
Serial.println(4);
delay(DELAY_INTERVAL*1000);
Serial.println(5);
}
void initWireless() {
/* Initialise the module */
if (!cc3000.begin()) {
Serial.println(F("Couldn't begin()! Check your wiring?"));
//displayRed();
while(1);
}
Serial.println(F("Initialization Complete"));
Serial.print(F("Attempting to connect to "));
Serial.println(WLAN_SSID);
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
//displayRed();
while(1);
}
Serial.println(F("Wireless Connected!"));
/* Wait for DHCP to complete */
while (!cc3000.checkDHCP()) {
delay(100); // ToDo: Insert a DHCP timeout!
}
Serial.println(F("DHCP Requested!"));
if (IP_NOT_DOMAIN) {
ip = cc3000.IP2U32(IP_1, IP_2, IP_3, IP_4);
} else {
ip = 0;
// Try looking up the website's IP address
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
}
}
void initSensors() {
Serial2.begin(38400);
Serial3.begin(38400);
// Tell the EC sensors to stop continuous mode
Serial2.print("c,0\r");
// Tell the pH sensor to stop all readings
Serial3.print("E\r");
// TODO: EC sensor's first reading is always empty, possibly delay?
}
void createPoint(String ec, String ph) {
if (ec && ph) {
postPointToServer("ec=" + ec + "&ph=" + ph);
} else if (ec) {
postPointToServer("ec=" + ec);
} else if (ph) {
postPointToServer("ph=" + ph);
} else {
Serial.println("createPoint: null");
}
}
void postPointToServer(String data) {
Serial.println("a");
char interval_c[20];
sprintf(interval_c, "&interval=%ds", DELAY_INTERVAL);
data += interval_c;
Serial.print("postPointToServer:");
Serial.println(data);
Serial.println("b");
Adafruit_CC3000_Client www = cc3000.connectTCP(ip, PORT);
Serial.println("c");
if (www.connected()) {
www.fastrprint(F("POST ")); www.fastrprint(WEBPAGE); www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r\n"));
Serial.println("d");
String auth_raw = serial + ":" + token;
char auth_input[200];
char auth_output[200];
auth_raw.toCharArray(auth_input, auth_raw.length() + 1);
base64_encode(auth_output, auth_input, auth_raw.length());
www.fastrprint(F("Authorization: Basic ")); www.fastrprint(auth_output); www.fastrprint(F("\r\n"));
www.fastrprint(F("Content-Type: application/x-www-form-urlencoded")); www.fastrprint(F("\r\n"));
Serial.println("e");
char len_c[7];
itoa(data.length(), len_c, 10);
www.fastrprint(F("Content-Length: ")); www.fastrprint(len_c); www.fastrprint(F("\r\n"));
// Extra empty line for post arguments
www.fastrprint(F("\r\n"));
Serial.println("f");
char data_c[200];
data.toCharArray(data_c, data.length() + 1);
www.fastrprint(data_c); www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
//displayGreen();
} else {
Serial.println(F("Connection failed"));
//displayRed();
}
Serial.println("g");
www.close();
Serial.println("h");
}
void getEC() {
ecSensorString = "";
Serial2.print("r\r"); // Read only 1
char inchar;
while (Serial2.available()) {
inchar = (char)Serial2.read();
if (inchar != '\r') {
ecSensorString += inchar;
}
}
Serial.print("getEC:");
Serial.println(ecSensorString);
}
void getPH() {
phSensorString = "";
Serial3.print("R\r"); // Read only 1
char inchar;
while (Serial3.available()) {
inchar = (char)Serial3.read();
if (inchar != '\r') {
phSensorString += inchar;
}
}
Serial.print("getPH:");
Serial.println(phSensorString);
}
I've had the same problem.
Do you need to put an L at the end to make an explicit conversion of this constant into a long integer:
delay(DELAY_INTERVAL*1000L);

Resources