การต่อสัญญาณเข้าไปประมวลผลใน 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 GPIOGPIO.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 timech1g = 21
ch1y = 20
ch1r = 16ch2g = 25
ch2r = 24ch3g = 27
ch3r = 17GPIO.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: "----------------------------------------------------------------------------ผลลัพธ์การทำงานของโปรแกรมดังแสดงในคลิป ด้านล่างนี้