NodeMCU control Web Animation through Cloud MQTT ควบคุม เว็บแอนิเมชั่น ด้วย NodeMCU ผ่านคลาวด์เซอร์วิซ CloudMQTT

NodeMCU control Web Animation through Cloud MQTT
ควบคุม เว็บแอนิเมชั่น ด้วย NodeMCU ผ่านคลาวด์เซอร์วิซ CloudMQTT

สวัสดีครับหลังจากที่ผมได้ลองทดลองทำคลิปโพสบน Youtube ไปซักพักก็มีเพื่อนถามมาว่าทำอย่างไร นิ่งไปนานเพราะจำไม่ได้ว่าทำอะไรลงไปบ้าง ฮา…. วันนี้มีเวลาเลยค้นไฟล์รวบรวมมาเขียนสรุปอีกครั้งครับ (ก่อนจะลืมแบบถาวร T^T)

Scenario สถานการณ์

สถานการณ์นี้เราอยากจะสั่งงานโดยการกดปุ่ม สวิตช์ หรือรับค่ามาจากเซนเซอร์จับการเคลื่อนไหว ที่ต่อด้วยกับ NodeMCU หรือใช้ ESP8266 ก็ได้ เมื่อกดปุ่มแล้ว เราจะส่งข้อความไปที่ Cloud Broker ซึ่งอีกฝั่งเป็น Web app animation ที่เราสร้างขึ้นมาให้เชื่อมต่อ (subscribes) กับ Cloud Broker ไว้คอยเช็คว่ามีข้อความเข้ามาหรือไม่ ถ้ามีข้อความเข้ามา(สวิตช์ถูกกด) แอนิเมชั่นของเราจะทำการเล่น

nodeMCU

 

อุปกรณ์ฮาร์ดแวร์ Hardware

  1. NodeMCU หรือ ESP8266

ซอฟต์แวร์ Software

  1. Arduino IDE
  2. CloudMQTT
  3. Adobe Edge Animate CC

ขั้นการสมัครใช้ฟรี Cloud Service (CloudMQTT)

  1. เริ่มเข้าไปสมัครกันเลยครับที่เว็บ https://www.cloudmqtt.com/

26-03-2016 11-23-10

2. หลังจากสมัครเสร็จเรียบร้อยแล้ว ให้เข้าไปที่ Control Panel

 

26-03-2016 11-23-56

3. ที่ CloudMQTT Console ให้สังเกตุที่หน้า Overview จะมีข้อมูลที่ต้องจดจำคือ Server, User, Password และ Port

26-03-2016 14-47-54

ขั้นตอนการเขียนโปรแกรมสำหรับ NodeMCU หรือ ESP8266

  1. เขียนโปรแกรมตามตัวอย่างเลยครับ หรือ สามารถโหลดได้ที่ https://github.com/spidyhero/NodeMCU_MQTT/blob/master/MQTT_HelloMama_example.ino

26-03-2016 15-07-30

