Hardware kept on resetting

Hi Blynkers,

I have been facing this issue where I have 3 separate controllers with a unique function each, and all of them seem to keep on resetting at random times. I could see in the application’s connected device tab (top right corner), that the 3 controllers that I have, could not connect for more than half a day without disconnecting. The codes below is one of the simplest codes among the 3 controllers, but the hardware still disconnects.

I’ve tried many things based on what was suggested by the community such as:

  1. Add a 47 uF capacitor in parallel to Vcc and GND of the microcontroller
  2. Made sure power supply is a constant 5V into the micro usb-B port of a WEMOS D1 Mini Pro with at least 2A capable.
  3. Functions has no delays. Only a 10 ms delay between each loop.

Versions:

  1. Arduino IDE - 1.8.9
  2. Blynk Library - 0.6.1

I can guarantee one thing, that the local blynk server it is connected to isn’t the issue. I ran a much simpler blynk code on another WEMOS which constantly sends a single data to the server and it ran without any issues.

This issue is quite critical and urgent for me and all suggestions would very much be appreciated. Thanks in advance.


/*
   POWER CONTROLLER CONTROLLER

  ================================================================================
                                    Version 0.9 Changelog
  ================================================================================
  - changed MISTING_PUMP_BRIDGE_PAIR from V1 -> V0
  - changed LIQUID_PUMP_BRIDGE_PAIR from V2 -> V64
  - Added PRINT_ERROR function to easily refer to error code and send out notifications to serial monitor, application terminal and phone notification
*/


/****************************************************************************/
//                         Relay Module Variables
/****************************************************************************/
//String LIQ_PUMP_PWR D0
//#define MISTING_PUMP_PWR D1

#define SWITCH1_PIN D5
#define SWITCH2_PIN D6
#define SWITCH3_PIN D7
#define SWITCH4_PIN D8

/*
   The ID represents the index of the device that is connected to it
   ID = 1 = Misting Pump
   ID = 2 = LED Grow Lights
   ID = 3 = Liquid Pump
   
*/
#define MISTING_PUMP_ID 1
#define LIGHTS_ID 2
#define LIQ_PUMP_ID 3

int switchId_1 = 0, switchId_2 = 0, switchId_3 = 0, switchId_4 = 0;


/****************************************************************************/
//                     Blynk Server Definitions and Variables
/****************************************************************************/
#include <BlynkSimpleEsp8266.h>

BlynkTimer timer;

#ifndef APSSID
#define APSSID "<id>"
#define APPSK  "<password>"
#endif


const char *ssid = APSSID;
const char *password = APPSK;
const char transmitterAuth[] = "<AuthToken>";      // Used for connecting to Local Blynk Server
const char server[] =  "<IP>";   // IP Address of Server
const int port = <PORT>;


#define MISTING_PUMP_BRIDGE_PAIR V0 // The virtual pin assigned on the other device. MUST match the pin set on the other device
#define LIGHTS_BRIDGE_PAIR V1 // The virtual pin assigned on the other device. MUST match the pin set on the other device
#define LIQUID_PUMP_BRIDGE_PAIR V64

#define SWITCH_SELECTOR_1 V11
#define SWITCH_SELECTOR_2 V12
#define SWITCH_SELECTOR_3 V13
#define SWITCH_SELECTOR_4 V14

WidgetTerminal TERMINAL (V100);

void setup() {
  Serial.begin(9600);
  Serial.println ("Initializing Power Controller");
  TERMINAL.println ("Initializing Power Controller");
  pinMode (LED_BUILTIN, OUTPUT);
  pinMode (SWITCH1_PIN, OUTPUT);
  pinMode (SWITCH2_PIN, OUTPUT);
  pinMode (SWITCH3_PIN, OUTPUT);
  pinMode (SWITCH4_PIN, OUTPUT);

  digitalWrite (SWITCH1_PIN, LOW);
  digitalWrite (SWITCH2_PIN, LOW);
  digitalWrite (SWITCH3_PIN, LOW);
  digitalWrite (SWITCH4_PIN, LOW);
  delay (100);

  CONNECT_BLYNK();
  Serial.println(F("Connection with Blynk Server --------------------------- OK"));
  TERMINAL.println(F("Connection with Blynk Server --------------------------- OK"));

  timer.setInterval (2000, CONTROL);
}

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

  // Protection from unintetional disconnect from server. Attempt to reconnect after that.
  while (!Blynk.connected()) {
    digitalWrite (LED_BUILTIN, LOW);
    PRINT_ERROR ("001");
    CONNECT_BLYNK();
    if (!Blynk.connected()) delay (1000); // If still not connected, wait for 1 second
  }

  // For safety, if nothing is assigned, disable the switch
  if (switchId_1 == 0)
    digitalWrite (SWITCH1_PIN, LOW);
  if (switchId_2 == 0)
    digitalWrite (SWITCH2_PIN, LOW);
  if (switchId_3 == 0)
    digitalWrite (SWITCH3_PIN, LOW);
  if (switchId_4 == 0)
    digitalWrite (SWITCH4_PIN, LOW);

  TERMINAL.flush();
  delay (10);
  
}

