FreeRTOS Task for UART communication - c++

I'm developing a program, which receives commands via UART. My idea was to create a FreeRTOS Task, which runs during the complete program lifecycle and is responsible only for receiving uart messages, interprets them and sends a command into a queue.
I tested this with the built-in Serial functions, before writing my own UART functions.
/*========== Static Function Implementations ================================*/
static void uartControllerTaskLoop(void *pvParameters)
{
Serial.begin(115200);
Serial.println("Start Task");
for (;;)
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval)
{
Serial.println("Start Task loop");
previousMillis = currentMillis;
}
}
}
/*========== Extern Function Implementations ================================*/
extern void uartControllerCreateTask()
{
xTaskCreate(uartControllerTaskLoop, "uartControllerTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
}
When running this code I get the following error:
Guru Meditation Error: Core 1 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x800d0eee PS : 0x00050a33 A0 : 0x800d0eee A1 : 0x3ffb2780
A2 : 0x3ffb27c0 A3 : 0x3ffb9818 A4 : 0x00000158 A5 : 0x00000000
A6 : 0x3ffb89dc A7 : 0x400d0ef4 A8 : 0x00000000 A9 : 0x800d1209
A10 : 0x3ffb2800 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x3ffb9818
A14 : 0x00000001 A15 : 0x00000000 SAR : 0x00000000 EXCCAUSE: 0x00000014
EXCVADDR: 0x800d0eec LBEG : 0x3ffb9408 LEND : 0x00000400 LCOUNT : 0x3ffc155c
When I start the Serial communication with Serial.begin()from outside the Task the program works fine. For me this is a little bit ugly, because I wanted to have all UART dependend stuff within the Task.
What are here the best practices? Leave the setup of the UART outside the Task or find a way to set up the UART within the task?
Thanks!

I switched from the Arduino framwork to the espidf framework.
Using then the uart driver from espressif let's me install the uart driver within a task.
#include "driver/uart.h"
#include "esp_log.h"
static const char *TAG = "example";
static void uartController(void *pvParameters)
{
int64_t previousMillis = 0UL;
int64_t interval = 1000000UL;
// configure the UART peripheral
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
};
uart_param_config(UART_NUM_0, &uart_config);
uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(UART_NUM_0, 256, 0, 0, NULL, 0);
for (;;)
{
int64_t currentMillis = esp_timer_get_time();
// print messages to the serial monitor
if (currentMillis - previousMillis > interval)
{
char my_char_array[20];
snprintf(my_char_array, sizeof(my_char_array), "%lld", currentMillis);
ESP_LOGI(TAG, "%s", my_char_array);
ESP_LOGI(TAG, "This is an informational message.");
ESP_LOGW(TAG, "This is a warning message.");
ESP_LOGE(TAG, "This is an error message.");
previousMillis = currentMillis;
}
vTaskDelay(1);
}
}
void app_main()
{
xTaskCreate(uartController, "uartController", 4096, NULL, 1, NULL);
}

Related

ESP32 - How to make a PubSubClient function in a utils file that connects to AWS IoT Core [duplicate]

This question already has an answer here:
Platformio C++ multiple "multiple definition of"
(1 answer)
Closed 19 days ago.
I want to make a function that uses PubSubClient and WifiClientSecure to connect to AWS MQTT broker, and I want to define it in a separate file so I can reuse it, but the ESP32 is crashing every time the code runs.
I want to reuse this function I found in this tutorial in a iot_utils.cpp file, instead of definining it in the main file. When i define it in the main file, it works fine, but thats not what i want to do.
This is the function in the tutorial:
WiFiClientSecure net = WiFiClientSecure();
PubSubClient client(net);
 
