Close

note for speed

A project log for Current Reader

a Arduino base ~10Khz 2 port current and voltage sensor

will-whangWill Whang 03/23/2016 at 09:270 Comments

So for this project useful, I needs to have at least ~10 to 20 Khz of sampling speed.

for the Arduino API, using analogRead() like this

Serial.println(analogRead(A2)*2.048/51150.0/USB_resistor*1000.0;);
gives me about ~600us per sample.

to improve this, first of all is to speed up ADC clock, by changing the devider to 16, I have 1Mhz for ADC, thus 77khz of sample rate.(13 clock per sample)

but now it gives about 500us per sample, so not only the ADC speed is important, there must be something slow down the code.

and later, I found that the performance neck is converting from float to char.

also note that in Arduino leonardo the USB endpoint of USB CDC is 64byte, so I send 12 samples in one buffer to maximize the usage.

and I decide to leave the conversion to my computer, and modified my code to

char data[60] = {0};
for(int i=0;i<12;i++){
            int usb = analogRead(A2);
            char buf[4] = {0};
            itoa(usb,buf,10);
            memcpy(data+5*i,buf,4);
            data[4+5*i] = '\n';
}
Serial.write(( uint8_t*)data,60);
which gives me about 45us per sample

last but not least, because I know the ADC port I want to sample,

I can bypass Arduino API and speed up a little bit, and I change my code to

ADMUX =  (0 << 6) | (pin & 0x07);
char data[60] = {0};
for(int i=0;i<12;i++){
            ADCSRA = ADCSRA | (1<<ADSC);
            while (ADCSRA &  (1<<ADSC));
            uint8_t  low  = ADCL;
            uint8_t high = ADCH;
            uint16_t usb = ((high << 8) | low);

            char buf[4] = {0};
            itoa(usb,buf,10);
            memcpy(data+5*i,buf,4);
            data[4+5*i] = '\n';
}
Serial.write(( uint8_t*)data,60);

finally, it gives me 35us per sample, which is about 28khz sampling rate.

Discussions