I suggest you make your loop() clean like @PeteKnight always suggests.
Do something similar to this

.....

void setup() {
  Serial.begin(115200);
  Serial.println ("Initializing Power Controller");
  TERMINAL.println ("Initializing Power Controller");
  pinMode (LED_BUILTIN, OUTPUT);
  pinMode (SWITCH1_PIN, OUTPUT);
  pinMode (SWITCH2_PIN, OUTPUT);
  pinMode (SWITCH3_PIN, OUTPUT);
  pinMode (SWITCH4_PIN, OUTPUT);

  digitalWrite (SWITCH1_PIN, LOW);
  digitalWrite (SWITCH2_PIN, LOW);
  digitalWrite (SWITCH3_PIN, LOW);
  digitalWrite (SWITCH4_PIN, LOW);
  delay (100);

  CONNECT_BLYNK();
  TERMINAL.clear();
  Serial.println(F("Connection with Blynk Server --------------------------- OK"));
  TERMINAL.println(F("Connection with Blynk Server --------------------------- OK"));

  timer.setInterval (2000, CONTROL);
}

void CONTROL()
{
  // Do something you need to do here
  //  .......................

  // Put it here if you really need !!
  // For safety, if nothing is assigned, disable the switch
  if (switchId_1 == 0)
    digitalWrite (SWITCH1_PIN, LOW);
  if (switchId_2 == 0)
    digitalWrite (SWITCH2_PIN, LOW);
  if (switchId_3 == 0)
    digitalWrite (SWITCH3_PIN, LOW);
  if (switchId_4 == 0)
    digitalWrite (SWITCH4_PIN, LOW);

  TERMINAL.flush();
}

#define BLYNK_SERVER_HARDWARE_PORT     8080

void CONNECT_BLYNK()
{
  Blynk.begin(transmitterAuth, ssid, password, server, BLYNK_SERVER_HARDWARE_PORT);
}

void loop() 
{
  // Protection from unintentional disconnect from server. Attempt to reconnect after that.
  if (!Blynk.connected()) {
    digitalWrite (LED_BUILTIN, LOW);
    PRINT_ERROR ("001");
    CONNECT_BLYNK();
  }
    
  Blynk.run();
  timer.run();
}
1 Like

I have tried the above with similar results. I’m using a raspberry pi zero W as the local server. Is it possible that it could receive so much data at once from three controllers? Each controller is transmitting data approximately every 5 seconds

Tell us more about how you have these three ’controllers’ set up.
Are you using different Auth codes for each one?
Where is your local server hosted, what sort of cloud service are you using for this?

Pete.

The above is the system architecture that I have designed. Each controller has its own authentication code and I’m utilizing the bridge widget for device to device communication.
My local server is hosted in a residential home environment with high speed fibre network while the system above is located few hundred kilometres away but with Wireless Wifi Network.

I am currently not using any cloud service.

The sketch you posted doesn’t contain any Bridge code.

From what you’ve described, you’re effectively using a self-hosted cloud server, is that correct?

Pete.

If you’ve tried with similar results (random reset), I think that the problem lies somewhere else in your code. As we don’t have the whole picture (your code), I can only suggest that you debug, check your code again and again to search for:

  • Stray pointers / NULL pointers
  • Corrupted memory caused by your code
  • Watchdog timer

Good luck

Thanks for the prompt replies. @PeteKnight, yes it is a self-hosted server.

@khoih I have rechecked my codes many times. Today, 3 of the controllers manage to go up to 12 hour without any hiccups until my home Wifi disconnected for a bit. This is beginning to sound like the issue with my home network again.

IMHO, I still think that you’d better recheck your code to avoid the same reset problem in the future, especially if your project needs high reliability.
Bad WiFi/Internet or local Blynk server normally don’t trigger a reset to your boards, unless there is problem in your code.
Anyway, isn’t it the pain and joy / beauty of debugging !!!

@Justin_Choo a few observations…

  1. You’ve not addressed my comment about the lack of Bridge code. I see from the JSON file for your project that you do indeed have a Bridge widget in your app, but that doesn’t actually do anything.
    See the documentation here:
    https://docs.blynk.cc/#widgets-other-bridge
  1. Your app uses an image widget that has URLs to images that are outside of your control. I believe that the images are cached locally, but as your app is shared I think you could run into issues long term. Probably be better to put copies of those images on your server and link to them that way (assuming that there are no copyright issues with this).
  1. You’ve shared the url to your server, the port you’re using and the Auth code of your project on a public forum. As you can see from my previous comments, I’ve been able to use an API call to your server to retrieve your project JSON data, and I could have controlled the status of any of your widgets in the same way. Based on the sketch you provided, I could also have changed the state of your hardware device in the same way. I haven’t done either of these things, but if I can do it then so can thousands of other people. You need to change your Auth code, port and preferably your server url as well.

  2. From your description and choice of words like “crops”, I think that there’s a good chance that this project has some commercial use, which is in breach of the Blynk Terms & Conditions.

