CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem with Analog Reading 16f877a

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Adil



Joined: 11 Jul 2013
Posts: 2

View user's profile Send private message

Problem with Analog Reading 16f877a
PostPosted: Thu Jul 11, 2013 12:56 am     Reply with quote

I am writing code for a line follower. I have to read 7 analog values from different channels and make the robot act accordingly. I read different kinds of question on this forum and tutorials outside the forum and tried to apply the things I read there, however was not successful. Here is my code:
Code:

//all these # below set up the PIC
#include <16F877A.h>
#device adc=10
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS         //Highspeed Osc > 4mhz
#FUSES PUT        //Power Up Timer
#FUSES NOPROTECT  //Code not protected from reading
#FUSES NODEBUG    //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD      //No EE protection
#use delay(clock=20000000) //crystal oscillator at 20000000 hertz

void fwrd(int16,int16);
void left(int16,int16,int16);
void right(int16,int16,int16);

unsigned long threshold = /*0b0011101100;*/ 0b1011001100;
unsigned long a0,a1,a2,a3,a4,a5,a6,S_dec,S_dec_last;
unsigned short d0,d1,d2,d3,d4,d5,d6;
unsigned short big=40;
unsigned short middle=30;
unsigned short small=20;
unsigned short current_duty=59;
unsigned short current_duty1=41,gtime=80;


//main program starts here
void main() {
   setup_adc(ADC_CLOCK_DIV_32); //configure analog to digiral converter
   setup_adc_ports(ALL_ANALOG);   //set pins AN0-AN7 to analog

   while(true){     
      set_adc_channel(0);//set the pic to read from AN0
      delay_us(20);//delay 20 microseconds to allow PIC to switch to analog channel 0
      a0=read_adc(); //read input from pin AN0: 0<=photo<=255
     
      set_adc_channel(1);//set the pic to read from AN1
      delay_us(20);
      a1=read_adc();
     
      set_adc_channel(2);  //set the pic to read from AN2
      delay_us(20);
      a2 = read_adc();
      set_adc_channel(0);//set the pic to read from AN0
      delay_us(20);//delay 20 microseconds to allow PIC to switch to analog channel 0
      a0=read_adc(); //read input from pin AN0: 0<=photo<=255
     
      set_adc_channel(1);//set the pic to read from AN1
      delay_us(20);
      a1=read_adc();
     
      set_adc_channel(2);  //set the pic to read from AN2
      delay_us(20);
      a2 = read_adc();
     
      set_adc_channel(3);//set the pic to read from AN4
      delay_us(20);//delay 20 microseconds to allow PIC to switch to analog channel 4
      a3=read_adc();
     
      set_adc_channel(4);//set the pic to read from AN1
      delay_us(20);
      a4=read_adc();
     
      set_adc_channel(5);  //set the pic to read from AN5
      delay_us(20);
      a5 = read_adc();
     
      set_adc_channel(6);//set the pic to read from AN6
      delay_us(20);//delay 20 microseconds to allow PIC to switch to analog channel 4
      a6=read_adc();
     
     
if (a0<threshold)
d0=0;
else d0=1;


if (a1<threshold)
d1=0;
else d1=1;

if (a2<threshold)
d2=0 ;
else d2=1;

if (a3<threshold)
d3=0 ;
else d3=1;

if (a4<threshold)
d4=0 ;
else d4=1;

if (a5<threshold)
d5=0 ;
else d5=1;

if (a6<threshold)
d6=0 ;
else d6=1;

S_dec=d6*64+d5*32+d4*16+d3*8+d2*4+d1*2+d0;
if (S_dec!=0b0000000)
{S_dec_last=S_dec;
switch (S_dec)
       {
          case 0b1101000:
          case 0b1111000:
          case 0b1111100:
          case 0b1111110:
          case 0b1101100:
          case 0b1001100:
          case 0b1011000:
                left(4.4*gtime,current_duty1-big,current_duty+big);
          break;
       
          case 0b1000000:
          case 0b1100000:
          case 0b1110000:
                left(3.6*gtime,current_duty1-big,current_duty+big);
          break;
         
          case   0b0100000:
          case   0b0110000:
          case   0b0111000:
                 left(3*gtime,current_duty-big,current_duty+big);
          break;
         
          case   0b0010000:
          case   0b0011000:

                 left(1.2*gtime,current_duty-middle,current_duty+small);
          break;
         
          case   0b0001000:
          case   0b0011100:
                 fwrd(gtime,current_duty+middle);
          break;
         
          case   0b0001100:
          case   0b0000100:
                right(1.2*gtime,current_duty-middle,current_duty+small);
          break;
         
          case   0b0000110:
          case   0b0000010:
          case   0b0001110:
                 right(3*gtime,current_duty-middle,current_duty+big);
          break;
         
          case   0b0000111:
          case   0b0000011:
          case   0b0000001:
                 right(3.6*gtime,current_duty1-big,current_duty+big);
          break;
          case   0b0001011:
          case   0b0001111:
          case   0b0011111:
          case   0b0111111:
          case   0b0011011:
          case   0b0011001:
          case   0b0001101:
              right(4.4*gtime,current_duty1-big,current_duty+big);
          break;

         }

}   else
    S_dec=S_dec_last;
switch (S_dec)
       {
          case 0b1101000:
          case 0b1111000:
          case 0b1111100:
          case 0b1111110:
          case 0b1101100:
          case 0b1001100:
          case 0b1011000:
                left(4.4*gtime,current_duty1-big,current_duty+big);
          break;
       
          case 0b1000000:
          case 0b1100000:
          case 0b1110000:
                left(3.6*gtime,current_duty1-big,current_duty+big);
          break;
         
          case   0b0100000:
          case   0b0110000:
          case   0b0111000:
                 left(3*gtime,current_duty-big,current_duty+big);
          break;
         
          case   0b0010000:
          case   0b0011000:

                 left(1.2*gtime,current_duty-middle,current_duty+small);
          break;
         
          case   0b0001000:
          case   0b0011100:
                 fwrd(gtime,current_duty+middle);
          break;
         
          case   0b0001100:
          case   0b0000100:
                right(1.2*gtime,current_duty-middle,current_duty+small);
          break;
         
          case   0b0000110:
          case   0b0000010:
          case   0b0001110:
                 right(3*gtime,current_duty-middle,current_duty+big);
          break;
         
          case   0b0000111:
          case   0b0000011:
          case   0b0000001:
                 right(3.6*gtime,current_duty1-big,current_duty+big);
          break;
          case   0b0001011:
          case   0b0001111:
          case   0b0011111:
          case   0b0111111:
          case   0b0011011:
          case   0b0011001:
          case   0b0001101:
              right(4.4*gtime,current_duty1-big,current_duty+big);
          break;

         }
   
   }
}

