-->
Page 1 of 1

Configure WiFi from SD, Post & Display Data(OLED)

PostPosted: Tue Jan 03, 2017 10:47 am
by GengusKahn
This is using the basic examples from the Libraries to configure an ESP8266-12, this uses the NTP client and the OLED Analogue Clock as a basic starter.

Retrieving the SSID & Passphrase from files on the SDCard, this also configures the Thingspeak Write Key from a file on the SDCard.

This is using an ESP8266-12E, with a 0.96" I2C OLED Display(SSD1306), SHT21 and A Micro SDCard Breakout.

This will retrieve live Weather Data from Thingspeak provided by a Fine Offset WH1080 Weather Station located in Renfrew Scotland with MQ-2 & MQ-7 data also displayed.

The Local Data is provided by an I2C SHT21 Temperature & Humidity Sensor, this is written to a Thingspeak Channel via a simple "GET".
MQ-2 + MQ-7 Feed....
https://thingspeak.com/channels/209159
WH1080 Feed....
https://thingspeak.com/channels/168700
The Output of the Sketch is here.....
https://thingspeak.com/channels/209164


This is the sketch the Icon files should be included also......
Code: Select all/*

 Udp NTP Client

 Get the time from a Network Time Protocol (NTP) time server
 Demonstrates use of UDP sendPacket and ReceivePacket
 For more on NTP time servers and the messages needed to communicate with them,
 see http://en.wikipedia.org/wiki/Network_Time_Protocol

 created 4 Sep 2010
 by Michael Margolis
 modified 9 Apr 2012
 by Tom Igoe
 updated for the ESP8266 12 Apr 2015
 by Ivan Grokhotkov
Used as the Basis for this Sketch Jan 2017

    Connect the SDCard to the following pins on the esp8266:
  | GPIO    NodeMCU   Name  |
  ===========================
  |  15       D8       SS   |
  |  13       D7      MOSI  |
  |  12       D6      MISO  |
  |  14       D5      SCK   |
  ===========================

  Files Required on SDCard :

   ssid.txt Maximum length 24 Chars, increase if more Chars needed !!! ssid[24]
   wifipsk.txt Maximum length 32 Chars, increase if more Chars needed !!! wifipsk[32]
   thingkey.txt Maximum length 20 Chars, increase if more Chars needed !!! thingspeak_key[20]

   

    Connect the I2C to the following pins on the esp8266:
  | GPIO    NodeMCU   Name  |
  ===========================
  |  4       D3       SCL   |
  |  5       D4       SDA   |
  ===========================



 This code is in the public domain.

 */
// Include the correct display library
// For a connection via I2C using Wire include
#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
#include "HTU21D.h"
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include "ThingSpeak.h"
#include <TimeLib.h>
#include <SPI.h>
#include <SD.h>
// Include the UI lib
#include "OLEDDisplayUi.h"


char ssid[16];                      //  Storage for your network SSID (name) from SDCard
char pass[24];                      //  Strorage for your network password from SDCard   
char thingspeak_key[20];            //  Strorage for your Thingspeak Write Key from SDCard


// Include custom images
#include "images.h"

unsigned long ulNextMeas_ms;        //  Counter for loop selection, no delay......
unsigned long epoch;
unsigned int localPort = 2390;      //  local port to listen for UDP packets

/* Don't hardwire the IP address or we won't get the benefits of the pool.
 *  Lookup the IP address for the host name instead */
//IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
IPAddress timeServerIP; // time.nist.gov NTP server address
const char* ntpServerName = "time.nist.gov";

const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

// A UDP instance to let us send and receive packets over UDP
WiFiUDP udp;
WiFiClient  client;

unsigned long i2ctimer=20000;
float newval,newval1;
HTU21D myHTU21D;

// Thinspeak Channels....
unsigned long weatherStationChannelNumber = 168700;
unsigned long AirQuailityChannelNumber = 209159;

// Initialize the OLED display using Wire library
SSD1306  display(0x3c, 4, 5);

OLEDDisplayUi ui ( &display );

int screenW = 128;
int screenH = 64;
int clockCenterX = screenW/2;
int clockCenterY = (screenH/2)+5;
int clockRadius = 25;
int LcNt=0;
int cLckset=0;
float humidity,temperature,Inttemperature,Inthumidity,pressure,rainfall,windSpeed,CloudBase,Ds1,Ds2,CH4Smoke,CMonoxide;


// utility function for digital clock display: prints leading 0
String twoDigits(int digits){
  if(digits < 10) {
    String i = '0'+String(digits);
    return i;
  }
  else {
    return String(digits);
  }
}

void clockOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {

}

void analogClockFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
//  ui.disableIndicator();

  // Draw the clock face
