Post topics, source code that relate to the Arduino Platform

User avatar
By Nirodam
#87301 I made a digital clock that uses neopixels to display 6 different digits. Everyone in the code seems to work as intended. Time is kept via NTP. Temp and humidity is measured and recorded through IFTTT to a google sheet. OTA updates can be made from Arduino.

The issue I am having is the device will not run longer than about 12 hours before it triggers a Hardware Watchdog Error ... " epc1:0x401030e1 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000000 depc:0x00000000"

I have also seen this error...

Fatal exception:29 flag:2 (Exception) epc1:0x4000df64 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000000 depc:0x00000000

I have gone through the code over and over and I cannot see anything that would cause it to hang. My assumption is that the device is running out of memory from the way I coded it. I am very new to programming and do not know how to trouble shoot it any further. Any help or input would be greatly appreciated!

Code: Select all/*
   LED NeoPixel Digital Clock
   OTA password = esp8266

   static const uint8_t D0 = 16;  = Built-in LED on main board (Set in "Tools")
   static const uint8_t D1 = 5;   = NeoPixel Data Pin
   static const uint8_t D2 = 4;   = Push Button
   static const uint8_t D3 = 0;   = Flash button (INPUT_PULLUP & LOW if pressed)
   static const uint8_t D4 = 2;   = Built-in LED next to Wifi (Set in "Tools")
   static const uint8_t D5 = 14;
   static const uint8_t D6 = 12;  = DHT Pin
   static const uint8_t D7 = 13;
   static const uint8_t D8 = 15;  (must be disconnected during upload)
   static const uint8_t D9 = 3;
   static const uint8_t D10 = 1;

    Library https://github.com/esp8266/Arduino
*/

//##########################   Library/Variables   ###################################//

/***************************   WiFi  ********************************************/
#include <ESP8266WiFi.h>
#define STASSID "SSID"   // I removed my SSID and Password
#define STAPSK  "PASSWORD"
const char* ssid     = STASSID;
const char* password = STAPSK;


/***************************   OTA   ********************************************/
#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>


/***************************   NeoPixel  ****************************************/
#include <Adafruit_NeoPixel.h>
#define LED_PIN    5                                        // Which pin on the Arduino is connected to the NeoPixels?
#define LED_COUNT  130                                      // How many NeoPixels are attached to the Arduino?
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
long firstPixelHue = 0;
byte brightnessLED = 128;                                   // Ranges 0 to 255 - Adjustable by button
unsigned int clockColor = 0;                                // Ranges 0 to 65535
const int colorChangeAmount = 65536 / 6;
int colorWipePixel = 0;
int colorWipeColor = 0 + colorChangeAmount;
int prevWipeColor = 0;
// red = 0, yellow = 10923, green = 21845, sky blue = 32768, blue = 43691, purple = 54613


/***************************   Time  ********************************************/
#include <TimeLib.h>
#include <WiFiUdp.h>
static const char ntpServerName[] = "us.pool.ntp.org";
//const int timeZone = -5;                  // Eastern Standard Time (USA)
const int timeZone = -4;                    // Eastern Daylight Time (USA)
WiFiUDP Udp;
unsigned const int localPort = 8888;        // local port to listen for UDP packets
time_t prevDisplay = 0;                     // when the digital clock was displayed
byte hourPM = 0;
const int NTP_PACKET_SIZE = 48;             // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE];         // buffer to hold incoming & outgoing packets
byte currentMinute = 0;
byte previousMinute = 0;


/***************************   Button  ******************************************/
#define button 4
byte buttonPushCounter = 0;                 // counter for the number of button presses
unsigned long buttonTimer = 0;
const int longPressTime = 500;              // time to hold button for secondary action
boolean buttonActive = false;
boolean longPressActive = false;


/***************************   Temp/Hum  ****************************************/
#include "DHT.h"
#define DHTPIN  12                          // ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
#define DHTTYPE DHT22                       // DHT 22  (AM2302),
DHT dht(DHTPIN, DHTTYPE);
//change to float if you want decimal and adjust Temperature() and Humidity() functions
int humid = 0;                              //Humidity
float Humid = 0;
int tempC = 0;                              //Temperature as Celsius
int tempF = 0;                              //Temperature as Fahrenheit
float TempF = 0;
const int dhtScanRate = 500;               //Time between measurements
unsigned long tempLastMillis = 0;
unsigned long humidLastMillis = 0;
const int tempAdj = -2;                     //Number of degrees to adjust temperature