void fwrd(int16 time,int16 duty)
{
int8 i;
  for(i=0;i*25<time;i++)
  {
  output_high(PIN_B0);
  output_high(PIN_B1);
  delay_ms(duty/4);
  output_low(PIN_B0);
  output_low(PIN_B1);
  delay_ms((100-duty)/4);
  }
}

void  right(int16 time,int16 dutyr,int16 dutyl)
{
int8 i;
  for(i=0;i*25<time;i++)
  {
  output_high(PIN_B0);
  output_high(PIN_B1);
  delay_ms(dutyr/4);
  output_high(PIN_B0);
  output_low(PIN_B1);
  delay_ms((dutyl-dutyr)/4);
  output_low(PIN_B0);
  output_low(PIN_B1);
  delay_ms((100-dutyl)/4);
  }
}
void  left(int16 time,int16 dutyl,int16 dutyr)
{
int8 i;
  for(i=0;i*25<time;i++)
  {
  output_high(PIN_B0);
  output_high(PIN_B1);
  delay_ms(dutyl/4);
  output_low(PIN_B0);
  output_high(PIN_B1);
  delay_ms((dutyr-dutyl)/4);
  output_low(PIN_B0);
  output_low(PIN_B1);
  delay_ms((100-dutyr)/4);
  }
}

I would be very grateful if you could be of help.
oxo



Joined: 13 Nov 2012
Posts: 219
Location: France

View user's profile Send private message

PostPosted: Thu Jul 11, 2013 3:46 am     Reply with quote

Posting a wall of code with no information on what the problem is will not get you anywhere.

What exactly does not work?
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jul 11, 2013 1:12 pm     Reply with quote

Huge problem is in using binary for your threshold and comparisons.
Sorry but understand hex or integers a LOT easier.
Using binary is very hard on the brain to comprehend what you're trying to do.
A 'line follower' robot would..
read the sensors
evaluate the readings
take appropriate action.

So first, are the reading stable? Seems you're using analog sensors, so you'll need some kind of 'filtering' to get stable data to the ADC.I'd start with using the ADC in 8 bit mode,as 10bit could be too 'sensitive'.

It looks like you've got 7 sensors arranged in a 'linear' fashion to decide how far you're away from the line, where 1,2,3 are left of the line,4 is dead center, and 5,6,7 are right of the line. Is this correct?

Sensors? Are they matched? Depending on the photoransistors, they will output different voltages.Perhaps build a test jig to get 7 'matched' units.
You might need to adjust the 'threshold' for each sensor unless you have 7 matched units.

hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Fri Jul 12, 2013 7:34 am     Reply with quote

As comments, there are several ways to simplify what you are trying to do.
First, it appears you are trying to build a bit pattern, from incoming adc readings. So you set a number of flags, then multiply these by binary multipliers to make the byte to test. Why not build the byte as you go?.
Code:

     int8 bit_number;
     for (bit_number=0;bit_number<7;bit_number++)
         set_adc_channel(bit_number);//set the pic to read from channel
         delay_us(20);//delay 20 microseconds to allow
         //internal capacitor to charge to selected input
         if (read_adc()<threshold)   //read input from pin ANx
            bit_clear(S_Dec,bit_number);
         else
            bit_set(S_Dec,bit_number);
      }

This replaces all the code you currently have to read the inputs and build S_dec,

Then all the code to decide 'what to do', is identical, just with the change between using S_dec, and S_dec_last. Make it into a routine, and call it with the corresponding value.

Now, S_Dec, can have 128 possible values, but your switch only tests 32 of them What is meant to happen in the other 96 conditions?.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group