Pete.

Hi Pete,

  1. Below are the codes for another controller. Here is where the bridge is first called. I understand that the bridge virtual pin here has to match with the first controller I’ve posted above.

  2. The image widget uses the URL from a weather website with proper permissions. By that I mean I have made an account with them as well as being able to take data straight from their APIs. The images you saw there were suggested under the developers section

  3. Thanks for heads up and your kindess. I will be more careful with these things in the future.

  4. It is not commercialized yet but I have seen their terms and conditions. Will be considering in subscribing into their services once I have confidence that this project can work well with Blynk

/*
   INTERIOR CONTROLLER

  ================================================================================
                                    Version 0.9.1 Changelog.
  ================================================================================
  - Removed most of the terminal prints as that could be causing the hardware crash
  - Fix issues with spamming notification on application device.
    Notifications will now be sent every 15 minutes
    Error messages will now be sent every hour
  - Added a fix to reset timers when millis() returns back to 0. Approximately every 50 days

  ================================================================================
                                    Version 0.9 Changelog
  ================================================================================
  - Added PRINT_ERROR function to easily refer to error code and send out notifications to serial monitor, application terminal and phone notification
  - Added RTC
  - Prevented hardware reset from turning off Auto mode (if already set on the App). This is done by moving the activeFlag in BLYNK_CONNECTED() to the main Loop()
  - Manually call for each function in while loop rather than to use BlynkTimer as that could be the cause of the hardware reset.
  - Only allow hardware to send notification every hour
*/

/****************************************************************************/
//                         Other Global Variables
/****************************************************************************/
#include <Adafruit_MCP3008.h>
#include <RunningMedian.h>

bool alertFlag = false;   // Raised when alert is raised by sensors
bool activeFlag = false;  // Raised when module is actively transmitting
bool autoFlag = false;  // Raised when automation is required by user

int weatherID = -1; // Used to control the lights if weather ID = overcast based on https://openweathermap.org/weather-conditions
bool pumpState; //  Used to determine if soil is suppose to be wet when pump is turned on
long pumpOnTime;

bool notificationFlag = false;
long notificationTimer;

bool errorFlag = false;
long errorTimer;

long sensorReadTime, controlTime, writeTime;



/****************************************************************************/
//                     MCP3008 Definitions and Variables
/****************************************************************************/
Adafruit_MCP3008 adc;

// Define SPI Pins
#define SS D8
#define MOSI D7 // ADC Din 
#define MISO D6  // ADC Dout
#define SCK D5

/****************************************************************************/
//                   Soil Moisture (SM) Sensor Definitions and Variables
/****************************************************************************/
#define SM_PIN A0
#define ADC_SM_CHANNEL 0
int sm;
int minSm, maxSm;

RunningMedian smSamples = RunningMedian (100);
/****************************************************************************/
//                     DHT 22 Definitions and Variables
// With sensor holes facing towards you:
// Connect pin 1 (Left-most) to 3.3 - 5 V
// Connect pin 2 to digital pin or controller
// Connect pin 4 to GND
// Add a parallel 10K resistor in parallel between pin 2 and pin 1
/****************************************************************************/

#include "DHT.h"
#define DHT1_TYPE DHT22
#define DHT2_TYPE DHT22
#define DHT1_PIN D1
#define DHT2_PIN D2

// Run the MATLAB file "dht22Calibration.m" to determine the values needed for offset
#define DHT1_TEMP_OFFSET 1.472243
#define DHT1_HUMID_OFFSET 5.349533
#define DHT2_TEMP_OFFSET 0.732006
#define DHT2_HUMID_OFFSET 7.374223

/*
   The amount of buffer region  between the max and min values before parameter is considered nominal
   Example: If maxTemp = 28 degC and minTemp = 25 degC and safetyFactor = 0.4
   Misting Pump turns on when max temperature exceeds 28 degC and only turns off when,
        temperature = maxTemp - [(maxTemp - minTemp) * 0.2] = 26.8
   Values: 0 < Safety Factor < 1
*/
#define temprtSF 0.4
#define extremeMinTemp 15
#define extremeMaxTemp 30

DHT dht1(DHT1_PIN, DHT1_TYPE);
DHT dht2(DHT2_PIN, DHT2_TYPE);

float h1, t1;
int minTemp, maxTemp, minHumid, maxHumid;