/***************************   IFTTT  *******************************************/
const char* resource = "/trigger/ENV_Reading2/with/key/*********";   //  I removed my key here
const char* server = "maker.ifttt.com";                    // Maker Webhooks IFTTT
String EspReset = "";


/***************************   Variables  ***************************************/
const bool digit[15][21] =  {
  // 1      2      3      4      5      6      7
  {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 0
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 1
  {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1}, // 2
  {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, // 3
  {1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 4
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0}, // 5
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 6
  {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 7
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 8
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, // 9
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Blank
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, // F
  {1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1}, // H
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // upper circle
  {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // lower circle
};

byte pixelNumber[130];

byte digitOne =  0;    //variable to designate which number to show
byte digitTwo =  0;    //variable to designate which number to show
byte digitThree =  0;  //variable to designate which number to show
byte digitFour =  0;   //variable to designate which number to show
byte digitFive =  0;   //variable to designate which number to show
byte digitSix =  0;    //variable to designate which number to show
/*
  byte green  =  0;      //variable to control green pixels
  byte red    =  0;      //variable to control red pixels
  byte blue   =  0;      //variable to control blue pixels
*/
unsigned long currentMillis = 0;


/***************************   EEPROM  ******************************************/
#include <EEPROM.h>
int addr = 0;



//##########################   Setup  ############################################//
void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  /***************************   EEPROM  ******************************************/
  EEPROM.begin(16);                       // Number of bytes allocated for EEPROM
  buttonPushCounter = EEPROM.read(addr);
  addr++;                                 // Changes from 0 to 1
  brightnessLED = EEPROM.read(addr);

  /***************************   Button  ******************************************/
  pinMode(button, INPUT);

  /***************************   Temp/Hum  ****************************************/
  dht.begin();

  /***************************   WiFi  ********************************************/
  WiFi.setAutoReconnect (true);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  digitalWrite(LED_BUILTIN, HIGH);

  /***************************   OTA   ********************************************/
  ArduinoOTA.setHostname("ESP8266");
  ArduinoOTA.setPassword("esp8266");
  ArduinoOTA.onStart([]() {
    addr = 0;                                //button address = 0
    EEPROM.write(addr, buttonPushCounter);
    addr++;                                  //brightness address = 1
    EEPROM.write(addr, brightnessLED);
    EEPROM.commit();
    digitalWrite(LED_BUILTIN, LOW);
  });
  ArduinoOTA.onEnd([]() {
    for (byte i = 0; i < 5; i++) {
      delay(250);
      digitalWrite(LED_BUILTIN, HIGH);
      delay(250);
      digitalWrite(LED_BUILTIN, LOW);
    }
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
  });
  ArduinoOTA.onError([](ota_error_t error) {
    ESP.restart();
  });
  ArduinoOTA.begin();

  /***************************   NeoPixel  ****************************************/
  strip.begin();                // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();                 // Turn OFF all pixels ASAP
  strip.setBrightness(255);     // Set BRIGHTNESS (max = 255)
  strip.clear();                // Clear the pixels

  /***************************   Time  ********************************************/
  Udp.begin(localPort);
  setSyncProvider(getNtpTime);
  setSyncInterval(60 * 20 * 1);     // seconds * minutes * hours

  /***************************   IFTTT  *******************************************/
  EspReset = ESP.getResetInfo();
  //jsonObject.reserve(300);
}


//##########################   Loop   ############################################//
void loop() {
  currentMillis = millis();
  buttonControl();
  ArduinoOTA.handle();

  switch (buttonPushCounter) {
    case 0:
      runClock();
      singleColor(10);
      break;
    case 1:
      runClock();
      rainbow(10);
      break;
    case 2:
      runClock();
      colorWipe(20);
      break;
    case 3:
      Temperature();
      singleColor(10);
      break;
    case 4:
      Humidity();
      singleColor(10);
      break;
  }

  /***************************   IFTTT  *******************************************/
  currentMinute = minute();
  if (currentMinute == 0 || currentMinute == 5 || currentMinute == 10 || currentMinute == 15
      || currentMinute == 20 || currentMinute == 25 || currentMinute == 30 || currentMinute == 35
      || currentMinute == 40 || currentMinute == 45 || currentMinute == 50 || currentMinute == 55) {
    if (currentMinute != previousMinute) {
      makeIFTTTRequest();
      previousMinute = currentMinute;
    }
  }
}


//##########################   Functions   #########################################//

/***************************   Button  ******************************************/
void buttonControl() {
  if (digitalRead(button) == HIGH) {
    if (buttonActive == false) {
      buttonActive = true;
      buttonTimer = millis();
    }
    if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
      longPressActive = true;
      brightnessLED = brightnessLED - 32;                   // Brightness wraps around at 255
      addr = 1;                                             // Brightness address
      Serial.println(brightnessLED);
      EEPROM.write(addr, brightnessLED);
      EEPROM.commit();
    }
  } else {
    if (buttonActive == true) {
      if (longPressActive == true) {
        longPressActive = false;
      } else {
        buttonPushCounter++;
        if (buttonPushCounter > 4) buttonPushCounter = 0;   // Match number to the number of cases
        addr = 0;                                           // Button address
        Serial.println(buttonPushCounter);
        EEPROM.write(addr, buttonPushCounter);
        EEPROM.commit();
      }
      buttonActive = false;
    }
  }
}


/***************************   Temperature  *************************************/
void Temperature() {
  if (currentMillis - tempLastMillis > dhtScanRate) {
    TempF = (dht.readTemperature(true) + tempAdj);          //adjusted temperature
    if (isnan(TempF)) {
      TempF = tempF;
    } else {
      tempF = TempF;
    }
    tempLastMillis = currentMillis;

    digitOne = 10;
    digitTwo = 13;
    digitThree = tempF % 10;
    digitFour = ((tempF - digitThree) / 10) % 10;
    if (tempF > 100) {
      digitFive = 1;
    } else {
      digitFive = 10;
    }
    digitSix = 11;

    pixelNumber[42] = 0;
    pixelNumber[43] = 0;
    pixelNumber[86] = 0;
    pixelNumber[87] = 0;

    prepDigits();
  }
}


/***************************   Humidity  ****************************************/
void Humidity() {
  if (currentMillis - humidLastMillis > dhtScanRate) {
    Humid = dht.readHumidity();
    if (isnan(Humid)) {
      Humid = humid;
    } else {
      humid = Humid;
    }
    tempLastMillis = currentMillis;

    digitOne = 14;
    digitTwo = 13;
    digitThree = humid % 10;
    digitFour = ((humid - digitThree) / 10) % 10;
    if (humid == 100) {
      digitFive = 1;
    } else {
      digitFive = 10;
    }
    digitSix = 12;

    pixelNumber[42] = 0;
    pixelNumber[43] = 0;
    pixelNumber[86] = 0;
    pixelNumber[87] = 0;

    prepDigits();
  }
}


/***************************   Clock  ********************************************/
void runClock() {
  if (timeStatus() != timeNotSet) {
    if (now() != prevDisplay) {                     //update the display only if time has changed
      prevDisplay = now();
      clockDigits();
      prepDigits();
    }
  }
}

void clockDigits() {
  digitOne = second() % 10;
  digitTwo = (second() - digitOne) / 10;
  digitThree = minute() % 10;
  digitFour = (minute() - digitThree) / 10;
  digitFive = hourFormat12() % 10;
  digitSix = (hourFormat12() - digitFive) / 10;
  if (digitSix == 0) {
    digitSix = 10;       // 10 is blank
  }

  pixelNumber[42] = 1;
  pixelNumber[43] = 1;
  pixelNumber[86] = 1;
  pixelNumber[87] = 1;
}


/***************************   Digits  ********************************************/
void prepDigits() {
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i] = digit[digitOne][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 21] = digit[digitTwo][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 44] = digit[digitThree][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 65] = digit[digitFour][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 88] = digit[digitFive][i];
  }
  for (byte i = 0; i < 21; i++) {
    pixelNumber[i + 109] = digit[digitSix][i];
  }
}


