The hardware stops working

Good day everyone.

So, I’ve made the simplest project to switch on and off some relays. There is a code:

#include <SmartDelay.h>
SmartDelay send_data_time(5000000UL);
#include <UIPEthernet.h>
#include <BlynkSimpleUIPEthernet.h>
const char AUTH[] = "6b3057b7fc43495baf9d39d40d08ce0b"; // токен для ethernet
 
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS A5
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
 
#define temp1_VP V1
#define temp2_VP V2
 
void setup() {
  // put your setup code here, to run once:
  sensors.begin();
  Blynk.begin(AUTH);
  Blynk.notify("Я включился! Видимо, не было электричества.");
  Blynk.syncAll();
}
 
void loop() {
  // put your main code here, to run repeatedly:
  sensors.requestTemperatures();
  int temp1 = sensors.getTempCByIndex(0);
  int temp2 = sensors.getTempCByIndex(1);
  Blynk.run();
  if (send_data_time.Now() and Blynk.connected()) {
    Blynk.virtualWrite(temp1_VP, temp1);
    Blynk.virtualWrite(temp2_VP, temp2);
  }
}

But why the hardware goes offline sometimes?

It can go offine each day and each moment without any notice. I have no idea why. Maybe, problem hides in my code?

2 Likes

Okay, I’ll slove it in Sunday. But can you connect it back right now?

I need to switch all heaters and pumps in my house on.

Ummm… what do you want me to do?

Okay, from the article I understood, that you disconnect the hardware witch spams the cloud.

So, I thought, that if somebody dissconects it, than somebody can connect it back.

I guessed, that you can do it because you’re an admin

I am not a Blynk Developer, just a volunteer.

Blynk doesn’t disconnect your hardware due to email or notification spamming… they (email & notifications) just stop working. I suspect they are automatically released in time.

No one is sitting around pushing the disconnect button at Blynk HQ :stuck_out_tongue: The hardware disconnections happen because your code is poorly implemented and the device cannot communicate with the server properly. There is a regular "heartbeat’ that if missed will disconnect the server link until you either reboot or run some connection management routines.

But first you have to follow the guidelines and write your code properly in order to get it to work correctly and stay connected.

1 Like

So, can I use delay() in function handled by BlynkTimer?

Because it is a totally blocking command, you shouldn’t use delay() anywhere… except perhaps in the smallest of timings ( <1 second) once in a rare moment and only where absolutely needed (falls into the “don’t do this at home unless you are an expert” category :stuck_out_tongue: ). Run BlynkTimer instances instead.

The problem is still there.

I wrote new code using recommendations.

#include <BlynkSimpleUIPEthernet.h>
const char AUTH[] = "ba2024ad11874d1d8e73cfbcf9b1fde0"; // токен для ethernet
BlynkTimer timer;

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS A5
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

#define temp1_VP V1
#define temp2_VP V2

void tempCheck() {
  sensors.requestTemperatures();
  float temp1 = sensors.getTempCByIndex(0);
  float temp2 = sensors.getTempCByIndex(1);
  if (Blynk.connected()) {
    Blynk.virtualWrite(temp1_VP, temp1);
    Blynk.virtualWrite(temp2_VP, temp2);
  }
}


void setup() {
  // put your setup code here, to run once:
  sensors.begin();
  Blynk.begin(AUTH);
  Blynk.notify("Я включился! Видимо, не было электричества.");
  Blynk.syncAll();
  tempCheck();
  timer.setInterval(1000L, tempCheck);
}

void loop() {
  Blynk.run();
  timer.run();
}

What hardware are you using? Ethernet shields can be notoriously unstable.

Neither of these seems necessary with your current code. You don’t have anything that needs syncing and the timer starts running in one second anyhow for the temp reading

And neither is this… since if it is not connected then nothing happens with the following commands anyhow.

The reading of the temperature - the way it is currently implemented - causes a delay of 750ms+.

See here for a fix:

Thanks a lot! I guess it should be very helpful.

So, as I understood, that strings fix the problem?

  DS18B20.setWaitForConversion(false); // make reading NON blocking
  DS18B20.requestTemperatures();       // start conversion for first reading

