วันพุธที่ ๒๙ มิถุนายน พ.ศ. ๒๕๕๙

Internet of Things (IoT) ตอนที่ 5

ตอนที่ 5 ว่าด้วยเรื่อง Raspberry Pi กับการต่อ input ที่เป็น micro switch เข้าทาง GPIO

การต่อสัญญาณเข้าไปประมวลผลใน MCU ของ Raspberry Pi เปรียบเสมือนกับการที่เราใช้ keyboard ป้อนข้อมูลเข้าเครื่องคอมพิวเตอร์ เพียงแต่ Raspberry Pi ได้ออกแบบ GPIO สำหรับให้เราต่ออุปกรณ์อิเล็คทรอนิกส์ เช่น สวิทช์ เพื่อส่งสัญญาณไปบอก MCU ว่ามีการกด หรือส่งสัญญาณไป แล้วคำสั่งใน MCU จะไปประมวลผลเพื่อไปควบคุมเครื่องใช้ไฟฟ้า หรืออุปกรณ์อิเล็คทรอนิกส์อีกทีหนึ่ง

แต่การต่อไมโครสวิทช์ ที่เราจะต่อวงจรเองนั้น มีความซับซ้อนและมีปัญหาหลาย ๆ อย่าง ในกรณีที่จะนำไปใช้งานจริง จึงต้องทดสอบ และพิถีพิถัน ให้มากยิ่งขึ้น

วงจรการต่อสวิทช์

การต่อสวิทช์ที่เกี่ยวข้องกับงาน MCU นั้น มี 2 วิธี ได้แก่


  • การต่อให้ส่งสัญญาณไปยัง MCU เป็น  0 volt หรือ Active Low
  • การต่อให้ส่งสัญญาณไปยัง MCU เป็น 3.3 volt หรือ Active Hi

วงจรสวิทช์ที่ทำงานแบบ Active Low






กรณีที่เป็น 0 volt (active low) นั่นหมายถึง ปกติแรงดันไฟฟ้าที่รออยู่เป็นสถานะ Hi หรือมีแรงดันไฟฟ้าประมาณ 3.3 volt เพราะกระแสไฟฟ้าจะไหลจาก vcc 3.3v ผ่าน R1 ที่เป็นความต้านทานขนาด 10K และผ่าน R2 ขนาด 1K ไปยังขา GPIO IN 

แต่เมื่อเรากดสวิทช์ สถานะ Hi จะเปลี่ยน Low เพราะว่า ขากราวด์ (0 volt) จะไหลผ่านสวิทช์ ไปสู่ R2 แล้วไปสู่ขา GPIO IN  ในขณะที่ R1 มีความต้านทานสูงถึง 10 K มันจึงไม่สามารถไหลผ่านไปได้ ตามหลักการของไฟฟ้าที่กระแสไฟฟ้าจะไหลผ่านสิ่งที่มีความต้านทานน้อยกว่า

วงจรสวิทช์ที่ทำงานแบบ Active Hi



การทำงานของวงจรสวิทช์แบบนี้ จะทำงานตรงกันข้ามกับแบบแรก ให้พิจารณาที่สวิทช์และ R1 จะสลับกับภาพแรก ดังนั้น เมื่อกดสวิทช์แรงดันไฟฟ้า 3.3 volt จากขา Vcc จะไหลผ่านสวิทช์ผ่านไปยัง R2 แล้วไปยังขา GPIO IN ประมาณแรงดันที่ 3.3 volt หรือ Active Hi นั่นเอง


การเขียนโปรแกรมทั้งสองวิธีก็แตกต่างกัน แต่ในปัจจุบันอุปกรณ์ที่เป็น micro switch ที่ใช้ในงาน MCU มักจะทำมาขายสำเร็จรูปมีความต้านทานอยู่ภายในอยู่แล้ว จึงมีขาเสียบ 3 ขา คือขา Vcc, GND และขาต่อ GPIO 

ในบอร์ดของ Arduino อาจต้องต่อวงจรแบบนี้ แต่สำหรับ Raspberry Pi แล้ว เขาออกแบบมาให้สามารถต่อวงจรไม่ต้องใช้ R ทั้ง 2 ตัวเลยก็ได้ ดังนี้



จากวงจรสวิทช์ที่ต่อใน breadboard นั้น เราสามารถต่อขาจาก Vcc 3v3 จาก GPIO มาเข้าขาเข้าสวิทช์ ส่วนขาออกสวิทช์ก็สามารถต่อไปยัง GPIO input ได้เลย แต่เราต้องกำหนดใน setup เป็นดังนี้


GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

มาดู Source code ในการเขียนคำสั่งเพื่อรับ input จาก switch กันเลย