RunningMedian temprtSamples = RunningMedian (100);
RunningMedian humidtSamples = RunningMedian (100);
/****************************************************************************/
//                     Blynk Server Definitions and Variables
/****************************************************************************/
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>

BlynkTimer timer;
WidgetRTC rtc; // Required for Real-time clock widget

#ifndef APSSID
//#define APSSID <id>
//#define APPSK  <password>
#endif


const char *ssid = APSSID;
const char *password = APPSK;
const char transmitterAuth[] = "<auth token>";      // Used for connecting to Local Blynk Server
const char server[] =  "<ip>";   // IP Address of Server
const int port = <port>;

int cropSelectorId = 0;

#define RED "#F44336"
#define YELLOW "#FFEB3B"
#define GREEN "#00E676"
#define GREY "#808080"
#define BLUE "#03A9F4"
#define BLACK "#000000"
#define WHITE "#FFFFFF"

#define TEMPRT_GAUGE V10
#define HUMIDT_GAUGE V11
#define SOIL_MOIST_GAUGE V12

WidgetLED ACTIVE_LED (V15);

#define LIGHTS_BUTTON V20
#define AUTOMATE_BUTTON V21
#define MISTING_PUMP_BUTTON V22
#define CROP_SELECTION_LIST V25

// Outgoing Bridge to power controller
#define POWER_CONTROLLER_AUTH_TOKEN "<Auth token of power controller>"  // Authentication token of power controller
WidgetBridge POWER_CONTROLLER_BRIDGE (V40);  // The virtual pin assigned on this device
#define MISTING_PUMP_BRIDGE_PAIR V0 // The virtual pin assigned on the other device. MUST match the pin set on the other device
#define LIGHTS_BRIDGE_PAIR V1 // The virtual pin assigned on the other device. MUST match the pin set on the other device

// Incoming Bridge
#define WEATHER_BRIDGE_PAIR V50
#define PUMP_STATE_BRIDGE_PAIR V51

#define MIN_TEMPRT_SETTING V90
#define MAX_TEMPRT_SETTING V91
#define MIN_HUMIDT_SETTING V92
#define MAX_HUMIDT_SETTING V93

WidgetTerminal TERMINAL (V100);

/****************************************************************************/
//                                  Setup
/****************************************************************************/
void setup() {
  Serial.begin(9600);
  Serial.println ("Initializing Interior Controller");
  //TERMINAL.println ("Initializing Interior Controller");
  pinMode (LED_BUILTIN, OUTPUT);
  pinMode (SM_PIN, INPUT);

  CONNECT_BLYNK();
  Serial.println(F("Connection with Blynk Server --------------------------- OK"));
  //TERMINAL.println (F("Connection with Blynk Server --------------------------- OK"));


  adc.begin(SCK, MOSI, MISO, SS); // Specify SPI pins for MCP3008 ADC chip

  // Start the DHT sensors
  dht1.begin();
  dht2.begin();


  // Initial readout
  READ_DHT_TEMP ();
  READ_SOIL_MOIST();
  CONTROL();
  WRITE_TO_BLYNK();

  //  // Try to use timer instead of calling function in the loop()
  timer.setInterval (5499, READ_DHT_TEMP);
  timer.setInterval (5499, READ_SOIL_MOIST);
  timer.setInterval (2000, CONTROL);
  timer.setInterval (5000, WRITE_TO_BLYNK);

}

/****************************************************************************/
//                                 LOOP*
/****************************************************************************/

void loop() {
  activeFlag = true;
  Blynk.run();
  timer.run();

  // To handle scenarios when millis gets resetted back to zero (This will only happen once every ~50 days). If so, set new end time for scheudledEndTimer
  if (millis() < errorTimer || millis() < notificationTimer) {
    errorTimer = millis();
    notificationTimer = millis();
  }

  //Protection from unintetional disconnect from server. Attempt to reconnect after that.
  while (!Blynk.connected()) {
    activeFlag = false;
    digitalWrite (LED_BUILTIN, LOW);
    PRINT_ERROR ("001");
    CONNECT_BLYNK();
    if (!Blynk.connected()) delay (1000); // If still not connected, wait for 1 second
  }


  TERMINAL.flush();
  delay (10);
}

This clearly isn’t the full sketch, as what you’ve posted is missing some key functions such as:
void CONNECT_BLYNK()
void READ_DHT_TEMP()
void READ_SOIL_MOIST()
void CONTROL()
void WRITE_TO_BLYNK()

As a result its difficult to tell exactly what programming errors you’re making which could lead to the reset issues you’ve described, but here’s one…

I’m going to take a step back from this thread, as I’m finding it frustrating to only be given snippets of code without any acknowledgement that the code is incomplete.
Also, I’m not really interested in providing free coding consultancy to allow you to develop your commercial product.

Good luck with the project.

Pete.

1 Like