void connectAWS()
{
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.println("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Configure WiFiClientSecure to use the AWS IoT device credentials
net.setCACert(AWS_CERT_CA);
net.setCertificate(AWS_CERT_CRT);
net.setPrivateKey(AWS_CERT_PRIVATE);
// Connect to the MQTT broker on the AWS endpoint we defined earlier
client.setServer(AWS_IOT_ENDPOINT, 8883);
// Create a message handler
client.setCallback(messageHandler);
Serial.println("Connecting to AWS IOT");
while (!client.connect(THINGNAME)) {
Serial.print(".");
delay(100);
}
if (!client.connected()) {
Serial.println("AWS IoT Timeout!");
return;
}
// Subscribe to a topic
client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);
Serial.println("AWS IoT Connected!");
}
I dont want to use it in the main file, instead, i want to put it in a separate file.
To do this, i made the corresponding header and src file, and in the iot_utils.cpp file I defined the function like this:
void connectAWS(WiFiClientSecure& net, PubSubClient& client, const char* topic) {
// the code here...
}
But when in my main file, I call it like this:
WiFiClientSecure net = WiFiClientSecure();
PubSubClient client(net);
void setup() {
connectAWS(net, client, "esp32/pub");
}
The ESP32 crashes with the following information:
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
Connecting to Wi-Fi
.Connecting to AWS IOT
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x4015b50c PS : 0x00060f30 A0 : 0x800d3bba A1 : 0x3ffb26f0
A2 : 0x3ffc2c74 A3 : 0x3f4050f9 A4 : 0x00000015 A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x800d78a6 A9 : 0x3ffb2700
A10 : 0x000003e8 A11 : 0x3f4050f9 A12 : 0x00000002 A13 : 0x0000ff00
A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000017 EXCCAUSE: 0x0000001c
EXCVADDR: 0x000003e8 LBEG : 0x40089729 LEND : 0x40089739 LCOUNT : 0xfffffffa
Backtrace:0x4015b509:0x3ffb26f00x400d3bb7:0x3ffb2710 0x400d3de2:0x3ffb2750 0x400d3915:0x3ffb2780 0x400d3819:0x3ffb27a0 0x400d877e:0x3ffb2820
What am I doing wrong? I just want to reuse the connectAWS in other files, so i dont have to copy-paste it every time
I realized how to do it, and it is declaring net and client in theiot_utils.hpp header file, and defining them in iot_utils.cpp source file, just like this:
iot_utils.hpp
#ifndef iot_utils
#define iot_utils
#include "WiFi.h"
#include <ArduinoJson.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>
// The reason why net and client are both in the header and in the source: https://stackoverflow.com/questions/74729454/platformio-c-multiple-multiple-definition-of
extern WiFiClientSecure net;
extern PubSubClient client;
void connectAWS();
#endif
iot_utils.cpp
#include "iot_utils.hpp"
#include "leds_secrets.h"
// The reason why net and client are both in the header and in the source: https://stackoverflow.com/questions/74729454/platformio-c-multiple-multiple-definition-of
WiFiClientSecure net = WiFiClientSecure();
PubSubClient client(net);
void connectAWS()
{
(...)
}
And then just including "iot_utils.hpp" in my main file

ESP32: Getting Guru Meditation Error because having an extremly long string (~15.000 characters long)

