วันอาทิตย์ที่ 3 ตุลาคม พ.ศ. 2553

Lab13: การวัด Position Encoder

จะใช้ Code นี้ได้ต้อง Copy QEI Lib เข้าไปไว้ใน 18F2431, 18F4431, 18F2331, 18F4331 แล้วแต่ว่าใช้เบอร์ไหน

#include <18F2431.h>
 #use delay(clock=20000000)
#fuses HS,PUT,BROWNOUT,MCLR,NOWDT,NOPROTECT,NOLVP
#define  TxD         PIN_C6  
#define  RxD         PIN_C7  
#use rs232(baud=115200, xmit=TxD,rcv=RxD)

void main()
{
   POSCNT = 0;
   MAXCNT = 0xFFFF;
   QEICON = 24;         // quad in x4 mode, resettable by maxcount

   enable_interrupts(GLOBAL);               
   enable_interrupts(INT_IC2QEI);


   while(true)
   {
printf("%lu\r\n", POSCNT);

}
}


Lab14: การวัด Velocity Encoder

#include <18F2431.h>
 #use delay(clock=20000000)
#fuses HS,PUT,BROWNOUT,MCLR,NOWDT,NOPROTECT,NOLVP
#define  TxD         PIN_C6  
#define  RxD         PIN_C7  
#use rs232(baud=115200, xmit=TxD,rcv=RxD)

void main()
{
   int16 pos1,pos2;
   float time;
   float Vel;

   POSCNT = 0;
   MAXCNT = 0xFFFF;
   QEICON = 24;         

   enable_interrupts(GLOBAL);               
   enable_interrupts(INT_IC2QEI);
  setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);

   while(true)
   {
set_timer1(0);
pos1 = POSCNT;
printf("%.3f\r\n", Vel);
pos2 = POSCNT;
time = get_timer1();
time = time*8*0.0000002;

  if(pos2>pos1){
      Vel = (float)(pos2 - pos1)/time;
       }
      else{
       Vel = (float)(pos1 - pos2)/time;
      }

}
}

Lab12: การใช้งาน MCP3201(Analog to Digital 12 bits)

#include <16F877.h>
#fuses HS,NOLVP,NOPROTECT,NOWDT
#use delay(CLOCK = 20000000)
#define use_portb_lcd
#use fast_io(A)
               
#define Vbe 0.0012210012210012210012210012210012     // Vref/4095(5/4095)

#define cs   PIN_A0                 // bit output. //
#define clkm PIN_A1                 // bit output. //
#define Dout PIN_A2                 // bit input. //


unsigned int16 Read_mcp3201()
{
   unsigned int16 digi;
   unsigned char z;
  
   output_high(cs);
   digi = 0;
   output_low(clkm);
   output_low(cs);
  
   //clock 1.//
   output_low(clkm);
   output_high(clkm);
   //clock 2.//
   output_low(clkm);
   output_high(clkm);
   //clock 3.//
   output_low(clkm);
   output_high(clkm);
  
   //clock 4-15.//  
       for(z=0;z<12;z++)
       {  
         output_low(clkm);
         output_high(clkm);
         digi = digi << 1;
         digi = digi | input(Dout);          
       }    
   output_high(cs);
   return(digi);
}

void main(void)
{
      unsigned int16 a;       // digi 12 bit. //
      float vol;              // volte type float. //
     
      set_tris_a(0xFC);       // set port output PINA0,PINA1 ||
      while(TRUE)
      {
         set_tris_a(0xFC);
         delay_ms(10);
         a = Read_mcp3201();
         vol = (a*Vbe);
      }    
}

Lab11: การใช้งาน MCP4922(Digital to Analog 12 bits)


การใช้งาน IC MCP4922 เป็น IC D to A ขนาด 12 bits ซึ่งสามารถหาซื้อได้ทั่วไปในเมืองไทย

#include <16F877A.h>
#DEVICE ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,  parity=N, Bits=8, xmit=PIN_C6, rcv=PIN_C7)

#define MCP4922_CS    PIN_B1
#define MCP4922_CLK   PIN_B2
#define MCP4922_DIN   PIN_B3
#define MCP4922_LDAC  PIN_B4
#define MCP4922_SHDN  PIN_B5

