ผู้เขียน หัวข้อ: งานครั้งที่ 5 เขียนโปรแกรมรับสวิตช์แบบโพลลิ่งและแบบอินเตอร์รัพท์  (อ่าน 7498 ครั้ง)

admin

  • Administrator
  • Hero Member
  • *****
  • กระทู้: 688
    • ดูรายละเอียด
    • อีเมล์
เขียนโปรแกรมรับสวิตช์แบบโพลลิ่งและแบบอินเตอร์รัพท์
การเขียนโปรแกรมตรวจสอบการกดสวิตช์มีให้เลือก 2 วิธีการคือ
1. แบบวนซ้ำตรวจสอบหรือที่เรียกว่าโพลลิ่ง (Polling)
2. แบบขัดจังหวะการทำงานหรือที่เรียกว่าการอินเตอร์รัพท์ (Interrupt)

คำสั่ง Interrupt มี 2 คำสั่ง
-attachInterrupt() เป็นการสั่งให้เริ่มเช็ค Interrupt
-detachInterrupt()  เป็นการสั่งยกเลิกเช็ค Interrupt
เงื่อนไขเหตุการณ์ที่ทำให้เกิดการเรียก Interrupt มี 3 แบบ
-CHANGE : เมื่อไฟที่ขา interrupt มีการเปลี่ยนค่า เช่น จาก 0 เป็น 1 หรือ จาก 1 เป็น 0
-RISING : เมื่อไฟที่ขา interrupt มีการเปลี่ยนสถานะจาก 0 เป็น 1
-FALLING : เมื่อไฟที่ขา interrupt มีการเปลี่ยนสถานะจาก 1 เป็น 0
* ขา GPIO ทุกขาสามารถใช้คำสั่ง Interrupt ได้ ยกเว้นขา GPIO16(D0)

โดยเขียนส่วนของการอ่านสวิตช์เป็นฟังก์ชั่นที่มีการส่งคืนค่า
ฟังก์ชั่นอยู่ในกลุ่ม Serial http://arduino.cc/en/Reference/Serial
-Serial.begin() http://arduino.cc/en/Serial/Begin
-if (Serial) http://arduino.cc/en/Serial/IfSerial
-Serial.available() http://arduino.cc/en/Serial/Available
-Serial.read() http://arduino.cc/en/Serial/Read
-Serial.print() http://arduino.cc/en/Serial/Print
-Serial.println() http://arduino.cc/en/Serial/Println
-Serial.flush() http://arduino.cc/en/Serial/Flush

ฟังก์ชั่นทั่วไป
-pinMode() http://arduino.cc/en/Reference/PinMode
-digitalRead() http://arduino.cc/en/Reference/DigitalRead
-digitalWrite() http://arduino.cc/en/Reference/DigitalWrite
-delay() http://arduino.cc/en/reference/delay

Digital IO
Pin numbers in Arduino correspond directly to the ESP8266 GPIO pin numbers. pinMode, digitalRead, and digitalWrite functions work as usual, so to read GPIO2, call digitalRead(2).
Digital pins 0—15 can be INPUT, OUTPUT, or INPUT_PULLUP. Pin 16 can be INPUT, OUTPUT or INPUT_PULLDOWN_16. At startup, pins are configured as INPUT.
reference http://esp8266.github.io/Arduino/versions/2.0.0/doc/reference.html

การชื่อเรียกขาพอร์ตของ NodeMCU และ Wemos D1 mini  ใช้อักษร D นำหน้า ส่วนชิพ ESP8266 (ซึ่งอยู่บนบอร์ด NodeMCU,WeMos) ใช้อักษรนำหน้าว่า GPIO เมื่อนำมาใช้งานสามารถใช้ได้ทั้งสองแบบโดยหากใช้เรียกขาที่เป็น GPIO จะใส่เพียงตัวเลข แต่ถ้าใช้ดังตัวที่สกีนบนบอร์ดจะใช้ D นำหน้า เมื่อเทียบกันแล้วจะได้ดังรูป