/***************************   WiFi  ********************************************/
bool wifiConnection() {
  if (WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN, LOW);
    WiFi.disconnect();
    delay(100);
    Serial.println("Wifi Reconnecting");
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    delay(800);
    if (WiFi.status() == WL_CONNECTED) {
      digitalWrite(LED_BUILTIN, HIGH);
      return 1;
    } else {
      return 0;
    }
  } else {
    return 1;
  }
}


/***************************   NTP  *********************************************/
time_t getNtpTime() {
  if (wifiConnection()) {
    IPAddress ntpServerIP;                          // NTP server's ip address
    while (Udp.parsePacket() > 0) yield();          // discard any previously received packets
    WiFi.hostByName(ntpServerName, ntpServerIP);    // get a random server from the pool
    sendNTPpacket(ntpServerIP);
    uint32_t beginWait = millis();
    while (millis() - beginWait < 1500) {
      yield();
      int size = Udp.parsePacket();
      if (size >= NTP_PACKET_SIZE) {
        Udp.read(packetBuffer, NTP_PACKET_SIZE);    // read packet into the buffer
        unsigned long secsSince1900;                // convert four bytes starting at location 40 to a long integer
        secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
        secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
        secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
        secsSince1900 |= (unsigned long)packetBuffer[43];
        return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
      }
    }
  }
  return 0;                                        // return 0 if unable to get the time
}

