Go Down

Topic: [solved] Howto build a network sound recorder / osciloscope (Read 876 times) previous topic - next topic


Sep 06, 2011, 09:13 am Last Edit: Sep 06, 2011, 11:38 am by Emmeran Reason: 1
Hey guys,

I'm currently trying to write an audio recorder on the Arduino Ethernet, that streams data from it's A3 input to a network client.
So far I changed the prescaler of the ADC to get a higher sample rate (currently ~40kHz), also using interrupts for the ADC, to speed up the process.

It works pretty nicely together with a little program that I coded in Qt, to print out the results.

But unfortunately the interrupts from the ADC conflict with the Ethernet libs Server::write function, so that the Arduino crashes after sending the first packet of data (I'm buffering 1024 bytes before sending).

This code stopped it from crashing:
Code: [Select]

bufferPos = 0;
server.write(buffer, BUFFERSIZE);

But this causes my data to have little holes, which lead to a noise and distortion in the audible signal.

How can I speed up the write process? Shouldn't it simply be a simple buffer copy and send command? Why does it crash if I don't protect it from interrupts?



Why does it crash if I don't protect it from interrupts?

We'd need to see all of your code. Are you adding data to buffer while trying to write it out?
The art of getting good answers lies in asking good questions.


Ahh I managed by now, your tip with the buffer helped me realize that I should use two buffers at least.

Here's my code if anyone's interested. It basically can be used as a network osciloscope or to record audio over network. Sampling rate is ~ 53kHz with the applied settings.
Still a nonfinished code tho, so use at own risk.

Code: [Select]
#include <SPI.h>
#include <Ethernet.h>
#include <utility/w5100.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0, 177 };
byte gw[] = { 192,168,0, 1 };

#define DATA_BUFFER_SIZE 512
uint8_t buffer2[2][DATA_BUFFER_SIZE];
int bytes = 0;
int active = 0;

// Initialize the Ethernet server library
Server server(18844);

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

void addToBuffer(SOCKET s, volatile uint8_t * buf, uint16_t len)
  // copy data
  W5100.send_data_processing(s, (uint8_t *)buf, len);

void sendBuffer(SOCKET s)
  W5100.execCmdSn(s, Sock_SEND);

volatile bool needSend[2] = { false, false };
// ADC interrupt
  buffer2[active][bytes++] = ADCH;
  // buffer filled -> change buffer
  if (bytes == DATA_BUFFER_SIZE)
    bytes = 0;
    needSend[active] = true;
    active = active ? 0 : 1;

void setup()
  // start the Ethernet connection and the server: 
  Ethernet.begin(mac, ip, gw);

  // ADC setup (see atmega datasheet for reference)
  sbi(ADCSRA, ADEN);
  cbi(ADCSRA, ADSC);
  cbi(ADCSRA, ADIF);
  sbi(ADCSRA, ADIE);
  sbi(ADCSRA, ADPS2);
  cbi(ADCSRA, ADPS1);
  cbi(ADCSRA, ADPS0);
//  sbi(ADCSRB, ??);
  cbi(ADCSRB, ACME);
//  sbi(ADCSRB, ??);
//  sbi(ADCSRB, ??);
//  sbi(ADCSRB, ??);
  cbi(ADCSRB, ADTS2);
  cbi(ADCSRB, ADTS1);
  cbi(ADCSRB, ADTS0);
  cbi(ADMUX, REFS1);
  sbi(ADMUX, REFS0);
  sbi(ADMUX, ADLAR);
  //sbi(ADMUX, ??);
  cbi(ADMUX, MUX3);
  cbi(ADMUX, MUX2);
  sbi(ADMUX, MUX1);
  sbi(ADMUX, MUX0);
  // start measuring
  sbi(ADCSRA, ADSC);

int nonactive;
void loop()
  nonactive = active ? 0 : 1;
  if (needSend[nonactive])
    addToBuffer(0, buffer2[nonactive], DATA_BUFFER_SIZE);
    needSend[nonactive] = false;

Go Up