I have no idea why stack overflow still happens, I’ve tried using timers/the mustDo() function yet i cant fix it. I changed from strings to char, even double temp and press to char.
Device 1 Code
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
#include <blynk.h>
BlynkTimer timer;
SerialLogHandler logHandler(LOG_LEVEL_ERROR, {{"app", LOG_LEVEL_INFO}});
const int led3=D0; // Blynk Nightlight Control (Slider) + HTML Nightlight Toggle On/Off
int led3_status=-1; // HTML Nightlight Toggle On/Off
const int ldr=A0; // Blynk Ambience Brightness
int ldr_status=0; // Blynk Ambience Brightness
WidgetLCD lcd(V1); // Blynk LCD (Date Day Greeting + Ambience Status)
WidgetLCD lcd2(V3); // Blynk LCD (Temp + Pressure)
WidgetLCD lcd3(V5); // Blynk LCD (Door status)
const char auth[] = "";
bool ldrNeedUpdate = false;
void blynkLDRdata(){
ldrNeedUpdate = true;
}
bool ambienceNeedUpdate = false;
void UpdateAmbience(){
ambienceNeedUpdate = true;
}
// cannot be called from a Software Timer!
void mustDo() {
if (Particle.connected()) {
Blynk.run();
timer.run();
if (ldrNeedUpdate) {
ldr_status = analogRead(ldr);
Blynk.virtualWrite(V0, ldr_status);
ldrNeedUpdate = false;
}
if(ambienceNeedUpdate){
pub_ambience_status();
ambienceNeedUpdate = false;
}
}
Particle.process(); //Particle.process() is a blocking call, and blocks for a few milliseconds.
}
// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
Log.trace("%s: <%s>", event, data);
char msg[20];
double val = atof(data);
Log.info("Temperature Handler executed, %.2f°C", data);
snprintf(msg, sizeof(msg), "%.2f°C %s", val, (val > 32.50) ? "Warm" : "Cool");
lcd2.print(0,0, msg);
}
void myPressHandler(const char *event, const char *data){
//Log.trace("%s: <%s>", event, data);
char msg[20];
double val = atof(data);
Log.info("Pressure Handler executed, %.2fPa", val);
snprintf(msg, sizeof(msg), "%.2fPa %s", val, (val > 900) ? "High" : "Low ");
lcd2.print(0,1, msg);
}
void myDoorHandler(const char *event, const char *data){
//Log.trace("%s: <%s>", event, data);
char msg[60];
Log.info("Door Handler executed: %s", data);
if(!strcmp(data, "DOOR UNLOCKED!")) {
snprintf(msg, sizeof(msg), "Your door was UNLOCKED on %s.\r\n"
"Please ignore if this was you."
, (const char*)Time.format("%a %e %b at %I:%M%p"));
Log.info(msg);
Blynk.email("email@gmail.com", "SECURITY ALERT!", msg);
lcd3.print(0,0, "DOOR UNLOCKED!");
}
lcd3.print(0,0, "door locked ");
}
void softDelay(uint32_t timeout) {
for (uint32_t ms = millis(); millis() - ms < timeout; mustDo());
}
void setup(){
// Nightlight Toggle On/Off
pinMode(led3, OUTPUT);
Particle.function("led",ledToggle);
// HTML Ambience Brightness Gauge
ldr_status=analogRead(ldr); // pinMode not needed since analogRead used
Particle.variable("ldranalogvalue", ldr_status);
Blynk.begin(auth);
// bLYNK LCD Time Display (Set Timezone to SG using +8)
Time.zone(+8);
lcd.clear();
lcd2.clear();
lcd3.clear();
// IP ADDRESS
// iot_C8 MQTT sub to door status, temp and pressure data vals from D8 published temp and pressure readings
Particle.subscribe("D8_temperature", myTempHandler, MY_DEVICES);
Particle.subscribe("D8_pressure", myPressHandler, MY_DEVICES);
Particle.subscribe("D8_door_status", myDoorHandler, MY_DEVICES);
// Push ldrdata into blynk app every 3 seconds
//timer.setInterval(3000, blynkLDRdata);
timer.setInterval(3000, functions);
Log.info("Serial is Running");
}
void functions(){
blynkLDRdata();
UpdateAmbience();
}
void pub_ambience_status(){
char msg[10] = "";
if (ldr_status <= 100){
strncpy(msg, "Dark", sizeof(msg));
Particle.publish("C8_ambience", msg, PRIVATE);
lcd.print(9,0, "Dark ");
Log.info("Ambience Status - %s", msg);
}
else if (ldr_status >= 300){
strncpy(msg, "Bright", sizeof(msg));
Particle.publish("C8_ambience", msg, PRIVATE);
lcd.print(9,0, "Bright");
Log.info("Ambience Status - %s", msg);
}
else{
strncpy(msg, "Dim", sizeof(msg));
Particle.publish("C8_ambience", msg, PRIVATE);
lcd.print(9,0, "Dim ");
Log.info("Ambience Status - %s", msg);
}
}
void loop(){
mustDo();
DisplayTimeDate();
softDelay(2000);
Greeting();
softDelay(2000);
}
void DisplayTimeDate(){
lcd.print(0,0, (const char*)Time.format("%I:%M%p"));
lcd.print(0,1, (const char*)Time.format("%a %e %b "));
}
void Greeting(){
float hh = (Time.local() % 86400) / 3600.0; // Current decimal hour of the day , currenthr*24hr/1hr
if (hh < 5.0){
lcd.print(0, 1, "Midnight ");
}
else if (hh < 12.0){
lcd.print(0, 1, "Good Morning ");
}
else if (hh < 17.0){
lcd.print(0, 1, "Good Afternoon");
}
else if(hh < 20.0){
lcd.print(0, 1, "Good Evening ");
}
else if(hh < 24.0){
lcd.print(0, 1, "Night ");
}
}
int ledToggle(const char* command){ // Assign command str as const char
if(command="on") {
digitalWrite(led3,HIGH);
Log.info("HTML led3 on");
return 1;
}
else if(command="off") {
digitalWrite(led3,LOW);
Log.info("HTML led3 off");
return 0;
}
else if(command="read") {
Log.info("HTML led state");
return digitalRead(led3);
}
else {
return -1;
}
}
Device 2 Code
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
#define DEBUG_PRINT(...) { Particle.publish( "DEBUG", String::format(__VA_ARGS__) ); } void setup() { } void loop() { DEBUG_PRINT("HELLO"); delay(1000); }
#include <Adafruit_BMP280.h>
#include <blynk.h>
SerialLogHandler logHandler(LOG_LEVEL_ERROR, {{"app", LOG_LEVEL_INFO}});
Adafruit_BMP280 bmp; // I2C
BlynkTimer timer;
const int led1 = D2; // Ambience light
const int button = D4; // Fingerprint scanner
const char auth[] = "";
// HTML Temp + Press Gage Data
double t_temp;
double t_press;
void myAmbienceHandler(const char *event, const char *data);
// Update fingerprint status every 5s
Timer timer1(1000, fingerprint_scanner);
Timer timer2(5000, pub_Temp);
Timer timer3(20000, pub_Press);
bool tempNeedUpdate = false;
bool pressNeedUpdate = false;
void tempdata(){
tempNeedUpdate = true;
}
void pressdata(){
pressNeedUpdate = true;
}
void pub_Temp(){
char temp_data[16];
t_temp = bmp.readTemperature();
snprintf(temp_data, sizeof(temp_data), "%.2f", t_temp);
Particle.publish("D8_temperature", temp_data, PRIVATE);
}
void pub_Press(){
char press_data[16];
t_press = bmp.readPressure();
snprintf(press_data, sizeof(press_data), "%.2f", t_press);
Particle.publish("D8_pressure", press_data, PRIVATE);
}
// cannot be called from a Software Timer!
void mustDo() {
if (Particle.connected()) {
Blynk.run();
timer.run();
if (tempNeedUpdate) {
char temp_data[16];
t_temp = bmp.readTemperature();
snprintf(temp_data, sizeof(temp_data), "%.2f", t_temp);
Particle.publish("D8_temperature", temp_data, PRIVATE);
tempNeedUpdate = false;
}
if (pressNeedUpdate) {
char press_data[16];
t_press = bmp.readPressure();
snprintf(press_data, sizeof(press_data), "%.2f", t_press);
Particle.publish("D8_pressure", press_data, PRIVATE);
pressNeedUpdate = false;
}
}
Particle.process();
}
void functions(){
tempdata();
pressdata();
}
// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){
//Log.trace("%s: <%s>", event, data);
if(!strcmp(data, "Dark")){
digitalWrite(D2, HIGH);
Log.info("Led turns on");
}
else if(!strcmp(data, "Bright") || !strcmp(data, "Dim")){
digitalWrite(D2, LOW);
Log.info("Led stays off");
}
}
void pubDoorState(bool state) { // bool state flag 1/0 button
Particle.publish("D8_door_status", state ? "door locked" : "DOOR UNLOCKED!");
}
void fingerprint_scanner() {
pubDoorState(digitalRead(button));
}
BLYNK_WRITE(V4) {
pubDoorState(param.asInt());
}
void softDelay(uint32_t timeout) {
for (uint32_t ms = millis(); millis() - ms < timeout; mustDo());
}
void setup() {
pinMode(led1, OUTPUT);
pinMode(button, INPUT_PULLUP);
// HTML Temp and pressure gauge reading
Particle.variable("temp", t_temp);
Particle.variable("press", t_press);
// iot_D8 Device MQTT subscribe to Ambience_C8
Particle.subscribe("ambience_C8", myAmbienceHandler, MY_DEVICES);
Blynk.begin(auth);
//timer1.start();
//timer2.start();
//timer3.start();
// Update temp and press every 5 seconds
timer.setInterval(5000, functions);
Log.info("Serial is Running");
if (!bmp.begin()){
Log.warn("Can't find the sensor BMP280");
}
}
void loop(){
mustDo();
//Blynk.run();
fingerprint_scanner();
softDelay(1000);
}