//  display->drawCircle(clockCenterX + x, clockCenterY + y, clockRadius);
  display->drawCircle(clockCenterX + x, clockCenterY + y, 2);
  //
  //hour ticks
  for( int z=0; z < 360;z= z + 30 ){
  //Begin at 0° and stop at 360°
    float angle = z ;
    angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
    int x2 = ( clockCenterX + ( sin(angle) * clockRadius ) );
    int y2 = ( clockCenterY - ( cos(angle) * clockRadius ) );
    int x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 8 ) ) ) );
    int y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 8 ) ) ) );
    display->drawLine( x2 + x , y2 + y , x3 + x , y3 + y);
  }

  // display second hand
  float angle = second() * 6 ;
  angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
  int x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 5 ) ) ) );
  int y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 5 ) ) ) );
  display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y);
  //
  // display minute hand
  angle = minute() * 6 ;
  angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
  x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 4 ) ) ) );
  y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 4 ) ) ) );
  display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y);
  //
  // display hour hand
  angle = hour() * 30 + int( ( minute() / 12 ) * 6 )   ;
  angle = ( angle / 57.29577951 ) ; //Convert degrees to radians
  x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 2 ) ) ) );
  y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 2 ) ) ) );
  display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y);
}

void digitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  String timenow = String(hour())+":"+twoDigits(minute())+":"+twoDigits(second());
  if(CloudBase<=1500){
    display->drawString(clockCenterX + x , 10, "Cloudy" );
  }
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_24);
    if(CloudBase<=1500){
    display->drawString(clockCenterX + x , 10, "Cloudy" );
  }
  display->drawString(clockCenterX + x , clockCenterY + y, timenow );
}

void digitalLTempHumFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_16);
  display->drawString(clockCenterX + x , 10, "Local Sensor" );
  display->drawString(clockCenterX + x , 25, "Temp " + String(newval1)  );
  display->drawString(clockCenterX + x , 40, "Humid " + String(newval)  );
     
}

void digitalTempHumFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  String timenow = String(hour())+":"+twoDigits(minute())+":"+twoDigits(second());
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_16);
  display->drawString(clockCenterX + x , 10, "E-Monitor INT" );
  display->drawString(clockCenterX + x , 25, "Temp " + String(Inttemperature)  );
  display->drawString(clockCenterX + x , 40, "Humid " + String(Inthumidity)  );
     
}

void digitalETempHumFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  String timenow = String(hour())+":"+twoDigits(minute())+":"+twoDigits(second());
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_16);
  display->drawString(clockCenterX + x , 10, "E-Monitor EXT" );
  display->drawString(clockCenterX + x , 25, "Temp " + String(Ds1)  );
  display->drawString(clockCenterX + x , 40, "Humid " + String(Ds2)  );
     
}

void digitalFTempHumFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  String timenow = String(hour())+":"+twoDigits(minute())+":"+twoDigits(second());
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_16);
  display->drawString(clockCenterX + x , 10, "E-Monitor AIR" );
  display->setFont(ArialMT_Plain_10);
  display->drawString(clockCenterX + x , 25, "Barometer " + String(pressure) + " MSL" );
  display->drawString(clockCenterX + x , 40, "Wind " + String(windSpeed) + " MPH"  );
     
}

void digitalGTempHumFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  String timenow = String(hour())+":"+twoDigits(minute())+":"+twoDigits(second());
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_16);
  display->drawString(clockCenterX + x , 10, "E-Monitor Rain" );
  if(rainfall>0){
  display->drawString(clockCenterX + x , 25, "Rainfall Today" );
  display->drawString(clockCenterX + x , 40,  String(rainfall) + "MM" );
  }else{
  display->drawString(clockCenterX + x , 25, "Dry Today..."  );
  display->drawString(clockCenterX + x , 40, "So Far.... "  );       
  }
}


void digitalAQTempHumFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_16);
  display->drawString(clockCenterX + x , 10, "E-Monitor AIR-Q" );
  display->setFont(ArialMT_Plain_10);
  display->drawString(clockCenterX + x , 25, "CH4/Smoke " + String(CH4Smoke) + " PPM" );
  display->drawString(clockCenterX + x , 40, "CO " + String(CMonoxide) + " PPM"  );
     
}


// This array keeps function pointers to all frames
// frames are the single views that slide in
FrameCallback frames[] = { analogClockFrame, digitalClockFrame, digitalLTempHumFrame, digitalTempHumFrame, digitalETempHumFrame, digitalFTempHumFrame, digitalAQTempHumFrame, digitalGTempHumFrame  };

// how many frames are there?
int frameCount = 8;

