|
|
View previous topic :: View next topic |
Author |
Message |
martines Guest
|
adc calculations |
Posted: Fri Jul 07, 2006 3:19 pm |
|
|
hi
i've got problem with converting adc value cause i'm not sure what kind of variable to use
here is my code
Code: |
#include <18F458>
//#define adc=10
#fuses HS, NOWDT, PUT ,nolvp
#use delay(clock=1000000)
#include <math>
#include <flex_lcd>
int16 result1;
int32 accx;
void main()
{
lcd_init();
lcd_init();
delay_ms(200);
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_DIV_64);
delay_ms(200);
while(true)
{
set_adc_channel(0);
delay_us(1000);
result1=0;
result1 = read_adc();
accx=0;
accx=((result1*15.68)-8035);
//calculation to transform the adc_number to acceleration
printf(lcd_putc , "\fAcc X: %06u", accx);
} |
the formula i want to use is ((adc-value*15.68)-8035)=accx
(i wanted to avoid the floating point but stil no luck
(which is acceleration going from -5000mg to +5000mg ; (the adxl320 sensor gives 0,94V(at -5G) to 4,06(at+5G acceleration)
so the question is where i am wrong- with the type of accx or the format( i tried with float but the numbers that came out had no sense) or smt else
10x in advance
Martin
Bulgaria |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Fri Jul 07, 2006 5:08 pm |
|
|
I would use
accx = ((read_adc() - midscale)*1568)/100;
where midscale is whatever the A/D reads for zero acceleration, probably something close to 2048 for a 12 bit A/D. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
Ttelmah Guest
|
|
Posted: Sat Jul 08, 2006 2:43 am |
|
|
I might modify this to cast the adc result to a signed int32 though. Otherwise the arithmetic is almost sure to wrap.
Best Wishes |
|
|
martines Guest
|
still problem |
Posted: Sat Jul 08, 2006 5:23 am |
|
|
ok
the formula i'm using is (((adc_num*1000)/64) - 8000)=result(in mG)
Code: |
int32 result1;
int32 result2;
int16 x;
int16 y;
float accx;
Float accy;
int8 i;
void main()
{
setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_low_volt_detect(FALSE);
setup_oscillator(False);
lcd_init();
lcd_init();
delay_ms(200);
while(true)
{
set_adc_channel(0);
delay_us(1000);
result1=0;
for(i=1;i<=8;i++)
result1+= read_adc();
result1/=8; /8samples of the adc and dev by8
result1=(result1*1000);
result1=(result1/64)
//works so far ,shows 00000-15000mG (but the zeroG should be around 2.5V so i need to subtract by smt around 7500
result1=(result1-8000);
accx=result1;
printf(lcd_putc ,"\fAcc.X: %03.0f", accx);
printf(lcd_putc,"mG");
delay_ms(100);
}
} |
the problem comes when i try to substract "result1" with a constant number
if i apply 5V on AN0 channel -shows 7000mG which is ok but if i grounded
shows -256 ?????? its obvious that the problem is with the negative numbers and i need help to solve it
10x
p.s the other probllem is that if i increase yhe delay time in the last code line to lets say 300ms and the PIC stops working |
|
|
Ttelmah Guest
|
|
Posted: Sat Jul 08, 2006 7:04 am |
|
|
Multiple things.
The result values, need to be _signed_ int32 values, if the result is ever going to go below zero.
Don't fiddle around converting to float. This implies the printf arithmetic, has to be done in floating point, and will be large/slow. Leave the value as an integer, and use %03ld, or if you want it to display in 'G' (rather than mG), use %04.3w, which will scale the output by 1000.
Also, as an aside, put the 'mG' into the same printf statement. Each seperate 'constant' string, incurs an overhead for it's header.
Best Wishes |
|
|
martines Guest
|
10x |
Posted: Sat Jul 08, 2006 10:22 am |
|
|
@Ttelmah
its workinggggggggg
10x a lot ,
and if its not rude another question : waht has to be done to slow down the refreshing rate of the lcd (lets say 3-4-5 times per second)
10x again |
|
|
Ttelmah Guest
|
|
Posted: Sat Jul 08, 2006 10:41 am |
|
|
I'd suggest putting a delay in the ADC reading loop. As it stands,you pause for 1mSec, then take eight ADC readings (only takes perhaps 0uSec each), then do the maths, output the data,and pause another 100mSec. Now you don't show the chip's clock rate, so the exact times can't be worked out, but obviously faster than you want. You can obviously increase the delay after the display to any vaue you want, but a slight delay between the ADC readings might also be worth considering.
As another comment, be aware, that ADC_CLOCK_INTERNAL, is _not_ recommended on many chips running at faster clock rates. You may want to use another source, depending on your master clock.
Best Wishes |
|
|
|
|
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
|