Go Down

Topic: Specific arduino uno dac to 8ohm speaker question (Read 939 times) previous topic - next topic


Sep 04, 2016, 01:06 am Last Edit: Sep 04, 2016, 03:26 pm by developerjordy
For a school project I made a circuit that amplifies a microphone input and sends it to the arduino analog input, there it samples it at approximately 16kHz. I did this like this:

Code: [Select]

#define FASTADC 1
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
void setup(){                                  // set prescale to 64
   sbi(ADCSRA,ADPS2) ;
   sbi(ADCSRA,ADPS1) ;
   cbi(ADCSRA,ADPS0) ;

Next I just analogread on the input and save this as 8bit data on a 23LC1024 (1Mbit SRAM) chip. But now I need to send this sampled values trough an 8ohm speaker so I can hear what I recorded and saved.

I have read a lot about pwm and I think this is the way to go for this project, however I know little about setting register bits, and I already have set my prescaler to 64 for the analogread so I dont know how this effects all the pwm tutorials I find online.

I use this time test in the setup:

Code: [Select]

start = millis() ;
  for (i = 0 ; i < 1000 ; i++)
     analogWrite(speaker, i);delay(44);

  timeTest = (millis() - start);
  Serial.print(timeTest) ;
  Serial.print("msec / 1000 calls ->  ");
  Serial.println("Hz writing output") ;

My time test results in "+-18000Hz sampling output" so I thought I could just connect my speaker in series with 250ohm resistor to a pwm pin and write the data that comes from the SPI to the digital pwm pin with analogWrite(speakerPin, value) directly but this results in only a sinus-like beep.
I already looked at the resulting waveform of the recorded samples and the sampling part is ok, with a mean value of 125 and the signal always staying between 0-255.
All help is welcome since I am stuck here for over three days, thanks in advance !


I'm not familiar with those ADC functions and I'm not completely following your code...

PWM is not analog and the default PWM rate is about 500Hz.   That means you'll hear the ~500Hz clock and you can't reproduce high-audio frequencies.  

There is an audio library called TMRpcm.  I've never used it, but I think it's supposed to work at a higher frequency and give a better approximation of analog.

You also need to re-calculate your playback clock because your 44mS delay is 22.7Hz.   And, I'm not sure why you're only playing 1000 samples, which is 1/16th of a second at 16kHz.  And I'm not sure why you'd want to record at 16kHz and play back at 18kHz.

I hope your'e not forgetting that the ADC is 10-bits.    You need to divide by 4 before storing the data as 8-bits.   If you simply ignore the two most significant bits you'll get garbage.

...Here's how I'd approach this project -

1. Generate some sine waves with an algorithm and write-out the audio (or make a sine table/array in the Arduino's internal RAM and loop it).  

You may find that the TMRpcm library works, or you may find that you need to add a DAC, but there's no point in proceeding if you can "make sound" at different frequencies.

2. Use an algorithm to write "waves" into your SRAM chip, and then play those sounds.

3. After you can play sounds from the SRAM, work on "capturing" audio data and writing to the SRAM.


Sep 06, 2016, 06:49 pm Last Edit: Sep 06, 2016, 06:52 pm by el_supremo
Code: [Select]
  for (i = 0 ; i < 1000 ; i++)
     analogWrite(speaker, i);delay(44);

This does not do what you are probably expecting.

The structure of a for loop is either:
Code: [Select]
for( ... ) ONE_STATEMENT;
Code: [Select]
for ( ... ) {

Your code does one thousand analog writes as fast as it can and THEN waits for 44 milliseconds.
It doesn't matter that you wrote the analogWrite and delay on the same line. Without the braces, only the analogWrite is in the for loop.

Don't send me technical questions via Private Message.

Go Up