// กำหนดค่า Register ต่างๆ ของ MCP4922
#define MCP4922_DAC_A_BUFFERED_GAIN_1X_NON_SHDN      0x70  // DAC A, Buffered, Gain 1x, Output power control
#define MCP4922_DAC_A_BUFFERED_GAIN_2X_NON_SHDN      0x50  // DAC A, Buffered, Gain 2x, Output power control
#define MCP4922_DAC_A_NON_BUFFERED_GAIN_1X_NON_SHDN  0x30  // DAC A, Non buffered, Gain 1x, Output power control
#define MCP4922_DAC_A_NON_BUFFERED_GAIN_2X_NON_SHDN  0x10  // DAC A, Non buffered, Gain 2x, Output power control
#define MCP4922_DAC_B_BUFFERED_GAIN_1X_NON_SHDN      0xF0  // DAC B, Buffered, Gain 1x, Output power control
#define MCP4922_DAC_B_BUFFERED_GAIN_2X_NON_SHDN      0xD0  // DAC B, Buffered, Gain 2x, Output power control
#define MCP4922_DAC_B_NON_BUFFERED_GAIN_1X_NON_SHDN  0xB0  // DAC B, Non buffered, Gain 1x, Output power control
#define MCP4922_DAC_B_NON_BUFFERED_GAIN_2X_NON_SHDN  0x90  // DAC B, Non buffered, Gain 2x, Output power control

void mcp4922_init() {  //ฟังก์ชั่นเริ่มต้นการทำงาน
   output_high(MCP4922_CS);
   output_high(MCP4922_CLK);
   output_high(MCP4922_DIN);
   output_high(MCP4922_LDAC);
   output_high(MCP4922_SHDN);
}

void main()
{
   int8 cmd[2],i;              //ประกาศตัวแปร cmd, I เป็น integer 8 bits
   int16 data;                  //ประกาศตัวแปร data เป็น integer 16 bits
   mcp4922_init();           //กำหนดฟังก์ชั่นเริ่มต้นการทำงาน

   while(TRUE) {

   data =  4095;            //กำหนด data = 4095((4095 * 5)/(2^12-1) = 5 V)
   cmd[0]=data;              // cmd[0] = data 8 bits ล่าง
   cmd[1]=(data>>8)|MCP4922_DAC_B_BUFFERED_GAIN_1X_NON_SHDN;
                                    // cmd[0] = data 4 bits บน

   output_low(MCP4922_CS);               //เริ่มต้นการแปลงสัญญาณด้วย MCP4922
   output_low(MCP4922_CLK);
   output_high(MCP4922_LDAC);

   for(i=0;i<=15;i++) {
      output_bit(MCP4922_DIN,shift_left(cmd,2,1));
      output_high(MCP4922_CLK);
      output_low(MCP4922_CLK);
   }
   output_high(MCP4922_CS);
   output_low(MCP4922_LDAC);
   delay_us(10);
   output_HIGH(MCP4922_LDAC);
   delay_us(10);
    
  }
}

Lab10: การควบคุม DC MOTOR


การควบคุม DC MOTOR มีประโยชน์ในด้านสามารถควบคุมทิศทาง และความเร็วในการเคลื่อนที่ ซึ่งจะสามารถพัฒนาไปเป็นการควบคุมแบบป้อนกลับ (Feed Back Control)

#include<18F4431.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()
#use rs232(baud=9600,xmit= PIN_C6,rcv= PIN_C7 ) // ใช้งาน module RS232

void forward(){
output_high(pin_c4);
output_low(pin_c5);
}           // ฟังก์ชันควบคุมการเคลื่อนที่ไปข้างหน้า
void backward(){
output_low(pin_c4);
output_high(pin_c5);
}          // ฟังก์ชันควบคุมการเคลื่อนที่ถอยกลับ
void stop(){
output_low(pin_c4);
output_low(pin_c5);
}          // ฟังก์ชันหยุดการเคลื่อนที่

