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 support@ccsinfo.com

accelerometer reading incorrectly by ADC

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
vinniewryan



Joined: 29 Jul 2009
Posts: 154
Location: at work

View user's profile Send private message MSN Messenger

accelerometer reading incorrectly by ADC
PostPosted: Sun Oct 25, 2009 11:42 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Oct 25, 2009 12:45 pm     Reply with quote

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

View user's profile Send private message MSN Messenger

PostPosted: Sun Oct 25, 2009 1:07 pm     Reply with quote

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







PostPosted: Sun Oct 25, 2009 3:43 pm     Reply with quote

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

View user's profile Send private message MSN Messenger

PostPosted: Mon Oct 26, 2009 9:35 am     Reply with quote

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

 
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