// Overlays are statically drawn on top of a frame eg. a clock
OverlayCallback overlays[] = { clockOverlay };
int overlaysCount = 1;

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println();
    Serial.print(F("Initializing SD card..."));

  if (!SD.begin(15)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));
  File myFile0 = SD.open("ssid.txt");
  if (myFile0) {
    String tmsg="";
    Serial.println("ssid.txt:");
    // read from the file until there's nothing else in it:
    while (myFile0.available()) {
      tmsg=myFile0.readString();
    }
    tmsg.trim();
     int len = tmsg.length()+1;
     ssid[len];
     tmsg.toCharArray(ssid, len);
    // close the file:   
    myFile0.close();
    Serial.println(ssid);
  }
     File myFile1 = SD.open("wifipsk.txt");
  if (myFile1) {
   String tmsg1="";
    Serial.println("wifipsk.txt:");
    // read from the file until there's nothing else in it:
    while (myFile1.available()) {
      tmsg1=myFile1.readString();
    }
    tmsg1.trim();
     int len1 = tmsg1.length()+1;
     pass[len1];
     tmsg1.toCharArray(pass, len1);
    // close the file:
    myFile1.close();
    Serial.println(pass);
  }

     File myFile2 = SD.open("thingkey.txt");
  if (myFile2) {
   String tmsg2="";
    Serial.println("thingkey.txt:");
    // read from the file until there's nothing else in it:
    while (myFile2.available()) {
      tmsg2=myFile2.readString();
    }
    tmsg2.trim();
     int len2 = tmsg2.length()+1;
     thingspeak_key[len2];
     tmsg2.toCharArray(thingspeak_key, len2);
    // close the file:
    myFile2.close();
    Serial.println(thingspeak_key);
  }

  delay(250);
  Wire.begin(4,5);
  delay(250);   
    while (myHTU21D.begin() != true)
  {
    Serial.println(F("HTU21D sensor is not present"));
    delay(5000);
  }
 
  Serial.println(F("HTU21D sensor is present"));
        newval = myHTU21D.readCompensatedHumidity();
        newval1 = myHTU21D.readTemperature();
  Serial.println(F(""));
  Serial.print(F("Compensated Humidity: "));
  Serial.print(newval);
  Serial.println(F(" +-2%RH     in range 0%RH - 100%RH at tmp. range 0deg.C - 80deg.C"));

  Serial.println(F(""));
  Serial.print(F("Temperature: "));
  Serial.print(newval1);
  Serial.println(F(" +-0.5 deg.C"));

  Serial.println(F(""));
  Serial.println(F(""));
  // The ESP is capable of rendering 60fps in 80Mhz mode
  // but that won't give you much time for anything else
  // run it in 160Mhz mode or just set it to 30 fps
  ui.setTargetFPS(60);

  // Customize the active and inactive symbol
  ui.setActiveSymbol(activeSymbol);
  ui.setInactiveSymbol(inactiveSymbol);

  // You can change this to
  // TOP, LEFT, BOTTOM, RIGHT
  ui.setIndicatorPosition(TOP);

  // Defines where the first frame is located in the bar.
  ui.setIndicatorDirection(LEFT_RIGHT);

  // You can change the transition that is used
  // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN
  ui.setFrameAnimation(SLIDE_LEFT);

  // Add frames
  ui.setFrames(frames, frameCount);

  // Add overlays
  ui.setOverlays(overlays, overlaysCount);

  // Initialising the UI will init the display too.
  ui.init();

  display.flipScreenVertically();
  // We start by connecting to a WiFi network
  Serial.print(F("Connecting to "));
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.setFont(ArialMT_Plain_10);
    display.drawString(0, 0, "Connecting to .....");
    display.drawString(0, 10, ssid);
    display.display();
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(F("."));
  }
  Serial.println(F(""));
    String ipADD = "";
    for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    ipADD+=WiFi.localIP()[thisByte], DEC;
    ipADD+=".";
  }
  Serial.println(F("WiFi connected"));
  Serial.println(F("IP address: "));
  Serial.println(WiFi.localIP());
    // clear the display
  display.clear();
  display.drawString(0, 0, "WiFi  Connected to....");
  display.drawString(0, 10, ssid);
  display.drawString(0, 30, ipADD);
  display.drawString(0, 40, "Please Wait....");
  display.drawString(0, 50, "Setting Time.......");
  display.display();
  Serial.println(F("Starting UDP"));
  udp.begin(localPort);
  Serial.print(F("Local port: "));
  Serial.println(udp.localPort());
  delay(1000);
  ThingSpeak.begin(client);
  delay(10000);
  humidity = ThingSpeak.readFloatField(weatherStationChannelNumber,1);
  if(humidity!=0){Ds2=humidity;}
  temperature = ThingSpeak.readFloatField(weatherStationChannelNumber,2);
  if(temperature!=0){Ds1=temperature;}
  Inttemperature = ThingSpeak.readFloatField(weatherStationChannelNumber,3);
  Inthumidity = ThingSpeak.readFloatField(weatherStationChannelNumber,4);
  pressure = ThingSpeak.readFloatField(weatherStationChannelNumber,5);
  rainfall = ThingSpeak.readFloatField(weatherStationChannelNumber,6);
  windSpeed = ThingSpeak.readFloatField(weatherStationChannelNumber,7);
  CloudBase = ThingSpeak.readFloatField(weatherStationChannelNumber,8);
  CH4Smoke = ThingSpeak.readFloatField(AirQuailityChannelNumber,1);
  CMonoxide = ThingSpeak.readFloatField(AirQuailityChannelNumber,2); 
  while(cLckset==0){
  // wait ten seconds before asking for the time again
  delay(10000);
  sEtNTP();}
  setTime(epoch+1);// Allow for the time to get this displayed.....
  ulNextMeas_ms = millis()+300000;
}



