Author Topic: One last try...  (Read 7599 times)

crambo

  • Jr. Member
  • **
  • Posts: 52
One last try...
« on: December 11, 2016, 09:03:45 am »
Does anyone have an example of code that can work and not crash that can do the following:

Get NTP time
Control some number of WS2812 LEDs
(NOT CRASH. Yes, it can and sometimes WILL run for days, but more likely it will not and crash within hours)

I thought making a clock should have been one of the simpler projects one could undertake, aside from the blink sketch....

kh

  • Jr. Member
  • **
  • Posts: 64
  • OakTerm developer
Re: One last try...
« Reply #1 on: December 11, 2016, 01:50:25 pm »
Sorry, I don't have any example code, but this sounds like an application where you need a watchdog timer. Even if your code and the firmware is completely bug-free, you still can't expect it to run forever without crashing. A power fluctuation, intense EMI, or a cosmic ray could still cause a crash.

This is where watchdog timers come in. All mission critical embedded systems use them. The watchdog timer is continually counting down, and if the timer reaches zero, it will trigger a reboot. In the main loop of your code, you reset the watchdog timer, so that, while your code working properly, the timer will never reach zero.

Unfortunately, while the Oak chip definitely does have a watchdog timer, I'm not sure if the firmware currently lets the user access it. PeterF talked about it in this post, so hopefully he might be able to dig into this a little further.

crambo

  • Jr. Member
  • **
  • Posts: 52
Re: One last try...
« Reply #2 on: December 11, 2016, 02:07:27 pm »
I would love for the Oak to be able to reboot itself, if such possibility exists... I will start googling, I guess.

crambo

  • Jr. Member
  • **
  • Posts: 52
Re: One last try...
« Reply #3 on: December 11, 2016, 02:11:12 pm »
Huh, from the few sources I have found the WDT is enabled by default. It seems to be there for this very reason...However, it sure isn't working. Once frozen, the interface is inaccessible and the program seems to be frozen and noting gets to Particle ....

Is there special sauce that the Oak is missing?

PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: One last try...
« Reply #4 on: December 12, 2016, 02:51:15 am »
God dang it... the Oak SHOULD have a WDT... but why it don't work I don't know... I checked it out, and it don't look like the software WDT is working... and from the timeline for the Oak development, it should have been present in it's code (and does appear to be present somewhat... there isn't a compiler error when you try to configure it)... but I couldn't get it to trigger. Even a dumb while(1) didn't seem to trip it!  :o I'm surprised that didn't trip my Oak even in its auto reboot into safe mode...

Just for giggles, I've loaded an oak with a neopixel version of the standard Arduino blink sketch, to see how long it runs before failing... I'm curious if the near constant 1000 millisecond delays allow it to run without issue... whatever the issue is... it is somehow neopixel related, as I have two other units - one running a TFT LCD and another with a NRF transceiver on it, and they have been running for weeks without any hiccups, with code that is always running (as opposed to my other two units with deepSleep and reset code).

crambo

  • Jr. Member
  • **
  • Posts: 52
Re: One last try...
« Reply #5 on: December 12, 2016, 06:58:35 pm »
PeterF,

I really do appreciate the degree to which you look into stuff. For giggles, I have been running a straight up LED on Pin1 going HIGH/LOW every 1000ms getting time from NTP to see if it is Neopixel related. It has been running two days, not a hiccup....

Will update if that changes, but it really feel like a timing issue related to Neopixels...

-Cam

PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: One last try...
« Reply #6 on: December 13, 2016, 08:41:07 pm »
Well, the neopixel oak fell over overnight... but just to be sure, I'll let it run again just to make sure... as it could have been the powerbank it was running on shutting down. And I've just set another one off with a NTP time routine doing a regular 1 sec on, 1 second off led pulse on the normal built-in led. I'm getting a periodic message on OakTerm every five minutes saying it's requesting the time, it's getting a response, and then the current time, so it appears to be working just fine. Now to see what the mileage is on it! ;)

Code: [Select]
/*
   Time_NTP.ino
   Example showing time sync to NTP time source

   This sketch uses the ESP8266WiFi library
*/

#define DEBUG
#define DEBUG_OI Particle

#ifdef DEBUG
#define   DebugBegin(...) DEBUG_OI.begin(__VA_ARGS__)
#define   DebugPrint(...) DEBUG_OI.print(__VA_ARGS__)
#define   DebugPrintln(...) DEBUG_OI.println(__VA_ARGS__)
#else
// Define the counterparts that cause the compiler to generate no code
#define   DebugBegin(...) (void(0))
#define   DebugPrint(...) (void(0))
#define   DebugPrintln(...) (void(0))
#endif

#include <TimeLib.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// NTP Servers:
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov

const int timeZone = 10;     // Australian Eastern Standard Time

WiFiUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets

long lastUpdate = 0, lastBlink = 0;
long updateInterval = 5 * 60 * 1000;
long blinkInterval = 1000;
bool firstRun = true;

void setup()
{
  DebugBegin();

  pinMode(1, OUTPUT);
  digitalWrite(1, LOW);

  Particle.publish("oak/startup", "TimeNTP Example", PRIVATE);

  DebugPrintln("Starting UDP");
  Udp.begin(localPort);
  DebugPrint("Local port: ");
  DebugPrintln(Udp.localPort());
  DebugPrintln("waiting for sync");
  setSyncProvider(getNtpTime);
}

void loop()
{
  if (millis() - lastUpdate > updateInterval || firstRun)
  {
    firstRun = false;
   
    if (timeStatus() != timeNotSet)
    {
        digitalClockDisplay();
    }
    else
    {
      DebugPrintln("Haven't gotten time sync???");
    }

    lastUpdate = millis();
  }

  if (millis() - lastBlink > blinkInterval)
  {
    digitalWrite(1, !digitalRead(1));
    lastBlink = millis();
  }
}

void digitalClockDisplay() {
  // digital clock display of the time
  DebugPrint(hour());
  printDigits(minute());
  printDigits(second());
  DebugPrint(" ");
  DebugPrint(day());
  DebugPrint(".");
  DebugPrint(month());
  DebugPrint(".");
  DebugPrint(year());
  DebugPrintln();
}

void printDigits(int digits) {
  // utility for digital clock display: prints preceding colon and leading 0
  DebugPrint(":");
  if (digits < 10)
    DebugPrint('0');
  DebugPrint(digits);
}

/*-------- NTP code ----------*/

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

time_t getNtpTime()
{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  DebugPrintln("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      DebugPrintln("Receive NTP Response");
      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;
    }
  }
  DebugPrintln("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  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
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

crambo

  • Jr. Member
  • **
  • Posts: 52
Re: One last try...
« Reply #7 on: December 14, 2016, 09:57:58 am »
Are you using a voltage levelshifter in your set up? Could the differential of the 3.3v signal and the 5v supply to the  leds be the issue? Shouldn't all outputs be 5v? Its weird because I have a version of this clock running on a arduino nano with an RTC, and it too has the difference of voltage on the data pin and the 5v supply. It has been running for months ...but without NTP.....:(

My test with FastLED ran for many hours but it too eventually locks up. The OakTerm shows:

Event: spark/status - online
Event: spark/status - offline
Event: spark/status - online

Going up and down, and yet the unit is frozen.


PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: One last try...
« Reply #8 on: December 14, 2016, 03:50:20 pm »
No, no level shifter.. just a 24 neopixel ring attached directly to the Oak, and sending data for just one pixel/led. As long as the first pixel accepts the data, the lower voltage I/O  isn't an issue, as it will boost the voltage and transmit the data to the next pixel itself (and so on down the strip/ring). It appears that as long as the supply voltage is less than 2x the logic voltage, we can get away with different voltages. All that would happen if that went wrong is the LEDs would display wrong colours, or simply do strange things, the Oak should keep plodding along doing it's thing.

It looks like something has happened with the Oak that has gotten it constantly rebooting, hence the offline/online state. Was the P1 LED on the Oak doing anything (i.e. triple blink) at that time... as perhaps it rebooted into safe mode? There is a glitch in safe mode where it will sometimes do that for a while, and then settle down... something to do with the OTA firmware update that wasn't disabled in the config/mode side of things.

crambo

  • Jr. Member
  • **
  • Posts: 52
Re: One last try...
« Reply #9 on: December 16, 2016, 07:04:49 pm »
Hi PeterF,

No, P1 led (also wired to LED) didn't do anything irregular. It would come one occasionally during the online/offline bit, but would never provide any meaningful state. It seemed more like it was stalling in the execution of the sketch rather than rebooting, but it well may have been.

That is very interesting regarding the voltage of the signal wire. It make sense that it would eventually have access to 5V, given that v and gnd on the pixels are 5v. Did you find that in a ws2812 spec sheet?

PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: One last try...
« Reply #10 on: December 16, 2016, 08:44:56 pm »
Ok, if it was just doing random stuff, the Oak was probably just constantly crashing and rebooting.

No the reference to supply voltage being less than 2x logic voltage (i.e. if supply is 5v, logic must be more than 2.5v - and Oak is 3.3v)  was not from the datasheet... it was on the Adafruit forums where customers had been asking about powering and controlling neopixels.

pippin88

  • Newbie
  • *
  • Posts: 7
Re: One last try...
« Reply #11 on: December 22, 2016, 09:22:34 pm »
I'm running into a crashing issue, I think in similar circumstances.

I'm building a clock also, with WS2812b LEDs (Neopixels) and a DS3231 RTC. I'm also using a BH1750 light sensor to adjust the LED brightness to the room conditions.
The code worked fine on an arduino pro mini, but I wanted NTP so switched to an oak. The oak works, but crashes about 15-30 mins after being turned on. I haven't actually put in any code for NTP yet.

I'm powering from my PC powersupply at 12v to a 5v 25a DC converter. The oak is powered via VIN. I'm using a level shifter to on the output pin to the neopixels.

http://pastebin.com/7iJ0qk8T

PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: One last try...
« Reply #12 on: December 22, 2016, 10:43:11 pm »
Is it possible to substitute the Adafruit NeoPixel library for Makun's NeoPixelBus one? Cam seems to have had success by using it instead of the Adafruit NeoPixel library, which isn't unsurprising as there are ESP8266 (thus Oak) specific optimisations present. It is apparently a near drop-in replacement - just a change of the library include line, but I haven't tried it myself yet...

Edit: typo
« Last Edit: December 23, 2016, 01:38:47 am by PeterF »

emardee

  • Full Member
  • ***
  • Posts: 135
Re: One last try...
« Reply #13 on: December 23, 2016, 12:56:01 am »
For reference: I'm also running neo-pixels directly off the 3.3v pins for signal (eg without a level shifter) and they are running fine. I power the Oak and Neo-pixels  from the same 5v psu. That might simplify your circuit slightly (although should affect stability, but might make packaging it neater)

pippin88

  • Newbie
  • *
  • Posts: 7
Re: One last try...
« Reply #14 on: December 23, 2016, 11:11:06 pm »
I'm attempting to switch to NeoPixelBus.

Got the basics working, but cannot for the life of my figure out the animations. I'm building a word clock, and have the words fade in. I can get NeoPixelBus to turn on the LEDs fine, with no animation, but cannot work out how to do the fading.

Does not seem to crash with NeoPixelBus, but more time needed to see.