2016/Sep/18

Workshop 5 . NodeMCU/ESP8266 + DH11+T16x2 LCD Display I2C+NTP+Sparkfun

วัตถุประสงค์

เพื่อให้สามารถทำการเขียนชุดคำสั่งให้ NodeMCU สามารถทำการเชื่อมต่อกับ Internet ผ่าน WIFI และให้ไปรับค่าวันที่/เวลา จาก NTP:Network Time Protocols ซึ่งเป็น Protocol ที่ใช้สำหรับปรับเทียบเวลา ( Time Synchronization) ของ Computer โดยอาศัยเครือข่าย Internet เป็นสื่อกลางในการส่งข้อมูลเวลามาตรฐานไปยังเครื่องลูกข่าย โดยมีเครื่องแม่ข่าย ( NTP Server) เป็นตัวให้บริการส่งเวลามาตรฐาน เพื่อใช้ในการปรับเทียบเวลาให้ตรงกลับเวลามาตรฐาน ( Time Standard) ซึ่งเป็นค่าเวลาที่ทาง Time & Frequency Lab. ได้ทำการเก็บรักษาไว้โดยวิธีการเปรียบเทียบกับเวลามาตรฐานของประเทศอื่นๆ ซึ่งเป็นที่ยอมรับในระดับนานาชาติ โดยมีความถูกต้องอยู่ที่ ประมาณ 1 millisecond ในระบบ LAN และประมาณ 10 millisecond ในระบบ WAN นับว่าเป็นความคลาดเคลื่อนที่อยู่ในระดับต่ำ อีกทั้งยังง่ายต่อการเข้าถึงของผู้ใช้ทั่วไป แค่เพียงมี PC หรืออุปกรณ์ที่สามารถเชื่อมต่อ เข้าระบบ Internet ได้ผู้ใช้ก็สามารถที่จะ Synchronize เวลามาตรฐานผ่านระบบ NTP ได้ทันที

เมื่อได้ค่าเวลาจาก NTP มาแล้วเราก็จะนำค่า วันที่ เวลา อุณหภูมิ (Temperature) และ ความชื้น (Humidity) จาก DHT11 Sensor DHT11 sensor มาแสดงผลทางหน้าจอ 16x2 LCD Display I2C พร้อมๆ กัน

จากนั้นเราจะทำการส่งค่าที่อ่านได้จาก DHT11 Sensor ขึ้นไปเก็บยัง Cloud Service ของ Sparkfun

