|
|
View previous topic :: View next topic |
Author |
Message |
yoda Guest
|
can i do this: |
Posted: Tue Dec 22, 2009 1:58 am |
|
|
hye can i do this:
Code: |
#include <16f877a.h>
#device adc=10
#include <STDLIB.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
void main ()
{
int value,pass_value1,pass_value2;
setup_adc_ports( ANALOG_RA3_RA2_REF ); //ch.2&3 vref
setup_adc( ADC_CLOCK_INTERNAL ); //or should i use 32 instead???
while (1)
{
set_ADC_channel(0);
read_adc();
value=read_adc();
delay_us(20);
pass_value1=............;
delay_us(5);
set_ADC_channel(1);
read_adc();
value=read_adc();
delay_us(20);
pass_value2=.............;
delay_us(5);
}//while
}//main
|
what i'm going to do is to read 2 adc channel 0&1 from accelerometer and gyro... is that code sufficient?
also, anyone who experience using both sensor can help me to calculate pass_value1 & 2 which will give value of both tilt reading? because the value from read_adc() is raw value right? how to convert them to something useful like tilt |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Dec 22, 2009 2:57 am |
|
|
I wonder, what you are doing with your delays? There's exactly one meaningful place for a delay in
your code, it's between set_adc_channel() and read_adc(), but there you don't have it... |
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 22, 2009 3:37 am |
|
|
A number of comments:
Layout should be:
First the processor include.
Then it's defines
Then fuses
Then clock
RS232 setup if being used.
Only now, other includes.
Though probably not a problem with stdlib, in general, you should put includes _after_ the fuses, clock rate settings, and RS232 setup. There will be problems with libraries that use delays, or stdio, ithey are put first.
Then there is no point in reading the adc an extra time before you want the value. This actually makes the delay problem mentioned by FvM _worse_, since the internal ADC is disconnected from the external voltage source during a cnversion...
So, select the channel, pause for the capacitor to charge (20uSec on your chip), then take the reading.
Yes, you do want to use /32, rather than internal for the ADC clock. The data sheet tells you this.
Then, you want 'HS' for the clock fuse, rather than 'XT', if you are running at 20MHz.
Best Wishes |
|
|
yoda Guest
|
|
Posted: Tue Dec 22, 2009 4:17 am |
|
|
thanks guys...
thats new to me..
here the correct 1 right...
Code: |
#include <16f877a.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#include <STDLIB.H>
void main ()
{
int value,pass_value1,pass_value2;
setup_adc_ports( ANALOG_RA3_RA2_REF ); //ch.2&3 vref
setup_adc( ADC_CLOCK_INTERNAL ); //or should i use 32 instead???
while (1)
{
set_ADC_channel(0);
delay_us(20);
read_adc();
value=read_adc();
pass_value1=............;
delay_us(5);
set_ADC_channel(1);
delay_us(20);
read_adc();
value=read_adc();
pass_value2=.............;
delay_us(5);
}//while
}//main |
anyone can help me in this?
Quote: |
what i'm going to do is to read 2 adc channel 0&1 from accelerometer and gyro... is that code sufficient?
also, anyone who experience using both sensor can help me to calculate pass_value1 & 2 which will give value of both tilt reading? because the value from read_adc() is raw value right? how to convert them to something useful like tilt |
i mean how is this raw value were present after conversion & to change it please
this value:
|
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 22, 2009 4:22 am |
|
|
You are still reading the ADC twice. Don't.
Code: |
set_ADC_channel(0);
delay_us(20);
// read_adc(); get rid of this
value=read_adc();
|
Best Wishes |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Tue Dec 22, 2009 6:19 am |
|
|
yoda wrote: | what i'm going to do is to read 2 adc channel 0&1 from accelerometer and gyro... is that code sufficient?
also, anyone who experience using both sensor can help me to calculate pass_value1 & 2 which will give value of both tilt reading? because the value from read_adc() is raw value right? how to convert them to something useful like tilt | The reason why accelerometers are used in conjunction with gyros is because gyros suffer from drift, ie, the gyro reading varies with time. The accelo reading is used from time to time to correct this drift. If you just want to find out short term tilt, you only need to read the gyro.
Converting the analog reading from your gyro/accelo into meaningful values is upto you. Read the datasheets for both. Find out the sensitivity of the devices. In all probability all you will need to do is multiply the raw reading with some factor to get the angle of tilt in degrees or radians. Without knowing what devices you're working with it is impossible to help you further.
This approach is very simple. Also note that most gyros are 'rate' gyros, which means that you get the rate of change of angle with time. To get the _actual_ angle you would need to integrate. A lot of people use Kalman filters to 'fuse' readings from accelos and gyros into meaningful data. Do a forum search to find more info.
Rohit |
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 22, 2009 6:28 am |
|
|
On your value. The number returned from the ADC, is just a number. Not 'presented' in any way. One problem, is that it has 10 significant bits, and you are putting the values into variables that only hold 8...
It is entirely up to you, what you do with the returned number. You show a routine being called 'pass_valuex', but no details of this, so we can't really comment. However the data sheet will tell you what voltage the chip returns for 0g, and how many volts/g it generates from this. You show your ADC being setup to use an external reference, so can then calculate what number you should get for '0', and how many counts/g you should see.
Best Wishes |
|
|
yoda Guest
|
|
Posted: Tue Dec 22, 2009 9:46 am |
|
|
Quote: |
On your value. The number returned from the ADC, is just a number.
Not 'presented' in any way. One problem, is that it has 10 significant bits,
and you are putting the values into variables that only hold 8...
|
How do I correct this... is it like this:
use Code: | int ((long) value,pass_value1,pass_value2); |
I read the datasheet and figured that I should:
1st. Get voltage level from adc.
2nd. Then using the voltage level calculate the value of (g).
Is this right?
But, how do I do no. 1---> calculate voltage lvl |
|
|
yoda Guest
|
|
Posted: Tue Dec 22, 2009 11:35 am |
|
|
update of my code;
Code: |
#include <16f877a.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#include <STDLIB.H>
void main ()
{
int value,pass_value1,pass_value2;
setup_adc_ports( ANALOG_RA3_RA2_REF ); //ch.2&3 vref
setup_adc( ADC_CLOCK_32 );
while (1)
{
set_ADC_channel(0);
delay_us(20);
value1=(((float)read_adc(ROLL_ADC) / 1023*3.3)-1.5)/0.002; //value for gyro meas
delay_us(5);
set_ADC_channel(1);
delay_us(20);
value2=...; // can figure yet
delay_us(5);
}//while
}//main |
|
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 22, 2009 4:06 pm |
|
|
First, simplify maths. If you want to divide by a constant value, then multiply by another, do this maths in advance. The compiler may optimise this sort of thing away, but otherwise every extra stage is wasted time.
Remember also multiplication is always faster than division.
Second, your variable needs to be able to hold what you end up with.
int, can only hold integers from 0 to 255.
int16 an hold integers from 0 to 65535.
float holds a floating point value (but at a cost in speed for _everything).
Unless you need the float value, for output presentation, work with the numbers you have, rather than changing the values to float. If you do need float, then remember that your variables need to hold these.
Then 'read_adc, does not take a value called 'ROLL_ADC'. The only parameters it accepts are control parameters to make it perform parts of the function (separating the start and read operations for example). This is simply 'wrong'.....
Currently, you have a value from 0 to 1023 from the ADC. Divided by 1023, times 3.3 = 0 to 3.3. Then subtracting 1.5, so you have -1.5 to + 1.8. Then dividing by 0.002, giving -750 to 900, whih you then put into a variable that can only hold 0 to 255.......
Your total output range, is 1650 counts, so the same conversion can be done with:
val=(read_adc()*1.6129)-750;
Remember that 'val' will need to be a variable that can store a value from -750 to 900.
As a final comment, for real accuracy, the /1023 value is wrong.
This is down to the 'nature' of the ADC in the PIC. For many ADC's the value would be 1023, but for the PIC ADC, the most accurate approximation, is given by:
(adc_val/1024.0)+0.49999
However this only makes a tiny difference....
Best Wishes |
|
|
yoda Guest
|
|
Posted: Tue Dec 22, 2009 7:34 pm |
|
|
Thank for your explanation. I will try to solve the math and come up with better one. Then I hope you will take a look at it... |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Wed Dec 23, 2009 9:50 pm |
|
|
Ttelmah wrote: | As a final comment, for real accuracy, the /1023 value is wrong.
This is down to the 'nature' of the ADC in the PIC. For many ADC's the value would be 1023, but for the PIC ADC, the most accurate approximation, is given by:
(adc_val/1024.0)+0.49999 | The '0.49999' appears due to the 0.5LSB accuracy, right? Is there someplace 'nice' I can read about this in detail? When to divide by 1023, when to divide by 1024, etc? Thanks!
Rohit |
|
|
yoda2 Guest
|
|
Posted: Sun Jan 17, 2010 5:30 am |
|
|
hye,, i do this to check for my gyro...
Code: | #include<16F877A.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#include <lcd flex driver.c> //pcm flexible lcd driver in ccs code library forum
float gyro_roll_rad();
void main ()
{
lcd_init();
setup_adc_ports( ANALOG_RA3_REF );
setup_adc( ADC_CLOCK_DIV_32 );
while (1)
{
printf(lcd_putc, "\f%3.2f", gyro_roll_rad());
delay_ms(200);
}
}
float gyro_roll_rad()
{
set_ADC_channel(1);
delay_us(20);
return ((read_adc()*1.6129)-750);
} |
but my lcd show no 'trusted' value..
the value can go down to -500/below to +899.. even when the gyro in flat surface in static condition..
i dont think the problem with my lcd because i already test using test program and its good |
|
|
|
|
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
|