โจทย์โปรแกรม
-กดสวิตช์ดิจิตอล แสดงผลการกดสวิตช์ต่าง ๆ บนจอคอมพิวเตอร์ผ่านพอร์ตอนุกรม
-การกดสวิตช์ควบคุมการติดดับของ LED
(เช่น เมื่อสวิตช์ SW1 ถูกกด ให้แสดงผลว่า "SW1 is Pressed"
-โปรแกรมรายละเอียดพิเศษรายกลุ่ม (แจ้งให้ทราบเมื่อถึงชั่วโมงเรียน)

วงจรที่ใช้ทดลอง
กรณีใช้บอร์ดรุ่น NodeMCU

กรณีใช้บอร์ดรุ่น WeMos D1 mini


หมายเหตุ ขาพอร์ตของ NodeMCU ในแต่ละขามีคุณสมบัติต่างกัน บางขาไม่ต้องสั่ง INPUT_PULLUP บางขาต้องสั่ง และบางขาถึงจะสั่งแล้วก็ใช้งานไม่ได้ต้องใช้ตัวต้านทานพูลอัพข้างนอกเท่านั้น ให้นักศึกษาทดลองและทดสอบคุณสมบัติของขาพอร์ตที่จะนำมาใช้งานเป็นอินพุทก่อนการใช้งานจริง  เช่นขา D3(GPIO0), D4(GPIO2), D8(GPIO15) ซึ่งจะเห็นว่ามีการต่อตัวต้านทานทั้ง Pull up และ Pull down ไว้แล้ว


และในขณะเดียวกันยังมีขาที่ใช้เชื่อมต่อสื่อสารทางพอร์ตอนุกรม D9(RxD), D10(TxD) ซึ่งจะต้องต่อพ่วงกับไอซี USB to UART ทำให้มีผลจากตัวต้านทานเข้ามายังขาพอร์ตดังรูป




ตัวอย่างโปรแกรมแบบใช้ polling
วิธีการเขียนโปรแกรมลักษณะนี้เป็นการให้ไมโคร ฯ วนตรวจสอบการกดสวิตช์ตลอดเวลาและเมื่อตรวจพบการกดสวิตช์แล้วจึงให้ทำงานตามเงื่อนไขที่กำหนด ตัวอย่างโค้ดเป็นดังนี้
โค๊ด: [Select]
#define LED D1
#define SW D5
void setup()
{
  pinMode(LED,OUTPUT);
  pinMode(SW,INPUT_PULLUP);
  digitalWrite(LED,LOW);
  delay(500);
}
void loop()
{
    if(digitalRead(SW))
    {
      digitalWrite(LED,HIGH);
    }
    else
    {
      digitalWrite(LED,LOW);     
    }
}


ตัวอย่างโปรแกรมแบบใช้ Interrupt
วิธีการเขียนโปรแกรมตรวจสอบการกดสวิตช์แบบใช้การขัดจังหวะการทำงาน ตัวโปรแกรมหลักไม่ต้องวนตรวจสอบการกดสวิตช์ เมื่อสวิตช์ถูกกดไมโคร ฯ จะกระโดดไปทำงานตอบสนองที่เตรียมไว้ ตัวอย่างโค้ดเป็นดังนี้
โค๊ด: [Select]
#define LED D1
#define interruptPin D5
volatile int new_num =0;
int old_num=0;
void setup(){
  pinMode(LED, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), increment, FALLING);
  Serial.begin(9600);
}
void loop(){
  digitalWrite(LED, !digitalRead(LED)); 
  delay(250);
  if (new_num != old_num){
    Serial.print("value of interrupt: ");
    Serial.println(new_num);
    old_num=new_num;
  }
}
ICACHE_RAM_ATTR void increment(){
  (new_num<99)? new_num++:new_num=0;
}
หมายเหตุ 1
 ตัวแปรที่นำมาใช้งานในโปรแกรมตอบสนองการอินเตอร์รัพท์ต้องประกาศเป็นแบบ volatile เพื่อให้ค่าที่อ่านจากโปรแกรมหลักถูกต้องตรงกับค่าที่เกิดขึ้นภายในโปรแกรมตอบสนองการอินเตอร์รัพท์

หมายเหตุ 2
ต้องใส่ ICACHE_RAM_ATTR ไว้หน้าฟังก์ชั่นตอบสนองการอินเตอร์รัพท์สำหรับผู้ที่ใช้ Package ESP8266 เวอร์ชั่น 2.5.2 ขึ้นไป
 
« แก้ไขครั้งสุดท้าย: กันยายน 04, 2019, 02:22:26 PM โดย admin »