void sEtNTP(){

//get a random server from the pool
  WiFi.hostByName(ntpServerName, timeServerIP);

  sendNTPpacket(timeServerIP); // send an NTP packet to a time server
  // wait to see if a reply is available
  delay(1000);
 
  int cb = udp.parsePacket();
  if (!cb) {
    Serial.println("no packet yet");
    cLckset=0;
  }
  else {
    cLckset=1;
    Serial.print(F("packet received, length="));
    Serial.println(cb);
    // We've received a packet, read the data from it
    udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print(F("Seconds since Jan 1 1900 = " ));
    Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    Serial.print(F("Unix time = "));
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    epoch = secsSince1900 - seventyYears;
    // print Unix time:
    Serial.println(epoch);


    // print the hour, minute and second:
    Serial.print(F("The UTC time is "));       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(F(":"));
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print(F("0"));
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(F(":"));
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print(F("0"));
    }
    Serial.println(epoch % 60); // print the second
  }
}

void loop()
{
  if (millis()>=ulNextMeas_ms)
 {
ulNextMeas_ms = millis()+300000;
// Use WiFiClient class to create Thingspeak Post
  WiFiClient client;
  if (!client.connect("api.thingspeak.com", 80)) {
    return;
  }
  String url = "/update?key=";
  url += thingspeak_key;
  url += "&field1=";
  url += newval1;
  url += "&field2=";
  url += newval;
// This will send the request to Thingspeak
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: api.thingspeak.com\r\n" +
               "Connection: close\r\n\r\n");
  delay(50);
  client.stop();

 
 }
    int remainingTimeBudget = ui.update();

  if (remainingTimeBudget > 0) {
    // You can do some work here
    // Don't do stuff if you are below your
    // time budget.
    //delay(remainingTimeBudget);
    if(millis()>=i2ctimer){     // 1 second repeat......
        newval = myHTU21D.readCompensatedHumidity();
        newval1 = myHTU21D.readTemperature();
        i2ctimer=millis()+1000;
        LcNt++;
        if(LcNt==300){          // 5 minute repeat......
            LcNt=0;
  humidity = ThingSpeak.readFloatField(weatherStationChannelNumber,1);
  if(humidity!=0){Ds2=humidity;}
  temperature = ThingSpeak.readFloatField(weatherStationChannelNumber,2);
  if(temperature!=0){Ds1=temperature;}
  Inttemperature = ThingSpeak.readFloatField(weatherStationChannelNumber,3);
  Inthumidity = ThingSpeak.readFloatField(weatherStationChannelNumber,4);
  pressure = ThingSpeak.readFloatField(weatherStationChannelNumber,5);
  rainfall = ThingSpeak.readFloatField(weatherStationChannelNumber,6);
  windSpeed = ThingSpeak.readFloatField(weatherStationChannelNumber,7);
  CloudBase = ThingSpeak.readFloatField(weatherStationChannelNumber,8);   
  CH4Smoke = ThingSpeak.readFloatField(AirQuailityChannelNumber,1);
  CMonoxide = ThingSpeak.readFloatField(AirQuailityChannelNumber,2);       
            sEtNTP();
            if(cLckset!=0){
              cLckset=0;
              setTime(epoch+1);// Allow for the time to get this displayed.......
            }
        }
    }
 
  }
}

// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address)
{
  Serial.println(F("sending NTP packet..."));
  // 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();
}

This is provided separately to maintain consistency with the Library Example.....
Code: Select allconst char activeSymbol[] PROGMEM = {
    B00000000,
    B00000000,
    B00011000,
    B00100100,
    B01000010,
    B01000010,
    B00100100,
    B00011000
};

const char inactiveSymbol[] PROGMEM = {
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00011000,
    B00011000,
    B00000000,
    B00000000
};

Re: Configure WiFi from SD, Post & Display Data(OLED)

PostPosted: Tue Feb 21, 2017 5:13 am
by t_andersen
Impressive!