|
|
View previous topic :: View next topic |
Author |
Message |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
accelerometer reading incorrectly by ADC |
Posted: Sun Oct 25, 2009 11:42 am |
|
|
Hey all, I have an ADXL335 accelerometer which is being driven by an OP amp, and the output of the amp is going into the ADC of a PIC16F684. After the OP amp, my output voltages are reading 2.13 when level, 2.53 when tilted +90 degrees, and 1.73 when tilted -90 degrees. This is all perfect, and the voltages increment very smoothly.
The problem lies in the PIC. When I use the adc to convert these voltages into digital values, I only get a fraction of the resolution I should be getting. Basically I have a servo connected to the PIC which changes rotation based on the accelerometers reading. when the accelerometer is +90 degrees, the servo is +90 degrees, and same for -90 degrees respectively. For some reason though, the servo only moves to about 6 different incremental positions between +90D and -90D, where it should be moving very precisely in closer to 100 different incremental positions between -90 and +90. In simpler terms, where my resolution should be 255, I'm only getting a resolution of about 6.
I'm wondering if the ADC in my PIC is set up correctly. I'm using the command "ADC=10" which I believe to be correct. If this is hard to understand, I can post a video of what it's doing exactly. Here is my code:
Code: |
#include "16f684.h"
#device adc=10
#use delay(clock=4000000)
#Fuses FCMEN,PROTECT,MCLR,BROWNOUT,CPD,NOPUT,IESO,NOPROTECT
int16 LSERVO;
void servo()
{
output_high(PIN_C3);
delay_us(LSERVO);
output_low(PIN_C3);
delay_ms(15);
}
void main(float32 adc)
{
while(1)
{
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(sAN6 | VSS_VREF);
set_adc_channel(6); //X
delay_ms(20);
adc=read_adc();
if(adc>11.0)
{
adc=(adc-11.0)*300;
LSERVO=1500+adc;
}
else if(adc<11.0)
{
adc=(11.0-adc)*300;
LSERVO=1500-adc;
}
else
{
LSERVO=1500;
}
servo();
}
}
|
PS, when the accelerometer is level, and outputting 2.13 volts, my adc reads it as the number 11.0, and 1500us is center position for the servo.
Thanks in advance! I'm sure it's something simple that my inexperience is overseeing. _________________ Vinnie Ryan |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Oct 25, 2009 12:45 pm |
|
|
Quote: | The problem lies in the PIC | Actually, it lies in your code. Your ADC calculations look curious. read_adc() gives a value between 0 and 1023,
for your analog range, it can be expected between 350 and 520.
As a result LSERVO=1500+adc will always overflow. Don't understand what you try to achieve here. |
|
|
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Sun Oct 25, 2009 1:07 pm |
|
|
But you see, read_adc() is returning values of between 8.0 and 13.0, where 11.0 is my result when the accelerometer is level. Perhaps I should declare ADC as something other than float32? This is why my math is:
Code: | [if adc>11.0] LSERVO = 1500 + (read_adc - 11.0) * 300
[if adc<11.0] LSERVO = 1500 - (11.0 - read_adc) * 300 |
so if the accelerometer was level, and my adc read was 11.0, the result would be LSERVO = 1500, or center. If the accelerometer was tilted + 90 degrees, the adc would read 13.0 and the result would be LSERVO = 2100 or LSERVO = 1500 + ((adc-11)*300), which equals 2100. And the same, respectively, for a -90 degree tilt, which the adc would read 8.0. _________________ Vinnie Ryan |
|
|
Ttelmah Guest
|
|
Posted: Sun Oct 25, 2009 3:43 pm |
|
|
The ADC, returns an _integer_ nothing else.
The PIC itself, only 'knows' about integers. Float arithmetic and values, are added libraries from the compiler. Hardware components inside the chip itself only ever return integers.
Using a float, won't 'matter' (the compiler will silently convert the integer to a float), _but_ will cost time.
Your are running the ADC using the external Vref connection. What is connected to pin 12 of your PIC? The value returned by the ADC, will depend on this.
You also don't have an oscillator fuse selected. The default appears to be working for you, but it should always be set.
Lastly read the data sheet on the ADC 'clock' settings. Table 9.1 note 4.
Best Wishes |
|
|
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Mon Oct 26, 2009 9:35 am |
|
|
The Vref pin is connected to 3V+. I think it should be correct, someone on here suggested it. I'll check that table today on the adc clock. _________________ Vinnie Ryan |
|
|
|
|
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
|