แสดงบทความที่มีป้ายกำกับ Network แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ Network แสดงบทความทั้งหมด

วันเสาร์ที่ 7 ธันวาคม พ.ศ. 2562

ESP32:Coding:Network:ThingSpeak

วิธีการเก็บค่า Sensor บน ThingSpeak

  ThingSpeak เป็นบริการเก็บข้อมูลโดยอิงกับเวลา เก็บไปเรื่อยๆเพื่อสร้างกราฟ สามารถนำไปวิเคราห์ด้วยโปรแกรม MathLAB ได้ ถ้าเก็บข้อมูลไม่มากนักใช้ได้ฟรี ก่อนใช้งานควรอ่านข้อจำกัดของบริการฟรีให้เรียบร้อย หลักๆคืออย่าส่งข้อมูลถี่จนเกินไป แนะนำให้ส่งทุกๆ 15นาทีหรือห่างกว่านั้น ในตัวอย่างจะส่งทุกๆหนึ่งนาที (6000 มิลลิวินาที)
    ไปที่ https://thingspeak.com/ ทำการ Sign Up ให้เรียบร้อยแล้ว สร้าง Channel แล้วเปิดใช้งาน field1 กับ field2 เพื่อเก็บค่า Hall และ Temperature นำค่า API Key มาใส่ในโค้ดด้านล่าง  ค่า "SSID" และ "password" ให้แก้เป็น Wifi ที่เราเชื่อมต่อ API ย่อมาจาก Application Programming Interface สำหรับคนไม่รู้จักดูความหมายได้ที่นี้
    ตัวอย่างนี้จะใช้เซนเซอร์ภายใน ESP32 อ่านค่าอุณหภูมิจากและสนามแม่เหล็ก(Hall) ค่าอุณหภูมิจะเป็นอุณหภูมิของ ESP32 ซึ่งจะสูงกว่าอุณหภูมิห้อง ตัวอย่างดัดแปลงมาจากเวปนี้ (แนะนำให้เข้าไปอ่านดู) สามารถเข้าไปดูวิธีการเซ็ตอัป ThingSpeak สำหรับตัวอย่างนี้ได้
การส่งข้อมูลด้านล่างจะเป็นแบบ Method GET คือส่งค่าผ่าน URL
สามารถทดสอบแบบง่ายๆโดยการใส่ลิงค์นี้ลงบนเว็บ เบราว์เซอร์
https://api.thingspeak.com/update.json?api_key=API_KEY&field1=1234&field2=35
แล้วไปดูกราฟ ใน Private View
ตรง #ifdef __cplusplus , extern "C" { , และ #endif สำหรับคนที่ไม่เชี่ยวชาญภาษา C++ อาจจะงงหน่อย นำไปใช้ก่อนแล้วกันมันจำเป็นสำหรับการเรียกใช้ฟังก์ชั่น temprature_sens_read() ซึ่งเป็นฟังก์ชั่นของระบบ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#ifdef __cplusplus
extern "C" {
#endif
uint8_t temprature_sens_read();
#ifdef __cplusplus
}
#endif
uint8_t temprature_sens_read();

#include <WiFi.h>
String apiKey = "API_KEY";  //ใส่ API Key ที่ได้รับจาก ThingSpeak
const char *ssid =  "SSID"; // Wifi ที่เชื่อมต่อ และรหัสผ่าน
const char *pass =  "password";
const char* server = "api.thingspeak.com";
WiFiClient client;
void setup() {
  Serial.begin(9600);
  delay(10);
  Serial.println("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) 
  {
      delay(500);
      Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
}

void loop() {
  //ใช้ GET method ฟอร์แม็ตเป็นดังข้างล่าง
  //https://api.thingspeak.com/update.json?api_key=API_KEY_HERE&field1=1234&field2=35
  int h = hallRead();
  float t = ((temprature_sens_read()-32)/1.8); //changing temperature parameter to celsius
  if (client.connect(server,80))
  {
    Serial.println("ThingSpeak  connected");      
    String url = "/update.json?api_key="+apiKey +"&field1=";
    url += String(h);
    url += "&field2=";
    url += String(t);

    Serial.print("Requesting URL: ");
    Serial.println(url);
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + server + "\r\n" +
                 "Connection: close\r\n\r\n");
    unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 20000) {
        Serial.println(">>> Client Timeout !");
        client.stop();
        return;
      }
    }
    while(client.available()) { //ข้อความที่ตอบกลับจาก server
      String line = client.readStringUntil('\r');
      Serial.print(line);
    }
  }else{
    Serial.println("Connection fail"); 
  }
  Serial.println("");
  client.stop();
  Serial.println("Waiting...");
  delay(60000); //รอหนึ่งนาที(60000 มิลลิวินาที)
}


