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

Shapr IR
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
amjad_alahdal



Joined: 19 Feb 2013
Posts: 50

View user's profile Send private message Yahoo Messenger MSN Messenger

Shapr IR
PostPosted: Tue Feb 19, 2013 9:54 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Tue Feb 19, 2013 11:17 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger MSN Messenger

PostPosted: Tue Feb 19, 2013 11:27 am     Reply with quote

Yes , one of its kind.
Number is : GP2Y0A21YK
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Feb 19, 2013 11:44 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger MSN Messenger

PostPosted: Tue Feb 19, 2013 11:57 am     Reply with quote

It's already made.
Thank you , will try that
moha



Joined: 07 Jun 2011
Posts: 2

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 3:39 pm     Reply with quote

Code:

set_adc_channel(0);
delay_ms(100);
value=read_adc();
distance=5220/(value -16.92);
amjad_alahdal



Joined: 19 Feb 2013
Posts: 50

View user's profile Send private message Yahoo Messenger MSN Messenger

PostPosted: Tue Feb 19, 2013 4:03 pm     Reply with quote

Thank you , I am going to try it.
Very Happy
amjad_alahdal



Joined: 19 Feb 2013
Posts: 50

View user's profile Send private message Yahoo Messenger MSN Messenger

PostPosted: Thu Feb 21, 2013 4:19 pm     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Thu Feb 21, 2013 5:19 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Feb 22, 2013 2:02 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger MSN Messenger

PostPosted: Sun Feb 24, 2013 12:28 pm     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Sun Feb 24, 2013 12:39 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Feb 24, 2013 2:05 pm     Reply with quote

This smells like a duplicate of thread you've already got running.

Please clarify.

Mike
amjad_alahdal



Joined: 19 Feb 2013
Posts: 50

View user's profile Send private message Yahoo Messenger MSN Messenger

PostPosted: Mon Feb 25, 2013 2:22 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 2:55 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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