I've written a little program, which in a loop first sends a POST-request to a special machine, the machine returns an other API-path in its response header, afterwards I can execute a GET-request on that API path and get an extremly long string (~ about 15.000 characters). This works pretty fine - the string is returned and I can print it afterwards. But then something really strange happens: After each print of the string, my ESP seems to restart somewhy. Please see Output:
005 03.07. 08:25
========================
ENDE NC NL
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x4015c44c PS : 0x00060430 A0 : 0x800d30f2 A1 : 0x3ffb1dc0
A2 : 0x3ffb1f10 A3 : 0x00000000 A4 : 0x00003de8 A5 : 0x00003de8
A6 : 0x3ffd9098 A7 : 0x00003de8 A8 : 0x800d5105 A9 : 0x3ffb1da0
A10 : 0x3ffd7938 A11 : 0x3f4015a2 A12 : 0x00000002 A13 : 0x0000ff00
A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000010 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x4015c44c:0x3ffb1dc0 0x400d30ef:0x3ffb1de0 0x400d3161:0x3ffb1e00 0x400d1ae2:0x3ffb1e20 0x400d6301:0x3ffb1fb0 0x40088b9d:0x3ffb1fd0
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac
Connecting
ENDE NC NL is the last line of the string, one line is maximal 24 characters long and ends with \n (LF), the program starts with Connecting.
If I do not print the string directly, but first do some string "manipulation" operations and than try to print the manipulation result, the first 2 or 3 rounds the Guru Meditation Error is shown, then suddenly the ouput changes to the following:
Connecting
..
Connected to WiFi network with IP Address: 192.168.200.244
Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.
POST-Request to: https://192.168.200.101/api/vdai-daten
HTTP Response code: 201
Header Payload: /api/vdai-daten/vdai-daten.txt
=> GET-Request to: https://192.168.200.101/api/vdai-daten/vdai-daten.txt
2nd HTTP Response code: 200
Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception)
Debug exception reason: Stack canary watchpoint triggered (loopTask)
Core 1 register dump:
PC : 0x400d55b4 PS : 0x00060236 A0 : 0x800d57e9 A1 : 0x3ffaf5c0
A2 : 0x3ffb005c A3 : 0x00000025 A4 : 0x00000000 A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x80000000 A9 : 0x3ffaf5a0
A10 : 0x3ffb0050 A11 : 0x3f4016d2 A12 : 0x00000001 A13 : 0x3ffb1cc0
A14 : 0x00000000 A15 : 0x3ffb0060 SAR : 0x0000000a EXCCAUSE: 0x00000001
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000
Backtrace: 0x400d55b4:0x3ffaf5c0 0x400d57e6:0x3ffaf5e0 0x400d1afd:0x3ffaf600 0x400d63e9:0x3ffb1fb0 0x40088b9d:0x3ffb1fd0
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac
Connecting
..
Connected to WiFi network with IP Address: 192.168.200.244
Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.
POST-Request to: https://192.168.200.101/api/vdai-daten
HTTP Response code: 201
Header Payload: /api/vdai-daten/vdai-daten.txt
=> GET-Request to: https://192.168.200.101/api/vdai-daten/vdai-daten.txt
2nd HTTP Response code: 200
***ERROR*** A stack overflow in task loopTask has been detected.
abort() was called at PC 0x4008c69c on core 1
Backtrace: 0x4008c454:0x3ffaf430 0x4008c685:0x3ffaf450 0x4008c69c:0x3ffaf470 0x40089768:0x3ffaf490 0x4008b3cc:0x3ffaf4b0 0x4008b382:0x833dcfb1
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac
Connecting
Anyone had something like this before or can explain what is happening/wrong and how I can handle / deal with this 15.000 characters long string?^^
Would be really happy for every answer,
Best regards
P.S.: Please finally let me add my code... the commented part is the string "manipulation" part.
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "MyWiFiName";
const char* password = "MyWiFiPassword";
const char* serverName = "https://192.168.200.101/api/vdai-daten";
unsigned long lastTime = 0;
unsigned long timerDelay = 5000;
const char * headerKeys[] = {"HeaderKey"} ;
const size_t numberOfHeaders = 1;
String payload;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}
void loop() {
if ((millis() - lastTime) > timerDelay) {
//Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
HTTPClient http;
Serial.print("POST-Request to: ");
Serial.println(serverName);
http.begin(serverName);
http.collectHeaders(headerKeys, numberOfHeaders);
http.setAuthorization("Username", "Password");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Send HTTP POST request
int httpResponseCode = http.POST("kassierung=false");
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String headerServer = http.header("HeaderKey");
Serial.print("Header Payload: ");
Serial.println(headerServer);
// Free resources
http.end();
HTTPClient http2;
String newServerName = "https://192.168.200.101" + headerServer;
Serial.print("=> GET-Request to: ");
Serial.println(newServerName);
http2.begin(newServerName.c_str());
http2.setAuthorization("Username", "Password");
httpResponseCode = http2.GET();
Serial.print("2nd HTTP Response code: ");
Serial.println(httpResponseCode);
Serial.println("=> Big string: ");
payload = http2.getString();
Serial.println(payload);
/*
//Count amount of lines
int counter = 0;
for (int i=0; i < payload.length(); i++){
if(payload.charAt(i) == '\n'){
counter++;
}
}
//Divide big string into a array, where each entry is one line
String sa[counter];
int r=0;
int t=0;
for (int i=0; i < payload.length(); i++){
if(payload.charAt(i) == '\n') {
sa[t] = payload.substring(r, i);
r=(i+1);
t++;
}
}
Serial.println("=> First line: ");
Serial.println(sa[0]);
*/
http2.end();
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}
It's clearly a stack overflow issue!
Either use malloc'ed memory for storing string instead OR increase task stack size for loopTask to about 20K.

Atmega328P+ENC28J60 freezes after 12 hours operation

I am quite new to the ethernet world. So please bear with me if I do ask stupid questions.
I designed a PCB using Atmega328P+ENC28J60 chip (schematic attached in the images below - sch1, sch2). The function of this board is basically sending GET requests to the server and retrieve a set of json data to turn on output pins, so based on my understanding my board acts as a client only right? The code is attached below:
#include <EEPROM.h>
#include <ArduinoJson.h>
#include <EthernetENC.h>
#define OUT0 2
#define OUT1 A3
#define OUT2 A2
#define OUT3 A1
#define OUT4 A0
#define OUT5 9
#define OUT6 8
#define OUT7 7
#define OUT8 6
#define OUT9 5
#define CS 10
// mac: 46 57 5a 6b 48 51
#define HOSTNAME "autolighting.afa-sports.com"
#define ID_SIZE 6
static byte mac[ID_SIZE];
static char macBuffer[ID_SIZE*2+1];
const byte output[] PROGMEM = {OUT0, OUT1, OUT2, OUT3, OUT4, OUT5, OUT6, OUT7, OUT8, OUT9};
EthernetClient client;
void clientRead() {
StaticJsonDocument<40> filter;
StaticJsonDocument<120> doc;
filter.clear();
doc.clear();
filter["data"]["relay_actions"] = true;
client.find("\r\n\r\n");
deserializeJson(doc, client, DeserializationOption::Filter(filter));
client.flush();
delay(50);
if (!doc["data"]["relay_actions"].isNull()) {
for (byte i = 0; i < 10; i++) {
// Serial.print(doc["data"]["relay_actions"][i].as<bool>());
digitalWrite(pgm_read_byte_near(&output[i]), doc["data"]["relay_actions"][i].as<bool>());
}
// Serial.println();
}
filter.clear();
doc.clear();
}
void sendReq() {
client.println(F("GET /api/iot/master-controller/get-command HTTP/1.1"));
client.println(F("Host: autolighting.afa-sports.com"));
// client.println(F("DEVICE-ID: 46575a6b4851"));
client.print(F("DEVICE-ID: "));
client.println(macBuffer);
client.println(F("Connection: close"));
client.println();
}
void setup() {
Serial.begin(115200);
for (byte i = 0; i < 10; i++) {
pinMode(pgm_read_byte_near(&output[i]), OUTPUT);
digitalWrite(pgm_read_byte_near(&output[i]), LOW);
}
for (uint8_t i = 0; i < ID_SIZE; i++) {
byte charByte = EEPROM.read(i);
if (charByte != 0) {
char temp[2];
mac[i] = charByte;
itoa(mac[i], temp, 16);
strcat(macBuffer, strlwr(temp)); // REMOVE strlwr IN RELEASE VERSION
free(temp);
delay(10);
}
}
strcat(macBuffer, '\0');
Ethernet.init(CS);
while (!Ethernet.begin(mac));
client.setTimeout(5000);
delay(1000);
}
void loop() {
while (!Ethernet.begin(mac)); // init fail
delay(1000);
if (client.connect(HOSTNAME, 80)) {
sendReq();
clientRead();
client.stop();
}
delay(3000);
}
Due to the high SRAM consumption and I might have other things (not sure what yet) to add in to the board in the future, I tried to minimize the dynamic memory by changing this (in the uipethernet-conf.h file):
#define UIP_SOCKET_NUMPACKETS 5
#define UIP_CONF_MAX_CONNECTIONS 4
#define UIP_CONF_UDP_CONNS 4
to this:
#define UIP_SOCKET_NUMPACKETS 2
#define UIP_CONF_MAX_CONNECTIONS 2
#define UIP_CONF_UDP_CONNS 1
I'm wondering will this affect the system performance? Btw, I've also set the timeout to 5s
After 13 hours of smooth operation, the board freezes and only became normal when i hard-reset the board. Currently, I'm connecting my board to a wireless extender, because I am not sitting right next to the wifi router. It looks like a memory leakage issue to me, but does memory leakage issue still exists in the latest ArduinoJson and EthernetENC/UIPEthernet library?
P/S: I was using UIPEthernet.h previously, but someone guided me to try out the EthernetENC library, the memory consumption definitely gone down a little bit, but the freezing problem still persist
Feel free to point out any mistakes I make, still in the learning adventure. =)
Your help is greatly appreciated. Thank you very much.
Library version:
ArduinoJson 6.17.2
EthernetENC 2.0.0
UIPEthernet 2.0.9
Schematics:
don't have these hardware, only analyses based on your code and Arduino references.
from your code
while (!Ethernet.begin(mac)); // init fail
which "may" cause freeze if :
Ethernet.begin always return false
is Ethernet.begin "ok" to call multiple time ?
These are some reference which may help :
Arduino DHCP failed to configure
https://electronics.stackexchange.com/questions/67045/ethernet-begin-only-works-with-sd-card-removed-why
according to the wiki :
https://github.com/jandrassy/EthernetENC/wiki/Examples
You should use :
Ethernet.maintain();
client.available();
write your own delay function :
void mDelay(unsigned long milliseconds) {
const unsigned d = 1;
while (milliseconds > d) {
Ethernet.maintain();
delay(d);
milliseconds -= d;
}
Ethernet.maintain();
delay(milliseconds);
}
note: for arduino or electronics question, may be
https://electronics.stackexchange.com/
is a more suitable site.
not sure about if the hardware can handle, you may try to "burst test" :
void loop() {
unsigned long currentMillis = millis();
Serial.print("Time: ");
Serial.println(currentMillis);
// burst test
if (client.connect(HOSTNAME, 80)) {
sendReq();
Serial.print(", After sendReq(); ");
clientRead();
Serial.print(", After client.clientRead(); ");
client.stop();
Serial.print(", After client.stop(); ");
}
mdelay( 500 );
Serial.println( ', mdelay(500); ' );
// mdelay will call Ethernet.maintain();
// Serial.print("After Ethernet.maintain(); ");
// use Serial.println to check where it freeze ?
}
based on your code, may be these can help to reduce memory problem :
move these two outside of void clientRead() as these 2 used every 4 seconds :
4 sec * 60 = 240 times / minutes
240 * 24 = 5760 times / day
StaticJsonDocument<40> filter;
StaticJsonDocument<120> doc;
void clientRead() {
...
note: all the code are illustration, not tested. you may need to modify to make it work.
note: please check with your hardware if it can handle, or will it burn when run such test ?
lots of thanks to #ocrdu and #Flash Ang for the suggestions, the code below is the working code and my PCB has been running continuously for 58 hours till now:
#include <EEPROM.h>
#include <ArduinoJson.h>
//#include <UIPEthernet.h>
#include <EthernetENC.h>
#define OUT0 2
#define OUT1 A3
#define OUT2 A2
#define OUT3 A1
#define OUT4 A0
#define OUT5 9
#define OUT6 8
#define OUT7 7
#define OUT8 6
#define OUT9 5
#define CS 10
// host name: "autolighting.afa-sports.com
// resource: "/api/iot/master-controller/get-command"
// mac: 46 57 5a 6b 48 51
// mac (char): FWZkHQ
#define HOSTNAME "autolighting.afa-sports.com"
#define ID_SIZE 6
static byte mac[ID_SIZE];
static char macBuffer[ID_SIZE*2+1];
const byte output[] PROGMEM = {OUT0, OUT1, OUT2, OUT3, OUT4, OUT5, OUT6, OUT7, OUT8, OUT9};
EthernetClient client;
void clientRead() {
StaticJsonDocument<40> filter;
StaticJsonDocument<120> doc;
filter.clear();
doc.clear();
filter["data"]["relay_actions"] = true;
client.find("\r\n\r\n");
deserializeJson(doc, client, DeserializationOption::Filter(filter));
client.flush();
delay(50);
if (!doc["data"]["relay_actions"].isNull()) {
for (byte i = 0; i < 10; i++) {
// Serial.print(doc["data"]["relay_actions"][i].as<bool>());
digitalWrite(pgm_read_byte_near(&output[i]), doc["data"]["relay_actions"][i].as<bool>());
}
// Serial.println();
}
filter.clear();
doc.clear();
}
void sendReq() {
client.println(F("GET /api/iot/master-controller/get-command HTTP/1.1"));
client.println(F("Host: autolighting.afa-sports.com"));
// client.println(F("DEVICE-ID: 46575a6b4851"));
client.print(F("DEVICE-ID: "));
client.println(macBuffer);
client.println(F("Connection: close"));
client.println();
}
void setup() {
for (byte i = 0; i < 10; i++) {
pinMode(pgm_read_byte_near(&output[i]), OUTPUT);
digitalWrite(pgm_read_byte_near(&output[i]), LOW);
}
for (uint8_t i = 0; i < ID_SIZE; i++) {
byte charByte = EEPROM.read(i);
if (charByte != 0) {
char temp[2];
mac[i] = charByte;
itoa(mac[i], temp, 16);
strcat(macBuffer, strlwr(temp)); // REMOVE strlwr IN RELEASE VERSION
free(temp);
delay(10);
}
}
strcat(macBuffer, '\0');
Ethernet.init(CS);
while (!Ethernet.begin(mac));
client.setTimeout(5000);
delay(1000);
}
void loop() {
Ethernet.maintain();
while (!Ethernet.begin(mac)) //Serial.println(F("IF")); // init fail
// Serial.println(F("IS")); // init success
delay(1000);
if (client.connect(HOSTNAME, 80)) {
sendReq();
clientRead();
client.stop();
}
Ethernet.maintain();
delay(3000);
}
//int freeRam () { // check remaining RAM space
// extern int __heap_start, *__brkval;
// int v;
// return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
//}
This time to work smart, I used the default ip address to my router and monitor whether my PCB is still connected to the router by looking at the DHCP client list, and remove all the serial commands in the code. I'm afraid for my past experiences on the disconnection issues, it might be just a short temporary disconnect from the router, instead of a permanent disconnection.
I'm sorry if there is any lack of testing in this program. Thank you for the time spent to provide me all the useful suggestions =)

How to fix Guru Meditation Error: Core 1 panic'ed (LoadProhibited) error

I am trying to write code for the ESP32 chip where it takes in readings from a DHT22 sensor, packages it into a json file, and then sends it to a Flask server. Everything works just fine up until I try to POST, where I get the following error:
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400d3488 PS : 0x00060030 A0 : 0x800d355c A1 : 0x3ffb1bb0
A2 : 0x00000000 A3 : 0x3ffb1bff A4 : 0x00000001 A5 : 0x00000001
A6 : 0x00000000 A7 : 0x00000000 A8 : 0x00000000 A9 : 0x00000000
A10 : 0x00000000 A11 : 0x3ffcb8fc A12 : 0x00000050 A13 : 0x00000001
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000008 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff
I have tried an exhaustive search on this issue to no avail, and I have no idea what is going on. Would anyone be able to give insight on how to fix this issue?
This is my Arduino code:
#include <HTTPClient.h>
#include <WiFi.h>
#include <DHT.h>
#include <ArduinoJson.h>
#define DHTTYPE DHT22
const char* ssid = "ssid";
const char* password = "password";
uint8_t sensor = 16;
DHT dht(sensor, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected!");
}
void loop() {
if(WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin("http://192.168.10.5:8090/");
http.addHeader("Content-Type", "text/plain");
Serial.println("Began http on Flask");
const int cap = JSON_OBJECT_SIZE(2);
StaticJsonDocument<cap> doc;
Serial.println("Created json document");
doc["temperature"] = dht.readTemperature();
doc["humidity"] = dht.readHumidity();
Serial.println("Read temperature and humidity correctly");
char output[256];
serializeJsonPretty(doc, output);
Serial.println(output);
//Code will give back error after trying to POST
int httpCode = http.POST(output);
Serial.println("Got httpCode");
if(httpCode > 0) {
Serial.println(httpCode);
} else Serial.println("Error in Connection");
http.end();
}
delay(10000);
}
There are print statements here that will print out various things depending on how far it gets into the code. It prints out the json document just fine, but does not print out "Got httpCode". Below is my code for the Flask server:
from flask import Flask, request
app = Flask(__name__)
#app.route('/', methods = ['POST'])
def hello():
req = request.get_json()
print(req)
return "Thanks", 200
if __name__ == "__main__":
app.run(host = '0.0.0.0', port = 8090)
Thank you in advance for the help.
I also got this error while using WebSockets.
It turned out that the buffer(declared globally) that I used for receiving messages was appending new messages instead of overwriting the pre-existing contents in it. So, an illegal memory-write attempt was made and the device panicked and rebooted.
Solution:
I simply declared the buffer locally inside the onWebSocketEvent() function and the problem of overwriting was solved as the buffer was getting re-declared on every event preventing illegal memory-write attempt. The device never panicked ever again.
I experienced a Guru error in the middle of a callback, the reason for that is because the micro is running out of memory. The solution was getting rid of unused libraries and using pointers instead of creating local variables.

I2C addresses > 63 are not usable with atTiny85

Hi I have a big problem with addressing multiple attiny85-chips with I2C:
For what I know the attiny uses 7-bit addresses for communication. I am using the TinyWireS lib, which works perfectly fine for me, untill I am reaching address: '64' which is '1000000' in binary. The highest usable address should be '1111111'.
This is what happens:
Slave:
Attiny85: switches led on or off when msg is received over I2C.
Slaveaddress: 64
#include <TinyWireS.h>
#include <usiTwiSlave.h>
#define output (4)
#define I2C_SLAVE_ADDR (64) //works if I2C_SLAVE_ADDR < 64
void setup() {
TinyWireS.begin(I2C_SLAVE_ADDR);
pinMode(output, OUTPUT);
}
volatile bool state = LOW;
void loop() {
byte msg = -1;
if(TinyWireS.available())
msg = TinyWireS.receive();
if(msg == 1)
state = HIGH;
else if(msg == 0)
state = LOW;
else if(msg == 2)
state = !state;
digitalWrite(output, state);
}
Master:
Arduino pro mini:
sendMsg(0, true); //works! led on chip: 64 switches on
sendMsg(64, true); //fails! led on chip: 64 is off.
#include <Wire.h>
#define DEVICE (64) //0 works!
void setup() {
Wire.begin();
}
void loop() {
sendMsg(1, DEVICE);
delay(2000);
sendMsg(0, DEVICE);
delay(2000);
}
void sendMsg(int msg, int device) {
Wire.beginTransmission(device);
Wire.write(msg);
Wire.endTransmission();
}
Have you any idea how to solve this problem?
TinyWireS version I am using: https://github.com/rambo/TinyWire/tree/master/TinyWireS