--------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
green = 18
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False) 
GPIO.setup(green,GPIO.OUT) 
GPIO.setup(17,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
i=0
while True:        
        if (GPIO.input(17)==1):        
                i+=1        
                print "button pressed: ", i
--------------------------------------------------------------------
จาก code นี้เพื่อแสดงให้เห็นถึงปัญหาจากการกดปุ่ม ในกรณีที่เขียนโปรแกรมแบบ poll หรือเข้าไปสอบถาม มันจะลูปซ้ำกันหลายครั้งในระยะที่เรากดครั้งหนึ่ง  นี้คือผลลัพธ์ของการกดปุ่ม 1 ครั้ง ด้านล่างนี้
จะเห็นว่ากดหนึ่งครั้งมันจะลูปประมาณ 1801 ครั้ง หากมีการกดสวิทช์ตัวถัดมา หรือตัวอื่น ๆ อาจจะมีปัญหา โดยเฉพาะมีการ delay ด้วย ดังนั้น raspberry pi จึงได้จัดให้มีคำสั่งสำหรับการเขียนแบบ ตรวจสอบการทำงานของปุ่มกดที่ขอบขาขึ้น และขอบขาลง คำสั่งดังตัวอย่างต่อไปนี้
--------------------------------------------------------------------
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) GPIO.setup(17, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
i=0 while True: GPIO.wait_for_edge(17, GPIO.RISING)
i+=1 print "button pressed: ",i
-----------------------------------------------
ผลลัพธ์ที่ได้ จะแสดงข้อความว่า
     button pressed:  1
เพียงครั้งเดียวต่อการกด 1 ครั้ง เมื่อเรากดอีกครั้ง ข้อความจะเพิ่มเป็น
     button pressed:  2
แต่กรณีเราออกแบบให้มีสวิทช์หลายตัว เช่น ระบบจราจรที่กำลังจะทำให้ดูเป็นตัวอย่าง หากเขียนให้รอการกดปุ่มตามลำดับแบบนี้ ถ้าหากผู้ใช้กดปุ่มไม่เป็นไปตามลำดับก็จะมีปัญหา
มาดูวงจรของการทำสวิทช์ 4 ตัวเพื่อควบคุมจราจร 4 แยก ที่มีการกดปุ่มไฟเขียนตามลำดับ ดังนี้
----------------------------------------------------------
import RPi.GPIO as GPIO import time
ch1g = 21
ch1y = 20 
ch1r = 16
ch2g = 25
ch2r = 24
ch3g = 27
ch3r = 17
GPIO.setmode(GPIO.BCM) GPIO.setup(ch1g,GPIO.OUT) GPIO.setup(ch1y,GPIO.OUT) GPIO.setup(ch1r,GPIO.OUT) GPIO.setup(ch2g,GPIO.OUT) GPIO.setup(ch2r,GPIO.OUT) GPIO.setup(ch3g,GPIO.OUT) GPIO.setup(ch3r,GPIO.OUT)
GPIO.setup(05,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(06,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(13,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(19,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
def ch1():          
            GPIO.output(ch1g,GPIO.HIGH)          
            GPIO.output(ch2r,GPIO.HIGH)          
            GPIO.output(ch3r,GPIO.HIGH)          
            GPIO.output(ch1r,GPIO.LOW)
            GPIO.output(ch1y,GPIO.LOW)
            GPIO.output(ch2g,GPIO.LOW)
            GPIO.output(ch3g,GPIO.LOW)
def ch2():
            GPIO.output(ch2g,GPIO.HIGH)
            GPIO.output(ch3r,GPIO.HIGH)
            GPIO.output(ch1r,GPIO.HIGH)
            GPIO.output(ch1g,GPIO.LOW)
            GPIO.output(ch1y,GPIO.LOW)
            GPIO.output(ch2r,GPIO.LOW)
            GPIO.output(ch3g,GPIO.LOW)
def ch3():
            GPIO.output(ch3g,GPIO.HIGH)
            GPIO.output(ch2r,GPIO.HIGH)
            GPIO.output(ch1r,GPIO.HIGH)
            GPIO.output(ch3r,GPIO.LOW)
            GPIO.output(ch1y,GPIO.LOW)
            GPIO.output(ch2g,GPIO.LOW)
            GPIO.output(ch1g,GPIO.LOW)
while True:
               GPIO.wait_for_edge(05, GPIO.RISING)
               ch1()
               print "channel 1: "
               GPIO.wait_for_edge(06, GPIO.RISING)
               ch2()
               print "channel 2: "
              GPIO.wait_for_edge(13, GPIO.RISING)
               ch3()
               print "channel 3: "
----------------------------------------------------------------------------
ผลลัพธ์การทำงานของโปรแกรมดังแสดงในคลิป ด้านล่างนี้


ไม่มีความคิดเห็น: