Go Down

Topic: [edit] analogRead/analogWrite Sampling Rates (Read 4095 times) previous topic - next topic

retroteck

Jul 21, 2012, 03:32 pm Last Edit: Jul 22, 2012, 06:09 am by CrossRoads Reason: 1
Hi There

I am a newbie to Arduino and would like to know how to alter the default sampling rate
on the analogue in ports from 10 bits to 8 bits on the UNO board.

Thanks

Rod


Magician

The question isn't correct. Subject line says analogWrite, which is related to digital PWM output. Message says analog input, which is using analogRead. Sampling rate defines how quickly you need to  read or sample an analog signal presented at the input, and expressed in Hertz.
Number of bits is different species, why do you think you need only 8 of them? 

retroteck

Hi Magician
Sorry i should have headed this topic analogRead.
I want to convert some low bandwith audio up to about 8kHz or so to PCM.
Sampling resolution is not too important for my purpose but sampling rate is.
I was thinking that if i could reduce the analogRead resolution to 8 bits 256 levels
to match the analogWrite PWM resolution of 256 levels, this would allow a higher
analogRead sampling rate allowing a higher modulation bandwith.
For testing i am using a software analogue sweep generator sweeping between 300Hz
and 15kHz.
I have set the PWM output frequency on pin 11 to 62.5kHz to make output filtering easier
and am writing to the PWM output the contents of a variable set to hold the input samples
from analogRead but doing this at a quater rate as to make the read samples at 1024 match the native PWM output rate of 256.
This is working after a fashion but is giving some strange results:

At the start of the input sweep from the generator at 300Hz everything is fine but after about
1kHz there is a rapid roll off and at 2.5kHz there is zero output.
Continuing the generator sweep, at about 5kHz the output starts to rise again but the audio out starts at 2.5kHz and sweeps down to 300Hz and then increases to 2.5kHz again before the output once again falls to zero. By this time the sweep gen has reached about 10kHz.
Continuing the generator sweep, at about 12.5kHz this process starts to repeat once again,
finishing with output at zero again when the sweep gen reaches 17.5kHz.

The whole process seems similar to having two double sideband radio transmissions within the audio spectrum and am wondering if there are issues with timers counting up and down.
As i said in my first post i am a newbie to Arduino and i probably need info on how the timers work as well as how to set analogRead to 8 bit sampling.

Thanks

Rod

Magician

Quote
I was thinking that if i could reduce the analogRead resolution to 8 bits 256 levels to match the analogWrite PWM resolution of 256 levels, this would allow a higher analogRead sampling rate allowing a higher modulation bandwith.
No, false assumption. One conversion is always outputs 10 bits value, doesn't matter if you want only 8 bits. It's how ADC wired inside. But you could alter speed of conversion, setting dirrerent prescaler bits. http://coolarduino.wordpress.com/2011/03/14/quasi-real-time-oscilloscope/
You could also generate PWM output with more than 256 steps, setting 2 PWM pins, and sum up via resistors  it's possible to get up to 16-bit.
There is other my project, where 10 bit value created summing up 32R - R.
http://coolarduino.wordpress.com/2012/04/09/voice-pitch-shifting-scrambler/
Quote
from analogRead but doing this at a quater rate as to make the read samples at 1024 match the native PWM output rate of 256.

I'm not following this.
Quote
At the start of the input sweep from the generator at 300Hz everything is fine but after about
1kHz there is a rapid roll off and at 2.5kHz there is zero output.
What you observed, is most likely alliasing. Looks like your sampling rate 2.5 kHz or multiple of that. How do you define rate? Could you post your code?

retroteck

Thanks for the info. I didnt realise that analogRead always read 10 bit samples.
I was skipping 3 of every 4 analogRead samples so there would be 256 input samples to pass to the analogWrite function for the PWM output on pin 11 which appears to only support 256 sampling levels. Here is the code i am using.

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const int PWM =11; //pin for the PWM output
int val=0;              //variable used to store the
                           //audio samples in analogRead
               
                 
void setup()
{
cli(); //disable interrupts while registers are configured

bitSet(TCCR2A, WGM20);
bitSet(TCCR2A, WGM21); //set Timer2 to fast PWM mode

bitSet(TCCR2B, CS20);
bitClear(TCCR2B, CS21);
bitClear(TCCR2B, CS22);


//set prescaler to /1 (no prescaling).  The timer will overflow every
//62.5nS * 256ticks = 16uS, giving a frequency of 62,500Hz, I think.   */

sei(); //enable interrupts now that registers have been set

  pinMode (PWM,OUTPUT); 
}



void loop()
{
  val=analogRead(0);             //read value of audio in at analogRead on pin 0
  analogWrite(PWM,val/4);    //output value to PCM on pin 11 skipping three out
                                            //of four samples of analogRead to give PWM outut
                                           //analogWrite 256 sample levels
}

Magician

Plz, select your code and hit a # button in the tool bar above.
Quote
skipping 3 of every 4 analogRead samples so there would be 256 input samples
I see what you mean, just you are skipping not samples, rather steps or levels on magnitude scale.
Code: [Select]
void loop()
{
  val=analogRead(0);             //read value of audio in at analogRead on pin 0
  analogWrite(PWM,val/4);    //output value to PCM on pin 11 skipping three out
                                            //of four samples of analogRead to give PWM outut
                                           //analogWrite 256 sample levels
}

There are two problems with such sampling, first, it keeps uCPU 100% busy, and second, sampling rate is unpredictable, as it would depends on code in main loop. Plus there would be always a jitter, due interruption services executed in background, like Timer2 overflow, serial,  etc.
Look in the code from link I posted earlier, I used TIMER2 to take samples at 8 kHz sharp. In latest projects, I'm using TimerOne library, to sample at 10 and 15.6 kHz. http://coolarduino.wordpress.com/2012/06/28/stereo-audio-vu-meter-on-arduino/

Are you gonna to "tweak" samples in some DSP-way?

retroteck

Thanks
Will try ypour excellent suggestions.

Rod

Go Up