hello, I need to read data from a sensor at a rate of 1000 samples per second from a sensor using arduino. How can I do this accurately and efficiently?
I tried using the millis functions, but I can not get a uniform collection frequency.
You would have to program one of the timers to cause an interrupt every 16000 clock cycles, which would disable at least one and probably two PWM outputs (you'd use one of the output captures to change the "end" count of the counter.) The timer used for millis() interrupts every 16384 clock cycles (prescaler of 64, and "interrupt on overflow" at 256), which frees both OCRs for PWM.
What you have described and what code you presented do not match up.
Loop could compare current mills to previous mill and
if they are the same do nothing
if they are different, do something and set previous mills to equal the current mills
Then compare current mills to a “time to serial print” mills variable and if greater that that arbitrary 2100 you selected print and update time to serial print mills to current mills.
Besides just reading the analog value 1000 times a second, what is the actual goal for the data?
This method would get you pretty close to your sample speed, but as noted above you can really dial it in to get it “exactly”.
this sounds a bit unreasonalble that you would need 1000 readings per second. to put things into perspective, even the most advanced video games on desktops with 6 core CPU's generally function at 60 to 100 frames per second and do amazing things. high definition video runs at 50 - 60 times a second. asking a little development board to run 1000 times per second is a bit unreasonable. some arduino boards only carry around 2000 bytes of ram memory for variable storage so you would max out your little board in under a couple seconds if you did accomplish this. and even if you did its pry not enough time for the regester states in your sensors to change anyways.
but the good thing is if you tell us what you are accutally trying to accomplish, im sure your board can do it. i really dont think you need 1000 readings a second
Most arduinos use a resonator rather than a crystal, and the clock speed can drift by 5% or more in response to temperature. If you really need this kind of accuracy, purchase a clock module for ten bucks, get it to output a 1kHz square wave (which most of them will do), and hook that up to an interrupt pin.
In your code you are attempting to read the value of an analog pin multiple times per second. Similar to @Westfw’s solution, if you are using an AVR based micro controller (Nano, uno etc.) you can set a timer to directly drive the ADC at the required sample rate. This triggers an ADC interrupt when the sample conversion is complete and you can process that sample in the ADC interrupt service routine. There is an example here in a demodulator sampling an analog value at 9600 Hz (which I have also extracted successfully for one of my projects):
Hello, I'm sorry for not making some things clear on the topic.
I need to read 1000 samples per second from a PPG sensor, because I'm developing a prototype with some intelligent processing, and the dataset I use has that sampling, so it needs to at least get close to that value.
In fact, the accuracy of reading at the moment is not as important as long as it has something close to the value above.
As for the millis () function, I got a sampling of 700 per second.
Reading the above answers, will I have to work directly with the registers?
I'm using Arduino Uno, but I plan to use it on a NodeMCU card (ESP8266). I know the specs are different and the way they work as well, but I'd like to test both boards.
I apologize if I am asking questions that may not seem so clear, but I do not have much experience with the arduino.
As for the millis () function, I got a sampling of 700 per second.
A side-effect of the slow line speed you're printing to.
// Variables
int PulseSensorPurplePin = 0; // Pulse Sensor PURPLE WIRE connected to ANALOG PIN 0
int Threshold = 550; // Determine which Signal to "count as a beat", and which to ingore.
long initMillis = 0;
long count = 0;
long values = 2100;
long myValues[2100];
unsigned long currentMillis;
// The SetUp Function:
void setup() {
Serial.begin(9600); // Set's up Serial Communication at certain speed.
}
// The Main Loop Function
void loop() {
currentMillis = millis();
if ((currentMillis - initMillis < values)){
myValues[count++] = analogRead(PulseSensorPurplePin);
count++;
}else if(currentMillis - initMillis > values && count != 0){
Serial.println(currentMillis);
Serial.print("Count ");
Serial.println(count);
count=0;
}
}
It does compile for the Pro Mini without reporting any errors (IDE 1.8.9), and issues this report, which I can't believe. Where is myValues[]?
Sketch uses 1974 bytes (6%) of program storage space. Maximum is 30720 bytes.
Global variables use 200 bytes (9%) of dynamic memory, leaving 1848 bytes for local variables. Maximum is 2048 bytes.