These two lines are only part of the story related to the temp sensors - read again :wink:

Okay, there is my final code. It stops working!!!
Everything is good, the hardware continue working without Blynk, but it won’t connect to Blynk if you will not reboot the hardware.
Code:

#include <BlynkSimpleUIPEthernet.h>
 
const char AUTH[] = "ba2024ad11874d1d8e73cfbcf9b1fde0"; // токен для ethernet
 
BlynkTimer temp_timer;
BlynkTimer online_signal_timer;
BlynkTimer protection_signal_timer;
 
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS A5
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
 
DeviceAddress floor1_temp_sensor = {0x28, 0xFF, 0xCE, 0xD0, 0x01, 0x17, 0x05, 0xDF};
DeviceAddress floor2_temp_sensor = {0x28, 0xFF, 0x09, 0xD0, 0x01, 0x17, 0x05, 0xAC};
DeviceAddress podacha_temp_sensor = {0x28, 0x41, 0x0F, 0x43, 0x98, 0x18, 0x00, 0xCC};
DeviceAddress obratka_temp_sensor = {0x28, 0x57, 0x20, 0x43, 0x98, 0x25, 0x00, 0x16};
DeviceAddress radiator_temp_sensor = {0x28, 0xFF, 0xEC, 0xCE, 0x01, 0x17, 0x05, 0x89};
 
#define protection_pin_1 10
#define protection_pin_2 11
#define heater 12
 
#define radiator_temp_VP V0
#define temp1_VP V1
#define temp2_VP V2
#define podacha_temp_VP V3
#define obratka_temp_VP V4
#define delta_VP V5
#define mode_VP V6
#define heater_led_VP V7
#define online_led_VP V8
 
WidgetLED heater_led(heater_led_VP);
WidgetLED online_led(online_led_VP);
 
const byte PERIOD = 10;  //  heating period in minutes
const byte AVERAGE_FACTOR = 5;  // if 0 - don't average values
/* TIME_MULTIPLIER corrects the time counting
 * 60000 - in minutes
 * 1000 - in seconds
 * 1 - in millis
 */
const unsigned long TIME_MULTIPLIER = 60000;
 
unsigned long end_time;  // in millis
float radiator_temp;
float floor1_temp;
float floor2_temp;
float podacha_temp;
float obratka_temp;
byte mode;
byte heater_system_delta;
bool heater_state;
 
BLYNK_WRITE(delta_VP)
{
  byte delta = param.asInt();
  heater_system_delta = delta;
}
 
BLYNK_WRITE(mode_VP)
{
  byte new_mode = param.asInt();
  mode = new_mode;
  end_time = 0;  // for re-count in function
  heater_state = false;
}
 
void setup() {
  // put your setup code here, to run once:
  pinMode(protection_pin_1, OUTPUT);
  pinMode(protection_pin_2, OUTPUT);
  pinMode(heater, OUTPUT);
  
  sensors.begin();
  sensors.setResolution(radiator_temp_sensor, 11);
  sensors.setResolution(floor1_temp_sensor, 11);
  sensors.setResolution(floor2_temp_sensor, 11);
  sensors.setResolution(podacha_temp_sensor, 11);
  sensors.setResolution(obratka_temp_sensor, 11);
  sensors.setWaitForConversion(false); // make reading NON blocking
  sensors.requestTemperatures();       // start conversion for first reading 
  
  Blynk.begin(AUTH);
  Blynk.notify("Я включился! Видимо, не было электричества.");
  Blynk.syncAll();
  temp_timer.setInterval(1500L, tempRoutine);
  protection_signal_timer.setInterval(750L, protectionSignalSender);
  online_signal_timer.setInterval(5000L, onlineSignalSender);
}
 
void loop() {
  Blynk.run();
  temp_timer.run();
  protection_signal_timer.run();
  online_signal_timer.run();
}
 
void tempRoutine() {
  tempCheckerAndSender();
  heaterController();
}
 
