[solved] Howto build a network sound recorder / osciloscope

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:

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

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?

Thx,
Emmeran

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.

#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
ISR(ADC_vect)
{
  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);
  server.begin();
  
  interrupts();

  // ADC setup (see atmega datasheet for reference)
  sbi(ADCSRA, ADEN);
  cbi(ADCSRA, ADSC);
  sbi(ADCSRA, ADATE);
  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);
    sendBuffer(0);
    needSend[nonactive] = false;
  }
}