void main(void){
 
    enable_interrupts(GLOBAL);           //เปิดการใช้งาน interrupt รวม
    enable_interrupts(INT_CCP1);         //เปิดการใช้งาน interrupt CCP1
    setup_ccp1(CCP_PWM);                 // กำหนดค่า CCP1 ทำงานโหมด PWM
    setup_timer_2(T2_DIV_BY_1, 255, 1);       //กำหนดค่า Timer2 ควบคุมความถี่ของ PWM
    set_timer2(0);                                               //กำหนดค่า Timer2 เป็น 0
  
while(true){

if(!input(pin_a0)){                     //ตรวจสอบ input pin a0 ถ้า Low (กด switch)
   forward();                              //เคลื่อนที่ไปข้างหน้า
   set_pwm1_duty(1000);         //กำหนดความเร็วโดยปรับ duty Cycle 0 - 1023
}
if(!input(pin_a1)){                     //ตรวจสอบ input pin a1 ถ้า Low (กด switch)
   backward();                          //เคลื่อนที่ถอยหลัง
   set_pwm1_duty(1000);         //กำหนดความเร็วโดยปรับ duty Cycle 0 - 1023
}
if(!input(pin_a2)){                     //ตรวจสอบ input pin a2 ถ้า Low (กด switch)
   stop();                                   //หยุดการเคลื่อนที่
}
}
}

Lab9: การควบคุม RC SERVO MOTOR


การใช้งาน RC SERVO MOTOR นั้นสามารถเขียนโปรแกรมได้หลายวิธี ยกตัวอย่างเช่น ใช้ Library “SERVOS.c” , การใช้งาน Power PWM โดยกำหนดค่า Frequency = 50 Hz และการใช้งานฟังก์ชัน Delay ง่ายๆ ในที่นี้ขอนำเสนอวิธีใช้งานฟังก์ชัน Delay

#include<18F4431.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()
#use rs232(baud=9600,xmit= PIN_C6,rcv= PIN_C7 ) // ใช้งาน module RS232

void main(void){

while(true){

if(!input(pin_a0)){                      //ตรวจสอบ input pin a0 ถ้า Low (กด switch)
output_high(pin_b0);    
delay_us(2000);
output_low(pin_b0);
delay_ms(20);
//RC SERVO MOTOR หมุนที่ +90 องศา
}

if(!input(pin_a1)){          //ตรวจสอบ input pin a1 ถ้า Low (กด switch)
output_high(pin_b0);
delay_us(1000);
output_low(pin_b0);
delay_ms(20);
}
//RC SERVO MOTOR หมุนที่ -90 องศา

}
}

Lab8: การวัดค่า Duty Cycle (CCP1,CCP2)


#include<18F4431.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()
#use rs232(baud=9600,xmit= PIN_C6,rcv= PIN_C7 ) // ใช้งาน module RS232

float time1,time2;
BOOLEAN hook_cpp1, HookRise;

#int_ccp1
void capture_isr()
{
   if(HookRise)
   {
    time1 = get_timer1();
    HookRise = FALSE;
   }
   else
   {
    time2 = get_timer1();
    HookRise = TRUE;
    hook_cpp1 = FALSE;                          //done
   }
}

// ฟังก์ชัน interrupt CCP1 เพื่อจับเวลาขอบขาขึ้นของสัญญาณ โดยเก็บเวลาที่ตัวแปร time1,time2

long rise,fall,pulse_width;

#int_ccp2
void isr()
{
   rise = CCP_1;
   fall = CCP_2;

   pulse_width = fall - rise;    
}
// ฟังก์ชัน interrupt CCP2 เพื่อจับเวลาขอบขาขึ้นของสัญญาณ และขอบขาลงของสัญญาณ โดยเก็บเวลาที่ตัวแปร rise, fall