ตัวอย่างด้านล่างนี้เป็นแบบ Method POST จะการส่งค่าเหมือนการส่งผ่านฟอร์มบนเวป


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#ifdef __cplusplus
extern "C" {
#endif
uint8_t temprature_sens_read();
#ifdef __cplusplus
}
#endif
uint8_t temprature_sens_read();

#include <WiFi.h>
String apiKey = "API_KEY"; //  ใส่ API Key ที่ได้รับจาก ThingSpeakconst char *ssid =  "ssid";          // ชื่อไวไฟที่ต่อ
const char *pass =  "password";   // รหัสผ่าน
const char* server = "api.thingspeak.com";
WiFiClient client;
void setup() 
{
  Serial.begin(9600);
  delay(30);
  Serial.println("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
}
void loop() 
{
  int h = hallRead();
  float t = ((temprature_sens_read()-32)/1.8); //ทำอุณหภูมิเป็นเซลเซียส

  if(client.connect(server,80))              //เชื่อมต่อไปยัง api.thingspeak.com
  {                          
    String postStr = apiKey;
    postStr +="&field1=";
    postStr += String(h);
    postStr += "&field2=";
    postStr += String(t);
    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);
    
    unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 20000) {
          Serial.println(">>> Client Timeout !");
          client.stop();
          return;
      }
    }
    while(client.available()) { //ข้อความที่ตอบกลับจาก server
      String line = client.readStringUntil('\r');
      Serial.print(line);
    } 
    Serial.print("");
    Serial.print("Hall: ");
    Serial.println(h);
    Serial.print("Temperature:");
    Serial.print(t);
    Serial.println(" C");                          
    Serial.println("%. Send to Thingspeak.");
  }else{
    Serial.println(h);
  }
  client.stop();
  Serial.println("Waiting...");
  delay(60000); //รอหนึ่งนาที(60000 มิลลิวินาที)
}

การใช้งานหน้าเวปจะมีลักษณะใช้งานRequest และ Respond
Request เพื่อขอหน้าเวป ด้วย Method GET หรือ POST จะมีการส่งข้อมูลพร้อมไปด้วย
Respond จะส่งหน้าเวปกลับมา หลังประมวลผลข้อมูลที่ส่งไป
ในภายหลังนิยมใช้เวปเซิร์ฟเวอร์เพื่อประมวลผลแทนการสร้างเซิร์ฟเวอร์เฉพาะทางแบบเดิมเลยมีคอนเซ็บของ Web API ขึ้นมา การติดต่อผ่านเวป(โปรโตคอล HTTP) จะต้องมีการส่งค่าบางอย่างไปด้วยจะทำให้ดูมีอะไรซับซ้อนหน่อย หลังจากทำการ Request ก็จะได้ค่าตอบกับมา เช่นสำเร็จ หาหน้าเวปไม่เจอ ฯลฯ ในตัวอย่างจะใช้ client.readStringUntil('\r'); เพื่ออ่านค่าที่ตอบกลับมาทีละบรรทัด ซึ่งจะพิมพ์ออก Serial Monitor ไม่ได้ใช้ทำอะไร เราควรรอให้เวปทำการ Respond เสียก่อนจะเลือกติดต่อเพราะไม่งั้นการ Request อาจจะล้มเหลวได้
    ถ้าใช้ Library Manager ติดตั้งไลบารีของ ThingSpeak  จะมีโค้ดตัวอย่างจะดูง่ายกว่าใช้ WiFiClient ดังที่ใช้ในตัวอย่างหน่อยหนึ่ง แต่เท่าที่ลองใช้มันมีปัญหากับไลบารี่บางตัว เลยแนะนำให้ใช้ดังตัวอย่างข้างต้น


เพิ่มเติม
NETPIE FEED vs ThingSpeak Channel




วันศุกร์ที่ 29 พฤศจิกายน พ.ศ. 2562

ESP32:Coding:Network:Time

