I'm new to Arduino and have a question on the maximum frequency the Arduino can read an analog input.
From my understanding the signal frequency is dependent on length and complexity of the code. Is this correct?
For the test I have two accelerometers as analog inputs saving data in bits to a microSD card using the Sparkfun microSD shield. Using millis() I was able to find that we had a reading frequency of about 84 Hz. Does the code itself determine how fast the Arduino is able to take readings?
Thank you for the responses so quick. So my question is what ways could I edit the following code to get a faster loop processing rate?
/*
SD card datalogger
The circuit:
* accelerometers on analog ins 0 and 1
* SD card attached shield
*/
int led = 13;
int accel = 0;
int accel2 = 1;
#include <SD.h>
const int chipSelect = 10;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {}
Serial.print("Initializing SD card...");
pinMode(8, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
return;
}
Serial.println("card initialized.");
pinMode(led,OUTPUT);
}
void loop() {
float time = millis();
String dataString = "";
// read two sensors and append to the string:
for (int analogPin = 0; analogPin < 2; analogPin++) {
int sensor = analogRead(analogPin);
if (analogPin < 1) {
dataString += ",";
}
}
// //SD card file
int data = (analogRead(accel));
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
}
else {
Serial.println("error opening datalog.txt");
digitalWrite(led,HIGH);
}
Serial.println(data);
Serial.println(time);
//delay(1); //Assuming no delay from opening/closing files this delay determines frequency (milliseconds)
}
Sorry for the late response but I've been trying to fix the sketch. I've eliminated the serial connection but I still need to write to the SD card from two accelerometers. The shorter edited code is here but still only reads at about 50 loop cycles per second.
/*
SD card datalogger
The circuit:
* accelerometers on analog ins 0 and 1
* SD card attached shield
*/
int led = 13;
int accel = 0;
#include <SD.h>
const int chipSelect = 10;
void setup()
{
pinMode(8, OUTPUT);
SD.begin(chipSelect);
pinMode(led,OUTPUT);
}
void loop() {
//SD card file
int data = (analogRead(accel));
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
// if (dataFile) {
dataFile.println(data);
dataFile.close();
digitalWrite(led,HIGH);
digitalWrite(led,LOW);
}
The way to speed up writing to the SD card is to NOT open and close the file every time through loop. Of course, then you need to add a time-based duration during which you log, or add a switch to turn logging on or off. When you start logging, you open the file. When you finish logging, you close the file.
According to the Atmega 328 datasheet (you do have a copy, don't you? - Atmel doc8161.pdf) the ADC needs 13 clock cycles to process a sample and for maximum accuracy (10bits) the adc clock must be between 50khz and 200khz. There is a prescaler to divide the CPU clock (16mhz) down to a suitable frequency. The /128 prescaler will give an ADC clock frequency of 125khz or about 9,600 samples per second at full 10bit resolution. You can use a higher frequency adc clock if you are prepared to accept a lower resolution but I believe 2Mhz or about 150ksps is the max.
You also have to take into account how much data you want to store. If you can't store it all on the Arduino then you may find yourself limited by the speed of writing data to another device - such as your PC. At 115000 baud you can't expect to save more than about 11,000 samples per second and probably significantly less.
And, as said elsewhere, your code should separate the harvesting of samples from the business of transferring them elsewhere - unless your application only requires a very slow sample rate.
This sounds like you have the whole concept back to front.
Assume you have a short interrupt service routine that is triggered by something (perhaps by an ADC sample being completed). This routine stores the value in an array and makes a note of how many values have been collected.
Assume also that you have a program loop that checks how many values have been collected and if there are enough it sends them to the PC and resets the counter.
This will behave almost like there are two separate programs running at the same time. And you don't have to worry about the appropriate time for writing data to the PC because if an interrupt happens while it is in the middle of writing it will pause, deal with the interrupt, and carry on.
I hope this makes sense because you really need to understand this process before you go any further.
...R
ryanosu121:
I'm currently trying to work on opening, writing, and closing the file in separate defined timed areas. I've tried several things but the best results I can get are the file opening but no data is written to it. Let me know what changes I can make.
This is probably out of the scope of what you plan on throwing at this project hardware wise, but RobinJ's comment about two different programs made me think of this. On some DAQ systems here at work we actually use two processors. One processor handles the time-critical stuff like collecting data and formats the data and pushes it out to a FIFO while collecting. The other processor sits there and watches the half-full pin of the FIFO. When the FIFO reads half-full it pulls the data out of the FIFO to both store it on a SD card and transmit it via RS232.
void setup() {
Serial.begin(115200); // use the serial port
TIMSK0 = 0; // turn off timer0 for lower jitter
ADCSRA = 0xe5; // set the adc to free running mode
ADMUX = 0x40; // use adc0
DIDR0 = 0x01; // turn off the digital input for adc0
}
void loop() {
while(1) { // reduces jitter
cli(); // UDRE interrupt slows this way down on arduino1.0
for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
while(!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= 0x0200; // form into a signed int
k <<= 6; // form into a 16b signed int
fht_input[i] = k; // put real data into bins
}
sei();
Serial.write(255); // send a start byte
Serial.write(fht_log_out, FHT_N/2); // send out the data
Most examples of sampling fast are around audio. If you ignore the FHT (=FFT) bits, the rest of it will sample and send out the data as fast as possible
I am interested in this - do you know how fast? How many samples per second?
...R
markvr:
Most examples of sampling fast are around audio. If you ignore the FHT (=FFT) bits, the rest of it will sample and send out the data as fast as possible