[TH] Arduino : ESP8266 GPIO

ในบทความนี้เป็นการเรียนรู้เรื่องของ GPIO (General Purpose I/O) หรือขาเชื่อมต่อกับอุปกรณ์ภายนอกของไมโครคอนโทรลเลอร์ด้วยภาษา C++ ของ Arduino โดยใช้ esp8266 เป็นชิพอ้างอิง ซึ่งสามารถนำไปประยุกต์ใช้กับ Arduino Uno, Arduino Mega หรือ STM32 ได้เช่นกัน ภายใต้บทความนี้อธิบายเรื่องของการกำหนดหน้าที่ของขา การนำสัญญาณออก และการนำสัญญาณเข้า

ภาพที่ 1 WeMos D1 กับ GPIO ที่ทำหน้าที่ต่าง ๆ

จากภาพที่ 1 จะพบว่าขาต่าง ๆ ของ esp8266 นั้นมีชื่อเรียกที่แตกต่างกัน โดยแต่ละขามีหน้าที่แตกต่างกันด้วยเช่นกัน ซึ่งบทบาทหน้าที่ของขาเป็นดังตารางต่อไปนี้

ซึ่งจากตารางนี้จะพบว่าขาที่สามารถใช้งานได้โดยไม่มีผลกระทบกับการทำงานของ esp8266 เลยนั้น ได้แก่ D1, D2, D4, D5, D6, D7 และ A0 ซึ่ง a0 สามารถนำเข้าสัญญาณแอนาล็อกเท่านั้นและต้องมีแรงดันไม่เกิน 3.3VDC อีกด้วย (จริง ๆ รับได้ 1VDC แต่บทบอร์ดมีวงจรลดทอนแรงดัน)

การกำหนดหน้าที่ของขา

รูปแบบของคำสั่งที่ต้องกำหนดในฟังก์ชัน setup() เป็นดังนี้

pinMode( ขา, หน้าที่ )

โดย
ขา เป็นชื่อเรียกของขา
หน้าที่ เป็นค่าคงที่ INPUT สำหรับนำเข้าข้อมูลจากขาที่กำหนด หรือ OUTPUT สำหรับนำออกข้อมูลที่ขาที่กำหนด
ตัวอย่างการกำหนดให้ขา GPIO4 เป็นขานำเข้าสัญญารดิจิทัล และ GPIO5 เป็นขานำออกสัญญาณดิจิทัลสามารถเขียนโค้ดคำสั่งได้ดังนี้

void setup( ) {
	pinMode( 4, INPUT );
	pinMode( 5, OUTPUT );
}

การนำออกสัญญาณดิจิทัล

การนำออกสัญญาณดิจิทัลเป็นการสั่งงานให้ขาของพอร์ตไมโครคอนโทรลเลอร์มีสถานะลอจิกเป็น LOW หรือ HIGH ซึ่งมีผลต่อการส่งแรงดันในระดับสัญญาณแอนาล็อก คือ การส่ง LOW เปรียบเสมือนการปรับให้ขาของพอร์ตไมโครคอนโทรลเลอร์เป็นกราวด์ของวงจรไฟฟ้า และ HIGH เป็นการให้ขาของพอร์ตไมโครคอนโทรลเลอร์เป็นแหล่งแรงดันไฟฟ้ากระแสตรง 3.3V โดยสามารถขับโหลดได้ไม่เกิน และขาที่นำออกสัญญาณดิจิทัลต้องถูกกำหนดหน้าที่ให้เป็น OUTPUT ด้วยคำสั่ง pinMode( ) ก่อนดำเนินการนำออกสัญญาณดิจิทัล รูปแบบของคำสั่งนำออกสัญญาณดิจิทัลเป็นดังนี้

digitalWrite( ขา, ระดับสัญญาณดิจิทัล )

โดย ขา คือ หมายเลขขาที่ได้กำหนดหน้าที่ให้เป็น OUTPUT
ระดับสัญญาณดิจิทัล คือ ระดับสัญญาณดิจิทัลที่ต้องการนำออก ซึ่งมีได้ 2 ประเภท ได้แก่ HIGH และ LOW สำหรับแรงดันสัญญาณดิจิทัล 1 และ 0 ตามลำดับ