Network Time from NTP Server

    อุปกรณ์ไฟฟ้าทั่วๆไป ถ้าขาดไฟฟ้า เช่นปิดอยู่จะไม่สามารถนับเวลาที่เดินไปเรื่อยๆได้ เปิดมาก็ต้องตั้งค่าเวลาใหม่ ถ้าต้องการค่าเวลาต้องต่อกับ Real Time Clock (RTC) ที่มีไฟเลี้ยง เพื่อให้นาฟิกาเดินไปเรื่อยๆ ซึ่งต้องมีค่าใช้จ่ายเพิ่ม และต้องตั้งเวลาใหม่เมื่อแบตเตอรี่หมด ถ้าอุปกรณ์สามารถต่อกับเน็ตเวิร์กได้  ก็จะดึงค่าเวลาจากเน็ตเวิร์กเพื่อตั้งเวลาและนับเวลาต่อไปเรื่อยๆได้ ในอินเตอร์เน็ตจะมีเซิร์ฟเวอร์ NTP ( Network Time Protocol) ใช้บอกเวลาให้เรา เป็นเวลามาตรฐาน Coordinated Universal Time (UTC) ซึ่งเป็นค่าเดียวกันทั่วโลก ในแต่ละท้องถิ่นจำเป็นต้องปรับจากค่านี้ให้ตรงกับเขตเวลาในแต่ละท้องถิ่น ประเทศไทยจะใช้ UTC+7 ก็คือเพิ่มจากเวลามาตรฐาน 7ช.ม. ค่าของโซนเวลาที่เราจะใช้ปรับกับเวลามาตรฐาน (Time Offset) ต้องเป็นหน่วยมิลลิวินาที โดยแปลงจากหน่วยชั่วโมง ยกตัวอย่าง
UTC -5 จะมีค่า -5 * 60 * 60 = -18000
UTC +7 จะมีค่า 7 * 60 * 60 = 25200
บางประเทศจะมีช่วงเวลากลางวันกลางคืนที่แตกต่างกันมากในแต่ละฤดูจำเป็นต้องปรับเวลาท้องถิ่นให้ตรงกับฤดูต่างๆ (Daylight saving time) แต่ประเทศไทยไม่จำเป็นต้องปรับ  เพราะกลางวันกลางคืนแตกต่างกันไม่มากจึงใช้ค่านี้เป็น Daylight Offset เป็น 0 การใช้ดูโค้ดตัวอย่าง
Examples/ESP32/Time/SimpleTime


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <WiFi.h>
#include "time.h"
const char* ssid       = "SSID";
const char* password   = "PASSWORD";
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 25200; //UTC+7
const int   daylightOffset_sec = 0;//ไทยไม่ต้องปรับ
void setup()
{
  Serial.begin(9600); 
  //connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println(" CONNECTED"); 
  //ดึงเวลาจากเซิร์ฟเวอร์ NTP แล้วเก็บในระบบ
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime(); //พิมออกมา
  //ไม่จำเป็นต้องใช้ Wifi อีกต่อไป
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}
void loop()
{
  delay(1000);
  printLocalTime();
}
void printLocalTime()
{
  struct tm timeinfo; //ที่เก็บข้อมูลเวลา
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }//แสดงค่าด้วยวิธีต่างๆ
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  Serial.print(asctime(&timeinfo));
  String date_time = String(timeinfo.tm_year+1900)+"/"+String(timeinfo.tm_mon+1)+"/"+String(timeinfo.tm_mday);
  date_time += " "+String(timeinfo.tm_hour)+":"+String(timeinfo.tm_min)+":"+String(timeinfo.tm_sec);
  Serial.println(date_time);
  Serial.println("");

}

ผลของโปรแกรมผ่าน Serial Monitor

Connecting to oom .... CONNECTED
Tuesday, December 03 2019 06:35:10
Tue Dec  3 06:35:10 2019
2019/12/3 6:35:10

Tuesday, December 03 2019 06:35:11
Tue Dec  3 06:35:11 2019
2019/12/3 6:35:11


หลังจากเรียกฟังก์ชั่น configTime() ค่าของเวลาจะเก็บไว้ในระบบเลย แล้วเราใช้ getLocalTime() เพื่อเรียกใช้


เพิ่มเติม
Getting Date & Time From NTP Server With ESP32
Time structure


Module:Control:IFR 520

MOSFET Module  สวิตซ์ปิดเปิดไฟเหมือน Relay แต่เป็น Solid state (ไม่มีส่วนที่เคลื่อนไหว) มันทำงานที่ความถี่สูงได้เหมาะกับเอาไปใช้งาน PWM ...