void main(void)
{
   float T,F,width,duty;  //ประกาศตัวแปร T,F,width,duty เป็น floating point number

   while(true)
   {

      HookRise=TRUE;
      hook_cpp1=TRUE;
      setup_ccp1(CCP_CAPTURE_RE);           //กำหนดค่า CCP1 Capture ขอบขาขึ้น
      setup_ccp2(CCP_CAPTURE_FE);           //กำหนดค่า CCP2 Capture ขอบขาลง
      enable_interrupts(INT_CCP1);              // เปิดการทำงาน interrupt CCP1
      enable_interrupts(INT_CCP2);                   // เปิดการทำงาน interrupt CCP2
      enable_interrupts(GLOBAL);                // All interrupts ON
      set_timer1(0);                                             // กำหนดค่า Timer1 เป็น 0
      while(hook_cpp1==TRUE);                       //เงื่อนไขการตรวจสอบสัญญาณครบ 1 period
     
      setup_ccp1(CCP_OFF);                            //ปิดการทำงาน CCP1
      disable_interrupts (GLOBAL);                    //ปิดการทำงาน interrupt รวม
      
      T = (time2-time1)*0.0000002*8;                // Period time = cycle*(4/fosc)*PR
      width = (float)pulse_width / 5000000;            //width = pulse_width / (clock / 4)
      duty = (width*100)/T;                      //หาค่า Duty Cycle (T_on*100 / Period time)
     
      printf(“ %.3f\r\n",duty);                   //แสดงค่าผ่าน RS232
   
   }
}

Lab7: การใช้งาน CCP(Counter)


#include<18F4431.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()
#use rs232(baud=9600,xmit= PIN_C6,rcv= PIN_C7 ) // ใช้งาน module RS232

int16 A;                                    //ประกาศตัวแปร time1,time2 เป็น floating point number
BOOLEAN hook_cpp1, HookRise;     //ประกาศตัวแปร hook_cpp1, HookRise เป็น Boolean

#int_ccp1
void capture_isr()
{
   if(HookRise)
   {
    A = A+1;
    HookRise = FALSE;
   }
}
// ฟังก์ชัน interrupt ในการตรวจสอบสัญญาณเข้า ให้นับขึ้นที่ 1 เก็บไว้ที่ตัวแปร A

void main(void){
  
   while(true){

      HookRise=TRUE;
      hook_cpp1=TRUE;
      setup_ccp1(CCP_CAPTURE_RE);           //กำหนดค่า CCP1(Capture)
      enable_interrupts(INT_CCP1);              // Enable interrupt CCP1
      enable_interrupts(GLOBAL);                // ตั้งค่า interrupt รวมทำงาน
      printf("%lu\r\n",A);              //แสดงค่าผ่าน RS232
   
   }
}

Lab6: การใช้งาน Module CCP(Capture วัดความถี่)


#include<18F4431.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()
#use rs232(baud=9600,xmit= PIN_C6,rcv= PIN_C7 ) // ใช้งาน module RS232

float time1,time2;                      //ประกาศตัวแปร time1,time2 เป็น floating point number
BOOLEAN hook_cpp1, HookRise;     //ประกาศตัวแปร hook_cpp1, HookRise เป็น Boolean

#int_ccp1
void capture_isr()
{
   if(HookRise)
   {
    time1 = get_timer1();
    HookRise = FALSE;
   }
   else
   {
    time2 = get_timer1();
    HookRise = TRUE;
    hook_cpp1 = FALSE;                  
   }
}
// ฟังก์ชัน interrupt CCP1 เพื่อจับเวลาขอบขาขึ้นของสัญญาณ โดยเก็บเวลาที่ตัวแปร time1,time2

float T;                         //ประกาศตัวแปร T เป็น floating point number
void main(void){

while(true){

      HookRise=TRUE;
      hook_cpp1=TRUE;
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);      // กำหนดค่า timer1
      setup_ccp1(CCP_CAPTURE_RE);           //กำหนดค่า CCP1(Capture ขอบขาขึ้น)
      enable_interrupts(INT_CCP1);              // Enable interrupt CCP1
      enable_interrupts(GLOBAL);                // ตั้งค่า interrupt รวม
      set_timer1(0);                                 //ตั้งค่า timer1 เป็น 0
     
      while(hook_cpp1);             //ตรวจสอบสัญญาณ เข้ามาหรือไม่
      setup_ccp1(CCP_OFF);                //ปิดการใช้งาน CCP1
      disable_interrupts (GLOBAL);        //ปิดการใช้งาน interrupt รวม
      
      T = (time2-time1)*0.0000002*8;            // Period time=cycle*(4/fosc)*PR
      printf("Frequency:%f Hz\r\n",1/T);   //แสดงค่าผ่าน RS232
    }
   }

Lab5: การใช้งาน Power PWM(18F2431,18F2331,18F4331,18F4431)


#include<18F4431.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()

