Led blink using ADC in Pic 16f887

Discussion in 'Embedded Systems and Microcontrollers' started by corefinder, Jun 26, 2013.

  1. corefinder

    Thread Starter Member

    Oct 6, 2011
    55
    0
    Hi, I have made a program in which I ma using inbuilt ADC module of Pic 16F887. It is a simple program in which AN0 of port a is selected as analog input. I gave a variable supply to analog pin and compared it with 3 volt. If the variable voltage is greater than 3 volt then led should blink..but it didn't. I compiled the program using MicroPro C and it did not give any error but led is not blinking. I wonder that my program has some error...and here I need your help to understand what is going wrong in program.

    Here is a program
    Code ( (Unknown Language)):
    1.  
    2. # include<built_in.h>
    3. void delay();
    4. void ADC_Init();
    5. void ADC_Get_Sample();
    6. sbit led at PORTA.B1;
    7. void main() {
    8. int value;
    9. TRISA=0x01;
    10. ANSEL=0X01;
    11. do
    12. {
    13. delay();
    14. ADC_Init();
    15. delay();
    16. ADC_Get_Sample(1);
    17. delay();
    18. value= ADRESH*256+ADRESL;
    19. if(value>3)
    20. led=1;
    21. else
    22. led=0;
    23. }
    24. while(1);
    25. }
    26. void delay()
    27. {
    28. int i,j;
    29. for(i=0;i<255;i++)
    30. {
    31.  for(j=0;j<255;j++);
    32.  }
    33. }
    34.  
     
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,023
    Code ( (Unknown Language)):
    1. value= ADRESH*256+ADRESL;
    2. if(value>3)
    3.  led=1;
    4. else
    5. led=0;
    The ADC does not return volts. It returns a count value that is proportional to (Vin / Vref) * the full range count.. For example if Vref = 5.0V and 3 volts is applied the count will be 3.0 / 5.0 = .6*the full range count.

    What the full range count is depends on the number of bits in the ADC, how its scaled AND how the result is justified in ADRESH/L. Your PIC has a 10 bit ADC so its raw count will be 0-1023. In the example the raw count is (3.0/5.0)*1024 = 614, not 3.

    Code ( (Unknown Language)):
    1. value= ADRESH*256+ADRESL;
    From the datasheet, note that the 10 bit result can be justified left or right in ADRESH/L. If right justified, the raw result is 0-1023. Left justifying shifts the result to the left 6 bits (which is the same as multiplying by 64) so the raw result is 0-65472, going up 64 for each raw ADC count. Your scaling arithmetic is therefore incorrect for a 10 bit value (its OK for a right justified 8 bit value).

    The value register must be an UNSIGNED int for left justified results (or any scaled value >32767).

    In any case, you'll have to know how the ADC is configured by ADC_Init() i.e. what Vref is, justification etc, to know what to do.

    Finally, your code will not blink the LED above a particular value, it will turn it ON when above and OFF when below.
     
    Last edited: Jun 26, 2013
  3. donpetru

    Active Member

    Nov 14, 2008
    186
    25
    I wrote the code below for Atmega 8. It can easily adapt to a PIC microcontroller using mikroC for PIC.
    Code ( (Unknown Language)):
    1. /******* Atmega 8 software ****** F_CPU = 8MHz ******/
    2.  
    3. unsigned long adc;
    4. float VREF = 5.00;
    5. float voltage_read;
    6.  
    7. void main() {
    8.   DDC0_bit = 0;                    // Setup PORTC pin 0 as intput ADC
    9.  
    10.   DDB4_bit = 1;                    // Setup PORTB pin 4 as output for led blinking
    11.  
    12.   ADC_Init();                      // ADC init
    13.  
    14.   adc = 0;
    15.  
    16.   // Main loop
    17.   do  {
    18.  
    19.        // Measures and calculates voltage channel ADC0
    20.             adc = ADC_read(0);
    21.             voltage_read = adc * VREF / 1023;
    22.  
    23.        // Test - if voltage read is greater 3 V then led bliking
    24.             if (voltage_read > 3.00)
    25.         {
    26.                          do {
    27.                              DDB4_bit = 0;
    28.                              Delay_ms(1000);
    29.                              DDB4_bit = 1;
    30.                              Delay_ms(1000);
    31.                            
    32.                              adc = ADC_read(0);
    33.                              voltage_read = adc * VREF / 1023;    
    34.                          } while(voltage_read > 3.00);
    35.         }
    36.  
    37.        } while(1);
    38. }
     
    Last edited: Jul 1, 2013
    absf likes this.
  4. RRITESH KAKKAR

    Senior Member

    Jun 29, 2010
    2,831
    89
    At the place of ADRESH use if else....

    Code ( (Unknown Language)):
    1.  
    2. #include <htc.h>
    3. __CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
    4. #define _XTAL_FREQ 20000000
    5.  
    6.  
    7. #define DAD PORTB
    8.  
    9.  
    10. main(){
    11.     TRISB=0X00;
    12. TRISA = 0xff ;
    13. ADCON1=0b00000000;
    14. ADCON0=0b10000001;//000 = channel 0, (RA0/AN0)
    15.     ADIF=0;
    16.     ADIE=1;
    17.     PEIE=1;
    18. while(1){
    19.  
    20.     //GIE=1;
    21.    
    22.     __delay_us(10);
    23. GO_DONE=1;
    24.     __delay_us(10);
    25.  
    26. PORTB=ADRESH;
    27.     }
    28. }
     
Loading...