WIFIclient, ArduinJSON and hardware serial stall
Posted: Sun Apr 23, 2023 12:26 pm
Hi,
I have Arduino UNO as a sensor base that collects data and sends them in JSON files over serial communication to ESP8266 NodeMCU (a spinoff called HW-628 V1.1). NodeMCU shows it on display and sends it to a server on my laptop over WIFI.
I first tried sending the data from Arduino to NodeMCU over SoftwareSerial, but I read on the internet that it's not the best practice, and it may cause issues with interrupts and whatnot.
My problem:
The data seems to reach NodeMCU from Arduino at first, but then something happens. The JSON is allegedly deserialized correctly
(I use
but then the json seems to contain all zeros. I thought, it may just fall down to the default values in the struct I use, but that's not the fact, the default struct values are set to 999's etc. Any idea, what this might mean? How do I fix this? Are there any interrupt clashes between Serial and
What I already tried:
I would be thankful for any help, getting desperate here...
The NodeMCU code:
I also attach the Arduino part, but I don't think the problem is there.
An older NodeMCU dump that does not happen anymore (It seems, nodemcu does not restart), might maybe help:
I have Arduino UNO as a sensor base that collects data and sends them in JSON files over serial communication to ESP8266 NodeMCU (a spinoff called HW-628 V1.1). NodeMCU shows it on display and sends it to a server on my laptop over WIFI.
I first tried sending the data from Arduino to NodeMCU over SoftwareSerial, but I read on the internet that it's not the best practice, and it may cause issues with interrupts and whatnot.
My problem:
The data seems to reach NodeMCU from Arduino at first, but then something happens. The JSON is allegedly deserialized correctly
(I use
Code: Select all
)DeserializationError error = deserializeJson(doc, Serial);
but then the json seems to contain all zeros. I thought, it may just fall down to the default values in the struct I use, but that's not the fact, the default struct values are set to 999's etc. Any idea, what this might mean? How do I fix this? Are there any interrupt clashes between Serial and
What I already tried:
- - Using Hardware serial instead of the software one, because NodeMCU often restarted because of Fault(0), invalid instruction
- Using a less memory-demanding library for a display called `U8x8lib.h`
- lowering baud rate to 9600 on both sides
- Adding external voltage input for NodeMCU
- hooking Arduino's and NodeMCU 's ground together
- trying out the serial communication without the WIFI - it works - WIFI seems to do something with memory
- removing any `millis()` functions, since they might cause problems (? i read it somewhere)
- I had some stack dupms from NodeMCU which didn't seem to occur anymore after removing software serial, the translated dump is at the end of this post
I would be thankful for any help, getting desperate here...
The NodeMCU code:
Code: Select all
#include <U8x8lib.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
const char* ssid = "hotspot";
const char* password = "password";
// The IP address and port number of the remote server
const char* serverIP = "10.42.0.1";
const int serverPort = 1880;
const char* urlPath = "/url";
volatile bool START_WATERING = false;
WiFiClient client;
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
StaticJsonDocument<256> doc;
struct Data{
int temp = 99;
int hum = 99;
float dist = 999.9;
int wet = 9999;
int light = 9999;
int co2 = 9999;
bool pump = false;
} data;
struct Data doc2data(struct Data data, StaticJsonDocument<256> doc){
data.temp = doc["temp"];
data.hum = doc["hum"];
data.dist = doc["dist"];
data.wet = doc["wet"];
data.light = doc["light"];
data.co2 = doc["co2"];
data.pump = doc["pump"];
return data;
}
void setup() {
// minimal display setup
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
Serial.begin(9600);
WiFi.begin(ssid, password);
// setup the WIFI client
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void loop() {
data = Data();
DeserializationError error = deserializeJson(doc, Serial);
if (error){
u8x8.clearDisplay();
u8x8.setCursor(4,0);
u8x8.print("| Incorrect Json |");
u8x8.refreshDisplay();
return;
}
else {
data = doc2data(data, doc);
String jsonString;
serializeJson(doc, jsonString);
sendPostRequest(jsonString);
}
drawData(data);
}
void sendPostRequest(String jsonPayload) {
// check for connection
if (!client.connect(serverIP, serverPort)) {
client.stop();
return;
}
// Send the HTTP POST request
client.print(String("POST ") + urlPath + " HTTP/1.1\r\n" +
"Host: " + serverIP + "\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: " + jsonPayload.length() + "\r\n" +
"Connection: close\r\n\r\n" +
jsonPayload + "\r\n");
// Listen for the server's response
int n_of_trials = 5;
int k = 0;
while (client.connected() && k <= n_of_trials){
if (client.available()) {
String response = client.readStringUntil('\r');
k ++;
// delay(100);
if (response.indexOf("water") >= 0) {
START_WATERING = true;
}
}
}
// Close the connection
client.stop();
}
// below continues function `drawData()` for showing on display, I left it out for conciseness
I also attach the Arduino part, but I don't think the problem is there.
Code: Select all
#include "DHT.h"
#include <SPI.h>
#include <stdio.h>
#include <Wire.h>
#include <ArduinoJson.h>
// constants
#define DHTPIN 10
#define DHTTYPE DHT11
#define CO2_INTERRUPT 2
#define ADRESS_CDM_7160 0x69
#define ADRESS_REGISTER 0x03
#define wetPin0 A0
#define lightPin A1
#define echoPin 8
#define trigPin 9
#define pumpPin 3
// DHT 11 sensor variables
DHT dht(DHTPIN, DHTTYPE);
int hum = 0;
int temp = 0;
// CO2 sensor variables
byte co2_lower_bits = 0;
byte co2_upper_bits = 0;
int co2_ppm = 0;
volatile bool sensor_free = true;
const int AVG_BUFFER_SIZE = 5;
float running_average_wet = 0;
int bufferIndex = 0;
float run_avg_arr[AVG_BUFFER_SIZE] = {0};
// Moisture sensor variables
int wetVal0 = 0;
// Light sensor variables
int lightVal = 0;
// Pump variables
bool pump_on = false;
float get_run_avg(float new_meas){
run_avg_arr[bufferIndex] = new_meas;
bufferIndex = (bufferIndex + 1) % AVG_BUFFER_SIZE;
float sum = 0;
for (int i = 0; i < AVG_BUFFER_SIZE; i++){
sum += run_avg_arr[i];
}
float avg = sum / AVG_BUFFER_SIZE;
return avg;
}
void sensor_interrupt() {
sensor_free = true;
}
float echo_distance(){
// Clears the trigPin condition
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin HIGH (ACTIVE) for 10 microseconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
float duration = pulseIn(echoPin, HIGH);
// Calculating the distance
float distance = (duration * 0.034) / 2; // Speed of sound wave divided by 2 (go and back)
return distance;
}
StaticJsonDocument<256> doc;
StaticJsonDocument<256> get_doc;
void setup() {
// pinmodes
pinMode(CO2_INTERRUPT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(CO2_INTERRUPT), sensor_interrupt, FALLING );
Wire.begin();
pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
pinMode(echoPin, INPUT); // Sets the echoPin as an
pinMode(pumpPin, OUTPUT);
Serial.begin(9600);
dht.begin();
}
void loop() {
delay(100);
DeserializationError error = deserializeJson(get_doc, Serial);
hum = dht.readHumidity();
temp = dht.readTemperature();
wetVal0 = analogRead(wetPin0);
lightVal = analogRead(lightPin);
float distance = echo_distance();
if (isnan(hum) || isnan(temp)) {
return;
}
running_average_wet = get_run_avg(float(wetVal0));
if (running_average_wet > 850.0){
pump_on = true;
digitalWrite(pumpPin, HIGH);
}
else {
pump_on = false;
digitalWrite(pumpPin, LOW);
}
// CO2 sensor
if (sensor_free) {
Wire.beginTransmission(ADRESS_CDM_7160); // verified with I2C scanner
Wire.write(ADRESS_REGISTER);
Wire.endTransmission();
Wire.requestFrom(ADRESS_CDM_7160, 2); // request 2 bytes
co2_lower_bits = Wire.read();
co2_upper_bits = Wire.read();
co2_ppm = (co2_upper_bits << 8) | co2_lower_bits; //lower + upper shifted by 8 = resulting ppm
co2_ppm += 200; // offeset
}
doc["hum"] = hum;
doc["temp"] = temp;
doc["wet"] = int(running_average_wet);
doc["light"] = lightVal;
doc["dist"] = distance;
doc["co2"] = co2_ppm;
doc["pump"] = pump_on;
serializeJson(doc, Serial);
}
An older NodeMCU dump that does not happen anymore (It seems, nodemcu does not restart), might maybe help:
Code: Select all
Exception 0: Illegal instruction
PC: 0x4020a288: read_encoded_value_with_base at /workdir/repo/gcc-gnu/libgcc/unwind-pe.h line 251
EXCVADDR: 0x00000000
Decoding stack results
0x40100b3c: umm_malloc_core(umm_heap_context_t*, size_t) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 809
0x40100a78: umm_malloc_core(umm_heap_context_t*, size_t) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 746
0x40100600: puts(char const*) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/libc_replacements.cpp line 113
0x40100a78: umm_malloc_core(umm_heap_context_t*, size_t) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 746
0x402167a1: autoip_arp_reply at core/ipv4/autoip.c line 472
0x401000ab: app_entry_redefinable() at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_main.cpp line 386
0x40100b3c: umm_malloc_core(umm_heap_context_t*, size_t) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 809
0x40100a78: umm_malloc_core(umm_heap_context_t*, size_t) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 746
0x402114e7: dns_setserver at core/dns.c line 364
0x40100600: puts(char const*) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/libc_replacements.cpp line 113
0x40100600: puts(char const*) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/libc_replacements.cpp line 113
0x402112b9: dns_recv at core/dns.c line 1235
0x402114e7: dns_setserver at core/dns.c line 364
0x40211946: netif_add_LWIP2 at core/netif.c line 340
0x40218c74: ip_napt_new_port at core/ipv4/ip4.c line 500
0x40218d48: ip_napt_add at core/ipv4/ip4.c line 583
0x4021a6b8: sntp_send_request at apps/sntp/sntp.c line 558
0x4021a720: sntp_request at apps/sntp/sntp.c line 617
0x402121fd: raw_input at core/raw.c line 178
0x4021a746: sntp_request at apps/sntp/sntp.c line 627
0x40206a84: __stack_chk_fail() at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_postmortem.cpp line 321
0x40206bd9: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 201
0x40206c4e: Twi::write_start() at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 280
0x4020478c: ClientContext::wait_until_acked(int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/libraries/ESP8266WiFi/src/include/ClientContext.h line 352
0x4020487f: ClientContext::_write_from_source(char const*, unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/libraries/ESP8266WiFi/src/include/ClientContext.h line 529
0x40206b32: Twi::eventTask(ETSEventTag*) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 699
0x4020478c: ClientContext::wait_until_acked(int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/libraries/ESP8266WiFi/src/include/ClientContext.h line 352
0x40203f1c: std::swap (std::_Any_data&, std::_Any_data&) at /home/andrej/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-lx106-elf/include/c++/10.3.0/bits/move.h line 189
0x4020a860: search_object at /workdir/repo/gcc-gnu/libgcc/unwind-dw2-fde.c line 999
0x4020a860: search_object at /workdir/repo/gcc-gnu/libgcc/unwind-dw2-fde.c line 999
0x40205c04: String::copy(char const*, unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/WString.cpp line 258
0x402031f7: ArduinoJson::V6210PB::detail::TextFormatter >::writeFloat (double) at /home/andrej/Arduino/libraries/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp line 165
0x40202a82: ArduinoJson::V6210PB::detail::JsonDeserializer , ArduinoJson::V6210PB::detail::StringCopier>::parseVariant (ArduinoJson::V6210PB::detail::VariantData&, ArduinoJson::V6210PB::detail::AllowAllFilter, ArduinoJson::V6210PB::DeserializationOption::NestingLimit) at /home/andrej/Arduino/libraries/ArduinoJson/src/ArduinoJson/Variant/VariantData.hpp line 321
0x402066bc: ets_printf_P(char const*, ...) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_postmortem.cpp line 97
0x40202ab2: ArduinoJson::V6210PB::detail::JsonDeserializer , ArduinoJson::V6210PB::detail::StringCopier>::parseVariant (ArduinoJson::V6210PB::detail::VariantData&, ArduinoJson::V6210PB::detail::AllowAllFilter, ArduinoJson::V6210PB::DeserializationOption::NestingLimit) at /home/andrej/Arduino/libraries/ArduinoJson/src/ArduinoJson/Variant/SlotFunctions.hpp line 43
0x40206505: dtostrf(double, signed char, unsigned char, char*) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_noniso.cpp line 76
0x4020352d: sendPostRequest(String) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/libraries/ESP8266WiFi/src/WiFiClient.h line 88
0x40100b3c: umm_malloc_core(umm_heap_context_t*, size_t) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 809
0x40206bd9: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 201
0x40100a78: umm_malloc_core(umm_heap_context_t*, size_t) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 746
0x40208ab7: DhcpServer::parse_options(unsigned char*, short) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/LwipDhcpServer.cpp line 644
0x40206bd9: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 201
0x40206c15: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 215
0x40206c15: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 215
0x40206c15: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 215
0x40206c15: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 215
0x40206c15: Twi::setClock(unsigned int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_si2c.cpp line 215
0x40207a38: uart_set_baudrate(uart_t*, int) at /home/andrej/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/uart.cpp line 606