I need to read a signal from ADC at ~1200 samples/sec and another signal at ~400, at same time. To get this sampling frequency, I set the prescalar ro 16.
But when I test the output, the signals are distorted. As read in other posts, since there is only one converter for all pins, it needs some time to read next value. I am getting this even when I read same pin twice and discard the first one.
Could anyone tell me how to solve this problem, to get accurate high speed reading with multiple channels. I don't want to use external ADC.
To get this sampling frequency, I set the prescalar ro 16.
Why the default values will be ale to read plenty fast enough.
I need to read a signal from ADC at ~1200 samples/sec and another signal at ~400, at same time.
You can't read two signals at the same time, you can't even read two signals at different sample rates at the same time.
But when I test the output, the signals are distorted.
I find that odd how are you testing them? What is the impedance of the signals you are feeding into the A/D?
As read in other posts, since there is only one converter for all pins, it needs some time to read next value.
There is sufficient time to read in successive serial signals without adding extra time.
I am getting this even when I read same pin twice and discard the first one.
You only need to do this when you have a high input impedance.
So basically you are doing something wrong but without more details it is imposable to say what it is.
Sorry, here is the details:
Why the default values will be ale to read plenty fast enough.
I need to read the ADC value and the send it to Wifly Shield through SpiUart.
You can't read two signals at the same time, you can't even read two signals at different sample rates at the same time.
Since input_1 has 3 times the sampling rate than input_2, I am reading pin1 4 times, then pin2 1 time in a loop.
I find that odd how are you testing them? What is the impedance of the signals you are feeding into the A/D?
I am giving signal from signal generator and checking on Processing. The outputs seem to be superposition of each others. Even if I give signal to only one pin, I can see same signal on both outputs.
Can you upload your code ?
Use the code tag (the '#' button above the smileys).
Do you use a normal Arduino, or is there something special with Aref or the reference voltage.
The code is like this:
#include "WiFly.h"
#define FASTADC 1
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
void setup()
{
#if FASTADC
// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;
#endif
Serial.begin(115200);
SpiSerial.begin(921600);
.....
......
}
void loop()
{
count = 0;
while(count <= 1000)
{
a = analogRead(0);
SpiSerial.write('a'); //Marker
SpiSerial.write(highByte(a));
SpiSerial.write(lowByte(a));
if (count%4 == 0)
{
b = analogRead(1);
SpiSerial.write('b'); //Marker
SpiSerial.write(highByte(b));
SpiSerial.write(lowByte(b));
}
count++;
}
}
General guidance is to read an analog pin twice & ignore the first reading so the signal has time to settle internally:
while(count <= 1000)
{
a = analogRead(0);
a = analogRead(0);
SpiSerial.write('a'); //Marker
SpiSerial.write(highByte(a));
SpiSerial.write(lowByte(a));
if (count%4 == 0)
{
b = analogRead(1);
b = analogRead(1);
SpiSerial.write('b'); //Marker
SpiSerial.write(highByte(b));
SpiSerial.write(lowByte(b));
}
As you need a reading every 625uS (1/1600), I would also suggest using blink without delay style programming in void loop to comtrol the timing of when the samples occur.
I already tried reading twice and discarding first value method.
I need to read a signal from ADC at ~1200 samples/sec and another signal at ~400, at same time.
Why do you think you need to change a prescaler? Default settings is the LOWEST freq., 9.6 kHz or so, you can't make it 1.2 kHz.
The options: leave it as default, take two consequent readings (port 0, than port 1), so it will drops to 4.8 kHz/port, than take averaging 4 samples (moving average, not running) so bring it to 1.2 ksps. Other port has to be averaged on 12 samples.
Of course, you can just discard 3 and 11 samples, but averaging will increase noise immunity.
Also get rid of serial in the reading loop, better to take reading in the array, and output periodicaly, when samples array is full. Two prevent distortion, in real-time application, creating two array ping-pong configuration is common technics.
Other alternative is using TIMER library, and set a desired sampling frequency 2.4 ksps, read intermittent 0 &1 ports.
In one of my latest project, I read two channels (stereo) in this way, using TimerOne library.
http://coolarduino.wordpress.com/2012/06/28/stereo-audio-vu-meter-on-arduino/
And basic: http://coolarduino.wordpress.com/2012/06/22/audio-input-to-arduino/
If your signal is weak, it takes time to build back up between reads. I saw that plugging a red led between ground and A0 and then reading A0 in a loop that only updated to serial monitor on change. When I increased the reads per second, analog voltage fell.
Try changing to 600 and 200 reads and see if your data stabilizes.
Arduino has already macro's for the 'sbi' and 'cli'. Try it sometime.
This:
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
is the same this:
bitSet(ADCSRA,ADPS2);
bitClear(ADCSRA,ADPS1);
I am giving signal from signal generator
Most signal generators produce a signal + and - around ground. This will damage the arduino if you do not take measures to protect against the -ve voltage.
You should not be getting the results you are seeing therefore we need to drill down to see what you are doing wrong.
check my repo . I've worked a method that works like a charm.
Grumpy_Mike:
I am getting this even when I read same pin twice and discard the first one.
You only need to do this when you have a high input impedance.
Would "high input impedance" translate to "weak signal"?
Would "high input impedance" translate to "weak signal"?
It might but weak signal is not a very precise term it could mean many things.
Low current then?
The impedance problem is related to the situation where the current flowing into the ADC from the signal you are measuring, causes the signal voltage that you are trying to measure, to change. If your measurement process changes what you are trying to measure, then you won't get a very accurate measurement.
hareshmiriyala:
check my repo . I've worked a method that works like a charm.
That's just calling analogRead() for each input in turn, with delay() calls to loosely control the speed. Calling that a 'method' seems a bit of a stretch.