|
|
View previous topic :: View next topic |
Author |
Message |
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
Shapr IR |
Posted: Tue Feb 19, 2013 9:54 am |
|
|
I have written a program that read analog value from a sharp IR. The program is supposed to read the value and print out the distance by using a specific equation.
Code: |
#include<18F2455.h>
#device adc = 10
#include<math.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock = 8000000)
#use rs232(baud = 9600 , xmit = PIN_C6, stream = com_lcd)
void main()
{
double value;
setup_adc_ports(AN0_TO_AN2);
setup_adc(ADC_CLOCK_INTERNAL);
lcd_init(true);
delay_ms(2000);
printf("HELLO WORLD");
delay_ms(2000);
lcd_clear();
printf("Min: %% Max: %%");
while(true)
{
set_adc_channel(0);
delay_ms(100);
value = (double)((double)(41.543 * pow((read_adc(ADC_START_AND_READ ) + 0.30221), -1.5281)));
lcd_cursor_move(2,1);
printf("%lf",value);
delay_ms(500);
}
} |
Indeed it gives me wrong values. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Feb 19, 2013 11:17 am |
|
|
are you using GP2Y0A21YK0F or other unit?
Code: |
#include<18F2455.h>
#device adc = 10
#include<math.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock = 8000000)
#use rs232(baud = 9600 , xmit = PIN_C6, stream = com_lcd)
void main()
{
double value;
setup_adc_ports(AN0_TO_AN2);
setup_adc(ADC_CLOCK_INTERNAL);
lcd_init(true);
delay_ms(2000);
printf("HELLO WORLD");
delay_ms(2000);
lcd_clear();
printf("Min: %% Max: %%");
while(true)
{
set_adc_channel(0);
delay_ms(100);
value = (double)((double)(41.543 * pow((read_adc(ADC_START_AND_READ ) + 0.30221), -1.5281)));
lcd_cursor_move(2,1);
printf("%lf",value);
delay_ms(500);
}
}
|
first comment - the float calcs are a mess - i won't begin to try to unravel that math - tho it seems excessive and not aligned to the CURVE of displacement voltage.
if you have RS-232 , try feeding the raw ADC counts out that way , when using a white paper target |
|
|
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
|
Posted: Tue Feb 19, 2013 11:27 am |
|
|
Yes , one of its kind.
Number is : GP2Y0A21YK |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Feb 19, 2013 11:44 am |
|
|
walk before you run
in setupadc be sure to add second arg of
|vss_vdd
if that is what you are doing
then try feeding the RAW ADC count to an output device you can read -
thats a good start
BTW is this a real circuit you built or is it proteus/ isis ?? |
|
|
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
|
Posted: Tue Feb 19, 2013 11:57 am |
|
|
It's already made.
Thank you , will try that |
|
|
moha
Joined: 07 Jun 2011 Posts: 2
|
|
Posted: Tue Feb 19, 2013 3:39 pm |
|
|
Code: |
set_adc_channel(0);
delay_ms(100);
value=read_adc();
distance=5220/(value -16.92); |
|
|
|
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
|
Posted: Tue Feb 19, 2013 4:03 pm |
|
|
Thank you , I am going to try it.
|
|
|
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
|
Posted: Thu Feb 21, 2013 4:19 pm |
|
|
This is the last Version of the program , but still not good output
Code: |
#include<18F2455.h>
#device PASS_STRINGS=IN_RAM
#device adc = 10
#include<math.h>
#include<string.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock = 8000000)
#use rs232(baud = 9600 , xmit = PIN_C6, stream = com_lcd,rcv=PIN_A0)
void main()
{
double value,distance;
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(AN0_TO_AN2|vss_vdd );
lcd_init(true);
delay_ms(2000);
printf("HELLO WORLD");
delay_ms(2000);
lcd_clear();
printf("Min: %% Max: %%");
while(true)
{
set_adc_channel(0);
delay_ms(100);
value=read_adc();
distance=5220/(value -16.92);
lcd_cursor_move(2,1);
printf("%lf",distance);
delay_ms(500);
}
}
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Feb 21, 2013 5:19 pm |
|
|
what do you get with the simple ADC count from 0-1023 in base 10 - if you send THAT to the LCD ??
no math no nothing but the read_adc value ??
make value an INT16 and format and show IT !!
you dont have to keep setting adc chan 0 - do it before the loop |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19494
|
|
Posted: Fri Feb 22, 2013 2:02 am |
|
|
Agreed. As written, the maths will give a number from -308.5, to 5.277. Not exactly a logical range....
Several other little comments:
The PIC18, does not _have_ a 'double' type. It'll accept it, but it is just a normal float. Only chips like the DSPIC's support double.
Then format the output. Otherwise you are going to get really screwy numbers, probably wrapping the LCD. Use something like %7.3f.
Again same comment, there is no %lf format on the PIC18. The compiler is meant to ignore it, but better to use the format the chip actually has.
Several of the older compiler versions give display problems if you use 'unspecified' %f formats. So it is safer to always use a specified field width.
Best Wishes |
|
|
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
|
Posted: Sun Feb 24, 2013 12:28 pm |
|
|
Well, I corrected my mistakes. I also found how to measure the distance. But,
NO GOOD results.
Code: |
while(true)
{
delay_ms(100);
value=read_adc();
distance=12343.85*pow(value,-1.15);
lcd_cursor_move(2,1);
printf("%Lu",distance);
delay_ms(500);
}
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Feb 24, 2013 12:39 pm |
|
|
I would give you more help if you tried it the way i asked.
Make 'value' an int16 and show it RAW.
Sending ADC out to a "double" is silly and not useful at all.
Have you READ what we have been telling you ??
I suggest you post some experimental data.
-----------------
Where column one is a set of DISTANCES of target to sensor
and column two is the RAW ADC converter count from 0-1023 base ten.
-------------------
As long as you persist in adding useless MATH, using bad var types, and complaining about the bad results you are causing yourself,
I have no interest in your problem.
You are your own worst enemy here.
You are still trying to run when you can't walk. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Feb 24, 2013 2:05 pm |
|
|
This smells like a duplicate of thread you've already got running.
Please clarify.
Mike |
|
|
amjad_alahdal
Joined: 19 Feb 2013 Posts: 50
|
|
Posted: Mon Feb 25, 2013 2:22 am |
|
|
Thank you all for your comments. The problem wasn't because of the type or math equation that I used. The problem was because of the connection. This morning I checked links of the sensor. I found out that the VCC and the GND wasn't connected well, I did connected them very good. I tried my program and then , it gave me the correct distance.
Thank you all for your comments. Sorry for bothering you, it was my mistake. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19494
|
|
Posted: Mon Feb 25, 2013 2:55 am |
|
|
I think the key problem is that your thinking is slightly askew.
First, the ADC does not read voltage. It reads an integer number, _which can potentially be converted to represent a voltage reading_.
Now the point is that your sensor, will return certain numbers for certain distances. Given a table of such readings, it is then possible to generate a line of best fit through these to give an equation to turn the numbers into distances. This can then be applied. Trying to do this any other way, just leads to maths errors, and 'thinking errors', in what the numbers mean.
I'd expect the actual formula needed to be something like:
Distance(cm)=13553*(reading^-1.1708)
This is a 'best guess' from the data sheet figures, and is fairly close to the formula you have used in your last attempt, but the curve is noticeably different from yours.
You need to start from some real measured data, rather than trying to guess.
Then using maths like this, is problematic on a small chip like the PIC. As already explained, it does not have a 'double' data type. The reason is there is just not space to do complicated arithmetic. The single line:
distance=12343.85*pow(value,-1.15);
probably uses perhaps 1/5th the chip's memory, and will take several mSec to execute. Given you are only ever talking integer numbers in a range from about 80 to 660 (the chip gives output voltages from about 0.4v to 3.2v), much quicker, simpler, and more accurate, to take the real ADC readings, and distances, feed them into a spreadsheet on the PC, generate a best fit curve with this, and have it generate a table of int16 distances in mm, for each ADC value, and then program this into the PIC as a lookup table. You'd then just have distances from 100 to 800, corresponding to the readings from the ADC.
Then smooth the ADC. Single readings are always quite noisy, and the sensor chip itself, also returns quite a lot of noise. Single readings will jump around. With the now much reduced arithmetic, take the time to do an Olympic average of perhaps 10 readings, and use this to give the 'distance'.
These chips are _not_ accurate devices. The readings will vary with the surface being used, and even dust in the air. They are good for giving an 'approximation' as something approaches, but are not a way of actually measuring 'distance'.
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
|