BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

The hardware stops working

hardware

#21

So, I guess that the problem hides in ENC28J60. I added external protection module and arduino reboot function, so now I’m protected :slight_smile: Thanks everyone who helped me with my project.


#22

Hi. There is a new issue: in one moment (after one week of working), the hardware starts to leave offline always.
I gonna explain.
If the hardware goes offline, the device will be rebooted in 35 minutes. It starts to work like this: it comes online for a few seconds, sends the data several times, goes offline and comes back after 35 minutes.

#define MODE_EEPROM_INDEX 0
#define PUMP1_EEPROM_INDEX 1
#define PUMP2_EEPROM_INDEX 2
#define PERIOD_EEPROM_INDEX 3
#define RESET_DATA_EEPROM_INDEX 4

#include <UIPEthernet.h>
#include <BlynkSimpleUIPEthernet.h>

const char AUTH[] = "ba2024ad11874d1d8e73cfbcf9b1fde0"; // токен для ethernet

BlynkTimer temp_timer;
BlynkTimer online_signal_timer;
BlynkTimer protection_timer;
BlynkTimer set_all_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 pump1 7
#define pump2 8
#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
#define pump1_VP V9
#define pump2_VP V10
#define period_VP V11

WidgetLED heater_led(heater_led_VP);
WidgetLED online_led(online_led_VP);

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 period = 10;  //  heating period in minutes
byte mode;
byte heater_system_delta;
bool heater_state;
bool pump1_state;
bool pump2_state;

BLYNK_WRITE(pump1_VP)
{
  bool x = param.asInt(); // assigning incoming value from pin V1 to a variable
  pump1_state = x;
  EEPROM.update(PUMP1_EEPROM_INDEX, x);
}

BLYNK_WRITE(pump2_VP)
{
  bool x = param.asInt(); // assigning incoming value from pin V1 to a variable
  pump2_state = x;
  EEPROM.update(PUMP2_EEPROM_INDEX, x);
}

BLYNK_WRITE(delta_VP)
{
  byte delta = param.asInt();
  heater_system_delta = delta;
}

BLYNK_WRITE(mode_VP)
{
  byte new_mode = param.asInt();
  // for the case when in the start of program new_mode == mode
  if (mode != new_mode) {
    mode = new_mode;
    end_time = 0;  // for re-count in function
    heater_state = false;  // for restart it right now
    EEPROM.update(MODE_EEPROM_INDEX, new_mode);
  }
}

BLYNK_WRITE(period_VP)
{
  byte new_period = param.asInt();
  period = new_period;
  EEPROM.update(PERIOD_EEPROM_INDEX, new_period);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("started");
  pinMode(protection_pin_1, OUTPUT);
  pinMode(protection_pin_2, OUTPUT);
  pinMode(heater, OUTPUT);
  pinMode(pump1, OUTPUT);
  pinMode(pump2, 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

  setFromEEPROM();

  Blynk.begin(AUTH);
  if (EEPROM.read(RESET_DATA_EEPROM_INDEX)) {
    Blynk.notify("Тут сеть выпадала. Но я снова с вами!");
    EEPROM.update(RESET_DATA_EEPROM_INDEX, false);
  }
  else {
    Blynk.notify("Я включился! Видимо, не было электричества.");
  }
  Blynk.syncAll();
  set_all_timer.setInterval(1000L, setAll);
  temp_timer.setInterval(1500L, tempCheckerAndSender);
  protection_timer.setInterval(750L, protectionRoutine);
  online_signal_timer.setInterval(5000L, onlineSignalSender);
}

void loop() {
  Blynk.run();
  temp_timer.run();
  protection_timer.run();
  online_signal_timer.run();
  set_all_timer.run();
}

void setAll() {
  digitalWrite(pump1, pump1_state);
  digitalWrite(pump2, pump2_state);
  heaterController();  // for setting heater state using mode data
}

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(* resetFunc) (void) = 0;

void protectionRoutine() {
  byte pin;
  static bool parity;
  static bool reconnect;
  static unsigned long time_of_last_online;
  const unsigned long OFFLINE_IGNORE_PERIOD = 120000;  // in millis
  // if the hardware went offline
  if (!Blynk.connected()) {
    if (!reconnect) {
      reconnect = true;
      time_of_last_online = millis();
    }
    else if (millis() - time_of_last_online > 2100000) {
      // if there is no action for more than 10 minutes
      // soft reset routine
      EEPROM.update(RESET_DATA_EEPROM_INDEX, true);
      resetFunc();
    }
    else if (millis() - time_of_last_online > 1500000) {
      // leave the function because we don't need to send signals for reboot arduino
      EEPROM.update(RESET_DATA_EEPROM_INDEX, true);
      return;
    }
  }
  else {
    // if connected, stop the protection
    reconnect = false;
    EEPROM.update(RESET_DATA_EEPROM_INDEX, false);
    if (millis() - time_of_last_online > OFFLINE_IGNORE_PERIOD) {
      Blynk.notify("Тут сеть выпадала. Но я снова с вами!");
    }
    time_of_last_online = millis();
  }
  // if everything is OK, 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() {
  static bool overheat;
  if (podacha_temp >= 90 and !overheat) {
    digitalWrite(heater, LOW);
    overheat = true;
    Blynk.notify("О-о, подача перегрелась. Но я отключил ТЭНы, не волнуйтесь. Когда температура будет меньше 82°, я все верну.");
    return;  //  leave the function
  }
  else if (overheat and podacha_temp >= 82) {
    return;
  }
  else if (overheat and podacha_temp < 82) {
    overheat = false;  //for continue working in normal mode
  }

  // the next code will be completed if the previous cases won't leave the function
  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;
        }
      }
    }
  }

  static bool send_when_connect = false;  // it helps in case if the pump1_state changed automatically and button state in Blynk didn't changed
  if (heater_state and !pump1_state and !pump2_state) {
    pump1_state = true;
    EEPROM.update(PUMP1_EEPROM_INDEX, pump1_state);
    if (Blynk.connected()) {
      Blynk.virtualWrite(pump1_VP, pump1_state);
      Blynk.notify("Вы тут ошиблись и включили ТЭНы без насоса. Не волнуйтесь, я обо всем позаботился и включил насос первого этажа.");
    }
    else {
      send_when_connect = true;
    }
  }
  if (send_when_connect and Blynk.connected()) {
    send_when_connect = false;
    Blynk.virtualWrite(pump1_VP, pump1_state);
  }

  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;
  }
}

void setFromEEPROM() {
  mode = EEPROM.read(MODE_EEPROM_INDEX);
  // next code will save from overheat
  if (mode > 5) {
    mode = 3;
  }
  pump1_state = EEPROM.read(PUMP1_EEPROM_INDEX);
  pump2_state = EEPROM.read(PUMP2_EEPROM_INDEX);
  period = EEPROM.read(PERIOD_EEPROM_INDEX);
  setAll();
}

#23

and will the wifi be more stable?


#24

You gonna laugh)
The problem was in contacts.
Wires were soldered to the contacts of ENC28J60 and connected to the Arduino by dupont ends.

I gonna make a PCB and buy a mega screw shield.


#25

And I changed the periods of timers.

set_all_timer.setInterval(3767L, setAll);
temp_timer.setInterval(19846L, tempCheckerAndSender);
protection_timer.setInterval(8478L, protectionRoutine);
online_signal_timer.setInterval(5000L, onlineSignalSender);

I don’t know why, when I tried to make multipile timer (using only one timer!) the hardware went offline in a minute.