Lab 2.1 : เขียนโปรแกรมใช้งาน Sensor Input


LAB 2.1 เขียนโปรแกรมใช้งาน Sensor Input

เอกสารประกอบ :

โจทย์

ให้สร้างวงจรต่อไปนี้ให้เสร็จเป็นข้อๆ ไป

  1. การต่อเซ็นเซอร์เข้ากับ mcu เบื้องต้น – ให้ลองสร้างโคมไฟอัตโนมัติ โดยต่อเซ็นเซอร์แสงเข้ากับ mcu และควบคุมหลอดไฟ LED โดยให้เปิดเมื่อแสงมืด และให้ปิดเมื่อแสงสว่าง
  2. หลักการ Hysteresis – ให้ปรับปรุงโคมไฟอัตโนมัติข้างต้นโดยป้องกันไม่ให้ไฟติดๆ ดับๆ รัว ขณะที่ค่าเซ็นเซอร์อยู่บริเวณรอยต่อของเงื่อนไข  และใช้โปรแกรม Serial Plotter เป็นเครื่องมือแสดงและพิสูจน์พฤติกรรมของเซ็นเซอร์และไฟ
  3.  การใช้ Filter  – ให้ปรับปรุงวงจรโดยใช้หลักการตัวกรอง (filter) ป้องกันไม่ให้ไฟเปลี่ยนสถานะในกรณีที่ค่าแสงสว่างเปลี่ยนแปลงชั่วครู่  เช่น ตอนกลางคืนหากมีแสงสว่างที่เกิดเกิดฟ้าแลบฟ้าผ่า หลอดไฟไม่ควรดับ  หรือตอนกลางวันถ้ามีเงาพาดผ่านเซ็นเซอร์ทำให้แสงมืดไปชั่วขณะ หลอดไฟก็ไม่ควรติด  ขอให้ใช้โปรแกรม Serial Plotter สร้างกราฟเพื่อแสดงให้เห็นผลก่อนและหลังการใช้ filter ด้วยให้ทดลองเปรียบเทียบการใช้ Filter สองแบบคือ
    1. Analog Filter – ทดลองใช้ Capacitor ทำหน้าที่เป็นตัวกรอง (C3 ในรูปวงจรด้านล่าง) โดยทดลองใช้ Capacitor ค่าต่างๆ เช่น 10 uF และ 100 uF โดยควรจะเห็นผลว่า capacitor ที่ใหญ่ขึ้นก็จะหน่วงให้ค่าเซ็นเซอร์เปลี่ยนช้าลง

    2. Digital Filter – ทดลองใช้ Digital Filter ผ่านทางการคำนวณหาค่าเฉลี่ยตามที่อธิบายในเอกสารประกอบ

ประเด็นการเรียนรู้

  1. การทำงานของวงจร ADC (Analog to Digital Coverter) เป็นอย่างไร
  2. Voltage Divider คืออะไร และทำไมต้องนำมาใช้
  3. การ config PIC เพื่อให้ใช้งาน ADC ภายในตัวมันทำอย่างไรบ้าง
  4. เรียนรู้ความสำคัญของหลักการ Hysteresis และ Filter ในการป้องกันสัญญาณรบกวนในการนำเซ็นเซอร์ไปควบคุมการทำงานของอุปกรณ์ในชีวิตจริง

แนวทางการต่อวงจร ADC

วงจรแบ่งแรงดัน (Voltage Divider)

เนื่องจากวงจร ADC นั้นจะแปลงแรงดันให้เป็นค่าตัวเลข แต่เซ็นเซอร์แบบ Passive จำนวนมากมักมีค่าความต้านทานที่แปรตามสภาพแวดล้อมที่วัด ดั้งนั้นจึงต้องมีวงจรที่แปลง ความต้านทาน ให้กลายเป็น แรงดัน ซึ่งวงจรที่ง่ายที่สุดสำหรับงานนี้คือ วงจรแบ่งแรงดัน ภาพต่อไปนี้แสดงการต่อวงจรดังกล่าวกับ ADC port บน mcu โดยใช้เซ็นเซอร์แสงเป็นกรณีศึกษา

หลักการทำงานของวงจรแบ่งแรงดันขอให้ศึกษาจากเอกสารประกอบการสอน

แนวทางการใช้งาน Sensor Port บน PIC16

ตัวอย่างโปรแกรม

โปรแกรมต่อไปนี้จะอ่านค่าจากพอร์ท AN0 และพิมพ์ค่าออกมาทางหน้าจอทุกๆ 0.5 วินาที

#include <16F886.h>
#device ADC=10 *=16

#FUSES NOWDT //No Watch Dog Timer
#FUSES PUT //Power Up Timer
#FUSES NOMCLR //Master Clear pin not enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES BROWNOUT //Brownout reset
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#FUSES BORV40 //Brodddddwnout reset at 4.0V
#FUSES RESERVED //Used to set the reserved FUSE bits
#FUSES INTRC_IO 