void tempCheckerAndSender() {
  floor1_temp = averageFilter(sensors.getTempC(floor1_temp_sensor), floor1_temp);
  floor2_temp = averageFilter(sensors.getTempC(floor2_temp_sensor), floor2_temp);
  podacha_temp = averageFilter(sensors.getTempC(podacha_temp_sensor), podacha_temp);
  obratka_temp = averageFilter(sensors.getTempC(obratka_temp_sensor), obratka_temp);
  radiator_temp = averageFilter(sensors.getTempC(radiator_temp_sensor), radiator_temp);
  sensors.requestTemperatures();
  Blynk.virtualWrite(temp1_VP, floor1_temp);
  Blynk.virtualWrite(temp2_VP, floor2_temp);
  Blynk.virtualWrite(podacha_temp_VP, podacha_temp);
  Blynk.virtualWrite(obratka_temp_VP, obratka_temp);
  Blynk.virtualWrite(radiator_temp_VP, radiator_temp);
}
 
void onlineSignalSender() {
  static bool parity;
  online_led.setValue(parity * 255);
  parity = !parity;
}
 
void protectionSignalSender() {
  byte pin;
  static bool parity;
  // choose a pin to send the data
  if (parity) {
    pin = protection_pin_1;
  }
  else {
    pin = protection_pin_2;
  }
  // send short signal
  digitalWrite(pin, random(0, 2));  // send a random signal
  parity = !parity;
}
 
void heaterController() {
  if (mode == 0) {
    heater_state = false;
  }
  else {
    unsigned long time_on = mode * TIME_MULTIPLIER;
    unsigned long time_off = (PERIOD * TIME_MULTIPLIER) - time_on;
    if (time_off == 0) {
      heater_state = true;
    }
    else {
      if (millis() > end_time) {
        heater_state = !heater_state;
        if (heater_state) {
          end_time = millis() + time_on;
        }
        else {
          end_time = millis() + time_off;
        }
      }
    }
  }
  digitalWrite(heater, heater_state);
  heater_led.setValue(heater_state * 255);
}
 
float averageFilter (float new_val, float old_avg) {
  if (AVERAGE_FACTOR > 0) {
    return (old_avg * (AVERAGE_FACTOR - 1) + new_val) / AVERAGE_FACTOR;
  }
  else {
    return new_val;
  }
}```
Some ideas?
@gunner, can you help me too?

Some of your code is very odd. Take this as an example…

You’re defining a local Boolean variable called parity. It will have a value of false/zero, as you’ve just defined it and not assigned a value to it.
You’re then multiplying zero by 255 (still zero) and writing this to an LED widget.
You then do a ‘not’ on the variable, to make it have a value of 1.
However, as its a local variable and this is the end of the function, this value is then lost, as you re-define it again the next time the function is called.
Even if you’d defined this as a global variable, it would still be strange, a you’re using the same variable name in the protectionSignalSender() function, which has even more issues with the way that it’s written.

You’re doing a similar thing in your heaterController() function with the time_on and time_off variables.

You have no Serial.print statements to give you clues about what’s happening to any of these variables, so I don’t see how you can say that…

If it were me, I’d throw-in some Serial.print statements to show the key values (specially the temperature readings), reduce the frequency of the timers and comment-out all but one of your consecutive Blynk.virtualWrite statements to enable you to see what’s happening.

In addition, I’d try a very simple sketch to ensure that your Ethernet shield is working correctly, they can be very temperamental.

Pete.

1 Like

The function onlineSignalSender is used for change the state of LED each 5 seconds.
I use the construction led.setValue(x * 255), because it is faster and smaller than this once:

if (x) {
led.on();
}
else {
led.off();
}

ProtectionSignalSender sends a random signal to protector (attiny). If the signal state will not be changed for 5 minutes on each pin, attiny will reboot arduino. It is like the external watchdog

Now, I have the access to my device. After it went offline yesterday, I came to it. The hardware works normally, excepting the ENC28J60.
I guess, it was hung on, because the recieve and transmit LEDs on ENC28J60 blinked rarely and same, though it was looped.

I realise what it’s meant to do, but as I said, I don’t see how it can work when you re-declare the variable parity every time the function is called.

Pete.

I use the static qualifier, and it defines only once. More about static there

2 Likes

I learned something new today (always a good day when that happens!).
Thanks.

Pete.

2 Likes