Esp8266 Nokia 5110 NTP clock update

 

 

tmp_15687-IMG_20170430_0945171248615

Updated code with better graphics.  See gallery below for side by side.  The new library is the u8g2 library that has a lot of fonts but is more complicated to use than the standard Adafruit GFX library.

 

 

 

My biggest coding issue was that for the date, I couldn’t get the weekday to display.  I tried a ton of stuff before realizing that font only had numbers….duh!

Advertisements

ESP8266 with Blynk Driving Relay

Today’s China delivery was a relay board.  I ordered two to try different manufacturers but this is a Songle relay rated for 10A at both DC and AC.  Why I would use the relay for DC I’m not really sure but I hooked it up that way to test it.  I would use the much simpler irlb8721 MOSFET arrangement by itself if I just wanted to drive DC loads since it is rated higher and is noiseless, provided I don’t need true isolation of the circuit.

So here is what I’ve got diagrammed out on Fritzing.  The eventual goal is to drive under cabinet lighting using the relay, but this could also be done with MOSFET and ESP8266 arrangement.  It’s a warmish day and I had an 80mm case fan sitting right in front of me, so I thought I’d hook it up.

 

ESP8266_MOSFET_RELAY_bb

 

There are a couple of notable things:

  • The ESP8266 only puts out 12 mA from the pins, and from what I gathered, the relay draws about 70-80 mA so that’s a no-no to try to use the ESP on the relay alone.
  • The relay with MOSFET needs to be set in high level trigger mode with the jumper.
  • It is probably not the best idea to drive the MOSFET from Vcc through the FTDI cable that I’m using to program the ESP8266.
2017-04-13 17.49.45.jpg

My Hot Mess

ESP8266 with Dual DHT Sensors over Cat6 Cable

2017-04-12-171642_1366x768_scrotI had read a lot discussions about how far a DHT11/22 Sensor could be from source and still get readings.  I decided to test two out from the screen porch to the deck.  Results above and on thingspeak channel.

I had to adjust/calibrate the sensors in the code because they were about 4 degrees off.  I’ll try the DHT reset procedure when I tear this project down.   Right now I’m happy to report that transmission is fine over > 20 ft of Cat6 cable.  Same readings as if it were plugged into the breadboard.

ESP8266 #2 with DHT11 to Thingspeak

Today I got my new DHT11 Sensors from china, which may have been record time as far as I can tell.  Although I don’t *NEED* them, I thought I’d crack one open and put it to use.  I’m getting more comfortable with arduino C and increasing the complexity of the programs so I decided to functionalize the the Thingspeak Upload since I was having a hard time making heads or tails of inserting snippets from other programs.

I also wanted to see if the following elements could coexist.  I’m used to running virtualenv in python to limit the interactions of different libraries, but have not done this in C and don’t even know if it’s possible.  This program combines the following.

  • WiFi Manager (totally awesome utility for connecting)
    • This is so awesome because I no longer have to hardcode and subsequently erase WiFi creds when I upload to a repo.
  • NTP client for timestamping data (not yet implemented)
  • DHT11 Sensor and a calculated dewpoint
  • Thingspeak Web POST to API

Although to seasoned programmers, I’m guessing this is not too much going on, but for me, it’s the most activity in one device at once and it took some wrapping my head around.   I’m posting the code which is poorly documented and Dr. Purdum would probably shit a brick sideways at my lack thereof.  When I started with arduino, I relied heavily on his book to learn the basics of C and find myself regularly referring to it. 

I would like to add a non-blocking millis() timer to the mix next refactor.

The code is below, and after I clean it up a bit, it’ll go to github.

#include           //https://github.com/esp8266/Arduino

//needed for library
#include 
#include 
#include           //https://github.com/tzapu/WiFiManager

#include               //UDP Socket for NTP timekeeping

#include 
#define DHTTYPE DHT11
#define DHTPIN  12
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
float humidity, temp_f;  // Values read from sensor

//THINGSPEAK
String apiKey = "xxxxxxxxxxxxxxxx";
const char* server = "api.thingspeak.com";

//for LED status
#include 
Ticker ticker;

//UDP funcionality
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(98, 175, 203, 200 ); // 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;

void tick()
{
  //toggle state
  int state = digitalRead(BUILTIN_LED);  // get the current state of GPIO1 pin
  digitalWrite(BUILTIN_LED, !state);     // set pin to the opposite state
}