#use delay(clock=8M)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
void main() {
    setup_adc_ports(sAN0); // setup PIN A0 as analog input 
    setup_adc( ADC_CLOCK_INTERNAL ); 

    printf("Sampling:\r\n");
    set_adc_channel( 0 ); // set the ADC chaneel to read 
    delay_us(100); // wait for the sensor reading to finish

    while (1) {
       printf("Sensor value = %Lu\r\n", read_adc()); 
       delay_ms(500); 
    }
}

อธิบายการทำงาน

PIC หมายเลข 16F886 มี Analog Port (หรือ Sensor Port) ทั้งหมด 11 ช่อง  คือ AN0-AN10 โดยการใช้งาน port เหล่านี้ในโปรแกรมมีขั้นตอนดังต่อไปนี้

1. เปิดใช้ port

การใช้งาน Analog Port จะเริ่มต้นด้วยคำสั่งเปิดใช้งานวงจร ADC (Analog  to Digital Converter) ดังนี้

setup_adc_ports(sAN0); // setup PIN A0 as analog input   
setup_adc( ADC_CLOCK_INTERNAL );

คำสั่งแรกใช้เลือกว่าจะเปิด port ใดบ้าง ค่า parameter ที่ใช้ได้กับคำสั่งนี่สามารถเปิดหาดูได้ในไฟล์ 16F886.h แต่ค่าที่ใช้บ่อยๆ ได้แก่

NO_ANALOGS        // ปิดการใช้งาน ADC
ALL_ANALOGS     // เปิดใช้งาน Analog Port หมดทุก port
sAN0          // เปิดใช้งาน Analog Port 0 เท่านั้น
sAN0 | sAN1 | saN2  // เปิดใช้งาน Analog Port 0,1,2

2. กระตุ้นการทำงาน และอ่านผล

set_adc_channel( 0 ); // กระตุ้นการทำงานของ ADC ในช่องที่เลือก  
delay_us(100);  // รอให้การแปลงค่าจาก Analog เป็น Digital เสร็จสิ้น
sensorValue = read_adc();  // อ่านค่ามาเก็บไว้ในตัวแปร
  • คำสั่ง set_adc_channel เป็นตัวกำหนดว่าเราจะกระตุ้นให้ Analog Port หมายเลขใดเริ่มทำงาน
  • โดยหลังจากกระตุ้นแล้วจะต้องใช้คำสั่ง delay เพื่อรอให้วงจร ADC แปลงค่า Digital ให้เป็น Analog เสร็จสิ้นเสมอ (จุดนี้พลาดกันบ่อยมาก และทำให้โปรแกรมอ่านค่าออกมาผิดเพี้ยน)
  • ขั้นตอนสุดท้ายคือการอ่านค่า Analog ออกมาเก็บไว้ในตัวแปร
ระวัง
read_adc() จะคืนค่าขนาด 10 บิตและต้องใช้ตัวแปรชนิด int16 ในการเก็บค่า หากใช้ตัวแปรชนิด int ซึ่งมีขนาดเพียง 8 บิต ค่าจะผิดเพี้ยน

*หมายเหตุ: เราสามารถกำหนดให้วงจร ADC อ่านค่าออกมาเป็นตัวเลขขนาด 8 หรือ 10 bit ก็ได้ ซึ่งกำหนดโดยคำสั่ง

#device adc=10    // ตั้งค่าให้ ADC อ่านค่าออกมาเป็นตัวเลขขนาด 10 bit

โดยคำสั่งดังกล่าวจะต้องวางไว้ที่บรรทัดบนสุดใต้คำสั่ง include <16F886.h>

 

การแสดงกราฟด้วยโปรแกรม Serial Port Plotter

ในปฏิบัติกานี้การพล๊อทกราฟจะช่วยให้เห็นสิ่งที่เกิดขึ้นได้ดีขึ้น โปรแกรมที่แนะนำให้คือชื่อ Serial Port Plotter

Download Serial Port Plotter

การพล๊อทจะทำโดยการส่งค่าตามรูปแบบต่อไปนี้

$value value value;

เช่น หากต้องการแสดงกราฟการนับค่าก็สามารถใช้โปรแกรมนี้ได้

int16 i=0,j=1000;

while (1) {
 printf("$%lu %lu;", i,j);
 i++; j--
 delay_ms(100);
}
คำแนะนำ –  ในโปรแกรม Serial Plotter ขอให้ตั้งค่า Baudrate ให้ตรงกับในโปรแกรมท่าน (ปกติจะเป็น 9600) หากค่านี้ไม่ตรงก็จะสื่อสารกันไม่ได้

วิดิโอต่อไปนี้แนะนำวิธีการใช้โปรแกรม Serial Plotter

หมายเหต: video นี้แสดงการใช้งานโปรแกรมรุ่นเก่ากว่าปัจจุบัน หน้าตาโปรแกรมเปลี่ยนไปแล้วพอสมควร แต่อย่างไรก็ดี video นี้ยังให้ภาพรวมได้ว่าการใช้งานโปรแกรมเป็นอย่างไร