I have five piezoelectric elements attached to my Arduino Mega at the ANALOG IN-Ports. There is a 1M-Ohms resistor parallel to each of those piezos. The values of the sensors are being read with the following code:
int y;
int input[5] = {A0,A1,A2,A3,A4};
void setup() {
}
void loop() {
for(y = 0; y <= 5; y++) {
input[y] = analogRead(y);
}
}
Everything works fine and as expected. Now my problem is, that the values aren't being updated as fast as I need them to be updated. I read multiple posts about multithreading and that it isn't possible to do with the Arduino, so my question is, is there a faster way of updating all five values than the one stated above? This one seems to be the fastest I could do.
Um you aren't reading the pins you are reading pin y and putting that value in your pin array.
int y;
const int input[5] = {A0,A1,A2,A3,A4}; //using a constant would keep you from making your error
int result[5];
void setup() {
}
void loop() {
for(y = 0; y <= 5; y++) {
result[y] = analogRead(input[y]);
}
}
That's true but it's still bad practice. Something I found out when trying to use a similar approach with a Leonardo where if I remember correctly A0 is not pin 14.
@ Delta_G
I need them really as fast as possible. Now if one sensor is being hit (I use the sensors to precisely detect hits on a surface.) the chance that you skip and don't read its peak value is pretty high due to the shortness of the signal an the interrupts.
SpaceForOne:
I need them really as fast as possible.
You need to define what that means in terms of samples per second.
You need to study the Atmel datasheet to understand what is possible with the ADC - especially as you are using the ADC to take samples from different pins.
The maximum sample rate from a single pin at full resolution is 15,000 samples per second.
You may need to use a higher performance external ADC for your application.
Do you need to know whether a sensor has been hit or how hard it has been hit ? If so, do you need to use analogRead() or could you get away with digitalRead() which is faster in operation.
@ Robin2
Well, I can't tell you exactly how many samples per second but if only one or two sensors are attched, it reads the values frequent enough for good values.
@ UKHeilBob
I need to know how hard it was hit, so I can't use the digital inputs.
SpaceForOne:
@ Robin2
Well, I can't tell you exactly how many samples per second but if only one or two sensors are attched, it reads the values frequent enough for good values.
It would be easy to add a crude delayMicroseconds() into the code and try different values to figure out what makes it too slow to be useful. That should give you a good ball-park answer to my question.
@ Robin2
I understand what you're thinking about but it doesn't help me to know how fast I have to read the values, because I know that with one sensor it works just fine, ok with two but it isn't fast enough for more than three sensors. Since the way of reading the values I mentioned above seems to be the fastest possible way of analogRead() (no other suggestions yet) I can't really work around it, I will probably make it work with multiple Arduinos.
Analogread() on an Arduino is normally 10 bits resolution at about 8000 samples per second.
You can speed up the analogread by reducing the number of bits resolution you want.
from my code archive I got this trick to reduce the sample time.
you need to add this line
ADCSRA = (ADCSRA | 0x07) & (0xF8 | _prescale);
_prescale is a byte 2..7 ==> 2 is fast and 7 is slow.
const int input[5] = {A0, A1, A2, A3, A4}; //using a constant would keep you from making your error
int result[5];
uint32_t start;
uint32_t stop;
byte _prescale = 2;
void setup()
{
Serial.begin(115200);
}
void loop()
{
ADCSRA = (ADCSRA | 0x07) & (0xF8 | _prescale);
start = micros();
for (byte y = 0; y < 5; y++)
{
result[y] = analogRead(input[y]);
}
stop = micros();
Serial.print("_prescale:\t");
Serial.println(_prescale);
Serial.print("Time used:\t");
Serial.println(stop - start);
for (byte y = 0; y < 5; y++)
{
Serial.print("\t");
Serial.print(result[y]);
}
Serial.println();
_prescale++;
if (_prescale > 7)
{
_prescale = 2;
}
delay(1000);
}
give it a try
sample output
_prescale: 2
Time used: 40
391 312 255 227 199
_prescale: 3
Time used: 52
359 368 376 384 352
_prescale: 4
Time used: 88
461 476 502 526 483
_prescale: 5
Time used: 156
357 347 345 348 350
_prescale: 6
Time used: 284
243 224 208 196 221
_prescale: 7
Time used: 560
252 245 242 241 255
note 1: lines are floating.
note 2: see that different values for prescale give different timing (factor 10 in speed)
note 3: dive into the datasheet for the details
SpaceForOne:
I understand what you're thinking about but it doesn't help me to know how fast I have to read the values,
I'm wondering if the Atmel chip can work a bit faster if programmed directly, rather than with analogRead().
However there is clearly a limit to how fast the Atmel chip can work and if you conclude that you really need something faster it would be a complete waste of time trying to get your project to work without external hardware.
I answered this in a similar topic just a few minutes ago. It depends on how many sensors you wish to use:
for up to 5-10 sensors you can use a multiplexer. Above that it gets unreliable in the cheap versions.
for an unlimited (yes almost unlimited) number of sensors, you can use the photon-pixel coupling method which is a new thing, 2019 level stuff. It allows you to read all the sensors in parallel.
Specifically for 1 ms sampling (for lets say 4000 sensors or how ever many you want) you can use the photon-pixel coupling method which requires a video camera. In your case, unfortunately, for 1ms you will need a 1000 fps video camera (which Arduino can not tolerate). If you wish to sample these sensors in 41 milliseconds, you can use any webcam or the Arduino camera at 24 fps.
Arduino camera can go to a maximum of 60 fps, and that means that the maximum sampling speed will be of 16 milliseconds (which is pretty good since you can read a huge array of sensors in parallel). But you say you need 1 millisecond, and that requires a 1000 fps camera :o
To summarize this:
| | Sensor sampling | | 1 ms | | 16 ms | | 41 ms |
| - | - | - | - |
| | Video camera | | 1000 fps | | 60 fps | | 24 fps |
Read this for exact explanation on the principles and the implementation: P.A. Gagniuc et al. Photon-pixel coupling: A method for parallel acquisition of electrical signals in scientific investigations. MethodsX, 6:968-979, 2019.