Led blink using ADC in Pic 16f887

Thread Starter

corefinder

Joined Oct 6, 2011
55
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
Rich (BB code):
# include<built_in.h>
void delay();
void ADC_Init();
void ADC_Get_Sample();
sbit led at PORTA.B1;
void main() {
int value;
TRISA=0x01;
ANSEL=0X01;
do
{
delay();
ADC_Init();
delay();
ADC_Get_Sample(1);
delay();
value= ADRESH*256+ADRESL;
if(value>3)
led=1;
else
led=0;
}
while(1);
}
void delay()
{
int i,j;
for(i=0;i<255;i++)
{
 for(j=0;j<255;j++);
 }
}
 

JohnInTX

Joined Jun 26, 2012
3,809
Rich (BB code):
value= ADRESH*256+ADRESL;
if(value>3)
 led=1; 
else
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.

Rich (BB code):
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:

donpetru

Joined Nov 14, 2008
185
I wrote the code below for Atmega 8. It can easily adapt to a PIC microcontroller using mikroC for PIC.
Rich (BB code):
/******* Atmega 8 software ****** F_CPU = 8MHz ******/

unsigned long adc; 
float VREF = 5.00;
float voltage_read;

void main() {
  DDC0_bit = 0;                    // Setup PORTC pin 0 as intput ADC

  DDB4_bit = 1;                    // Setup PORTB pin 4 as output for led blinking

  ADC_Init();                      // ADC init

  adc = 0;

  // Main loop
  do  {

       // Measures and calculates voltage channel ADC0
            adc = ADC_read(0); 
            voltage_read = adc * VREF / 1023; 

       // Test - if voltage read is greater 3 V then led bliking
            if (voltage_read > 3.00)
        {
                         do {
                             DDB4_bit = 0; 
                             Delay_ms(1000);
                             DDB4_bit = 1;
                             Delay_ms(1000);
                            
                             adc = ADC_read(0); 
                             voltage_read = adc * VREF / 1023;    
                         } while(voltage_read > 3.00);
        }
  
       } while(1);
}
 
Last edited:

RRITESH KAKKAR

Joined Jun 29, 2010
2,823
At the place of ADRESH use if else....

Rich (BB code):
#include <htc.h>
__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
#define _XTAL_FREQ 20000000


#define DAD PORTB


main(){
    TRISB=0X00;
TRISA = 0xff ;
ADCON1=0b00000000;
ADCON0=0b10000001;//000 = channel 0, (RA0/AN0)
    ADIF=0;
    ADIE=1;
    PEIE=1;
while(1){

    //GIE=1;
    
    __delay_us(10);
GO_DONE=1;
    __delay_us(10);

PORTB=ADRESH;
    }
}
 
Top