ตัวอย่างการสั่งงานส่งสัญญาณดิจิทัลที่ขา 4 ให้เป็น LOW และขา 5 ให้เป็น HIGH สามารถเขียนสั่งงานได้ดังนี้

pinMode( 4, OUTPUT );
pinMode( 5, OUTPUT );
digitalWrite( 4, LOW );
digitalWrite( 5, HIGH );

ตัวอย่างโปรแกรมสำหรับสั่งงานให้หลอดแอลอีดีเปล่งแสงหรือดับ โดยในการทดลองนี้ใช้กับอุปกรณ์ ET-TEST 10P/OUT ดังภาพที่ 2 ได้โค้ดดังนี้

ภาพที่ 2วงจรของบอร์ด ET-TEST 10P/OUT

การนำเข้าสัญญาณดิจิตัล

การนำเข้าสัญญาณดิจิทัลจากพอร์ตของไมโครคอนโทรลเลอร์จะต้องกำหนดหน้าที่ให้ขานั้นเป็นขา INPUT ในส่วนของฟังก์ชัน setup( ) หรือปรับเปลี่ยนสถานะด้วย pinMode( ) ก่อนนำเข้าสัญญาณดิจิทัลเสมอ โดยรูปแบบคำสั่งการนำเข้าสัญญาณดิจิทัลไปเก็บในตัวแปร “ผลลัพธ์” จากพอร์ต “ขา” เขียนได้ดังนี้

ผลลัพธ์ = digitalRead( ขา )

โดย
ผลลัพธ์ เป็นตัวแปรเก็บผลลัพธ์แรงดันสัญญาณดิจิทัล ซึ่งมีค่าเป็น HIGH หรือ LOW สำหรับแทนค่าแรงดันสัญญาณดิจิทัล 1 และ 0 ตามลำดับ
ขา คือ หมายเลขขาที่กำหนดให้มีหน้าที่เป็นขานำเข้าสัญญาณดิจิทัล

ตัวอย่างการนำเข้าสัญญาณดิจิทัลจากขา 16 หรือ D0 ไปเก็บในตัวแปร d0_stat เขียนเป็นคำสั่งได้ดังนี้

pinMode( 16, INPUT );
int d0_stat = digitalRead( 16 );

ตัวอย่างโปรแกรมสำหรับการนำเข้าสัญญาณดิจิทัลจากบอร์ด ET-TEST 10P/INP เพื่อส่งไปยัง ET-TEST 10P/OUT ตามภาพที่ 3 มีโค้ดดังนี้

ภาพที่ 3 การต่อกับบอร์ด ET-TEST 10P/OUT และET-TEST 10P/INP

การรับสัญญาณแอนาล็อก

การแปลงสัญญาณแอนะล็อกซึ่งเป็นสัญญาณแบบต่อเนื่อง (Continuous Signal) จากขานำสัญญาณเข้าเป็นสัญญาณแบบไม่ต่อเนื่อง (Discrete Signal) ที่เรียกว่าดิจิทัลในรูปแบบของตัวเลขดิจิทัล ขั้นตอนของการแปลงสัญญาณแอนะล็อกเป็นสัญญาณดิจิทัล คือ

  1. เมื่อมีสัญญาณแบบแอนะล็อกส่งเข้ามาส่วนตัวแปลงที่เรียกว่าเอดีซี
  2. ตัวแปลงจะเปรียบเทียบแรงดันเป็นค่าตัวเลขจำนวนเต็มแบบดิจิทัล
  3. ตัวแปลงสัญญาณจะส่งข้อมูลที่แปลงเป็นค่าตัวเลขดิจิทัลกลับออกมา

คำสั่งสำหรับการอ่านข้อมูลสัญญาณแอนาล็อกที่อ่านค่าผลการแปลงสัญญาณแอนาล็อกเป็นดิจิทัลไปเก็บในตัวแปร vDigital มีรูปแบบดังนี้

vDigital = analogRead( 0 )

ตัวอย่างการอ่านค่าจากแรงดันที่ได้จากตัวต้านทานปรับค่าได้ตามภาพที่ 4 เป็นดังนี้

ภาพที่ 4 การต่อสำหรับทดสอบการวัดแรงดันจากภาค ADC

