|
|
View previous topic :: View next topic |
Author |
Message |
Adil
Joined: 11 Jul 2013 Posts: 2
|
Problem with Analog Reading 16f877a |
Posted: Thu Jul 11, 2013 12:56 am |
|
|
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
|
|
Posted: Thu Jul 11, 2013 3:46 am |
|
|
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: 9226 Location: Greensville,Ontario
|
|
Posted: Thu Jul 11, 2013 1:12 pm |
|
|
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: 19510
|
|
Posted: Fri Jul 12, 2013 7:34 am |
|
|
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 |
|
|
|
|
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
|