Wednesday, June 13, 2018

On the move...

I'm moving this blog over to noeldodd.com ... updates should be happening over there... stand by for an update when the dust has settled!

Thursday, November 16, 2017

ESP-8266 and Solving WDT Resets

So without adding much more complexity than WiFi to an ESP8266 sketch, you might get some WDT errors; if you have a serial link you can see the restart message, if not you might just notice a hang followed by a restart. Or not; if the hang is short enough but at the wrong (right?) time, you'll just get a restart.

Long story short: Writing software for the ESP8266 isn't like writing a blink sketch for an Arduino. But it's also not much different than writing a WiFi sketch for an Arduino, either. I think the primary difference is the libraries and Espressif SDK underpinning the ESP are a bit more complex, and it includes a hardware / software watchdog. If the watchdog timer expires, the system assumes that something hung, and restarts to recover.

There are some voodoo-type references to peppering your code with delay() and yield() statements to solve this. What I've done is wrap them in a simple function that manages  when to execute them.

There is one global (counter) and  you can call WDTPulse() whenever you might have a long running routine that won't quickly exit. Inside there is also a call to ESP.wdtFeed(), this requires no special #includes or other declarations as it's declared extern . It really does seem to feed the watchdog.

long counter;

// ******************************** wdt pulse ********************************
void WDTPulse() {
  if ( (counter % 100000) == 0 ) {
    ESP.wdtFeed();
    yield();
    delay(1); 
  }
  counter++;
}

// Example of use; within the possibly-never-ending WiFi setup:
while (stat != WL_CONNECTED) {
  WiFi.begin(ssid, pass);
  WiFi.waitForConnectResult();
  stat = WiFi.status();
  WDTPulse();
}


Or the as yet not totally tested version, which might be better....

// ******************************** wdt pulse ********************************
void WDTPulse() {
  if ( (counter % 100000) == 0 ) {
    ESP.wdtFeed();
    delay(1); 
  }
  yield();
  counter++;
}

Wednesday, November 15, 2017

ESP-8266 - Using UDP as a replacement for serial port debugging messages

The ESP-01 isn't exactly bristling with I/O pins, and running out of pins is a given. Assigning an entire pin for serial debugging output seems silly, so here is a thought; just send the strings via UDP to your workstation instead.

Below are two ways to do this.

In the first instance I'm using a String class which can copy itself to a global buffer, which is fine for quick-n-dirty messages, but as you'll see it is cumbersome for including variables.

It's just as easy to skip the String parameter and use sprintf to pre-fill the global char buffer. You get variable formatting with sprintf for free, too. Either way works and has a place. Unless you *really* hate the String class (some folks do).

// UDP_Test - Noel Dodd 2017
// One day I'll put this on git but for now, enjoy.


#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#define UDP_BUFFER_SIZE 256
#define DEBUG_PORT 10101
WiFiUDP UDP;
char udpBuffer[UDP_BUFFER_SIZE];
IPAddress logIP ( 172, 16, 25, 1 ); // Hardcoded destination IP address

uint8_t counter;

// ************ setup ****************
void setup() {
  // init
  counter = 0;

  // Do WiFi setup; hardcoded here for brevity
  IPAddress ip = IPAddress(172,16,25,100);
  IPAddress gw = IPAddress(172,16,25,1);
  IPAddress subnet = IPAddress(255,255,255,0);
  IPAddress dns = IPAddress(172,168,25,1);

  WiFi.persistent(false);
  WiFi.setAutoConnect(true);
  WiFi.mode(WIFI_STA);
  WiFi.config(ip,gw,subnet,dns); 
  
  int stat = WiFi.status();
  
  while (stat != WL_CONNECTED) {
    WiFi.begin("ssid", "pass");    // replace with real ssid, pass
    WiFi.waitForConnectResult();
    stat = WiFi.status();

    // optionally blink an LED here
    delay(50);
  }
  
  // Log that we are done, String method
  UDPSend( "Setup complete..." );  
}

// ************ Loop ****************
void loop() {
   // Log something (messy way, with Strings)
   String val = String(counter,DEC);
   String msg = String("String counter = " + val );
   UDPSend( msg );

   // Log something else (tidy, with sprintf)
   sprintf( udpBuffer, "Variable counter = %i", counter );
   UDPBufSend ( );

   // Do some work...
   delay(500);

   // Inc counter to see it work; let it wrap over 255
   counter++;
}

// ************ UDPSend ****************
void UDPSend ( String msg ) {

  // copy msg into buffer
  msg.toCharArray( udpBuffer, UDP_BUFFER_SIZE );
  
  UDP.beginPacket( logIP, DEBUG_PORT );
  UDP.write( udpBuffer, UDP_BUFFER_SIZE );
  UDP.endPacket();
  
}


// ************ UDPBufSend ****************
void UDPBufSend ( ) {

  UDP.beginPacket( logIP, DEBUG_PORT );
  UDP.write( udpBuffer, UDP_BUFFER_SIZE );
  UDP.endPacket();
  
}