Hey all. I am having some trouble with a project of mine. It's a little weather station with Davis Instruments sensor connected to an Arduino Nano and a BME280 connected to an ESP32. I am using the ArduinoJSON Library to serialize all the Davis Instruments values, send them to the ESP32 and then the ESP32 deserializes the values and posts them to an MQTT server. I am getting an error in the serial console of the ESP32 and I have no idea what it means or how to solve it. I would really appreciate some help.
The error that shows in the serial console:
Stack smashing protect failure!
abort() was called at PC 0x400e1bd8 on core 1
Backtrace:0x40083e2d:0x3ffb25600x4008bcf1:0x3ffb2580 0x40090f39:0x3ffb25a0 0x400e1bd8:0x3ffb2620 0x400d2f43:0x3ffb2640 0x400d30ca:0x3ffb2690 0x400d3812:0x3ffb26b0 0x400d92fd:0x3ffb2820
ELF file SHA256: 0000000000000000
After it displays this, it reboots, waits a few seconds and does it again. I've tried with
The code for the Arduino Nano:
#include "TimerOne.h" // Timer Interrupt set to 2.5 second for read sensors
#include <math.h>
#include <util/atomic.h>
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
SoftwareSerial nodemcu(5, 6);
#define WindSensorPin (3) // The pin location of the anemometer sensor
#define WindVanePin (A4) // The pin the wind vane sensor is connected to
#define VaneOffset 0 // define the anemometer offset from magnetic north
#define RainBucketPin (2) // Pin of the bucket
int VaneValue; // raw analog value from wind vane
int Direction; // translated 0 - 360 direction
volatile long LastValue = 0;
volatile bool IsSampleRequired = false; // this is set true every 2.5s. Get wind speed
volatile unsigned int TimerCount = 0; // used to determine 2.5sec timer count
volatile unsigned long Rotations = 0; // cup rotation counter used in interrupt routine
volatile unsigned long ContactRotationTime; // Timer to avoid contact bounce in interrupt routine
volatile unsigned long Tippings = 0;
volatile unsigned long ContactTippingTime; // Timer to avoid contact bounce in interrupt routine
volatile unsigned long CalDirection = 0; // converted value with offset applied
volatile uint32_t tl = 0;
String getHeading(int direction);
String getWindStrength(float speed);
void setup() {
LastValue = 0;
IsSampleRequired = false;
TimerCount = 0;
Rotations = 0; // Set Rotations to 0 ready for calculations
ContactRotationTime = millis();
Tippings = 0;
ContactTippingTime = millis();
Serial.begin(9600);
nodemcu.begin(9600);
delay(1000);
Serial.println("Program started");
pinMode(WindSensorPin, INPUT);
attachInterrupt(digitalPinToInterrupt(WindSensorPin), isr_rotation, LOW);
pinMode(RainBucketPin, INPUT);
attachInterrupt(digitalPinToInterrupt(RainBucketPin), isr_tipping, LOW);
tl = millis();
// Setup the timer intterupt
Timer1.initialize(500000);
Timer1.attachInterrupt(isr_timer);
}
void loop() {
uint32_t tn = millis();
uint32_t T = 0;
getWindDirection();
// Only update the display if change greater than 5 degrees.
if (abs(CalDirection - LastValue) > 5)
{
LastValue = CalDirection;
}
if (IsSampleRequired)
{
float WindSpeed = 0.0;
float TotalRain = 0.0;
float WindDirection = 0.0;
// Using formula V=P(2.25/T)
tn = millis();
T = abs(tn - tl) / 1000;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
WindSpeed = Rotations * (2.25 / T) * 1.609344;
TotalRain = Tippings * 0.2;
WindDirection = CalDirection;
}
Serial.print("rain:");
Serial.println(TotalRain);
Serial.print("windspeed:");
Serial.println(WindSpeed);
Serial.print("winddir:");
Serial.println(WindDirection);
Serial.print("windheading:");
Serial.println(getHeading(WindDirection));
Serial.print("windstrength:");
Serial.println(getWindStrength(WindSpeed));
StaticJsonDocument<96> doc;
doc["rain"] = TotalRain;
doc["windspeed"] = WindSpeed;
doc["winddir"] = WindDirection;
doc["windheading"] = getHeading(WindDirection);
doc["windstrength"] = getWindStrength(WindSpeed);
serializeJson(doc, nodemcu);
noInterrupts();
Tippings = 0;
Rotations = 0;
IsSampleRequired = false;
tl = tn;
interrupts();
}
}
// isr routine fr timer interrupt
void isr_timer() {
TimerCount++;
if (TimerCount == 5)
{
IsSampleRequired = true;
TimerCount = 0;
}
}
// This is the function that the interrupt calls to increment the rotation count
void isr_rotation () {
if (((millis() - ContactRotationTime) > 15) && (digitalRead(WindSensorPin) == LOW)) { // debounce the switch contact.
Rotations++;
ContactRotationTime = millis();
}
}
void isr_tipping () {
if (((millis() - ContactTippingTime) > 15) && (digitalRead(RainBucketPin) == LOW)) { // debounce the switch contact
Tippings++;
ContactTippingTime = millis();
}
}
// Get Wind Direction
void getWindDirection() {
VaneValue = analogRead(WindVanePin);
Direction = map(VaneValue, 0, 1023, 0, 360);
CalDirection = Direction + VaneOffset;
if (CalDirection > 360)
CalDirection = CalDirection - 360;
if (CalDirection < 0)
CalDirection = CalDirection + 360;
}
// Converts compass direction to heading
String getHeading(int direction) {
if (direction < 22)
return "N";
else if (direction < 67)
return "NE";
else if (direction < 112)
return "E";
else if (direction < 157)
return "SE";
else if (direction < 212)
return "S";
else if (direction < 247)
return "SW";
else if (direction < 292)
return "W";
else if (direction < 337)
return "NW";
else
return "N";
}
// converts wind speed to wind strength https://windows2universe.org/earth/Atmosphere/wind_speeds.html
String getWindStrength(float speed) {
if (speed < 1)
return "Calm";
else if (speed >= 1 && speed < 5)
return "Light Air";
else if (speed >= 5 && speed < 11)
return "Light Breeze";
else if (speed >= 11 && speed < 19)
return "Gentle Breeze";
else if (speed >= 19 && speed < 28)
return "Moderate Breeze";
else if (speed >= 28 && speed < 38)
return "Fresh Breeze";
else if (speed >= 38 && speed < 61)
return "Strong Breeze";
else if (speed >= 61 && speed < 74)
return "Fresh Gale";
else if (speed >= 74 && speed < 88)
return "Fresh Gale";
else
return "RUN";
}
Finally, code for ESP32:
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
SoftwareSerial arduino(26, 27);
double SEALEVELPRESSURE_HPA = 1013.25;
const char *host = "Home Weather Station";
const char *ssid = "xxx";
const char *password = "xxx";
const char *mqtt_broker = "xxx";
WiFiClient espClient;
PubSubClient client(espClient);
Adafruit_BME280 bme;
const int mqtt_port = 1883;
long lastMsg = 0;
long lastMsg2 = 0;
float a = 17.625;
float b = 243.04;
float bmeTemp;
float bmeHum;
float bmePres;
float bmeAlt;
float heatindex;
float rain;
float windspeed;
int winddir;
const char* windheading ;
const char* windstrength;
double dewpoint;
void setup()
{
Serial.begin(9600);
arduino.begin(9600);
Wire.begin();
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED)
{
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
client.setServer(mqtt_broker, mqtt_port);
while (!client.connected())
{
String client_id = "HomeWeatherStation";
client_id += String(WiFi.macAddress());
Serial.printf("The client %s connects to the MQTT broker\n", client_id.c_str());
if (client.connect(client_id.c_str()))
{
Serial.println("MQTT broker connected");
}
else
{
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
if (!bme.begin(0x76))
{
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1)
;
}
}
void loop()
{
reconnect();
client.loop();
long now = millis();
if (now - lastMsg > 20000)
{
lastMsg = now;
readBME();
}
long now2 = millis();
if ((now2 - lastMsg2 > 2500) && (arduino.available() > 0))
{
StaticJsonDocument<192> doc;
DeserializationError error = deserializeJson(doc, arduino);
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
float rain = doc["rain"];
float windspeed = doc["windspeed"];
int winddir = doc["winddir"];
const char* windheading = doc["windheading"];
const char* windstrength = doc["windstrength"];
Serial.println("JSON Object Recieved");
Serial.print("Recieved Rain: ");
Serial.println(rain);
Serial.print("Recieved Wind Speed: ");
Serial.println(windspeed);
Serial.print("Recieved Wind Direction: ");
Serial.println(winddir);
Serial.print("Recieved Wind Heading: ");
Serial.println(windheading);
Serial.print("Recieved Wind Strength: ");
Serial.println(windheading);
publisharduino();
}
}
void reconnect()
{
while (!client.connected())
{
String client_id = "LanHomeWeatherStation";
client_id += String(WiFi.macAddress());
Serial.printf("The client %s connects to the MQTT broker\n", client_id.c_str());
if (client.connect(client_id.c_str()))
{
Serial.println("MQTT broker connected");
}
else
{
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
while (WiFi.waitForConnectResult() != WL_CONNECTED)
{
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
}
void readBME()
{
bmeTemp = bme.readTemperature();
Serial.print("Temperature = ");
Serial.print(bmeTemp);
Serial.println("*C");
bmePres = (bme.readPressure() / 100.0F);
Serial.print("Pressure = ");
Serial.print(bmePres);
Serial.println("hPa");
bmeAlt = bme.readAltitude(SEALEVELPRESSURE_HPA);
Serial.print("Approx. Altitude = ");
Serial.print(bmeAlt);
Serial.println("m");
bmeHum = bme.readHumidity();
Serial.print("Humidity = ");
Serial.print(bmeHum);
Serial.println("%");
publishbme();
calcdewpoint();
calcheatindex();
Serial.println();
}
void calcdewpoint()
{
double gamma = log(bmeHum / 100) + ((a * bmeTemp) / (b + bmeTemp));
dewpoint = b * gamma / (a - gamma);
char dpString[8];
dtostrf(dewpoint, 1, 2, dpString);
client.publish("home/weather/dewpoint", dpString);
}
void calcheatindex()
{
double c1 = -42.379;
double c2 = -2.04901523;
double c3 = -10.14333127;
double c4 = -0.22475541;
double c5 = -6.83783 * (10 ^ 3);
double c6 = -5.481717 * (10 ^ 2);
double c7 = -1.22874 * (10 ^ 3);
double c8 = 8.5282 * (10 ^ 4);
double c9 = -1.99 * (10 ^ 6);
float tempF = (bmeTemp * 1.8) + 32;
float heatindexf = c1 + (c2 * tempF) + (c3 * bmeHum) + (c4 * tempF * bmeHum) + (c5 * (tempF * tempF)) + (c6 * (bmeHum * bmeHum)) + (c7 * (tempF * tempF) * bmeHum) + (c8 * tempF * (bmeHum * bmeHum)) + (c9 * (tempF * tempF) * (bmeHum * bmeHum));
heatindex = (heatindexf - 32) * 0.5556;
char hiString[8];
dtostrf(heatindex, 1, 2, hiString);
client.publish("home/weather/heatindex", hiString);
}
void publishbme()
{
char tempString[8];
dtostrf(bmeTemp, 1, 2, tempString);
client.publish("home/weather/temp", tempString);
char humString[8];
dtostrf(bmeHum, 1, 2, humString);
client.publish("home/weather/hum", humString);
char presString[8];
dtostrf(bmePres, 1, 2, presString);
client.publish("home/weather/pres", presString);
char altString[8];
dtostrf(bmeAlt, 1, 2, altString);
client.publish("home/weather/alt", altString);
}
void publisharduino()
{
char rainString[8];
dtostrf(rain, 1, 2, rainString);
client.publish("home/weather/rain", rainString);
char windspeedString[8];
dtostrf(windspeed, 1, 2, windspeedString);
client.publish("home/weather/windspeed", windspeedString);
char winddirString[8];
dtostrf(winddir, 1, 2, winddirString);
client.publish("home/weather/winddir", winddirString);
client.publish("home/weather/windheading", windheading);
client.publish("home/weather/windstrength", windstrength);
}
I'd really appreciate some help. Also, this is my first time posting in this forum, so please let me know if there is anything I can do to get the most out of posting here.