[solved] ADC Free Running Mode in ATMEGA 328 on Arduino Ethernet not working

Hey guys,

I'm trying to get the ADC on the Arduino Ethernet (atmega 328) to run in "Free Running Mode" (i.e. sample continuously without being asked to).
Basically I want to record a audio signal with at least 10kHz sampling rate and send out that information via Ethernet. So far I've achieved only 6300 Sa/s.

I'm setting the ADATE bit in the control register A and start the measurement (control register B is set to 0). It makes one ADC measurement and then just stops.
Here's my code:

// declarations removed to make this smaller
#define DATA_BUFFER_SIZE 1024
uint8_t buffer2[DATA_BUFFER_SIZE];
int bytes = 0;

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
Server server(18844);

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

// blink with "del" ms delays "num" times
void dbg(int del, int num = 1)
{
  for (int i = 0; i < num; i++)
  {
    digitalWrite(debugPin, HIGH);
    delay(del);
    digitalWrite(debugPin, LOW);
    delay(del);
  }
}

bool test = false;
// ADC interrupt, called when ADC finished measurement
ISR(ADC_vect)
{
  buffer2[bytes++] = ADCH;
  test = true;
}

// start conversion
void analogStart(unsigned char pin) 
{
  //ADMUX = (ADMUX & 0xf0) | pin;

  sbi(ADCSRA, ADSC);
}

void setup()
{
  // set pins to output (irrelevant)
  pinMode(pin_relais1, OUTPUT);
  pinMode(pin_relais2, OUTPUT);
  pinMode(debugPin, OUTPUT);
  
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gw);
  server.begin();

  // enable interrupts
  interrupts();

  //analogSetup(4, 1, 1);
  // enable ADC
  // enable external triggers
  // enable interrupts
  // set prescaler to 16
  ADCSRA = ADEN | ADATE | ADIE | ADPS2;
  
    // free running mode
  ADCSRB = 0;
  
  // set reference, left adjust and channel to 3 ( 0 0 1 1)
  ADMUX = REFS0 | ADLAR | MUX1 | MUX0;

  delay(1);

  // start ADC
  analogStart(3);
}

void loop()
{
/*part of code removed for shorter code*/
   
    if (test)
    {
     // blink once for debug purposes
      dbg(100, 1);
      test = false;
    }
      
    if (bytes == DATA_BUFFER_SIZE)
    {
      bytes = 0;
      server.write(buffer2, DATA_BUFFER_SIZE);
    }
}

Thanks for any help,

I already tried lots of stuff, but nothing seems to work.

How about some comments? I'm finding it hard to follow your code.

Outside of that, try sprinkling some serial.print statements throughout, see what the code is actually doing.

Sorry, I uploaded the wrong code. This one should be easier to understand (edited original post)

I can't use serial tho, since I use the Arduino Ethernet which doesn't have a USB plug. I'm using the LED to test stuff.

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

Because of the '~' your sbi macro is going to set every bit EXCEPT the one you specify. It should be:

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

Thanks a lot for pointing that out. This did not change anything tho; I already removed sbi & cbi completely.

I stripped the code to the bare minimum:

const int debugPin = 9;
void dbg(int del, int num = 1)
{
  for (int i = 0; i < num; i++)
  {
    digitalWrite(debugPin, HIGH);
    delay(del);
    digitalWrite(debugPin, LOW);
    delay(del);
  }
}

bool test = true;
ISR(ADC_vect)
{
  test = true;
}

void setup()
{
  pinMode(debugPin, OUTPUT);
  interrupts();

  ADCSRA = ADEN | ADATE | ADIE | ADPS2 | ADPS1 | ADPS0;
  ADCSRB = 0;
  ADMUX = REFS0 | ADLAR | MUX1 | MUX0;

  ADCSRA |= ADSC;
}

void loop()
{
    if (test)
    {
      test = false;
      dbg(100, 5);
    }
}

Maybe someone can test how this code works on their Arduino. Mine blinks 5 times then never again. (i.e. no measurement is done)

Seems like the registers of the atmega 328 aren't aligned with the 8 bit grid.

Using the makros sbi & cbi for all flags of ADCSRA I was able to achieve using the ADC with interrupts.

Thx for your help, guys!