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


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

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

โจทย์

  1. ให้นักศึกษาสร้างระบบเปิดปิดอัตโนมัติโดยให้เปิด LED เมื่อแสงมืด และปิดเมื่อแสงสว่าง
    การทำโจทย์นี้นักศึกษาจะได้หัดเขียนโปรแกรมใช้งาน Sensor Port ของ PIC โดยต่อเข้ากับ เซ็นเซอร์แสง
  2. ให้เพิ่มระบบป้องกันสัญญารบกวน เช่น ตอนกลางคืนหากเกิดฟ้าแลบฟ้าผ่า หลอดไฟไม่ควรดับ  หรือตอนกลางวันถ้ามีเงาพาดผ่านเซ็นเซอร์หลอดไฟก็ไม่ควรติด
    กำหนดให้ค่าเซ็นเซอร์ต้องเข้าเงื่อนไขเป็นเวลา 1 วินาทีระบบจึงจะทำงาน

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

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

แนวทางการต่อวงจร Sensor Port บน PIC16

ADC

 

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

PIC หมายเลข 16F886 มี Analog Port (หรือ Sensor Port) ทั้งหมด 11 ช่อง  คือ AN0-AN10

1. การใช้งาน 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. ต่อไปในโปรแกรมของเรา ทุกครั้งที่จะอ่านค่าจาก Analog Port ให้ใช้คำสั่งต่อไปนี้

set_adc_channel( 0 ); // เลือกช่อง ADC ที่จะอ่าน  
delay_us(100);  // รอให้การแปลงค่าจาก Analog เป็น Digital เสร็จสิ้น
sensorValue = read_adc();  // อ่านค่ามาเก็บไว้ในตัวแปร

คำสั่ง set_adc_channel เป็นตัวกำหนดว่าเราจะใช้ Analog Port หมายเลขใด โดยหลังจากกำหนดค่าแล้วจะต้องรอให้วงจร ADC ทำการแปลงค่า Digital ให้เป็น Analog เสร็จสิ้นเสมอ (นักศึกษาจะพลาดลืมตรงจุดนี้กันบ่อยมาก และทำให้โปรแกรมอ่านค่าออกมาผิดเพี้ยน) ขั้นตอนสุดท้ายคือการอ่านค่า Analog ออกมาเก็บไว้ในตัวแปร

สิ่งสุดท้ายที่ต้องคำนึงถึงคือค่าที่อ่านออกมาจากวงจร ADC นั้นมีขนาด 10 bit ซึ่งจะต้องใช้ตัวแปรประเภท int16 ในการเก็บค่า หากใช้ตัวแปร int ธรรมดาซึ่งมีขนาดเพียง 8 bit ก็จะทำให้เก็บค่าได้ไม่ครบและเกิดการผิดเพี้ยนขึ้น

*หมายเหตุ: เราสามารถกำหนดให้วงจร 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); 
    }
}