void main(){
   int16 period;

   period =511;            
   //ความถี่ของสัญญาณ = Fosc (ความถี่ของ Crystal)/ (4 * (period+1) * postscale)         setup_power_pwm_pins(PWM_COMPLEMENTARY,PWM_OFF,PWM_OFF,PWM_OFF);                     //กำหนดค่า Power PWM pin B0,B1 ในโหมด Complementary
setup_power_pwm(PWM_CLOCK_DIV_4|PWM_FREE_RUN,1,0,period,0,1,0);
            //กำหนดโหมดการทำงาน (ดูรายละเอียดเพิ่มเติม)
   while(true){
     
      set_power_pwm0_duty(500 * ((period>>8)+1));   //ตั้งค่า PWM 19.45kHz duty cycle 50% pin B0,B1 invert  กัน                                                                                                        
   }
}

Lab4: การใช้งาน Module CCP(PWM)


#include<16F877A.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()

void main(void){
    int16 duty = 500;                              //ประกาศตัวแปร duty เป็นแบบ integer 16 bits
    enable_interrupts(GLOBAL);           //เปิดการทำงาน interrupt รวม
    enable_interrupts(INT_CCP1);         //เปิดการทำงาน interrupt CCP1
    setup_ccp1(CCP_PWM);                //กำหนดค่า CCP1 ทำงานโหมด PWM
    setup_timer_2(T2_DIV_BY_16, 255, 1);  //กำหนดการใช้งาน Timer2
    set_timer2(0);                                   //ตั้งค่า Timer2 เป็น 0
  
while(true){

   set_pwm1_duty(duty);                       //ตั้งค่า PWM ความถี่ 1.22kHz(รายละเอียดใน Timer2) duty cycle ประมาณ 50% (0 – 1023 or 0 – 100%)
  
}
}

Lab3: การใช้งาน Module Analog to Digital


#include<16F877A.h>
#device ADC=10           //ตั้งการใช้งาน module ADC 10 bits
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()
#use rs232(baud=9600,xmit= PIN_C6,rcv= PIN_C7 ) // ใช้งาน module RS232

void main(void){                      
int16 A;                                    //ประกาศตัวแปร A เป็น integer 16 bits
float Volts;                                //ประกาศตัวแปร Volts เป็น floating point number

SETUP_ADC(ADC_CLOCK_INTERNAL); //กำหนดสัญญาณนาฬิกาในการแปลงA/D
SETUP_ADC_PORTS(ALL_ANALOG);                   //กำหนด port การใช้งาน A/D

while(true){     

 set_adc_channel(1);                             //กำหนดช่องการแปลง A/D
 A = read_adc();                                  //เก็บค่าการแปลงไว้ตัวแปร A (0-1023)
 Volts = ((float)A * 5)/1023;                 //แปลงค่าจำนวนบิต เป็น โวลต์

printf("%lu  %.3f\r\n",A,Volts);  //แสดงค่าผ่าน RS232 (จำนวนบิต  โวลต์)

}
}

Lab2: ไฟวิ่ง


#include<16F877A.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()

void main(void){
while(true){
output_d(1);                  // output port D = 00000001
delay_ms(300);              // delay 300 ms.
output_d(2);                  // output port D = 00000010
delay_ms(300);
output_d(4);                  // output port D = 00000100
delay_ms(300);
output_d(8);                  // output port D = 00001000
delay_ms(300);
}
}

Lab1: การใช้งาน RS232 และชนิดของข้อมูล


#include<18F4431.h>
#define  CLOCK_SP    20000000 // ความเร็วสัญญาณนาฬิกา
#fuses HS                     //   โหมดการทำงานแบบ High Speed
#fuses NOLVP,NOWDT           // No Low Voltage Program, No Watchdog timer
#fuses NOPROTECT              // Code no protection
#use delay (clock=CLOCK_SP)   // ใช้งานฟังก์ชัน delay_ms() & delay_us()
#use rs232(baud=9600,xmit= PIN_C6,rcv= PIN_C7 ) // ใช้งาน module RS232

void main(){

int A = 100;                  //ประกาศตัวแปร A เป็น integer 8 bits
int16 B = 1000;            //ประกาศตัวแปร B เป็น integer 16 bits
char C = 'C';                //ประกาศตัวแปร C เป็น character
float D =0.514; //ประกาศตัวแปร D เป็น floating point number 32 bits

while(true){
printf("%u  %lu  %c  %.3f\r\n",A,B,C,D);          //แสดงค่าผ่าน RS232
}
}