Greetings everybody!
I’m a frequent reader of this community’s posts and found much help in creating my project: I’m building an astrophotographical observatory 3km from home and trying to remote control it through Arduino and Blynk.
Still having a problem with disconnections which won’t stop me (I already found a plan B and, even, plan C), but I would like to solve it to avoid Hard Resets.
Sorry for long post, but I would like to be precise in describing the whole thing.
I’m using all Arduino devices, mainly MKR1010 WiFi, but I also have a Nano BLE and a UNO WiFi Rev.2.
Arduino IDE on Mac OS. Actually in developing phase, so I’m at home using my WiFi and trying to solve bugs before finishing the project in observatory.
Using Blynk server. Blynk library is up to date and I raised the number of BLYNK_MSG_LIMIT from 100 to 1000 in the BlynkConfig.h file to avoid flood error (I know I should edit another file, but I think I’m not finding it unless I use a local server).
I have 3 devices finished (Meteo_IN very stable, Meteo_OUT and Roof_control not) actually coding the Power_station (almost finished), yet not started the Telescope one.
I’m posting the whole code of the Roof_control only because it has the worst behavior (much frequent disconnection than others). Trying to explain the code with comment line by line. I hope it is clear
#include <WDTZero.h>
#include <NewPing.h>
#include <Wire.h>
#include <MPU6050_light.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include <BlynkSimpleWiFiNINA.h>
char auth[] = "xxxx";
char ssid[] = "xxxx";
char pass[] = "xxxx";
unsigned long lastConnectionAttempt = millis();
unsigned long WiFiDisconnectedTimer;
unsigned long BlynkDisconnectedTimer;
BlynkTimer timer;
WDTZero MyWatchDoggy;
#define SONAR_NUM 3 // Number of sensors.
#define MAX_DISTANCE 450 // Maximum distance (in cm) to ping.
NewPing sonar[SONAR_NUM] = { // Sensor object array.
NewPing(4, A0, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(4, A2, MAX_DISTANCE),
NewPing(4, A4, MAX_DISTANCE)
};
MPU6050 mpu6050(Wire);
int FanSpeed;
int Tetto;
int Rain;
int Giorno;
WidgetLED tetto(V18);
WidgetBridge bridgeTettoMillis(V125);
WidgetBridge bridgeTetto(V14);
BLYNK_CONNECTED() {
bridgeTettoMillis.setAuthToken("xxxx");
bridgeTetto.setAuthToken("xxxx");
bridgeTetto.setAuthToken("xxxx");
}
BLYNK_WRITE(V5) {
FanSpeed = param.asInt();
}
BLYNK_WRITE(V17) {
Giorno = param.asInt();
}
//------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
Wire.begin();
Blynk.begin(auth, ssid, pass);
pinMode(6, OUTPUT); //fan speed control via PWM
pinMode(8, OUTPUT); //relay control to open/close roof. It basically pushes a button of the gate-motor remote
digitalWrite(0, LOW); //interrupt pin, must be low on reboot because of RISING method for interrupt
mpu6050.begin(); //accelerometer to check actual roof movement
mpu6050.calcOffsets(false, true);
attachInterrupt(digitalPinToInterrupt(0), chiudiSePiove, RISING); //cabled interrupt coming from Meteo_OUT in case of rain
MyWatchDoggy.setup(WDT_HARDCYCLE16S); //watchdog control set to 16s via WDTZero library in case of stuck loop
timer.setInterval(30000L, connectionCheck);
timer.setInterval(10000L, autoReset);
timer.setInterval(5000L, controlFanSpeed);
timer.setInterval(1000L, sendHeartbeat);
timer.setInterval(500L, senseMovement);
timer.setInterval(5000L, apertoOchiuso);
timer.setInterval(5000L, chiudiSeGiorno);
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
void sendHeartbeat() { //send actual millis value to Power_station once per second.
bridgeTettoMillis.virtualWrite(V125, millis()); //If stuck for more than 60s, Power_station will shut down and up again to hard reset
MyWatchDoggy.clear(); //stops watchdog timer once for every loop (about 3s)
}
//------------------------------------------------------------------------------------------------
void senseMovement() { //Read accelerometer 3 axis data and send them to server twice per second - 180 float values per minute
mpu6050.update();
Blynk.virtualWrite(V0, mpu6050.getAccX());
Blynk.virtualWrite(V1, mpu6050.getAccY());
Blynk.virtualWrite(V2, mpu6050.getAccZ() - 1);
}
//------------------------------------------------------------------------------------------------
void apertoOchiuso() { //Read ultrasonic sensor clearence of roof to understand if it is open or closed.
delay(100); //100ms delay necessary for correct reading.
int sonar0 = sonar[0].ping_cm(); //5 int values for every 5s - total 60 int per minute
Blynk.virtualWrite(V25, sonar0);
delay(100);
int sonar1 = sonar[1].ping_cm();
Blynk.virtualWrite(V26, sonar1);
delay(100);
int sonar2 = sonar[2].ping_cm();
Blynk.virtualWrite(V27, sonar2);
int proximity = (sonar0 + sonar1 + sonar2) / 3;
Blynk.virtualWrite(V28, proximity);
if (proximity > 50) { //WidgetLED switching ON/OFF and changing roof status
Tetto = 0;
tetto.off();
}
else {
Tetto = 1;
tetto.on();
}
Blynk.virtualWrite(V14, Tetto); //Sending roof status
bridgeTetto.virtualWrite(V14, Tetto); //bridging roof status for other operation in Meteo_stations
}
//------------------------------------------------------------------------------------------------
void chiudiSePiove() { //interrupt - close roof if it's raining
if (Tetto == 0) {
digitalWrite(8, HIGH);
delay(1000); //keep button pushed for 1s
digitalWrite(8, LOW);
Blynk.notify("PIOVE! Chiusura tetto avviata");
delay(15000); //wait 15s for roof closing. I don't mind disconnection after this. Roof must be closed
}
}
//------------------------------------------------------------------------------------------------
void chiudiSeGiorno() { //close roof at sun rise, same closing routine
if (Giorno == 1 && Tetto == 0) {
Blynk.notify("È giorno. Chiusura tetto avviata");
digitalWrite(8, HIGH);
delay(1000);
digitalWrite(8, LOW);
delay(15000);
}
}
//------------------------------------------------------------------------------------------------
void connectionCheck() { //wifi status check, copied and pasted from Handle_disconnection example
if (WiFi.status() != WL_CONNECTED) {
if (millis() - lastConnectionAttempt >= 5000) {
lastConnectionAttempt = millis();
if (pass && strlen(pass)) {
WiFi.begin((char*)ssid, (char*)pass);
}
else {
WiFi.begin((char*)ssid);
}
}
}
if (!Blynk.connected()) { //added connection to server check
Blynk.connect();
}
}
//------------------------------------------------------------------------------------------------
void autoReset() { // 3 cases for autoreset routine:
if (millis() >= 3600000) { //1 hour is passed,
NVIC_SystemReset();
}
if (WiFi.status() != WL_CONNECTED) { //1 minute without WiFi connection,
WiFiDisconnectedTimer = millis();
if (millis() - WiFiDisconnectedTimer >= 60000) {
NVIC_SystemReset();
}
}
if (!Blynk.connected()) { //1 minute without Blynk connection
BlynkDisconnectedTimer = millis();
if (millis() - BlynkDisconnectedTimer >= 60000) {
NVIC_SystemReset();
}
}
}
//------------------------------------------------------------------------------------------------
void controlFanSpeed() { // PWM control of fans
if (Tetto == 1) {
analogWrite(5, FanSpeed);
}
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
void loop() {
Blynk.run();
timer.run();
}
I counted 180 float and 48 int values per minute and 2 bridge (60 long and 12 int) per minute.
I really will appreciate any help