เครื่องมือที่ใช้

  1. NodeMCU/ESP8266 พร้อม สาย USB สำหรับ Upload ไฟล์
  2. ชุดโปรแกรม Arduino studio (ดาวน์โหลดได้จาก https://www.arduino.cc/en/Main/Software)
  3. DHT11 sensor (Digital Humidity and Temperature Sensor)
  4. ESP8266 – 16x2 LCD Display I2C

หมายเหตุรายละเอียดของการดึงเวลาจาก NTP ทำสามารถดูเพิ่มเติมได้จาก
ขอขอบคุณ  Mr.Comdet Phudphut
      ESP8266 Tutorial ดึงเวลาสากลมาใช้งาน => https://www.youtube.com/watch?v=c8MpndNKOTs
      Time.ino at => https://github.com/esp8266/Arduino/blob/4cf72e7ef4fcabde230de44ba1d1ab5d57cdeee0/tests/Time/Time.ino
      Time.c at => https://github.com/esp8266/Arduino/blob/4b8fb2093fa9dcabe19e4d836c9fb5fc7becf250/cores/esp8266/time.c
      Time.h at => https://github.com/metalheart/esp8266/blob/master/include/time.h

ลงมือซิครับรออะไรอยู่  ** ไม่ต้องคุยเรื่องการติดตั้งนะครับ หาอ่านได้ตาม Internet

  1. หลังจากที่ได้ทำมาใน Workshop 4 ที่ผ่านมา หน้าตาสุดท้ายที่ได้ครับ
  2. กรณีที่เราจะส่งค่าขึ้นไปยัง Sparkfun เราต้องมีสิ่งที่เรียกว่า “host”  “streamId” “privateKey” “deleteKey” จะได้มาอย่างไร ไปอ่านดูได้ครับมีคนเขียนไว้ดีอยู่แล้วครับ ที่ Link นี้เลย
    http://cpre.kmutnb.ac.th/esl/learning/index.php?article=iot_data_sparkfun หรือ
    http://www.ayarafun.com/2015/04/pushing-data-to-data-sparkfun-com-with-esp8266/

  1. เมื่อได้ “streamId” “privateKey” “deleteKey” มาแล้วก็จับมาใส่ใน Workshop 5 เลยครับ (save จาก Workshop 4)

คำสั่งที่จะเรียกดูข้อมูลผ่าน URL : http://data.sparkfun.com/streams/aG8Jya5G4ZUo7Nbv904q

Public Key :   aG8Jya5G4ZUo7Nbv904q

Private Key : KEPNYZ4ERgtvN9epq8x1

Keep this key secret, and in a safe place.  You will not be able to retrieve it.

Delete Key : Xv24eqgvBOtV3rakqnE7

รูปแบบคำสั่ง :

http://data.sparkfun.com/input/[publicKey]?private_key=[privateKey]&humidity=[value]&temperature=[value]

ตัวอย่าง:

http://data.sparkfun.com/input/aG8Jya5G4ZUo7Nbv904q?private_key=KEPNYZ4ERgtvN9epq8x1&humidity=19.21&temperature=29.55

ทดลองส่งค่าผ่าน Browser

ลองเข้าไปดูข้อมูลในเว็บหลังจากที่ทดสอบแบบ Manual สังเกตุ เวลาที่บันทึกจะเป็นเวลา GMT+0 เราต้อง +7 เข้าไปถึงจะเป็นเวลาประเทศไทย

ลองกดปุ่ม Export to Analog.io ดูจะเห็นกราฟ ของข้อมูลที่เก็บใน Sparkfun เวลาจะถูกเปลี่ยนไปเป็นตามเครื่อง PC

  1. เมื่อเข้าใจหลักการแล้วก็เข้าไปลบข้อมูล แล้วทำการเพิ่มชุดคำสั่ง เข้าไปในไฟล์ workshop 5 ดังนี้

 

// Start Code

// ขอขอบคุณนักพัฒนา ทุกๆ ท่าน

// ขอขอบคุณ อาจารย์อานนท์ หม้อสุวรรณ จาก TESR : Thai Embeded System and Robotic

//    https://www.facebook.com/ThaiEmbedded/?fref=ts

// ขอขอบคุณ Mr.Comdet Phudphut

//    https://www.facebook.com/comdet?fref=ts

//    ESP8266 Tutorial ดึงเวลาสากลมาใช้งาน

//    https://www.youtube.com/watch?v=c8MpndNKOTs

//    Time.ino at => https://github.com/esp8266/Arduino/blob/4cf72e7ef4fcabde230de44ba1d1ab5d57cdeee0/tests/Time/Time.ino

//    Time.c at => https://github.com/esp8266/Arduino/blob/4b8fb2093fa9dcabe19e4d836c9fb5fc7becf250/cores/esp8266/time.c

//    Time.h at => https://github.com/metalheart/esp8266/blob/master/include/time.h

//  ขอขอบคุณ

//    Khon Kaen Maker Club => https://www.facebook.com/KhonKaenMakerClub/?fref=ts

//    Chiang Mai Maker Club => https://www.facebook.com/ChiangMaiMakerClub/?fref=ts

//    Lampang Maker Club => https://www.facebook.com/groups/907239239368989/

// ขอขอบคุณนักพัฒนา Maker ของ การไฟฟ้าฝ่ายผลิตห่งประเทศไทย (กฟผ.) ทุกท่าน

// last update 17 Jan 2016 04:30PM By Mr.Sridetch Pancharkan EGAT Maemoh Mine Lampang Thailand 52220

// ปรับปรุงครั้งสุดท้าย  17 กันยายน 2559 16.30 น. โดย นายศรีเดช  ปัญจขันธ์  กฟผ. เหมืองแม่เมาะ อ.แม่เมาะ จ.ลำปาง 52220

// Mailto : sridetch.p@egat.co.th , sridetch@gmail.com

   

 

#include <ESP8266WiFi.h>

#include <time.h>

#include "DHT.h"

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

 

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

 

#define DHTPIN D5     // what digital pin we're connected to

#define DHTTYPE DHT11   // DHT 11

#define LEDOnboard D4

 

const char* ssid = "YourSSID";

const char* password = "YourPassword";

const int ledbuiltin =  D4;      // the number of the LED pin

const char* host = "data.sparkfun.com";   //  data.sparkfun.com

const char* streamId   = "YourPublicKey"; // Public Key

const char* privateKey = "YourPrivateKey"; // Private Key

//deleteKey = "YourDeleteKey"; // Delete Key

int timezone = 7*3600;

int dst = 0;

DHT dht(DHTPIN, DHTTYPE);

 

void setup() {

  pinMode(LEDOnboard,OUTPUT);

  digitalWrite(LEDOnboard,HIGH);  // LED Builtin ดับขณะเริ่มต้น

    // Welcome message to the LCD.

  lcd.init();                      // initialize the lcd

  lcd.backlight();

  lcd.setCursor(0,0);

  lcd.print("EGAT Expert Pool");

  lcd.setCursor(0,1);

  lcd.print("BigTUI at Maemoh");

 

  Serial.begin(115200);

  Serial.setDebugOutput(true);

  dht.begin();

 

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

  Serial.println("\nConnecting to WiFi");

  while (WiFi.status() != WL_CONNECTED) {

    Serial.print(".");

    delay(3000);

  }

  configTime(timezone, dst, 0, "pool.ntp.org", "time.nist.gov");

  Serial.println("\nWaiting for time");

  while (!time(nullptr)) {

    Serial.print(".");

    delay(1000);

  }

  Serial.println("");

}

 

void loop() {

  WiFiClient client;

  const int httpPort = 80;

  digitalWrite(LEDOnboard,LOW);

  time_t now = time(nullptr);

  Serial.println(ctime(&now));

  struct tm* p_tm = localtime(&now);

  Serial.print("Time=");Serial.print(p_tm->tm_hour);Serial.print(":");Serial.println(p_tm->tm_min);

  Serial.print("Date(d/m/yyyy)=");Serial.print(p_tm->tm_mday);

  Serial.print("/");Serial.print(p_tm->tm_mon+1);Serial.print("/");Serial.println(p_tm->tm_year+1900+543);

 

  // Reading temperature or humidity takes about 250 milliseconds!

  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)

  float h = dht.readHumidity();

  // Read temperature as Celsius (the default)

  float t = dht.readTemperature();

  // Read temperature as Fahrenheit (isFahrenheit = true)

  float f = dht.readTemperature(true);

 

  // Check if any reads failed and exit early (to try again).

  if (isnan(h) || isnan(t) || isnan(f)) {

    Serial.println("Failed to read from DHT sensor!");

    return;

  }

 

  // Compute heat index in Fahrenheit (the default)

  float hif = dht.computeHeatIndex(f, h);

  // Compute heat index in Celsius (isFahreheit = false)

  float hic = dht.computeHeatIndex(t, h, false);

 

  Serial.print("Humidity: ");Serial.print(h);Serial.print(" %\t");

  Serial.print("Temperature: ");Serial.print(t);Serial.print(" *C ");Serial.print(f);Serial.println(" *F\t");

 

  lcd.init();                      // initialize the lcd

  // Print a message to the LCD.

  lcd.backlight();

  lcd.setCursor(0,0);

  lcd.print("T=");lcd.print(t,0);lcd.print((char)223);lcd.print("C,");

  lcd.print(f,0);lcd.print((char)223);lcd.print("F,");

  lcd.print("H=");lcd.print(h,0);lcd.print("%");

  lcd.setCursor(0,1);

  lcd.print(p_tm->tm_mday);lcd.print("/");lcd.print(p_tm->tm_mon+1);lcd.print("/");lcd.print(p_tm->tm_year+1900+543);lcd.print("  ");

  lcd.print(p_tm->tm_hour);lcd.print(":");lcd.print(p_tm->tm_min,1);

  digitalWrite(ledbuiltin, LOW);

 

  //We now create a URI for the request

  // ตัวอย่างคำสั่งสำหรับทดลองส่งค่าผ่าน URL

http://data.sparkfun.com/input/YourStreamId?private_key= YourPrivateKey &humidity=19.21&temperature=29.55

  String url = " /input/";   //แก้ไขแล้วของเดิมผิด String url = "http://data.sparkfun.com/input/";

  url += streamId;

  url += "?private_key=";

  url += privateKey;

  url += "&humidity=";

  url +=  h ;

  url += "&temperature=";

  url +=  t ;    

 

  Serial.print("Requesting URL: ");

  Serial.println(url);

  

  // This will send the request to the server

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +

               "Host: " + host + "\r\n" +

               "Connection: close\r\n\r\n");

  delay(10);

  // คำสั่งที่จะเรียกดูข้อมูลผ่าน URL : http://data.sparkfun.com/streams/aG8Jya5G4ZUo7Nbv904q

  // Read all the lines of the reply from server and print them to Serial

  while(client.available()){

    String line = client.readStringUntil('\r');

    Serial.print(line);

  }

  digitalWrite(LEDOnboard,HIGH);  // LED Builtin ดับเมื่อส่งข้อมูลเรียบร้อยแล้ว            

  delay(1000);

}

