AprilDC
AprilDC

Reputation: 11

“Read Analog Voltage” sample rate

I want to make sure my code looks like working, since I don't have a lot of time with a signal generator tomorrow and I want to know how to set the sample rate.

I want to sample a 2kHz signal with a samplerate of 6kHz with a Arduino MEGA 2560. It, doesn't have to be in real time, so i'm thinking of filling a buffer and then sending those over the serial connection. Can anyone say if this code defenitly wouldn't work for this? And how could i set the samplerate to 6kHz?

void setup() {
Serial.begin(9600);
}

void loop() {

for(int x = 0; x < 1000; x++){
  // read the input on analog pin 0:
  int sensorValue[x] = analogRead(A0);
 } 

for( x = 0; x < 1000; x++){
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage[x] = sensorValue[x] * (5.0 / 1023.0);

  // print out the value you read:
  Serial.println(voltage[x]);
}

}

Thank you.

Upvotes: 0

Views: 1066

Answers (1)

KIIV
KIIV

Reputation: 3739

Well, as I've mentioned in another thread, you can use auto triggering mode of ADC (for UNO and ATMega328p based Arduinos):

void setup() {
    Serial.begin(256000);

    // ADC setup is done by arduino framework, but it's possible to change it slightly (for ATMega328) :
    ADCSRB  = _BV(ADTS2) | _BV(ADTS1) | _BV(ADTS0); // ADTS2..0 = 111, Timer 1 input capture event trigger source
    ADCSRA |= _BV(ADATE); // enable auto trigger mode    
    ADCSRA |= _BV(ADIF); // reset conversion end flag (= interrupt flag)

    // timer 1 setting:
    TCCR1A = 0; // clear all
    ICR1   = F_CPU/6000U; // 1 should be substracted here but result is about 2665.7 and it will be truncated to 2665 
    TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10); // CTC mode with ICR1 as TOP value, enabled with no prescaling
    TIMSK1 = _BV(ICF1); // not working without this... Flag must be cleaned up after the trigger ADC, otherwise it's stucked

    analogRead(A0); // dummy read to set correct channel and to start auto trigger mode
    pinMode(13, OUTPUT);
}

void loop() {
    if (ADCSRA & _BV(ADIF)) {
        ADCSRA |= _BV(ADIF); // reset flag by writing logic 1
        Serial.println(ADC);
    }
}

ISR(TIMER1_CAPT_vect) { // to clear flag
  PINB = _BV(PB5); // and toggle d13 so frequency can be measured (it'd be half of real rate)
  // it might be enabled on PWM pin too by setting force output compare and some compare register to half of value ICR1
}

This sketch uses baud rate 250000 but it's still too slow. The space character can be used as an separator, this'll save one character (as new line are usually two characters: \r\n). One value can be 1 to 4 characters long so for values:

  • 0-9 - 3B you need baud rate 3*10*6000 = 180000
  • 10-99 - 4B and you need baud rate 240000
  • and for the rest of cases you're too slow.

So the only way is sending those integers binary and without separator it'd be even better. The 2B per value results into minimal baud rate around 120000 baud/s.

Upvotes: 0

Related Questions