//gets called when WiFiManager enters configuration mode
void configModeCallback (WiFiManager *myWiFiManager) {
  Serial.println("Entered config mode");
  Serial.println(WiFi.softAPIP());
  //if you used auto generated SSID, print it
  Serial.println(myWiFiManager->getConfigPortalSSID());
  //entered config mode, make led toggle faster
  ticker.attach(0.2, tick);
}
//instantiate wifi client
WiFiClient client;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  dht.begin();           //DHT11 I2C Start

  //Set pin 13 as a indicator of NTP time activity
  pinMode(13, OUTPUT);

  //set led pin as output
  pinMode(BUILTIN_LED, OUTPUT);
  // start ticker with 0.5 because we start in AP mode and try to connect
  ticker.attach(0.6, tick);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;
  //reset settings - for testing
  //  wifiManager.resetSettings();

  //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
  wifiManager.setAPCallback(configModeCallback);

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  if (!wifiManager.autoConnect()) {
    Serial.println("failed to connect and hit timeout");
    //reset and try again, or maybe put it to deep sleep
    ESP.reset();
    delay(1000);
  }

  //if you get here you have connected to the WiFi
  Serial.println("connected...yeey :)");
  ticker.detach();
  //keep LED on
  digitalWrite(BUILTIN_LED, LOW);

  /*UDP LOOP SETUP

  */
  Serial.println("WiFi connected for NTP Service");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.println("Starting UDP");
  udp.begin(localPort);
  Serial.print("Local port: ");
  Serial.println(udp.localPort());


}

void loop() {
  digitalWrite(13, HIGH);
  //get a random server from the pool
  WiFi.hostByName(ntpServerName, timeServerIP);

  float h = dht.readHumidity();    // reading Humidity
  float tempC = dht.readTemperature(); // read Temperature as Celsius (the default)
  float temp = (32 + (9 * tempC) / 5); //approximately 2 degrees error correction for conversion and sensor inaccuracy

  float dP = (dewPointFast(tempC, h));
  float cDP = ((dP * 9) / 5) + 32;

  Serial.println("Temp\tRelHum\tcDewPt");
  Serial.print(temp);
  Serial.print("\t");
  Serial.print(h);
  Serial.print("\t");
  Serial.println(cDP);

  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");
  }
  else {
    //    Serial.print("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("Seconds since Jan 1 1900 = " );
    //    Serial.println(secsSince1900);

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


    // print the hour, minute and second:
    Serial.print("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(':');
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':');
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch % 60); // print the second


    //Now lets print the local time for EST
    Serial.print("The EST time is ");
    byte hourGMT = ((epoch  % 86400L) / 3600);  // print the hour (86400 equals secs per day)
    int hourEST = (hourGMT - 4);                //  adjust UTC to EST with DST
    if (hourEST < 0) {                          // if EST hour is negative then...
      hourEST = (24 + hourEST);                 // add it to 24 to get legit EST hour
    }

    Serial.print(hourEST);
    Serial.print(':');
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':');
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch % 60); // print the second

  }
  digitalWrite(13, LOW);
  // wait ten seconds before asking for the time again
  delay(60000);

  thingspeakPublish(temp, h, cDP);

  // END OF VOID LOOP END OF VOID LOOP

}

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

}
// DEW POINT CALCULATION********************
// delta max = 0.6544 wrt dewPoint()
// 6.9 x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
  double a = 17.271;
  double b = 237.7;
  double temp = (a * celsius) / (b + celsius) + log(humidity * 0.01);
  double Td = (b * temp) / (a - temp);
  return Td;
}

void thingspeakPublish(float temp, float h, float cDP) {
  if (client.connect(server, 80)) { // "184.106.153.149" or api.thingspeak.com
    String postStr = apiKey;
    postStr += "&field1=";
    postStr += String(temp);
    postStr += "&field2=";
    postStr += String(h);
    postStr += "&field3=";
    postStr += String(cDP);
    postStr += "\r\n\r\n";

    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(postStr.length());
    client.print("\n\n");
    client.print(postStr);

    Serial.print("Temperature: ");
    Serial.print(temp);
    Serial.println(" F");
    Serial.println("% send to Thingspeak");
  }
  client.stop();


};