void sendNTPpacket(IPAddress &address)             // send an NTP request to the time server at the given address
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE);        // set all bytes in the buffer to 0
  packetBuffer[0] = 0b11100011;                    // LI, Version, Mode
  packetBuffer[1] = 0;                             // Stratum, or type of clock
  packetBuffer[2] = 6;                             // Polling Interval
  packetBuffer[3] = 0xEC;                          // Peer Clock Precision
  packetBuffer[12] = 49;                           // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;                           // all NTP fields have been given values, now
  Udp.beginPacket(address, 123);                   //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
  Serial.println("Time Updated");
}


/***************************   NeoPixel  ****************************************/
// Input is a delay time (in milliseconds) between pixels.

void colorWipe(int wait) {                        // Fill strip pixels one after another with a color. Strip is NOT cleared first;
  for (byte i = 0; i < strip.numPixels(); i++) {  //For each pixel in strip...
    if (i > colorWipePixel) {
      clockColor = prevWipeColor;
    } else {
      clockColor = colorWipeColor;
    }
    strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(clockColor, 255, brightnessLED * pixelNumber[i])));
  }
  strip.show();                                     //Update strip to match
  colorWipePixel++;
  if (colorWipePixel > strip.numPixels()) {
    colorWipePixel = 0;
    colorWipeColor = colorWipeColor + colorChangeAmount;
    prevWipeColor = prevWipeColor + colorChangeAmount;
  }
  delay(wait);
}

void rainbow(int wait) {                            // Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
  for (byte i = 0; i < strip.numPixels(); i++) {    // For each pixel in strip...
    int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
    strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue, 255, brightnessLED * pixelNumber[i])));
  }
  strip.show();                                     // Update strip with new contents
  delay(wait);
  firstPixelHue = firstPixelHue + 256;
  if (firstPixelHue > 5 * 65536) firstPixelHue = 0;
}

void singleColor(int wait) {                       // Entire clock fades the colors of the rainbow.
  for (byte i = 0; i < strip.numPixels(); i++) {   // For each pixel in strip...
    strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(clockColor, 255, brightnessLED * pixelNumber[i])));
  }
  strip.show();

  clockColor = clockColor + 25;
  if (clockColor >= 65536) clockColor = 0;
  delay(wait);
}


/***************************   IFTTT  *******************************************/
void makeIFTTTRequest() {                       // Make an HTTP request to the IFTTT web service
  if (wifiConnection()) {
    TempF = (dht.readTemperature(true) + tempAdj);          //adjusted temperature
    Humid = dht.readHumidity();
    unsigned int runTimeSec = (currentMillis / 1000);

    WiFiClient client;
    byte retries = 5;
    while (!!!client.connect(server, 80) && (retries-- > 0)) {
      digitalWrite(LED_BUILTIN, LOW);
      delay(100);
    }
    digitalWrite(LED_BUILTIN, HIGH);

    String jsonObject = String("{\"value1\":\"") + (runTimeSec)
                        + "\",\"value2\":\"" + (TempF)  // Temperature in Fahrenheit
                        + "\",\"value3\":\"" + (Humid)
                        + " ||| " + EspReset + "\"}";

    client.println(String("POST ") + resource + " HTTP/1.1");
    client.println(String("Host: ") + server);
    client.println("Connection: close\r\nContent-Type: application/json");
    client.print("Content-Length: ");
    client.println(jsonObject.length());
    client.println();
    client.println(jsonObject);
    client.stop();
    Serial.println("IFTTT Sent");
  }
}
Last edited by Nirodam on Fri Jun 05, 2020 9:30 am, edited 1 time in total.
User avatar
By Bonzo
#87386 Thanks for coming back and posting your solution Nirodam.

I also made a clock using LED's and fastLED but not quite like yours: viewtopic.php?f=11&t=21124
It also has OTA but as it sits above my desk I can easily plug a USB cable in. But as the saying goes "If you've got it flaunt it".
I get my temp from my greenhouse via my website although it overflows the LED strip at the moment. I am updating another project and will put another temperature sensor in it so it should not go as high!