Go Down

Topic: [solved] Howto build a network sound recorder / osciloscope (Read 539 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?


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