I've been working on using the Arduino as a data logger for a while now, and I need to log data from various sensors and want to do it as fast as possible so I don't have to revert to using an NI DAQ and LabView all the time. I really need to log data very quickly and am having some issues getting above
200 Hz, so I thought I would simplify things today and get back to basics to try to find the maximum speed I can write to a file. The first thing I tried was just using a photocell hooked up like one of the FSRs
http://itp.nyu.edu/physcomp/Labs/AnalogIn, then I tried a speed test to see just how fast I could get data to print. While you can see data scroll in the serial monitor screen of Arduino, you can't save it to a file directly from there. I've found that CoolTerm is the easiest way to do this, and it's available in Mac, Windows, and Linux versions (yes, I'm still a PC):
http://freeware.the-meiers.org/So here's the initial code:
const int analogInPin = A0; // Analog input pin that the photocell is attached to
int sensorValue = 0; // value read from the photocell
void setup() {
// initialize serial communications at 115200 bps:
Serial.begin(115200);
}
void loop() {
// read the analog in value:
sensorValue = analogRead(analogInPin);
// print the results to the serial monitor:
Serial.print(millis());
Serial.print(",");
Serial.println(sensorValue);
}
And here's a section of the initial output:
953,828
954,828
954,827
955,828
956,828
957,828
957,827
958,828
The millis() function outputs milliseconds of time elapsed, and as you can see above, I'm getting some readings at the same ms! Which means this is printing faster than 1000Hz. So, is there a way to get more resolution in the time function so each time stamp is associated with only one sensor reading? Turns out there is! The micros() function outputs in, you guessed it, microseconds- sort of. According to the reference:
On 16 MHz Arduino boards (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four).
So then I checked the Arduino Uno hardware page (the version I'm using) to check if it is a 16Mhz version, and it is indeed. So, lets give this another shot and replace millis() with micros() in the above code.
1064,824
1908,824
2776,824
3664,824
Bingo! Now this time is going by so fast that two sensor readings never get logged to the same time reading. Okay, now to make sense of the data given the resolution...
I was confused by the resolution part of the statement above, but a user on the Arduino forum post I made cleared that up:
All it means is that, in effect, instead of incrementing a variable by one every microsecond, the variable is incremented by four every four microseconds.
So, there are 1,000 microseconds in 1 millisecond, and 1,000 milliseconds in 1 second, so there are 1,000,000 microseconds in 1 second. So all I have to do is divide each reading by 1,000,000 to get seconds. For example, the first time reading I get is 1024 microseconds = 1024/1000000 seconds = 0.00102400 seconds. If I do that calculation for the first few data points, I get a delay of about 0.000888 seconds between readings, which means I'm logging data at about
1150 Hz. Not bad, but not great, given that analogRead() happens at at the rate of about
10,000 Hz. So can it get better?
One possible thing slowing down the write is using 3 different commands to print the microseconds, comma, and sensor. I remember someone telling me to write data out all at once in a string. I had a little trouble figuring out how to make a string of a number, a comma, and another number at first, but finally the code below worked:
const int analogInPin = A0; // Analog input pin that the photocell is attached to
int sensorValue = 0; // value read from the photocell
String toprint;
void setup() {
// initialize serial communications at 115200 bps:
Serial.begin(115200);
}
void loop() {
// read the analog in value:
sensorValue = analogRead(analogInPin);
toprint = 0; // resets toprint to 0 each loop, instead of adding terms on to the end each time
toprint += micros();
toprint += ',';
toprint += sensorValue;
// print the results to the serial monitor:
Serial.println(toprint);
}
However, the frequency of data writing actually <strong>decreased </strong><em>to about
885 Hz. So, is there any way I can get faster than the
1150 Hz number?
Thanks!!