View previous topic :: View next topic |
Author |
Message |
fbasaris
Joined: 04 Mar 2011 Posts: 8
|
read 8 channel with 18f452 but time is too long... |
Posted: Fri Mar 04, 2011 5:12 pm |
|
|
Hi everyone,
I want to read 8 channel ADC with 18f452 (20 MHz). After that I want to use adc interrupt but this code takes long time. How can I reduce the reading time???
Code: |
void main()
{
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_DIV_32);
for(;;)
{
set_adc_channel(0);
delay_us(10);
data=read_adc();
voltage=0.0048828215*bilgi;
if(voltage>3)
aaaa=1;
else
aaaa=0;
set_adc_channel(1);
delay_us(10);
data=read_adc();
voltage=0.0048828215*bilgi;
if(voltage>3)
bbbb=1;
else
bbbb=0;
set_adc_channel(2);
delay_us(10);
data=read_adc();
voltage=0.0048828215*bilgi;
if(voltage>3)
cccc=1;
else
cccc=0;
set_adc_channel(3);
delay_us(10);
data=read_adc();
voltaj=0.0048828215*bilgi;
if(voltage>3)
dddd=1;
else
dddd=0;
set_adc_channel(4);
delay_us(10);
data=read_adc();
voltaj=0.0048828215*bilgi;
if(voltage>3)
eeee=1;
else
eeee=0;
set_adc_channel(5);
delay_us(10);
data=read_adc();
voltage=0.0048828215*bilgi;
if(voltage>3)
ffff=1;
else
ffff=0;
set_adc_channel(6);
delay_us(10);
data=read_adc();
voltage=0.0048828215*bilgi;
if(voltage>3)
gggg=1;
else
gggg=0;
set_adc_channel(7);
delay_us(10);
data=read_adc();
voltage=0.0048828215*bilgi;
if(voltage>3)
hhhh=1;
else
hhhh=0;
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Mar 04, 2011 5:20 pm |
|
|
It's not the reading time but the math, since you're using floating points!.
If you use integer math, it'll be a lot faster. |
|
|
fbasaris
Joined: 04 Mar 2011 Posts: 8
|
|
Posted: Fri Mar 04, 2011 5:25 pm |
|
|
yes you are right. my variables are like:
unsigned long int bilgi;
float voltaj;
Actually i dont need to know the channel's voltage value. i want to know what logical value they are.maybe ;
int data=input_d();
works.!!! |
|
|
fbasaris
Joined: 04 Mar 2011 Posts: 8
|
|
Posted: Fri Mar 04, 2011 5:33 pm |
|
|
and by the way on the top of codes i did not add any line like this.
#include <math.h>
is it problem to calculate float numbers??? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Mar 04, 2011 5:46 pm |
|
|
It is not a problem to use floating point numbers, just remember they take a LOT of time !
In your original code , you're reading the adc channel then seeing if it's over 3 volts.
A real FAST way to do that is to calculate on paper the ADC bits for 3 volts.
If using the ADC in 10 bit mode, with 5 vdc full scale it's
3/5*1024 = 614
2) save that number as a 'reference' value, must be long as it's > 256 bits
3) now simply read the adc channel and compare the reading to 'reference'.
if it's greater...do something ...else do nothing ..
This is probably the fastest way to do it,but you have to figure out the 'reference' value first.
If the adc as in 8 bit mode, it's be 3/5*256=153.
Obviously you can adjust the reference as required,or include several for different actions. |
|
|
fbasaris
Joined: 04 Mar 2011 Posts: 8
|
|
Posted: Fri Mar 04, 2011 6:33 pm |
|
|
Code: | //variables
long bilgi;
long referans=614;
.
.
.
for(;;)
{
set_adc_channel(0);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
sagsensor3=1;
else
sagsensor3=0;
}
|
is it true?
by the way thanks for replies temtronic |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Mar 05, 2011 9:35 am |
|
|
I'd like to ask what you think you are going to do with the 'adc interrupt'?....
The adc interrupt is one of the most misunderstood things. It signals just one thing. That an ADC conversion has _completed_. The conversion has to be started by something else. If by you, then trying to use the adc interrupt is pointless. It generally takes longer to get into the adc interrupt, and out again, than simply to wait for the conversion to have happened!.....
The only time using the adc interrupt is worthwhile, is if you have programmed the CCP module, to trigger an adc conversion at a specific interval. You can then interrupt when this conversion completes by using the adc interrupt, and just read the already converted result.
Best Wishes |
|
|
fbasaris
Joined: 04 Mar 2011 Posts: 8
|
|
Posted: Sat Mar 05, 2011 1:56 pm |
|
|
I did not use adc_interrupt before. This is the first time. I can use timer1 interrupt too.
But I did not know the adc conversion time. 10 ms or 100 ms or 500 ms!!!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Mar 05, 2011 4:12 pm |
|
|
The conversion time depends on the selected ADC clock. Generally 12 cycles of this. On older chips, minimum of 2uSec/cycle. On some latter chips, this drops to 11 cycles of the clock, and the clock rate can go up to 1uSec/cycle. Then on some of the really fast ones with 'high speed' ADC's, the total conversion time can get down to just a couple of uSec. So anything from 2uSec to perhaps 24uSec depending on the chip - read the data sheet. This gives the limits for clock rate on your chip, and how many cycles are needed.
Best Wishes |
|
|
fbasaris
Joined: 04 Mar 2011 Posts: 8
|
|
Posted: Sat Mar 05, 2011 4:33 pm |
|
|
Uc is 18f452 and osc. frequency is 20 Mhz. If I understand truly:
I can set my timer1 interrupt in 1 ms.
by the way I changed code like this. It is working well now .
Code: |
....
long bilgi;
long referans=614;
...
set_adc_channel(0);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d0);
else
output_low(pin_d0);
set_adc_channel(1);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d1);
else
output_low(pin_d1);
set_adc_channel(2);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d2);
else
output_low(pin_d2);
set_adc_channel(3);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d3);
else
output_low(pin_d3);
set_adc_channel(4);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d4);
else
output_low(pin_d4);
set_adc_channel(5);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d5);
else
output_low(pin_d5);
set_adc_channel(6);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d6);
else
output_low(pin_d6);
set_adc_channel(7);
delay_us(10);
bilgi=read_adc();
if(bilgi>referans)
output_high(pin_d7);
else
output_low(pin_d7); |
|
|
|
|