Example sketches for the new Arduino IDE for ESP8266

Moderator: igrr

User avatar
By mrburnette
#29151 This is a work in progress; which is to say it works but is not stable... the AP will eventually "hang" and it is not likely a stack issue as the console continuously shows free memory greater than 20K... 26784 generally but occasionally changes are displayed ... every 10K loop.

Note: the sketch originally had an HTTP webserver, too. I removed this code looking for the instability - the webserver was not at fault, but I have not replaced the code... references remain.

The code requires Streaming.h from
http://arduiniana.org/libraries/streaming/
and
the Utility library from this source:
https://github.com/internetofhomethings/ESP8266-WeatherSensor-Webserver/blob/master/UtilityFunctions.h

I am using a Chinese U-blox 6 GPS running at 1PPS with the serial at 9600 BAUD. IF your GPS processes faster than 1PPS, you should reprogram it to 1PPS - see your user manual.

Essentially, I set up an AP and a UDP broadcast to 255.255.255.255 which is reasonably easy using this code:
Code: Select all/*
   GPS Portal, part of Tardis Time Server by: M. Ray Burnette 20150915
   Create a private 10. network and capture all DNS requests to the Time Portal
   Respond to UDP and DHCP and DNS
   Compiled under Arduino 1.6.6 Hourly build 2015/09/04 04:42
    Sketch uses 340,080 bytes (78%) of program storage space. Maximum is 434,160 bytes.
    Global variables use 50,796 bytes (62%) of dynamic memory, leaving 31,124 bytes for local variables. Maximum is 81,920 bytes.
*/

#define LEDpin 2                                                // ESP82660-1 8-pin module LED is on GPIO-02
#include <Streaming.h>                                          // \Documents\Arduino\libraries\Streaming (legacy)
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <DNSServer.h>
#include "./Utility.h"                                          // See Notes tab for credits

const byte   DNS_PORT  =   53;                                  // Listen DNS requests on port 53
int          ack_Count =    0;
int          counter;
uint8_t      hour, minute, seconds;                             // hour, minure, seconds,
uint8_t      day, month, year;                                  // year, month, day;
unsigned int localPort = 8888;                                  // any unused port on LAN
IPAddress    apIP(10, 10, 10, 1);                               // Private network address: local & gateway
IPAddress    broadcastIP(255, 255, 255, 255);

char         packetBuffer[UDP_TX_PACKET_MAX_SIZE];              // buffer to hold incoming packet,
char         ReplyBuffer[] = "????????????";                    // a 12 character string to send back

DNSServer         dnsServer;                                    // Create the DNS object
WiFiUDP           UDP;                                          // UDP protocol on STA interface, localPort

extern "C" {
  #include "user_interface.h"                                   // used for diagnostic ESP.getFreeHeap()
}


void setup()
{
  Serial.begin(9600);                                           // Initialise Serial connection
  Serial << (F("2015 Ray Burnette")) << endl;
  Serial << (F("Tardis Time Portal Version 0.20150915")) << endl;
  Serial << (F("Visit my project web page on http://www.hackster.io/rayburne")) << endl << endl;

  WiFi.mode(WIFI_AP_STA);                                       // AP + STA
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));   // subnet FF FF FF 00
  WiFi.softAP("TardisTime");

  dnsServer.start(DNS_PORT, "*", apIP);                         // "*" creates a captive portal

  while (! UDP.begin(localPort) ) {                             // UDP protocol connected to localPort which is a variable
    Serial << "+" ;
    yield();                                                    // Play nicely with RTOS (alias = delay(0))
  }                                                             // This will loop forever if UDP fails

  Serial << endl;
  Serial << (F("Setting pin#2 to Output mode")) << endl;
  pinMode(2, OUTPUT);                                           // initialise pin mode
}


void loop()
{
  dnsServer.processNextRequest();                               // TCP Address handler when requested
  yield();                                                      // yield for RTOS
//  Listener();                                                   // UPD (can you hear me now?)
//  yield();

  if (Serial.available() > 0) {                                 // anything in the serial hw buffer?
      char c = Serial.read();                                   // if so, fetch the next character from FIFO
      GPSstuff(c);
  }

  yield();
  ++counter;

  if (counter > 9999) {                                         // for diagnostics, no other purpose
    long int RAM = ESP.getFreeHeap();
    Serial << "Free= " << RAM << endl;
    counter = 0;
    digitalWrite(LEDpin, !(digitalRead(LEDpin)));               // blink LED (Warning: using ESP8266-01 module)
    yield();
  }
}                                                               // loop repeats forever unless stack crashes or uC hangs