//END Code by BigTUI.

 

  1. ทดลอง Run ดู จะเห็นว่ามีการส่งค่าอุณหภูมิ ไปยัง Server Sparkfun

 

  1. ลองเปิดดูอุณหภูมิ กับ ความชื้นที่วัดได้จาก DTH11 Sensor บน Sparkfun อ้าวไม่มีค่าที่อัพโหลดเลย ไปลองเช็คดูปรากฏว่ามี Error HTTP/1.1 403 Permission denied มันคือ ??

 

  1. ถามคุณลุง Google ดูก็ไปเจอของเดิม http://www.ayarafun.com/2015/04/pushing-data-to-data-sparkfun-com-with-esp8266/ ลองแก้ไข ตรงบรรทัดดที่ 131 ให้เป็น String url = “/input”
  2. สามารถเข้าไปดูข้อมูลใน Sparkfun ได้แล้ว
    https://data.sparkfun.com/streams/aG8Jya5G4ZUo7Nbv904q
  1. สามารถเข้าไปดูกราฟใน io ได้ http://analog.io/sAFP

   

จบ Work shop 5 แล้วครับ
หากท่านไม่ได้สร้างสรร สิ่งแรกในโลกนี้
ไม่ต้องห่วงครับโลกนี้มีคนที่เจอปัญหาแบบท่านมาก่อน
และมีคนอีกหลายคนที่สามารถช่วยเหลือท่านได้จากโลกอินเตอร์เน็ต Google ช่วยเราได้

 

Comment

Comment:

Tweet


ศรีเดช ปัญจขันธ์
View full profile