วันอาทิตย์ที่ 23 ตุลาคม พ.ศ. 2559

เริ่มต้นใช้งาน 7-Segment (1 Digit)

เริ่มต้นใช้งาน 7-Segment (1 Digit)



              หลอดแสดงผล LED 7-Segment เป็นอุปกรณ์อิเล็กทรอนิกส์ที่ใช้ในการแสดงผลเช่นเดียวกับหลอดแสดงผล LED ทั่วไป แต่ต่างตรงที่หลอดแสดงผล LED 7 ส่วน เป็นการนำเอาหลอดแสดงผล LED จำนวน 7 ตัวมาต่อกันเป็นรูปตัวเลข เพื่อนำมาแสดงผลเป็นตัวเลข 0 ถึง 9 โดยในบทความนี้จะพูดถึงการเขียนโปรแกรมควบคุมการทำงานของหลอดแสดงผล LED 7 ส่วน ด้วย Arduino UNO R3

          1. รู้จักกับโครงสร้างและการทำงานของ 7-Segment


   
        2. ต่อวงจรตามภาพ




        3. จะได้ผังวงจร ดังนี้

  



        4. เขียนโปรแกรมแสดงผลตัวเลข (ตัวอย่าง โปรแกรมแสดงผลเลข 5)

#define A 2
#define B 3
#define C 4
#define D 5
#define E 6
#define F 8
#define G 9
#define DP 10
void setup()
{
pinMode(A, OUTPUT);
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT);
pinMode(E, OUTPUT);
pinMode(F, OUTPUT);
pinMode(G, OUTPUT);
pinMode(DP, OUTPUT);
}
void loop() {
digitalWrite(A,HIGH);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
}
view raw digit5.ino hosted with ❤ by GitHub

       5. ตัวอย่างโปรแกรม นับ 1 - 10