void GPSstuff(char c) {                                         // GPSbuffer[] is global
  static int i, j;                                              //   persistent within function scope
  static char q;
  static bool flag = false;
  static char GPSbuffer[120];                                   // GPS serial line input buffer
  q = c;

  if ( q == 0x24 )                                              // '$'
  {
    i = 0;                                                      // brute force sync on '$' to GPSbuffer[0]
    // Serial << "Found $" << endl;
  }

  if ( i < 120) GPSbuffer[i++] = q;
  // Serial << "Index=" << (i -1) << "Input=" << q << endl;
  //if (i = 120) i = 119;                                       // array limit safety

  if (q == 0x0d) {
    flag = true;                                                // is the character a CR for eol
    i = 0;
  }

  if (flag) {                                                   // test for end of line and if the right GPSbuffer
    flag = false;                                               // reset for next time
    UDP.beginPacketMulticast(broadcastIP, localPort, apIP);
    // Serial << "We are in the flag routine..." << GPSbuffer[3] << GPSbuffer[4] << GPSbuffer[5] << endl;
    // Serial << "Analyzing " << GPSbuffer[3] << GPSbuffer[4] << GPSbuffer[5] << endl;
    if ( (GPSbuffer[3] == 0x52) && (GPSbuffer[4] == 0x4d) && (GPSbuffer[5] == 0x43)) // 'R' && 'M' && 'C'
    {
      for (j = 0; j < 120 ; j++) {
        UDP.write(GPSbuffer[j]);
      }
      UDP.write("\r\n");                                        // terminate the line
      UDP.endPacket();                                          // clear UDP buffer
    }
  }
}


A remote PC is now being used as the GPRMC receiver but eventually this will be replaced with another ESP8266 (one or more) that will parse the time/date fields and format them for a nice clock display.

The test code for the PC using Processing 3 alpha:
Code: Select all// Processing UDP example to send and receive binary data
// https://thearduinoandme.wordpress.com/t utorials/esp8266-send-receive-binary-data/
// Badly hacked by Ray B. to display the UDP broadcast from ESP8266

import hypermedia.net.*;             // http://ubaa.net/shared/processing/udp/udp_class_udp.htm

String ip = "10.10.10.1";            // the remote IP address of ESP8266
int port = 8888;                     // the destination port - any unused port
long previousMillis = 0;
long interval = 500;

UDP udp;


void setup() {
  udp = new UDP(this, 8888);
  udp.listen( true );
}

void draw() {
    if (previousMillis < millis() - interval) {
      previousMillis = previousMillis + interval;

        byte[] message = new byte[2];
        message[0] = 0; message[1] = 0;
        udp.send(message, ip, port);
    }
}

void keyPressed() {
  if (key == '-')
  {
      byte[] message = new byte[2];
      message[0] = 0; message[1] = 0;
      udp.send(message, ip, port);
  }
}

void keyReleased() {
  if (key != '-') {
      byte[] message = new byte[2];
      message[0] = 0; message[1] = 0;
      udp.send(message, ip, port);
  }
}

void receive( byte[] data ) {        // <– default handler
  for (int i=0; i < data.length; i++)//void receive( byte[] data, String ip, int port ) { // <– extended handler
      print(char(data[i]));
  println();
}


The above code is from a Processing example - I am not the author but I surely did hack it.

To test: set up the AP with the GPS feeding URXD. I used the -01 model and put a led on GPIO2 with GPIO0 remaining used for the bootloader only. UTXD is going to a serial-USB to the PC for monitoring with the terminal emulator set at 9600 BAUD.

Connect to the AP from the remote PC by selecting the AP name: TardisTime
Load the Processing Script
Compile/Run the script
That should be it. Eventually, this sketch will be added to my projects blog on:
http://www.hackster.io/rayburne
https://www.hackster.io/rayburne/tardis-time-esp8266-ap-webserver-gps
Ray
You do not have the required permissions to view the files attached to this post.