/*
 MQTT publish/subscriber example https://www.cloudmqtt.com/

  - connects to an MQTT server
  - publishes to the topic "outTopic"
  - subscribes to the topic "outTopic"

  Modified by SpidyHero
*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 0;     // NodeMCU pushbutton pin
const int ledPin =  16;      // LED pin on NodeMCU

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

//-------------------------------//

const char *ssid =  "xxxxx";   // your WiFi network name
const char *pass =  "xxxxx";   //your WiFi network password

// Update these with values suitable for your network.
IPAddress server(xx,xx,xxx,xxx); // CloudMQTT Server IP, ping m11.cloudmqtt.com to get IP

WiFiClient wclient;
PubSubClient client(wclient,"m11.cloudmqtt.com", 18940); //your MQTT Port number

// use this function to receive message from CloundMQTT subscribes topic
void callback(const MQTT::Publish& pub) {
  Serial.print(pub.topic());
  Serial.print(" => ");
  Serial.println(pub.payload_string());
}

// setup
void setup()
{
  // Setup console
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.println();

  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);

  client.set_callback(callback);

  WiFi.begin(ssid, pass);

  int retries = 0;
  while ((WiFi.status() != WL_CONNECTED) && (retries < 10)) {
    retries++;
    delay(500);
    Serial.print(".");
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("");
    Serial.println("WiFi connected");
  }

//----MQTT validate connection ----//

  if (client.connect(MQTT::Connect("NodeMCU")
                    .set_auth("CloudMQTTusername", "CloudMQTTpassword"))) {
    Serial.println();
    Serial.println("Publish success.");
    client.publish("outTopic","NodeMCUconnected"); //Publish/send message to clound on outTopic

    Serial.println("Subscribe success.");
    client.subscribe("outTopic"); //Subscribes topic to receive message from cloud and print on monitor

               }
}

void loop()
{
  client.loop();

  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
  }
  else {
    // turn LED off:
    // send message to your topic when release button
    digitalWrite(ledPin, LOW);
    client.publish("outTopic","button is pushed"); // send message to "outTopic" when release button
    Serial.print("button is pushed");
    Serial.println();
    delay(300);
  }

}

บรรทัดที่ 24 ให้ระบุชื่อ WiFi ที่เราจะทำการเชื่อมต่อ
บรรทัดที่ 25 ให้ระบุ Password ของ WiFi ที่เราจะทำการเชื่อมต่อ
บรรทัดที่ 28 ให้ระบุ IP Server CloudMQTT เลขนี้ได้มาด้วยการ ping m11.cloudmqtt.com ใน Console

27-03-2016 10-59-57

บรรทัด 72 ให้ระบุ CloudMQTT username และ password
เสร็จแล้วเราก็ลองอัพโหลดเข้าNodeMCU หรือ ESP8266 กันเลยครับ….

ขั้นตอนการสร้าง Web Animation

26-03-2016 15-22-34

เริ่มต้นเรามาสร้างไฟล์งานใน Adobe Edge กันเลยครับ ในที่นี้ผมจะยกตัวอย่างไม่ซับซ้อนก่อนครับ

  1. ขั้นแรกให้เราสร้าง stage กำหนดขนาด และสี ของพื้นที่แสดงผลก่อน

27-03-2016 15-35-23

2. สร้างพื้นที่แสดงข้อความที่เรารับมาจาก CloudMQTT

27-03-2016 15-39-23

3. สร้าง Text ข้อความเพื่อแสดงข้อความ ตั้งชื่อว่า message

27-03-2016 15-42-11

4. สร้าง icon แสดงสถานะการเชื่อมต่อกับ CloudMQTT เมื่อเชื่อมต่อได้แสดงไอคอนสีเขียว ถ้าเชื่อมต่อไม่ได้ให้แสดงสีแดง และสร้างวัตถุอื่นๆไว้รอได้เลยครับ ผมใช้ Adobe Illustrator CC ในการสร้างVectorต่างๆไว้

27-03-2016 16-31-50

5. เราสามารถ Copy จาก AI และ Paste ลงใน AE ได้ดดยตรงเลย ไฟล์ที่นำเข้ามาจะเป็น SVG

27-03-2016 16-36-18

6. ตั้งชื่อให้กับ Vector ที่เรานำเข้ามา โดยตอนนี้เราจะมี ไฟล์ cloudON สีเขียว และ cloudOFF ที่เป็นสีแดง
7. จัดตำแหน่งไว้ โดยเราจะนำมาซ้อนกันดังรูป เราสามารถกดเครื่องหมายรูปดวงตาเพื่อแสดง/ซ่อนการแสดงผล

27-03-2016 16-58-07

27-03-2016 17-00-00

8. กดรูปตาเปิดการแสดงผลให้กับ CloudON (สีเขียว) แลัวให้เราตั้งStyleการแสดงผลด้านซ้ายมือ จาก Always On เป็น Off เพราะเราจะเขียนScript ให้เปลี่ยนเป็น On เพื่อแสดงการเชื่อมต่อภายหลัง ตอนนี้จะเห็นสีแดงแสดงผลอย่างเดียว

27-03-2016 17-02-08

9. นำตัวละคร และ กล่องข้อความที่สร้างไว้ใน AI เข้ามาและตั้งชื่อว่า character และ textBox

27-03-2016 17-10-56

10.ตั้งชื่อSymbol ว่า animation และยกเลิกการเล่นอัตโนมัติ

 

27-03-2016 17-29-45

11. เราสามารถแก้ไข Symbol ได้โดยดับเบิ้ลคลิ๊กที่ไอคอนSymbol ชื่อ Animation

27-03-2016 17-32-09

12. สร้างตัวอักษรตามต้องการดังภาพ

27-03-2016 17-43-52

13.ทำการ Group text และ textBox เข้าด้วยกันโดย Shift select คลิ๊กขวาและเลือกGroup (Ctrl+g)

27-03-2016 19-58-34

14.เปลี่ยนชื่อเป็น messageBox

27-03-2016 20-00-07

15. เราจะมาทำการแอนิเมท Character ก่อน โดยเลือกที่character และกด Pin ไอคอนแล้วลากเพื่อกำหนดเวลาในการเคลื่อนที่บนTimeline

27-03-2016 20-03-04.jpg

16. ใช้เมาส์คลิ๊กลากcharacter ลงมาด้านล่างให้พ้นกรอบของ Symbol

27-03-2016 20-05-35.jpg

17.กำหนดรูปแบบของแอนิเมชั่น Easing  แบบ Ease Out >Back ดังภาพ

27-03-2016 20-06-39

18. ทดสอบแอนิเมชั่นโดยการกดปุ่ม Enter หรือลาก Play head ที่ Timeline ดู จะเห็นว่าตัว character เราจะเด้งขึ้นมาเมื่อเล่นแอนิเมชั่น
19. ชุดตัวอักษร messageBox ให้ทำเช่นเดียวกันแต่อาจกำหนดเวลาให้ช้ากว่าเล็กน้อย ดูTimelineในภาพด้านล่าง เมื่อทดลองเล่นแอนิเมชั่นแล้ว จะเห็นว่าตัว character จะเด้งขึ้นมาก่อนและตัวอักษรจะเด้งขึ้นตามมา

27-03-2016 21-20-11.jpg

27-03-2016 21-57-16.jpg

27-03-2016 22-00-38.jpg

https://www.cloudmqtt.com/docs-websocket.html

…..เดี๋ยวกลับมาเขียนต่อครับ…..to be continuous…

โค้ดทั้งหมดของ Adobe Edge Animate


//CloudMQTT WebSockets
  client = new Paho.MQTT.Client("m11.cloudmqtt.com", 38940, "web_" + parseInt(Math.random() * 100, 10)); 

  // set callback handlers
  client.onConnectionLost = onConnectionLost;
  client.onMessageArrived = onMessageArrived;
  var options = {
    useSSL: true,
    userName: "xxxxxxx", //CloudMQTT username
    password: "xxxxxxx", //CloudMQTT password
    onSuccess:onConnect,
    onFailure:doFail
  }

  // connect the client
  client.connect(options);

  // called when the client connects
  function onConnect() {
    // Once a connection has been made, make a subscription and send a message.
    console.log("CloudMQTT Connected");
	 sym.$("cloudON").show();

    client.subscribe("outTopic");
    message = new Paho.MQTT.Message("Hello CloudMQTT");
    message.destinationName = "outTopic";
    client.send(message);
  }

  function doFail(e){
    console.log(e);
  }

  // called when the client loses its connection
  function onConnectionLost(responseObject) {
    if (responseObject.errorCode !== 0) {
      console.log("onConnectionLost:"+responseObject.errorMessage);
    }
  }

  // called when a message arrives
function onMessageArrived(message) {

   //get date time
   var d = new Date();

   console.log("Message from cloud: "+message.payloadString);

	sym.$("message").html("Cloud Message: "+message.payloadString+"
"+"Time: "+d);

	setTimeout(function() {sym.getSymbol("animation").stop(0);},2500);
   sym.getSymbol("animation").play(0);

  }

 

 

 

…..เดี๋ยวกลับมาเขียนต่อครับ…..to be continuous…

https://github.com/spidyhero/NodeMCU_MQTT

Using smart phone (Android) to control LED on Raspberry Pi 3 through Bluetooth connection

Using smart phone (Android) to control LED on Raspberry Pi 3 through Bluetooth connection

IMG_20160303_122623

หลังจากที่ผมได้สั่งซื้อ RPi3 มาดองซักระยะนึงแล้ว คิดว่ารสชาติน่าจะเปรี้ยวได้ที่ ก็เลยนำมาทดลองเขียนโปรแกรมที่ทุกคนต้องเคยได้ทดลองหัดเขียนตอนเริ่มเขียนโปรแกรมกันใหม่ๆนั่นก็คือ…….โปรแกรมปิดเปิดไฟLED…นั้นเองๆๆๆ แต่คราวนี้เรามาลองใช้ Feature ใหม่ของ RPi 3 คือเจ้า Bluetooth ส่วน WiFi 802.11n นั้นเราจะยังไม่พูดถึงเพราะเพื่อนๆคงใช้งานกันคล่องแล้ว

Scenario สถานการณ์

โจทย์ของเราก็คือเราอยากจะใช้โทรศัพท์มือถือที่มี Bluetooth เชื่อมต่อกับ Bluetooth ของ RPi3 และควบคุมสั่งปิดเปิดไฟ LED ตามต้องการ เราสามารถขยายผลไปควบคุมอุปกรณ์อื่นๆเช่น ปิดเปิดไฟบ้าน เครื่องใช้ไฟฟ้า เช่นเดียวกับเพื่อนๆเหล่า Maker ที่ใช้ ESP8266 ควบคุมปิดเปิดไฟผ่านสัญญาณ WiFi

อุปกรณ์ฮาร์ดแวร์

  1. Raspberry Pi 3
  2. Smart Phone Android
  3. LED

ซอฟต์แวร์

  1. Blue term (Bluetooth terminal)

ขั้นตอนทดสอบ RPi3 Bluetooth

เริ่มต้นให้เราทำการทดสอบ Bluetooth ในตัว RPi3 ของเราทำงานหรือไม่หลังจากที่เรา Install Pi OS (Raspbian) ตัวล่าสุด (v 1.8.0) https://www.raspberrypi.org/downloads/noobs/

ใช้คำสั่งทดสอบ Bluetooth

pi@raspberrypi ~ $ hciconfig
 14-03-2016 21-24-08

ตามภาพด้านบนเราจะเห็นว่า Bluetooth เราทำงานอยู่ UP RUNNING และหมายเลข Bluetooth Address คือ E8:27:EB:6C:57:A1

ขั้นตอนการ Install Bluez

เราต้องInstall Bluz ให้กับ RPi เพื่อที่เราจะสามารถจัดการ หรือเชื่อมต่อ Bluetooth กับอุปกรณ์อื่นๆได้ง่ายๆจากหน้าต่าง Bluetooth Manager ใน Raspbian

ใช้คำสั่ง

sudo apt-get install bluetooth bluez blueman

ทำการReboot และเข้าไปที่ Pi OS กัน ให้ไปที่เมนู Menu>Preferences>Bluetooth Manager

14-03-2016 20-59-42

จากนั้นให้กดปุ่ม Search ค้นหาอุปกรณ์ Bluetooth ที่อยู่ใกล้ๆ

14-03-2016 21-11-18

ที่มือถือของเราผมกดเครื่องหมายถูกเพื่อให้ RPi มองเห็นมือถือของเราด้วยในขณะที่ทำการ Scan

Screenshot_2016-03-14-21-11-48

หลังจากนั้นเราจะเห็นว่า RPi ค้นเจออุปกรณ์ต่างๆ รวมถึงมือถือของเราด้วย (Spidy Mobile)

14-03-2016 21-12-08

ให้เราเลือกอุปกรณ์ที่จะเชื่อมต่อ คลิ๊กขวาแล้วเลือก Pair หรือ กดเครื่องหมาย กุญแจ เพื่อทำการเชื่อมต่อ RPi กับ มือถือของเรา

14-03-2016 21-12-31

หลังจากนั้นจะมีข้อความหมายเลขเข้ามาที่มือถือเราเพื่อถามให้ทำการยืนยันการเชื่อมต่อ และในหน้าจอ RPi ก็จะมีข้อความเข้ามาที่มุมขวาบนเพื่อให้ยืนยันการเชื่อมต่อเช่นกัน

***จุดนี้ให้เรา กดปุ่มยืนยันที่ RPi ก่อน แล้วค่อย กดปุ่มยืนยันที่มือถือเรา***

15-03-2016 12-22-29

15-03-2016 12-22-49

ตอนนี้มือถือของเรากับเจ้า RPi ก็จับมือทำความรู้จักกันแล้ว เย้ๆๆ

เริ่มเขียนโปรแกรม Python เชื่อมต่อ Bluetooth

การเขียนโปรแกรม Python ให้เชื่อมต่อกับ Bluetooth ได้นั้นต้องทำการลง Lib ที่ RPi ก่อนโดยใช้คำสั่ง

sudo apt-get install python-bluetooth

หลังจากนั้นให้เราเปิดโปรแกรม Text Editor เพื่อเขียนโปรแกรมกัน ในที่นี่ผมใช้ Atom https://atom.io/

โปรแกรมที่เขียนจะเป็นการรัน Bluetooth Sever ไว้ที่ตัว RPi เพื่อคอยรับสัญญาณการร้องขอเพื่อทำการเชื่อมต่อจากมือถือเรา และเมื่อเชื่อมต่อสำเร็จก็จะทำการรับค่าและแสดงผลตัวอักษรในหน้าต่าง RPi console จากการที่เรากดคีย์บอร์ดในมือถือส่งเข้ามา ผมได้ดัดแปลงโปรแกรมจาก https://people.csail.mit.edu/albert/bluez-intro/x232.html เล็กน้อยให้ว่าถ้าเรากดตัวอักษร “e” จะให้หลุดจากการเชื่อมต่อ

15-03-2016 10-34-46

import bluetooth

server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )

port = 1
server_sock.bind(("",port))
server_sock.listen(1)

client_sock,address = server_sock.accept()
print "Accepted connection from ",address
while True:

 data = client_sock.recv(1024)
 print "received [%s]" % data
 if (data == "e"):
 print ("Exit")
 break

client_sock.close()
server_sock.close()

ลองรันโปรแกรมเลยครับ เมื่อเรารันโปรแกรมแล้ว RPi คอยรอเรียกการเชื่อมต่อ…..

การใช้ Blue Term app

15-03-2016 09-06-24

ตอนนี้ให้เราเปิดโปรแกรม app Blue Term ในมือถือของเรา

15-03-2016 10-42-59

Screenshot_2016-03-14-20-37-19

ตอนแรกเราจะเห็นสถานะด้านขวาบนของapp แสดงการยังไม่เชื่อมต่อ not connected

ให้เรากดปุ่ม Options menu ที่มือถือเรา (ผมใช้ SS S5 กดค้างที่ด้านซ้ายล่าง)

Screenshot_2016-03-14-20-37-29

เมื่อ Options menu ขึ้นมาแล้วให้กด Connect Device

Screenshot_2016-03-14-20-37-41

เราจะเห็น raspberrypi อยู่ใน List ให้เรากดเลือกได้เลยครับ หลังจากนั้นหน้าจอด้านขวาบนของ app จะโชว์ connected: raspberrypi

ให้ดูที่ console window RPi จะโชว์ว่าได้เชื่อมต่อกับมือถือของเราแล้ว

15-03-2016 10-54-52

ลองส่งข้อความไปดูครับ และถ้าเรากดตัวอักษร “e” จะให้หลุดจากการเชื่อมต่อดังภาพ

15-03-2016 10-40-18

เขียนโปรแกรม Python เชื่อมต่อ Bluetooth ควบคุมสว่าง/ดับ LED

เมื่อเราสามารถส่งตัวอักษรไปที่ RPi ได้แล้วเราก็ลองมาเขียนโปรแกรมสร้าง Conditions เพื่อดักตัวอักษรที่เราพิมพ์เข้ามาว่าถ้าเราพิมพ์ “1” ให้ไฟสว่าง ถ้าเราพิมพ์ “0” ให้ไฟดับ และถ้าพิมพ์ “5” ให้กระพริบ โดยเราจะเขียน function Blink มาเพื่อกำหนดความถี่และจำนวนในการกระพริบของ LED ได้

ในที่นี่เราจะต่อวงจรดังภาพโดยใช้ GPIO18

15-03-2016 11-01-37

ลองพิมพ์โค้ดดังภาพ

15-03-2016 11-07-39

import bluetooth
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(18,GPIO.OUT)

def Blink(numTimes,speed):
 for i in range(0,numTimes):
 GPIO.output(18,True)
 print "Blinking " + str(i+1)
 time.sleep(speed)
 GPIO.output(18,False)
 time.sleep(speed)
 print ("Done Blinking LED")

server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )

port = 1
server_sock.bind(("",port))
server_sock.listen(1)

client_sock,address = server_sock.accept()
print "Accepted connection from ",address
while True:

 data = client_sock.recv(1024)
 print "received [%s]" % data
 if (data == "1"):
 print ("LED ON")
 GPIO.output(18,GPIO.HIGH)
 if (data == "0"):
 print ("LED OFF")
 GPIO.output(18,GPIO.LOW)
 if (data == "5"):
 print ("LED Blink")
 Blink(10,0.1)
 if (data == "e"):
 print ("Exit")
 break

client_sock.close()
server_sock.close()

เมื่อเขียนโปรแกรมเสร็จแล้ว ลองรันดูเลยครับ……เย้เย้….ควบคุมLEDได้แล้ว

15-03-2016 11-15-31

ลองชมวิดีโอได้ครับ

 

อ้างอิง References

http://www.thirdeyevis.com/pi-page-2.php

http://thepihut.com/blogs/raspberry-pi-tutorials/27968772-turning-on-an-led-with-your-raspberry-pis-gpio-pins

http://www.modmypi.com/blog/installing-the-raspberry-pi-nano-bluetooth-dongle