#define A 2
#define B 3
#define C 4
#define D 5
#define E 6
#define F 8
#define G 9
#define DP 10
void setup()
{
pinMode(A, OUTPUT);
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT);
pinMode(E, OUTPUT);
pinMode(F, OUTPUT);
pinMode(G, OUTPUT);
pinMode(DP, OUTPUT);
}
// functions to display digits
void digit0 () {
// for 0 needed to turn ON F A B C D E segments, so:
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
//////////////////////// G segment should be turn OFF
digitalWrite(G, LOW);
}
void digit1 () {
digitalWrite(A,LOW);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
void digit2 () {
digitalWrite(A,HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, LOW);
digitalWrite(G, HIGH);
}
void digit3 () {
digitalWrite(A,HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, HIGH);
}
void digit4 () {
digitalWrite(A,LOW);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
}
void digit5 () {
digitalWrite(A,HIGH);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
}
void digit6 () {
digitalWrite(A,HIGH);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
}
void digit7 () {
digitalWrite(A,HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
void digit8 () {
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
};
void digit9 () {
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, LOW);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
}
//function to display digit from inputed int
void showdigit (int digit)
{
switch (digit) {
case 0:
digit0 ();
break;
case 1:
digit1 ();
break;
case 2:
digit2 ();
break;
case 3:
digit3 ();
break;
case 4:
digit4 ();
break;
case 5:
digit5 ();
break;
case 6:
digit6 ();
break;
case 7:
digit7 ();
break;
case 8:
digit8 ();
break;
case 9:
digit9 ();
break;
default:
break;
}
}
void loop ()
{
for (int i=0;i<10;i++) { //counting from 0 to 9
showdigit(i);
delay (1000); // 1000ms= 1s delay
}
}
view raw Count1-10.ino hosted with ❤ by GitHub





***************************************************
Montien Ngamkaew
***************************************************

วันพุธที่ 19 ตุลาคม พ.ศ. 2559

สั่งงาน Sonoff ด้วยเสียง ผ่าน App "ฟ้าใส เลขาส่วนตัว"


สั่งงาน Sonoff ด้วยเสียง ผ่าน App "ฟ้าใส เลขาส่วนตัว"



         Sonoff นอกจาก จะสามารถเปิด-ปิดไฟ ผ่านมือถือได้แล้ว สำหรับนัก Modify ทั้งหลายมักจะนำเจ้า Sonoff ไปดัดแปลงทำอย่างอื่นได้อีกหลากหลาย ถือว่าเป็นอุปกรณ์เล็กๆ ราคาเบาๆ ที่คุ้มค่า คุ้มราคา ตัวนึงเลยทีเดียว

           สำหรับวันนี้เราจะมาแนะนำวิธีการ สั่งงาน Sonoff ด้วยเสียง ผ่าน แอพที่ชื่อว่า ฟ้าใส "ฟ้าใส" คือแอพ ของคนไทย พูดง่ายๆ คือ Siri คนไทย นั่นเอง ในบทความนี้จะพูดถึงการควบคุม Sonoff ผ่าน Anto Cloud แล้วนำคำสั่งไปใช้งานผ่านแอพฟ้าใส อีกที เพื่อเป็นการไม่เสียเวลา มาเริ่มกันเลยดีกว่าครับ

          1. ก่อนอื่น เข้าไปสมัครสมาชิก Anto.io กันก่อนครับ โดยเลือกที่ Sign Up จากนั้น กรอกรายละเอียดให้เรียบร้อย แล้วดลือก Create a new account (จำ Username ที่เราตั้งไว้ด้วยนะครับ)




            กรอกหมายเลขโทรศัพท์  และจุดประสงค์ในการใช้งาน แล้วกด Update Account and Continue



              2. Login เพื่อเข้าใช้งาน Anto.io จากนั้นเข้าไปที่เมนู Thing ที่แถบเมนูด้านซ้ายมือ  จากนั้นเลือก Create new thing


             จากนั้นกรอกข้อมูลลงไป ดังนี้
                      NAME = ชื่องานที่เราจะสร้าง (ภาษาอังกฤษ)
                      Description = คำอธิบาย
                      Hardware = ใส่เป็น ESP8266
             แล้วกด  +Add New




             3. เมื่อสร้าง Thing เสร็จแล้ว ต่อไปเป็นการสร้าง Channel เพื่อใช้ควบคุม Input/Output ดดยเข้าไปที่ รูปแว่นขยายสีน้ำเงิน 

            คลิก +Create New Channel เพื่อ สร้าง Channel

            กรอกข้อมูล Channel ให้เรียบร้อย จากนั้นกด +Add new


             4. สร้าง Key เพื่อนำไปใช้งาน โดยไปที่ เมนู Key แล้วเลือก +Add New Key จากนั้นเลือก Permission ให้ LED1 โดยติ๊กเครื่องหมายถูกที่ Read และ Update ดังรูป แล้วคลิกที่ +Add New


            จะได้ Key สำหรับนำไปใช้ในการเขียนโปรแกรมพเื่อควบคุม ดังรูป
            

             5. เมื่อทำการตั้งค่าบน Anto.io แล้ว ต่อไปจะเป็นการ เขียนโปรแกรมลงบน Sonoff (คำเตือน : เมื่อเขียนลงไปแล้ว จะไม่สามารถใช้งาน Software เก่าได้นะครับ) โดยต่อ Sonoff เข้ากับ Bootloader ดังรูป


ขอบคุณภาพจาก http://tridenttd-iot.blogspot.com/2016/03/sonoff-hack-pin-upload.html

            6. ติดตั้ง Library Anto (Download คลิก) จากนั้นเขียนโปรแกรมบน Arduino IDE ดังตัวอย่าง

                  แก้ Code ต่อไปนี้
                             1. บรรทัดที่ 4 >> user = Username ที่ตั้งไว้ จากข้อ 1
                             2. บรรทัดที่ 5 >> key = key ที่ได้จากข้อ 4
                             3. บรรทัดที่ 8 >> thing = ชื่อ thing ที่ได้จากข้อ 2
                             4. บรรทัดที่ 19 >> ssid = ชื่อ Wifi ที่ต้องการเชื่อมต่อ
                                 บรรทัดที่ 20 >> pwd = รหัสผ่าน Wifi
                             5. บรรทัดที่ 101 และ 104 >> เปลี่ยนเป็น ขา 12

#include <AntoIO.h>
// username of anto.io account
const char *user = "montienmcu";
const char* key = "mBGoLWI6PYe0YYMyF5TZHr8Rcm8WvriYcWMO6g2w";
// your default thing.
const char* thing = "Sonoff";
AntoIO anto(user, key, thing);
bool bIsConnected = false;
int Led1,Led2,Led3 = 0;
int value = 0;
void setup() {
// SSID and Password of your WiFi access point.
const char* ssid = "iFocus";
const char* pwd = "00000000";
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.print("Anto library version: ");
Serial.println(anto.getVersion());
// Connect to your WiFi access point
if (!anto.begin(ssid, pwd)) {
Serial.println("Connection failed!!");
// Stop everything.
while (1);
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("Connecting to MQTT broker");
// register callback functions
anto.mqtt.onConnected(connectedCB);
anto.mqtt.onDisconnected(disconnectedCB);
anto.mqtt.onData(dataCB);
anto.mqtt.onPublished(publishedCB);
// Connect to Anto.io MQTT broker
anto.mqtt.connect();
//port output
//pinMode(D0,OUTPUT);
pinMode(12,OUTPUT);
pinMode(D2,OUTPUT);
pinMode(D3,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
}
/*
* connectedCB(): a callback function called when the connection to the MQTT broker is establised.
*/
void connectedCB()
{
// If the connection is establised, subscribe channels.
bIsConnected = true;
Serial.println("Connected to MQTT Broker");
anto.sub("LED1");
anto.sub("LED2");
anto.sub("LED3");
}
void disconnectedCB()
{
bIsConnected = false;
Serial.println("Disconnected to MQTT Broker");
}
/*
* msgArrvCB(): a callback function called when there a message from the subscribed channel.
*/
void dataCB(String& topic, String& msg)
{
uint8_t index = topic.indexOf('/');
index = topic.indexOf('/', index + 1);
index = topic.indexOf('/', index + 1);
topic.remove(0, index + 1);
Serial.print(topic);
Serial.print(": ");
Serial.println(msg);
if(topic.equals("LED1")){
value = msg.toInt();
if(value == 1){
digitalWrite(12,HIGH);
}
else{
digitalWrite(12,LOW);
}
}
else if(topic.equals("LED2")){
value = msg.toInt();
if(value == 1){
digitalWrite(D2,HIGH);
}
else{
digitalWrite(D2,LOW);
}
}
else if(topic.equals("LED3")){
value = msg.toInt();
if(value == 1){
digitalWrite(D3,HIGH);
}
else{
digitalWrite(D3,LOW);
}
}
}
void publishedCB(void)
{
Serial.println("published");
}
view raw AntoSonoff.ino hosted with ❤ by GitHub

             จากทำการ Upload โปรแกรม ลงบน Sonoff ได้เลยครับ (อย่าลืมกดปุ่ม Reset ก่อนเสียบ USB นะครับ)

            7. ทดลองเปิด-ปิดไฟ ผ่านหน้าเว็บ Anto.io โดยเ้าไปที่ เมนุ Thing แล้วไปที่ Channel ที่เราสร้างไว้


             ถ้าเปิด-ปิด ได้ ให้ข้ามไปข้อ 8 ได้เลย แต่ถ้ายังไม่ได้ให้กลับไปเช็คใหม่ อีกรอบครับ

             8. ดาวน์โหลดแอพ ฟ้าใส จาก Play Store จากนั้นเปิด แอพ ขึ้นมา แล้วทำการสมัครสมาชิกให้เรียบร้อยครับ


               พูดคำสั่ง "เชื่อมต่ออุปกรณ์ผ่านเน็ต"


              พูดคำสั่ง "เพิ่มคำสั่ง"


             พูดคำสั่ง "ส่งค่าผ่าน URL"


            จากนั้น พิมพ์คำสั่งที่ต้องการ เช่น ต้องการใช้คำสั่ง เปิดไฟ ให้พิมพ์ว่า

             เปิดไฟ ส่งค่า https://api.anto.io/channel/set/key/thing/channel/ค่าที่ต้องการส่ง

            จากตัวอย่างที่ผ่านมา จะได้

       เปิดไฟ ส่งค่า https://api.anto.io/channel/set/mBGoLWI6PYxxxx/Sonoff/LED1/1

           เช่นเดียวกันกับคำสั่งปิดไฟ ครับ จะได้

      ปิดไฟ ส่งค่า https://api.anto.io/channel/set/mBGoLWI6PYxxxx/Sonoff/LED1/0

            จากนั้นทดลอง ใช้คำสั่ง เปิด-ปิด ไฟ ผ่านฟ้าใสดูครับ (ดูวิธีการใช้งานได้จาก ในคลิปด้านล่างครับ)


วันอาทิตย์ที่ 28 สิงหาคม พ.ศ. 2559

ตอนที่ 1 เขียนโปรแกรมให้ยืดหยุ่นด้วย Macro (#define)


ตอนที่ 1 เขียนโปรแกรมให้ยืดหยุ่นด้วย Macro (#define)



         preprocessor คือพวกชุดคำสั่งที่ขึ้นต้นด้วย ‘#’ เช่น #include, #define เป็นชุดคำสั่งที่ compiler จะทำการแปลข้อความก่อนที่จะ compile ชุดคำสั่งจริง (เช่นการใช้ #include ไฟล์ ก็คือการนำเอา source code ของไฟล์นั้นมาแปะไว้ตรงบรรทัดนั้น ก่อนจะทำการ compile) macro ก็เป็น preprocessor ตัวหนึ่งที่เรียกใช้ด้วย #define ใช้ในการแทนที่ (เหมือนการใช้ replace ใน Microsoft Word) โดย macro นี้ สามารถนำมาใช้ได้ 2 แบบ คือแบบ object-like macro กับ function-like macro


object-like macro ก็คือ macro ที่ใช้แทนที่คำ ตัวอย่างเช่น

#define BUF_SIZE 128 

        เป็นการกำหนดขนาดของ buffer โดยคำว่า BUF_SIZE ใน code จะถูกจะแทนที่ด้วยคำว่า 128 ก่อนที่จะ compile

     ดังนั้น  ถ้าเราประกาศตัวแปรว่า unsigned char buf[BUZ_SIZE] 
คำว่า BUF_SIZE ก็จะถูกแทนที่ด้วย 128 ดังนั้นตอนที่ทำการ compile ตัว compiler จะเห็นเป็น
unsigned char buf[128]

**หมายเหตุ โดยทั่วไปการ define แบบนี้ จะใช้คำที่เขียนด้วยตัวพิมพ์ใหญ่ เพื่อให้มีความแตกต่างจากตัวแปร

function-like macro ก็คือ macro ที่ใช้แทนที่ แต่จะมีลักษณะเหมือนกับ function ตัวอย่างเช่น

#define average(a,b) ((a+b)/2)

ถ้าใช้เขียน code ว่า

int avg = average(x1,x2)

ตอนที่ทำการ compile ตัว compiler จะเห็นเป็น

int avg = ((x1+x2)/2)



           บางคนอาจจะสงสัยว่า แล้วมันต่างกับ function ยังไง สิ่งที่ต่างกันก็คือ การใช้ function ต้องมีการกระโดดเข้าไปทำงาน แล้วจึง return กลับออกมาจึงใช้เวลามากกว่าแต่ก็จะประหยัด code กว่า ส่วนการใช้ macro แบบนี้จะเห็นว่าจะใช้การแทนที่ทุกๆครั้งที่เจอคำว่า average ดังนั้นเมื่อใช้งานใน code แล้วก็จะทำให้ code ยาวขึ้นแต่จะทำงานได้เร็วกว่า

           นอกจากนี้ เราสามารถ define คำขึ้นมาเฉยๆ แล้วเขียน code เพื่อตรวจสอบว่ามีการ define คำนี้หรือไม่ก็ได้ เช่น

#define DEBUG_MODE
#ifdef DEBUG_MODE
… //code ส่วนที่ 1
#else
… //code ส่วนที่ 2
#endif

           ตัวอย่างการใช้งานในที่นี้คือ ถ้ามีการ define คำว่า DEBUG_MODE ไว้ ก็จะให้ทำงานตามที่เขียนใน code ส่วนที่ 1 แต่ถ้าไม่มีการ define ไว้ ก็จะทำงานใน code ส่วนที่ 2 หรือในทางตรงกันข้าม ถ้าเราไม่ทำการ #define DEBUG_MODE ไว้อาจจะใช้ #ifndef แทนเพื่อตรวจสอบเงื่อนไขที่จะเป็นจริงเมื่อไม่มีการ define
           จากตัวอย่างนี้ ถ้าถามว่าต่างจากการสร้างตัวแปร debug_mode ขึ้นมาแล้วใช้ if (debug_mode) ยังไง ก็คือถ้าเราใช้ #ifdef DEBUG_MODE แล้ว define DEBUG_MODE ไว้ compiler ก็จะ compile เฉพาะ code ส่วนที่ 1 และจะตัดส่วนที่ 2 ออกไปเลย ทำให้ได้ code ที่สั้นกว่า แต่ถ้าเราใช้ debug_mode เป็นตัวแปร compiler ก็จะ compile code ทั้งหมด ดังนั้นวิธีการเลือกว่าจะใช้แบบไหน จึงอยู่ที่ว่าใน run-time (คือในขณะที่โปรแกรมทำงาน) เราจะมีการปิดเปิดการ debug หรือไม่ ถ้าไม่มีเลย การใช้ macro ก็จะประหยัดพื้นที่ของ code มากกว่า



สรุปประโยชน์ของการใช้ macro (#define)

     1. ทำให้เราเข้าใจ code ได้ง่ายขึ้น ถ้าเราเขียนตัวเลขใน code เฉยๆ วันหลังเราอาจจะจำไม่ได้ว่าตัวเลขพวกนั้นมาจากไหน ทำให้เกิด bug ได้
     2. แก้ไขเปลี่ยนแปลงในภายหลังได้ง่าย อย่างตัวอย่างที่เรากำหนด BUF_SIZE ถ้าเราต้องการจะเปลี่ยน เราก็ไม่ต้องไปตามเปลี่ยนค่า 128 เป็นค่าใหม่ทุกที่ ทั้งที่ตัวเลข 128 บางที่อาจจะไม่เกี่ยวข้องกับขนาดของ buffer ก็ได้ หรือถ้าใช้กับการกำหนด pin ของ I/O ที่ใช้ควบคุม ในอนาคตก็จะเปลี่ยนแปลงได้ง่าย
     3. การใช้ function-like macro โดยส่วนใหญ่ จะใช้เพื่อให้เขียน code ได้ง่ายขึ้น ใช้คำสั่งที่สั้นลง ทำให้เขียน code ได้เร็วขึ้น
     4. ใช้กับ code ที่มีการนำไปใช้งานหลายๆรูปแบบได้ดี ไม่ต้องมาคอย comment ด้วย /**/ เช่นตัวอย่างการใช้ #define DEBUG_MODE



ข้อควรระวังในการนำไปใช้งาน

       ในการ define ค่าตัวเลขที่มาจากการบวก ลบ คูณ หรือหาร ควรใส่ ( ) ไว้เสมอ เพื่อให้การแทนที่ ไม่ผิดไปจากความตั้งใจ เช่น

#define WIDTH 5
#define HEIGHT 4
#define AREA (WIDTH* HEIGHT)

ค่า AREA อาจถูกนำไปใช้เป็นตัวหาร ถ้าเราไม่ใส่วงเล็บ ลำดับการคำนวณก็จะผิดไปจากที่ควรจะเป็น





################################################################################