90 analog inputs on Leonardo

Hello, I'm planning to put an Arduino Leonardo in an old piano, for recording midi. I'll use hall effect sensors, together with little magnets attached to the back of the keys. The problem here is that I'll need 90 analog inputs (88 for the keys and 2 for the pedals - damper and soft). I'm looking for advice on how to do this. Is it better to use analog multiplexers, or Attiny 44's or 84's (they have 8 analog inputs each) and connect them to the Leonardo via some sort of bus. The analog readings should happen really quickly, since while playing, multiple keys will be pressed at virtually the same time.

What is the best way to do this? Multiplexers or Attiny's? Or maybe something else?

Any help appreciated! Thanks!

Tttapa

Ratiometric hall sensor ? with an analog output ? not the hall switches ?

Do you know what kind of delay is allowed ? How often should the sensors be scanned ?

The analogRead() function requires 120us. When you use a number of analog mux, some extra delay is needed to stabilize the voltages.
Analog mux : Gammon Forum : Electronics : Microprocessors : 74HC4051 multiplexer / demultiplexer

Arduino Leonardo : 12 analog inputs. Each with 8-to-1 mux, is a total of 96 analog inputs.
120us per analogRead plus 20us to stabilize the voltages after the mux has changed (20us is just a guess, somewhere between 100ns and 100ms).
Total is 88 * 140 = 12ms.
The sensors can be scanned at a rate of about 80Hz.
That will be slower if the Leonardo has other things to do, and it will be faster when a timer and interrupt and direct register programming is used to optimize the analog-to-digital conversion timing.

If you want to know the speed of change in the hall sensor value, then I think it is possible with optimized code. There are many ways to optimize. For example 8-bit ADC. I think that will be more than enough bits. But for that you need to write the the registers of the microcontroller.

Thanks for your reply! Yes, ratiometric hall sensors. I think that the mux will be too slow, since I need to have 2 readings per key, to determine the velocity. And the Leonardo also needs to run a usb midi piece of code, so I guess I'll need to use 10 Attiny's ... Or are there better solutions? And if I use the Attiny's, what is the best way to communicate with the Leonardo? (If I use all 8 analog inputs, I have 3 digital pins left on each Attiny, and 10 on the Leonardo, where I only use 10 analog inputs)

Can you tell how many samples per second you need for the velocity ?
How would you program the ATtiny's ? Writing your own code with direct register access and without the Arduino libraries ?

The Arduino Micro is the same as the Arduino Leonardo. If you want to use the Arduino Libraries, then perhaps a number of Arduino Micro boards is easier than ATtiny's.
If you still want to use the ATtiny's then I suggest to use the Arduino Pro Mini (with ATmega328P) instead. Those are very small, and the ATmega328P is the most common microcontroller, and supported by Arduino libraries.

The SPI bus is the fastest. This is an tutorial: Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino (search for "How to make an SPI slave"). However, that example does not allow multiple SPI Slaves. I don't know if that is possible.
The I2C bus might be too slow. Setting a Arduino boards as I2C Slave is easy, and multiple Slaves is no problem.
I wrote a bit-toggle-handshake communication a few weeks ago. It does not use interrupts and no delay in the Slave and does not interfere the timing of other interrupts. But it is only 1400 bytes per second.

