How to handle multiple analog inputs potentially at the same time?

I'll try and work the code out for this on my own for a while, but I just want to see if this is a good way of doing it before begging advice :slight_smile:

Part of a project I want to experiment with involves a trigger pad to midi interface. There could be up to 8 pads, potentially any two or three of them could be hit at or near the same time (having only two arms to hit them with plus kickdrum input). I'm trying to visualise a way to handle these inputs.

What I had in mind was this: An array holds the state of each pad - i.e. how hard it was hit. If it wasn't hit, obviously that'd just be a zero (I hope!). The contents of this array are sent somewhere else, for example the pieces of code handling MIDI output, at a timed interval... many hundreds of times per second probably. In that part of the code, any pad returning a zero value is "not hit" and so no note data is output.

Now the interesting part, which I don't know how to do yet but have some idea where to start researching: Interrupts set up so that when a conversion is finished on any of the analog inputs, the value is immediately read and stored to the above array at the appropriate index number. I know we're supposed to keep any interrupt routines short - hoping that's short/simple enough!

Am I barking up anywhere close to the right tree? I am aware this is probably beyond the scope of the arduino language and am more than prepared to do some datasheet-diving, I just want to know if I'm wasting my time with an approach that's unlikely to work.

Thanks in advance!

What is the nature of the signal you're expecting from those pads? Are they peizo, variable resistance etc? This will determine what you need to do in the Arduino to detect an input and determine the amplitude. Gut feeling on the information so far is that this is not a problem that wants an interrupt based solution, and you will end up polling the analog inputs and doing peak detection and debounce and so on before you get the input value you want.

BulletMagnet83:
this is probably beyond the scope of the arduino language

Well, that depends on what you are considering the 'arduino language' to be. If you take the broad view, then it's well within the scope of the language, but will require writing your own code to read the analog inputs, as analogRead() is strictly a blocking read function.

BulletMagnet83:
potentially any two or three of them could be hit at or near the same time

What appears to be “at the same time” to you, really isn’t. Humans are slow. Microcontrollers are much faster. We measure things in seconds. They measure things in sub-microseconds.

  for (int x=0; x<6; x++) {
    throwAway[x] = analogRead(x);
  }

This takes about 1ms to execute with about 100us between each sample (which is the fastest rate the A/D can practically sample.) So you mean to tell me your arms have more precision than 1ms?

BulletMagnet83:
I am aware this is probably beyond the scope of the arduino language

There isn’t such thing as the “Arduino Langauge.” The Arduino is programmed with C/C++, with some Arduino-libraries (all which are written in C/C++) to make some things easier. You can manipulate any of the registers in the datasheet.

Full code to test speed of analogRead():

unsigned long timeArray[6];
int throwAway[6];

void setup() {
  Serial.begin(9600);

  unsigned long startingTime = micros();
  
  for (int x=0; x<6; x++) {
    throwAway[x] = analogRead(x);
    timeArray[x] = micros();
  }
  
  Serial.print("Completed in ");
  Serial.print(micros()-startingTime);
  Serial.println(" microseconds");
  
  for (int x=0; x<6; x++) 
    Serial.println(timeArray[x]);
}

void loop() {
}

Yep, it's a piezo input - however I had in mind using an op-amp circuit (for which I have already found examples) to give me a 0-5V output which can get fed into the MCU's analog inputs. I will probably be using a Mega1284P @ 16MHz for this application as I need a lot of free pins for other stuff.

In an ideal world, the MCU will be receiving a signal it's well equipped to deal with. Things I already have include:

Piezo elements
A metric shitload of passives, and 5V zener diodes (one schematic I saw used them, presumably to clamp the voltage between 0 and 5V)
Several choices of op-amp
An Uno/Pro/Pro Minis to practice on

So I think aside from having to go "outside" the normal functions of the IDE to set up my ADC interrupts, I might well be good-to-go :smiley: So have I got the right sort of approach for this? The end result should be that whatever notes are eventually played, if played together, SOUND together as far as the human ear is concerned.

EDIT: I didn't make it clear in my original post but I did mean "at the same time from a human's point of view" :wink:

Midi is very slow at 31250bps and an average command takes 3 bytes so you will spend far more time transmitting over serial than polling the analog in's.

BulletMagnet83:
EDIT: I didn't make it clear in my original post but I did mean "at the same time from a human's point of view" :wink:

Which is why interrupts are just going to add unnecessary complexity, especially when trying to debug the code.

Don't forget the high-hat, so 4 at a time.
There are fast ADCs that will perform multiple conversions at the same time, but they are expensive.
At the same time, really fast multi-channel ADCs are not expensive, and often available as samples, such as
http://www.analog.com/static/imported-files/data_sheets/AD7908_7918_7928.pdf
with fast SPI interface, you can be sampling for a rise that goes above a threshold and use that as trigger for sound playback, measure the peak and wait for it to settle some before allowing another peak (perhaps lower) from same channel to start next playback at perhaps different volume. How fast can you play repetive notes? maybe 20, 25 times a second? Lots of time betweeen hits, like 40mS+.

BulletMagnet83:
Yep, it's a piezo input - however I had in mind using an op-amp circuit (for which I have already found examples) to give me a 0-5V output which can get fed into the MCU's analog inputs.

Well, if your input to the Arduino takes the form of a bunch of 0-5V DC voltage values then all you need to do is poll the analog inputs at a suitable frequency.

Do you have any feeling for the sort of pulse length that you're expecting to generate?

PeterH:

BulletMagnet83:
Yep, it's a piezo input - however I had in mind using an op-amp circuit (for which I have already found examples) to give me a 0-5V output which can get fed into the MCU's analog inputs.

Well, if your input to the Arduino takes the form of a bunch of 0-5V DC voltage values then all you need to do is poll the analog inputs at a suitable frequency.

Do you have any feeling for the sort of pulse length that you're expecting to generate?

Not yet, however I intend to find out by measuring a test circuit on a scope (once the one I want is in stock!). All it really has to do is hold a peak value and pass it on to the analog input. I can find a circuit for this no trouble, and I could swear I've actually built something similar once, long ago...

Thanks very much for the replies guys, by the looks of things it's not nearly as complicated as I was trying to make it. Considering what I actually NEED to do, vs what I thought I should do, I'm gonna go with your suggestion, PeterH - polling the analog inputs ever x microseconds, and then sending on the collected values every y microseconds. (Values to be determined by experimentation!). Makes it a lot easier, and while I lose out a little by not having to force myself to learn something new, I gain by actually standing a chance at making it work :wink:

Given any display will spend almost its entire life - from a chip's point of view - sitting around doing nothing between updates, and panel buttons are unlikely to be pressed while the user is hitting things, there's probably enough time to allocate for everything.

Thanks again guys, I suppose I'd better get building/coding soon.