Using Arduino as DAQ? (Help with sampling)


First off I would like to thank the arduino community for their indirect help with my project so far! Almost everything I learned about coding on the arduino so far has been from the forums. I am currently a senior Biomedical Engineering major so I am comfortable with topics such as DSP, Nyquist, C programming and such; therefore I consider myself an intermediate user. I know what I want the arduino to do, but don't necessarily know how to exactly code it. So anyways back to the task at hand.

What I'm trying to do is sample an analog signal (microphone with custom pre-amp filter) and output each sample as binary over Bluetooth to a computer or cell phone as it's collected. This pre-amp filter will filter out frequencies over 2000Hz and bias around 0-5V, therefore I need to sample at 4000Hz or greater. This signal once on the computing platform, will be plotted and analyzed using some frequency analysis. The reason I'd like the sampling to be continuous as opposed to being stored in an array is because the computing platform will continuously plot the data as it comes in (similar to an ECG).

The problem that I am having is that I cannot figure out how to control the sampling rate to be consistent. At first I let the while loop run uninhibited, but the sample period would vary a little between samples. Then I thought that implementing an if statement in the loop to only sample when the difference between micros() and the last sample is 236uS (4237Hz), but I get a sampling rate of 4166.66Hz....?

My question is there any other better method to sample at a consistent sampling rate? Or is the problem with how I am calculating the sampling rate, and in actuality I am sampling at the prescribed rate?

I have attached my code so far for reference. To test, I use PUTTY and A0 connected to 3.3V rail. Thanks,


*                                                                                            *
*  This program reads 'n' data points at the A0 port and immediately sends out the value     *
*  over SPP. It calculates the sampling rate of each sample.                                 *
*                                                                                            *

const byte analogInPin = 0;  // A0
const byte samplePeriod = 236; // sampling period in uS, MUST BE MULTIPLE OF 4

unsigned int sensorValue = 0;        // value of microphone
unsigned long int i = 0; // number of samples
char test = 's'; // controls when program executed
unsigned long initial = micros(); // time that sample collected
unsigned long scratch1 = micros(); // used to calculate sampling rate
unsigned long scratch2 = micros(); // used to calculate sampling rate
byte scratch = 0; // used to control sampling
float rate = 0;

void setup() {
  Serial.begin(115200);  // initialize serial communications
  pinMode(13, OUTPUT);
  Serial.print("Forced Sampling at ");

void loop() { 
  test =;
  if (test=='r') {
    initial = micros();
    i = 0;
    scratch1 = micros(); // start of data collection
    while(test != 's'){ // if input 's' into serial from computer exit loop
      scratch = micros() - initial;
      if (scratch == samplePeriod) {
        initial = micros();
        sensorValue = analogRead(analogInPin); // read in value
        Serial.write(highByte(sensorValue)); // output MSB of int in binary
        Serial.write(lowByte(sensorValue)); // output LSB of int in binary
        test =; // read for value from serial
    scratch2 = micros(); // end of data collection
    rate = i/(0.000001*(scratch2-scratch1)); // calculate sampling rate
    Serial.println(" Total Samples");
    Serial.print("Calculated Sampling Rate: ");
else { // flash LED while waiting for input
  digitalWrite(13, HIGH);   // set the LED on
  delay(100);              // wait
  digitalWrite(13, LOW);    // set the LED off
  delay(100);              // wait

Please don't cross post.,100963.msg757022.html#msg757022

last sample is 236uS (4237Hz), but I get a sampling rate of 4166.66Hz....?

From the reference page for micros(): " this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four). "

1 / 4166 = 240µS. Which looks to be 4µS off of your 236µS value....

sorry. posted here then realized that it may fit better in another section :disappointed_relieved:

thanks for the response. on the other post they mentioned using an interrupt to control the sampling. this has worked but presented new challenges!

  • CODY