Week03: Arduino IoTs – ThingSpeak Interface
ทฤษฏี เนื้อหาที่เกี่ยวข้อง
|
Thingspeak
เป็นเว็ปที่ให้การบริการในการเก็บข้อมูล และสามารถแสดงข้อมูลแบบ real-time
ได้ ซึ้งเราสามารถ update ข้อมูล
หรือจะเรียกดูข้อมูลได้ตลอดเวลา ที่ไหนก็ได้ เพราะทำงานบน cloud ซึ่ง thingspeak สร้างมาเพื่อต้องการให้ตอบโจทย์ของ IoT
อยู่แล้ว ส่วนข้อมูลที่เก็บอยู่บน cloud นั้นก็ขึ้นอยู่กับเราว่าจะใช้ยังไง
รูปแบบไหน ในการที่จะส่งข้อมูล data ไปไว้บน cloud นั้น ทาง thingspeak ได้มี api ในการติดต่อไว้เรียบร้อยแล้ว
การทดลอง
1 การเปิดใช้งาน Thinkspeak
·
อันดับแรกเลย ให้ทำการสมัครสมาชิกให้เรียบร้อย
·
จากนั้นก็สร้าง channel ขึ้นมา โดยให้เรากดไปที่ My
channel แล้วก็ new channel ขึ้นมา
·
หลังจากที่ new channel ขึ้นมาแล้ว ไปที่ channel
setting ก็ป้อนข้อมูลเข้าไป
·
อย่าลืมเลือก þ Make Public
·
เสร็จแล้วก็กด save channel
|
·
เมื่อสร้างเสร็จแล้ว ก็จะแสดงหน้าต่าง
ในหน้าต่างนี้จะแสดงข้อมูลเป็นแบบเส้นกราฟ ซึ่งตอนนี้ยังไม่มีข้อมูลใด ๆ
ส่งมาจึงไม่เกิดอะไรขึ้น
2 การ update ข้อมูลไปยัง cloud ผ่าน api ของ
thingspeak
·
อันดับแรกให้ดูที่ API KEY ของเราว่ามันคืออะไร
o
Write
API Key 4741AGU8WGCJP0J5
o
Read
API Keys TYJ1J2AU2OV7Q0U8
·
ในการ update ข้อมูลจะเป็นการส่ง HTTP Request ไปยัง server เพื่อ update ข้อมูลที่ต้องการตาม
field ต่าง ๆ ที่เรากำหนด วิธีการ update โดยเราจะส่งข้อมูลแบบนี้
https://api.thingspeak.com/update?key=4741AGU8WGCJP0J5&field1=0
|
ที่ขีดเส้นไว้คือ
4741AGU8WGCJP0J5 คือ API
KEY
field1=0 คือ field ที่เราต้องการ update ในตัวอย่างคือ
field ที่ 1 และกำหนดให้มีค่าเท่ากับ 0
·
มาดูผลลัพธ์กันที่แท็บ Private View
จากรูปตัวอย่างฝั่งขวาคือเจ้าของบล็อกได้ทำการ Update ข้อมูล
โดยกำหนดให้ field ที่ 1 มีค่าเท่ากับ 0 และฝั่งซ้ายนั้นได้มีจุดเพิ่มมา 1
จุดก็คือค่าที่เราเพิ่มไปเมื่อซักครู่นั่นเอง
3 เขียนโปรแกรมให้กับ NodeMcu
ให้ส่งข้อมูลไป update
·
Test
Code on Arduino IDE
#include
<ESP8266WiFi.h>
#include
<OneWire.h>
#include
<DallasTemperature.h>
#define
ONE_WIRE_BUS D3
const
char* ssid = "testVirus"; // กำหนด SSID
(อย่าลืมแก้เป็นของตัวเอง)
const
char* password = "1510031510"; // กำหนด Password(อย่าลืมแก้เป็นของตัวเอง)";
String
apiKey = "4741AGU8WGCJP0J5";
const
char* server = "api.thingspeak.com";
OneWire
oneWire(ONE_WIRE_BUS);
DallasTemperature
sensors(&oneWire);
WiFiClient
client;
void
setup()
{
Serial.begin(115200);
delay(1000);
sensors.begin();
Serial.println(); Serial.println();
Serial.print("Connecting to "); Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{ delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void
loop()
{
Serial.println("-------------------------");
Serial.print("Requesting
temperatures...");
sensors.requestTemperatures(); //
Send the command to get temperatures
float cTemp = sensors.getTempCByIndex(0);
Serial.print("Temperature is: ");
Serial.println(cTemp, 4); // Display Temperature
if (client.connect(server, 80)) // "184.106.153.149" or
api.thingspeak.com
{ String postStr = apiKey;
postStr += "&field1=";
postStr += String(cTemp);
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('C)=
");
Serial.println(cTemp, 4);
}
client.stop();
Serial.println("Waiting...");
delay(20000); // thingspeak needs minimum
15 sec delay between updates
}
|
·
ผลการทำงาน
·
NodeMcu
ส่ง http request ไปที่ server เพื่อ update ข้อมูล ซึ่งฝั่ง thingspeak ก็ทำการ update แบบ real-time และพลอตออกมาในรูปแบบกราฟ
ซึ่งทาง thingspeak สามารถบันทึกข้อมูลได้ทุก ๆ 15 วินาที ซึ่งหากว่าเราสามารถบันทึกค่าข้อมูลลง cloud ได้แล้ว
ก็เหมือนกับว่าเรามีค่าอะไรบางอย่างที่เราพร้อมเรียกตลอดเวลาไม่ว่าจะอยู่ที่ไหนก็ตาม
·
ส่วนของการส่งข้อมูล ก็จะเป็นการส่งแบบ http request ซึ่งเราส่งออกไปว่า
GET /update?key=4741AGU8WGCJP0J5&field1=0
HTTP/1.1\r\n
Host:
api.thingspeak.com\r\n
Connection:
close\r\n\r\n
4. การมอนิเตอร์ การสั่งงานด้วย Hercules ดังนี้
POST Data to ThinkSpeak
Hercules Setup: TCP Client
§
Module
IP à api.thingspeak.com
§
Port
à 80
§
Connect
§
Send
à GET /update?key=4741AGU8WGCJP0J5&field1=1234 HTTP/1.1
§
Send
à 0A
§
Send
à Host: api.thingspeak.com
§
Send
à 0A
§
Send
à 0A
5. การนำไฟล์ออกมาเพื่อทำรายงาน
·
จากข้อมูลสามารถ Export CSV ไฟล์เพื่อทำรายงานต่างๆได้
6 การควบคุมเปิดปิด LED
ผ่าน Internet ด้วย NodeMcu
·
ต่อวงจร LED ที่ D1, D2, D5, D6 และทดสอบการทำงาน
|
#define
LED_1 D1
#define
LED_2 D2
#define
LED_3 D5
#define
LED_4 D6
void
setup()
{
pinMode(LED_1, OUTPUT); digitalWrite(LED_1,
LOW);
pinMode(LED_2, OUTPUT); digitalWrite(LED_2, LOW);
pinMode(LED_3, OUTPUT); digitalWrite(LED_3, LOW);
pinMode(LED_4, OUTPUT); digitalWrite(LED_4, LOW);
}
void
loop()
{
digitalWrite(LED_1, HIGH);
delay(200);
digitalWrite(LED_1, LOW);
delay(100);
digitalWrite(LED_2, HIGH); delay(200); digitalWrite(LED_2, LOW); delay(100);
digitalWrite(LED_3, HIGH); delay(200); digitalWrite(LED_3, LOW); delay(100);
digitalWrite(LED_4, HIGH); delay(200); digitalWrite(LED_4, LOW); delay(100);
}
|
·
วิธีที่เราจะควบคุม LED นั้นเราจำเป็นต้องมีข้อมูลเพื่อนำไปเช็คเป็นเงื่อนไขว่า
ถ้าเกิดเป็นค่านี้ให้ LED เปิด ถ้าเป็นอีกค่านึงให้ LED
ปิด ดังนั้นหากเราต้องการสั่งให้ LED เปิดหรือปิดผ่าน
Internet นั้น เราจึงจำเป็นต้องมีข้อมูลบน cloud โดยเราจะทำการส่ง Http request ไปยัง server เพื่อร้องขอข้อมูลที่เราต้องการ ถ้าเราส่ง http request ได้อย่างถูกต้องก็จะมี
http response ตอบกลับจาก server โดยส่งมาพร้อมกับข้อมูลที่เราต้องการ
และเราก็ทำการเขียนโปรแกรมเพื่อใช้ค่าที่ server ตอบกลับมานั้น
มาเป็นค่าในการควบคุม LED เพื่อเปิดหรือปิดนั่นเอง
·
การ get data หรือจะเป็นการ update data เราสามารถศึกษา หรือดู Example ได้จาก Documentation
จาก Support ของ ThingSpeak
·
ในส่วนของการ fill data จะใช้การเขียนทั่วไป
https://api.thingspeak.com/update?key=4741AGU8WGCJP0J5&field1=9
|
·
ในการ get data จะใช้ url
https://api.thingspeak.com/channels/110910/fields/1/last
|
o
ที่ขีดเส้นใต้ไว้นั้น 110910 คือช่อง channels ของเรา
o
ส่วน 1 คือ ต้องการดูที่ field ไหน ส่วนเจ้าของบล็อกขอเลือกดูที่ field 1 แล้วกันเพราะเจ้าของบล็อกบันทึกค่าไว้ที่ field นี้
o
ค่า response ตอบกลับมาเป็นเลข 9
นั่นก็คือค่าที่เราต้องการที่จะทราบว่า ค่าที่บันทึกล่าสุดของ field ที่ 1 คือค่าอะไร ก็มีการ response กลับมาเป็นค่าดังกล่าว
·
ตัวอย่างนี้เป็นเพียงการทดสอบดูว่าสามารถ get ค่าจาก server
ได้หรือไม่ ต่อมาเราก็มาดูกันว่า เราจะเขียนให้ NodeMcu ของเรานั้นไป get ค่ามาแล้วมาควบคุม LED ได้อย่างไร
#include
<ESP8266WiFi.h>
#define
LED_1 D1
#define
LED_2 D2
#define
LED_3 D5
#define
LED_4 D6
const
char* ssid = "testVirus";
// กำหนด SSID (อย่าลืมแก้เป็นของตัวเอง)
const
char* password = "1510031510";
// กำหนด Password(อย่าลืมแก้เป็นของตัวเอง)";
const
char* host = "api.thingspeak.com"; // ชื่อ host
ที่ต้องการติดต่อ
const
char* url = "/channels/110910/fields/1/last"; // path ที่ต้องการเรียก
String
line = ""; // ตัวแปรนี้จะเก็บค่าทั้งหมดที่อ่านได้จาก Server
const
WiFiServer
server(80); // สร้าง object จาก คลาส WiFiServer
กำหนด port 80
void
setup() {
Serial.begin(115200); //ใช้ buadrate
115200
delay(10);
pinMode(LED_1, OUTPUT); //
pinMode(LED_2, OUTPUT); //
pinMode(LED_3, OUTPUT); // กำหนด ขา ให้เป็น ขา OUTPUT
pinMode(LED_4, OUTPUT); //
Serial.println("\n\n");
Serial.print("Connecting to ");
Serial.println(ssid); // แสดงข้อความออกทาง Serial
ว่า Connecting to (SSID ที่เชื่อมต่อ)
WiFi.begin(ssid, password); // เชื่อมต่อ wifi จาก SSID และ password ที่เรากำหนด
while (WiFi.status() != WL_CONNECTED) { // ถ้าหากยังเชื่อมต่อกับ wifi ยังไม่ได้ก็จะแสดงข้อความ
... ไปเรื่อย ๆ
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi
Connected!!");
Serial.print("IP address : ");
Serial.println(WiFi.localIP()); // แสดง IP address ที่ได้รับจาก wifi ที่เราเชื่อมต่อ
}
void
loop()
{
delay(5000);
WiFiClient client = server.available();
Serial.print("Connecting to "); Serial.println(host);
Serial.print("Requesting URL :
"); Serial.println(url);
if (!client.connect(host, PORT))
{ Serial.print(".");
return;
}
else
{ client.print(String("GET ") +
url + " HTTP/1.1\r\n" + "Host: " + host +
"\r\n" + "Connection: close\r\n\r\n");
delay(50);
Serial.println("SEND !!"); // เมื่อส่งไปแล้วให้แสดงข้อความ
SEND !! ออกมา
}
while (!client.available()) //ถ้าหากไม่มี response
ตอบกลับมา ก็จะให้วนลูป จนกว่าจะมี responce ตอบกลับมา
while (client.available()) // และเมื่อมี response
ตอบกลับมาก็จะให้เข้า loop while แล้วทำการเก็บค่าทั้งหมดไว้ที่
line
{ line += (char)client.read();
}
Serial.println();
Serial.println("GET SUCCESSFULLY
!!");
Serial.print("###### rawData >> "); Serial.println(line);
int lengthData = line.length();
char data = line[lengthData - 1];
String s = (String)"Position " +
lengthData + (String)", Data " + data;
Serial.print("###### splitted >>
"); Serial.println(s);
switch (data) {
case '1':
digitalWrite(LED_1, HIGH); // ถ้าเป็น 1 led1 ติด
break;
case '2':
digitalWrite(LED_1, LOW); // ถ้าเป็น 2 led1 ดับ
break;
case '3':
digitalWrite(LED_2, HIGH); // ถ้าเป็น 3 led2 ติด
break;
case '4':
digitalWrite(LED_2, LOW); // ถ้าเป็น 4 led2 ดับ
break;
case '5':
digitalWrite(LED_3, HIGH); // ถ้าเป็น 5 led3 ติด
break;
case '6':
digitalWrite(LED_3, LOW); // ถ้าเป็น 6 led3 ดับ
break;
case '7':
digitalWrite(LED_4, HIGH); // ถ้าเป็น 7 led4 ติด
break;
case '8':
digitalWrite(LED_4, LOW); // ถ้าเป็น 8 led4 ดับ
break;
case '9':
digitalWrite(LED_1, HIGH); // ถ้าเป็น 9 All LED On
digitalWrite(LED_2, HIGH);
digitalWrite(LED_3, HIGH);
digitalWrite(LED_4, HIGH);
break;
case '0':
digitalWrite(LED_1, LOW); // ถ้าเป็น 0 All LED Off
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, LOW);
digitalWrite(LED_4, LOW);
break;
}
line = ""; // เคลียข้อมูลในตัวแปร
line ให้เท่ากับ "" เพื่อรอรับค่าใหม่ใน loop
หน้า
Serial.println();
Serial.println("Closing
Connection");
}
|
·
เป็นการ get ค่าจาก Server โดยส่ง http
request ขอดูในข้อมูลล่าสุดของ field 1 ถ้าส่ง
request ถูกต้อง Server ก็จะส่ง http
response กลับมาเป็นค่าที่เราต้องการ
·
เมื่อได้ค่าที่ต้องการแล้วก็ทำการ substring ก็คือตัดเอาข้อความเอาเฉพาะที่จำเป็นมาใช้งาน
7. การมอนิเตอร์ การสั่งงานด้วย Hercules ดังนี้
POST Data to ThinkSpeak
|
GET Data from ThinkSpeak
TCP
Client
§
Module
IP à api.thingspeak.com
§
Port
à 80
§
Connect
§
Send
à GET /channels/110910/fields/1/last HTTP/1.1
§
Send
à 0A
§
Send
à Host: api.thingspeak.com
§
Send
à 0A
§
Send
à 0A
คำถามท้ายการทดลอง
เอกสาร แหล่งข้อมูลอ้างอิง
โปรแกรมทดสอบ
Example1 – Read Weather Station
§ Request – SSID, Password
/*
ReadWeatherStation
Reads
the latest weather data every 60 seconds from the public MathWorks
weather
station in
ThingSpeak ( https://www.thingspeak.com ) is an analytic IoT platform
service that allows you to aggregate, visualize and
analyze
live data streams in the cloud.
Copyright 2017, The MathWorks, Inc.
Documentation for the ThingSpeak Communication Library for Arduino is
in the extras/documentation folder where the library was installed.
See the
accompaning licence file for licensing information.
*/
#include <ESP8266WiFi.h>
#include "ThingSpeak.h"
WiFiClient
client;
char ssid[] = "testVirus"; //
your network SSID (name)
char pass[] = "1510031510"; // your network password
/*
This is
the ThingSpeak channel number for the MathwWorks weather station
https://thingspeak.com/channels/12397.
It senses a number of things and puts them in the eight
field
of the channel:
Field 1
- Wind Direction (degrees where 0 is North)
Field 2
- Wind Speed (MPH)
Field 3
- Humidity (%RH)
Field 4
- Temperature (Degrees F)
Field 5
- Rainfall (inches since last measurement)
Field 6
- Atmospheric Pressure (inHg)
*/
unsigned long weatherStationChannelNumber =
12397;
void setup()
{ Serial.begin(9600);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while
(WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
ThingSpeak.begin(client);
}
void loop() {
float
windDirection = ThingSpeak.readFloatField(weatherStationChannelNumber, 1);
float
windSpeed = ThingSpeak.readFloatField(weatherStationChannelNumber, 2);
float
humidity = ThingSpeak.readFloatField(weatherStationChannelNumber, 3);
float
temperature = ThingSpeak.readFloatField(weatherStationChannelNumber, 4);
float
rainfall = ThingSpeak.readFloatField(weatherStationChannelNumber, 5);
float
pressure = ThingSpeak.readFloatField(weatherStationChannelNumber, 6);
Serial.println("======================================");
Serial.println("Current weather conditions in
Serial.print(temperature); Serial.print("
degrees F, ");
Serial.print(humidity); Serial.println("%
humidity");
Serial.print("Wind at "); Serial.print(windSpeed);
Serial.print(" MPH at "); Serial.print(windDirection);
Serial.println(" degrees"); Serial.print("Pressure
is ");
Serial.print(pressure); Serial.print("
inHg");
if
(rainfall > 0)
{
Serial.print(", and it's raining");
}
Serial.println();
delay(60000); // Note that the weather station only updates once a
minute
}
|
Example2 – Write Voltage to thingspeak
§ Request – SSID, Password
§ Request – thingspeak Channel,
thingspeak API Write Key
/*
WriteVoltage
Reads
an analog voltage from pin 0, and writes it to a channel on ThingSpeak every
20 seconds.
ThingSpeak ( https://www.thingspeak.com ) is an analytic IoT platform
service that allows you to aggregate, visualize and
analyze
live data streams in the cloud.
Copyright 2017, The MathWorks, Inc.
Documentation for the ThingSpeak Communication Library for Arduino is
in the extras/documentation folder where the library was installed.
See the
accompaning licence file for licensing information.
*/
#include <ESP8266WiFi.h>
#include "ThingSpeak.h"
WiFiClient
client;
/*
*****************************************************************************************
****
Visit https://www.thingspeak.com to sign up for a free account and create
**** a
channel. The video tutorial
http://community.thingspeak.com/tutorials/thingspeak-channels/
****
has more information. You need to change this to your channel, and your write
API key
**** IF
YOU SHARE YOUR CODE WITH OTHERS, MAKE SURE YOU REMOVE YOUR WRITE API KEY!!
*****************************************************************************************/
unsigned long myChannelNumber = 110910;
const char * myWriteAPIKey =
"CC9IVV278SU09QFL";
char ssid[] = "testVirus"; //
your network SSID (name)
char pass[] = "1510031510"; // your network password
void setup()
{ Serial.begin(9600);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while
(WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
ThingSpeak.begin(client);
}
void loop()
{ float voltage;
Serial.print("Data is = ");
for
(int i = 0; i < 15; i++)// ThingSpeak will only accept updates every 15
seconds.
{ int
sensorValue = analogRead(A0); // read the input on analog pin 0:
voltage = sensorValue * 3.3 / 1023.0; // 0 - 1023 maps to 0 - 3.3
volts
Serial.print(voltage, 2);
Serial.print(",");
delay(1000);
}
//
Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to
store up to 8 different
//
pieces of information in a channel.
Here, we write to field 1.
ThingSpeak.writeField(myChannelNumber, 1, voltage, myWriteAPIKey);
Serial.print("\nSend Data to Thinkspeak = ");
Serial.println(voltage);
}
|
Example2 – Read private channel from
thingspeak
§ Request – SSID, Password
§ Request – thingspeak Channel,
thingspeak API Write Key, thingspeak API Read Key
/*
ReadPrivateChannel
Reads
the latest voltage value from a private channel on ThingSpeak every 30 seconds
and
prints to the serial port debug window.
For an
example of how to read from a public channel, see ReadChannel example
ThingSpeak ( https://www.thingspeak.com ) is an analytic IoT platform
service that allows you to aggregate, visualize and
analyze
live data streams in the cloud.
Copyright 2017, The MathWorks, Inc.
Documentation for the ThingSpeak Communication Library for Arduino is
in the extras/documentation folder where the library was installed.
See the
accompaning licence file for licensing information.
*/
#include <ESP8266WiFi.h>
#include "ThingSpeak.h"
WiFiClient
client;
/*
*****************************************************************************************
****
Visit https://www.thingspeak.com to sign up for a free account and create
**** a
channel. The video tutorial
http://community.thingspeak.com/tutorials/thingspeak-channels/
****
has more information. You need to change this to your channel, and your read
API key
**** IF
YOU SHARE YOUR CODE WITH OTHERS, MAKE SURE YOU REMOVE YOUR READ API KEY!!
*****************************************************************************************
This is
the ThingSpeak channel used in the write examples (31461). It is private, and requires a
read
API key to access it. We'll read from
the first field.
*/
unsigned long myChannelNumber = 110910;
const char * myWriteAPIKey = "CC9IVV278SU09QFL";
const char * myReadAPIKey = "TYJ1J2AU2OV7Q0U8";
char ssid[] = "testVirus"; //
your network SSID (name)
char pass[] = "1510031510"; // your network password
void setup()
{ Serial.begin(9600);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while
(WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
ThingSpeak.begin(client);
}
void loop() {
// Read
the latest value from field 1 of channel 31461
float
voltage = ThingSpeak.readFloatField(myChannelNumber, 1, myReadAPIKey);
Serial.print("Latest voltage is: ");
Serial.print(voltage);
Serial.println("V");
delay(30000);
}
|