Pages: [1]   Go Down
Author Topic: [solved] ADC Free Running Mode in ATMEGA 328 on Arduino Ethernet not working  (Read 1466 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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.
« Last Edit: September 06, 2011, 02:04:38 am by Emmeran » Logged

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 435
Posts: 23601
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#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:

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

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
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)
« Last Edit: September 05, 2011, 10:50:46 pm by Emmeran » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
Logged

Pages: [1]   Go Up
Jump to: