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

can i do this:

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







can i do this:
PostPosted: Tue Dec 22, 2009 1:58 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 22, 2009 2:57 am     Reply with quote

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







PostPosted: Tue Dec 22, 2009 3:37 am     Reply with quote

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







PostPosted: Tue Dec 22, 2009 4:17 am     Reply with quote

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:
Code:
value=read_adc();
Ttelmah
Guest







PostPosted: Tue Dec 22, 2009 4:22 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 22, 2009 6:19 am     Reply with quote

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







PostPosted: Tue Dec 22, 2009 6:28 am     Reply with 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...

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







PostPosted: Tue Dec 22, 2009 9:46 am     Reply with quote

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







PostPosted: Tue Dec 22, 2009 11:35 am     Reply with quote

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







PostPosted: Tue Dec 22, 2009 4:06 pm     Reply with quote

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







PostPosted: Tue Dec 22, 2009 7:34 pm     Reply with quote

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... Smile
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Wed Dec 23, 2009 9:50 pm     Reply with quote

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! Smile

Rohit
yoda2
Guest







PostPosted: Sun Jan 17, 2010 5:30 am     Reply with quote

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
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