I did a quick test using an optical encoder (I didn't order the hall sensors yet) and this is the result.

I hit the key really hard, so this is the maximum velocity, and it looks like I'm going to need at least one reading per key every 5 ms. However, I don't know how a hall sensor will behave, since the magnetic field and the distance are inversely proportional.

I think using real Arduinos for the slaves is too expensive. I'd need 7 micros @ €22 each, or 10 pro minis @ €15 each, while 10 ATtiny 84's are only €16 on ebay.

This is the result of the same test, but with a more realistic velocity (the bottom one is at maximum velocity):

I'd eventually try to encode the hall sensor readings, into e.g. 2 or 3 bits each, just as required to find out which key(s) and how strong they are activated. Then you can use interrupts to find all changes and react immediately, faster than by ADC polling.

OTOH, when you also want to create sound output, multiple controllers can not only read 8 analogue keys, but also can create the according waves, which then are fed into a common mixer. For best polyphonic performance the keys should not be assigned to the controllers in sequential order, because then almost two of them would be active all the time (according to two playing hands). E.g. each board could be assigned the same note in all octaves. Also the mixer could become a digital one, outputting the sum of all amplitudes reported by the controllers. This would require only one DAC of good quality, instead of one for each controller.

If you are willing to buy cheap clones, don't forget to donate : https://www.arduino.cc/en/Main/Donate

On Ebay:
1 Pro Mini clone for 1.95 dollars
5 Pro Mini clones for 9.50 dollars (that is 1.90 dollars each).
The Pro Mini boards have sometimes a wrong pcb or wrong crystal, so no every Pro Mini on Ebay will work.
1 ATmega32U4 board (Arduino Micro compatible) is 3.48 dollars.
10 ATmega328P (the bare DIP-28 chip) is 16 dollars (that is 1.60 dollars each).
10 ATmega8 (the bare DIP-28 chip) is 9.07 dollars (that is 91 dollarcents each).
If you can't find these prices, just ask :stuck_out_tongue:

If you buy ATtiny84, you have to add the extra components.
The ATtiny85 is more or less Arduino compatible (Adafruit Trinket), but I still advice to use ATmega328P.

5ms sampling interval seems a little long for that steep slope. About 3ms or 4ms would be better.
Say 4ms, that is 250Hz. That is already fast for a normal Arduino and 8 or 10 analog channels.
That means that using a number of microcontrollers to read the analog hall sensors is a good idea. A single Arduino with a big mux is not possible.

Can you find code for SPI between Arduino boards with multiple Slaves ?
Perhaps something is in the "Projects" section of http://www.avrfreaks.net/

DrDiettrich, please explain the encoding, instead of ADC polling. I was assuming that the Slaves would detect the strength of a tone and transmit to the Master when a key is pressed (with strength information) and when a key is released.

I think it's going to bee the pro Mini clone, or the ATtiny84's. What do you mean by external components? Is only a 16MHz crystal suffiecient? The problem with the ATmega328 and ATmega8, is that they have only 6 analog inputs in DIP package.

For the SPI, I couldn't find a tutorial specificly for more than one Arduino slaves, but I think they just need one common MOSI, MISO and clock line, and then each their own 'slave enable' line. The leonardo can then take care of selecting the right slave to receive from. But that's a problem for later on.

@DrDiettrich: What exactly do you mean by encoding the hall sensor readings? The slaves will be checking the keypresses, releases and determine the velocity. When the master asks for it, it will send the key 'address' (8 inputs, so 3 bits) and the velocity (7 bits in midi protocol, but maybe less is also possible).
And I don't need a sound output, the piano itself will take care off this, it's just for midi recording.

Well, yes, only 6 analog inputs for the DIP-28 version. The Pro Mini has 8 analog inputs.
To run a barebone ATmega, a crystal, two 22pF, and a decoupling 100nF are needed. Plus a resistor and preferrably a diode for the reset circuit. Maybe also 100nF for AREF.

The MISO is the problem. In the SPI examples the Slave sets MISO to output, but it may only be output after the chip-select has activated that Slave.

tttapa:
@DrDiettrich: What exactly do you mean by encoding the hall sensor readings? The slaves will be checking the keypresses, releases and determine the velocity. When the master asks for it, it will send the key 'address' (8 inputs, so 3 bits) and the velocity (7 bits in midi protocol, but maybe less is also possible).
And I don't need a sound output, the piano itself will take care off this, it's just for midi recording.

ADC conversion time depends on the bitcount (resolution), there exist fast (flash...) converters with very low conversion times, at reduced bitcount. Your application doesn't require a high resolution, effectively only the rise time of the signal is of interest, not the voltage levels. There may exist other ways to measure those times or velocities, but I don't have a more concrete idea yet. Perhaps there exist specialized ICs for (musical) keyboards, did you check that already?

Just an idea: use two digital (hall...) sensors, that trigger at the begin and end of the slope, e.g. at 20% and 80% of the full voltage swing. Then pin change interrupts can be used to measure the delay time between both events, and there exist digital port expanders which already create the interrupt signals.

External components is always an option. The Arduino is programmable so the sketch can be changed if needed. For me, that is why I prefer Arduino or ATmega/ATtiny chips. They have already the option for 8-bit ADC for faster ADC. I think they have more than enough possibilities to make it work well.
If the Slave modules do all the hard analog detecting work, perhaps even the I2C bus is fast enough, with an extra interrupt signal from the Slaves.

I found this page on analogRead speeds. They just use a smaller prescaler for higher clock speeds of the ADC. Maybe that's an option?

But maybe the best solution is to use 2 hall switches instead. What kind of I/O-expanders do you suggest? Since I would need at least 178 inputs... And what do you mean by 'digital port expanders which already create the interrupt signals' ? I couldn't find any chips for digital keyboards ...

Using the prescaler to speed up the analogRead() is a very good option, since you don't need a very accurate analog value. I didn't know that the normal Arduino analogRead() could speed up to 20us.

I prefer do to things in software. So I prefer a single hall sensor. That simplifies the mechanical construction and gives less trouble. Perhaps later some extras could be added in software (detect a very light touch and not pressing it all the way down for example :stuck_out_tongue: ). But that's just me: less hardware and more software :smiley_cat:

Expanders like MCP23018 and MCP23S18 with 16 I/O pins and I2C or SPI interface.

And what are the interrupt signals you were talking about?

The word interrupt(s) has been used 9 times in this topic (now 10 times). You have to explain who and which and where :smiley_cat:

I'm sorry. Here:

DrDiettrich:
Just an idea: use two digital (hall...) sensors, that trigger at the begin and end of the slope, e.g. at 20% and 80% of the full voltage swing. Then pin change interrupts can be used to measure the delay time between both events, and there exist digital port expanders which already create the interrupt signals.

The ATmega328P has PCINT (pin change interrupts) on almost every pin. You could write an interrupt handler for changes on the pins, instead of polling all the pins.

If using a port expander, some have an interrupt output. I becomes active after a change of the input pins is detected. That means that the Arduino is doing nothing, just waiting for that interrupt signal from the port expander.
Even a simple and common I2C port expander like this one has already an interrupt output : MCP23008 - i2c 8 input/output port expander : ID 593 : $1.95 : Adafruit Industries, Unique & fun DIY electronics and kits

Let me try to summarize:

First (obvious) solution uses an fast ADC (low clock prescale), checks when the sensors reach some voltage level, and determine the attack strength from the rise time of each sensor signal, or the volume from the signal peak value.

A digital solution checks for two threshold levels of the same key, routed to two digital pins. Every change of such a pin can cause an pin change interrupt (PCINT...), where the interrupt handler computes the attack strength from the time between the interrupts of two related (same key) interrupt pins. Most port expanders monitor the input pins and raise an interrupt line when any pin changes, in any direction (high/low). That interrupt signal can be routed to an controller pin to cause an interrupt there.

The first (analogue) solution requires multiple controllers (for 8 keys/ADC inputs each), the second (digital) solution requires multiple sensors per key, or comparator circuits, but a single controller and a couple of port expanders is sufficient.