คำสั่งอื่น ๆ เกี่ยวกับสัญญาณแอนาล็อกที่น่าสนใจเป็นดังนี้

  1. analogReadResolution( จำนวนบิต ) ใช้สำหรับกำหนดค่าจำนวนบิตของการทำแซมปลิง (sampling) โดยปกติจะขึ้นอยู่กับไมโครคอนโทรลเลอร์ เช่น ถ้าเป็น esp32 จะมีค่าเป็น 12 บิต เป็นต้น
  2. analogSetWidth( ความกว้าง ) ใช้สำหรับกำหนดค่าช่วงความกว้างของค่าที่อ่านได้ เช่น ADC ขนาด 8 บิตจะได้ค่าเป็น 256 ค่า หรือ 0 ถึง 255 ถ้าเป็น ADC 10 บิตจะได้ค่า 1024 ค่า หรือ 0 ถึง 1023 เป็นต้น
  3. analogSetCycles( จำนวนไซเคิล ) กำหนดจำนวนไซเคิลต่อ 1 ตัวอย่าง ซึ่งค่าปกติเป็น 8 จากค่าในช่วง 1 ถึง 255
  4. analogSetClockDiv( ค่าตัวหาร ) กำหนดค่าตัวหารสำหรับวงจร ADC ซึ่งปกติกำหนดเป็น 1 จากค่าในช่วง 1 ถึง 255
  5. analogSetAttenuation( attenuation ) สำหรับการนำไปใช้กับ esp32 ค่าจอง attenuation ให้ผลดังนี้ โดยปกติค่าเป็น ADC_0db หรือไม่มีการลดทอนค่า
    1. ADC_0db ตั้งค่าไม่มีการลดทอน ADC สามารถวัดได้สูงถึงประมาณ 800 mV (อินพุต 1V = การอ่าน ADC ที่ 1088)
    2. ADC_2_5db แรงดันไฟฟ้าขาเข้าของ ADC จะถูกลดทอนลง โดยขยายช่วงของการวัดให้สูงถึงประมาณ 1100 มิลลิโวลต์ (อินพุต 1V = ค่า ADC ที่อ่านได้ 3722)
    3. ADC_6db แรงดันไฟขาเข้าของ ADC จะถูกลดทอนลง โดยขยายช่วงของการวัดให้สูงถึงประมาณ 1350 มิลลิโวลต์ (อินพุต 1V = การอ่าน ADC ที่ 3033)
    4. ADC_11db แรงดันไฟขาเข้าของ ADC จะถูกลดทอนลง โดยขยายช่วงของการวัดให้สูงถึงประมาณ 2600 มิลลิโวลต์ (อินพุต 1V = การอ่าน ADC 1575)
  6. analogSetPinAttuation( pin, attenuation ) ตั้งค่าการลดทอนข้อมูลนำเข้าจากขา pin โดบค่าเริ่มต้นของ attenuation เป็น ADC_11db
  7. ผลของการต่อ = adcAttchPin( pin ) ต่อขา pin เข้ากับ ADC ถ้าสำเร็จจะคืนค่า TRUE ถ้าล้มเหลวคืนค่า FALSE
  8. adcStart( pin ) สั่งให้ ADC ของขา pin เริ่มต้นทำงาน
  9. สถานะ = adcBusy( pin ) ตรวจสอบสถานะของขา pin ถ้าคืนค่าเป็น TRUE แสดงว่า ADC ว่าง แต่ถ้าเป็น FALSE หมายความว่า ADC กำลังทำงานอยู่
  10. resultadcEnd( pin ) อ่านค่าการแปลงจาก ADC ของขา pin

สรุป

จากบทความนี้จะพบว่า ขั้นตอนการใช้งาน GPIO มีขั้นตอนแรกที่ต้องกระทำ คือ กำหนดหน้าที่ของขา และเมื่อต้องการนำสัญญาณดิจิทัลออกให้ใช้คำสั่ง digitalWrite() ถ้าต้องการนำเข้าสัญญาณดิจิทัลให้ใช้คำสั่ง digitalRead() และถ้าต้องการนำเข้าสัญญาณแอนาล็อกให้เลือกใช้คำสั่ง analogRead() สุดท่ายขอให้มีความสุขกับการเขียนโปรแกรมครับ

(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-06-21, 2021-07-04, 2021-08-06, 2021