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


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

ประกอบ :

โจทย์

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

    2. ทดลองใช้ 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

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>

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

โปรแกรมทั้งหมดจากที่อธิบายมาจะมีโครงสร้างดังตัวอย่างต่อไปนี้

#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); 
    }
}

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

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

Download Serial Port Plotter (Windows only)

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

$value value value;

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

int16 i=0,j=1000;

while (1) {
 printf("$%lu %lu;", i,j);
 i++; j--
 delay_ms(100);
}

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