Go Down

Topic: [solved] ADC Free Running Mode in ATMEGA 328 on Arduino Ethernet not working (Read 2053 times) previous topic - next topic

Emmeran

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: [Select]

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

CrossRoads

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.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Emmeran

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.

johnwasser

Code: [Select]

#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: [Select]

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Emmeran

#4
Sep 06, 2011, 05:43 am Last Edit: Sep 06, 2011, 05:50 am by Emmeran Reason: 1
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: [Select]
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)

Emmeran

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!

Go Up