Electronic – Reading a huge number of analog sensors in real time

adcatmegamidimultiplexerreal time

I'm trying to build a MIDI-like controller that has a neck like a guitar. On that neck, there is a huge matrix of pressure sensors. The controller will emulate 3 strings.

The way this works is:
There are 3 long strips of double sided copper tape (0.5 cm in width, as long as the neck) which are connected to power (3.3V or 5V probably, doesn't matter for now).
On these strips is a layer of Velostat, which changes resistivity based on pressure.
On top of the velostat will be another layer of rows or cells of copper tape, connected to something, that spits out a reading of the voltage through the velostat layer. As the neck is about 40 cm long, there will be at least 80 rows.

If you imagine the bottom 3 strips of copper tape as columns of a chart along the neck, the sensors will either be the cells or rows, depending on the method of measurement (I thought one might be able to multiplex the columns as well, then there could be rows.) There are a few special conditions which might make this easier though: As this is a guitar-like controller not every interaction needs to be measured! Only the touch closest to the body of the controller matters. Also a resolution of 8 bits should be accurate enough. 255 pressure levels are probably more than is needed anyways.

Now the difficult bits:

The measurement needs to be real-time-y enough to detect hammer-ons etc. (no idea how high the sample rate needs to be – estimated at several kHz for good measure and playability) and the digital output of the controller should either be MIDI (on 3 separate channels – one per string) or a digital signal that can be processed with a Raspberry Pi.

Now as my knowledge is really limited, I could not think of the right tools for the job. What I do know though is: It is possible. There is a similar but different controller that uses a very similar technique (which I practically reverse engineered until I noticed, that they have a patent and the information on how they do it is not as arcane as i thought), it is called the ROLI Seaboard.

TL;DR:

  • roughly 240 sensors

  • can be seperated into groups of 80 that are powered by the same line

  • this is a real time application, I need to acquire pressure from every sensor as it is touched (some conditions apply, see above)

Thanks in advance, I know it's a lot to read. I am thankful for any suggestion and would be very glad if you could help me accomplish the terrible mess I set out to produce!

Things I have thought of so far:

Multiplexing rows and columns, reading each cell with an MCP3008 or larger ADC and chaining up (daisy chain or tree like) ATmegas which only push the position-wise lowest interaction to the final signal, but from my calculations, that could possibly be bottlenecked by the communication overhead. Also an earlier model included ribbon potentiometers, which I have discarded, because the design was bad (several attempts, wasn't cool enough).

EDIT/UPDATE:

Thanks for the good suggestions so far!
Thanks to them I am now able to phrase my problem much more clearly:

I have a matrix of 80 rows * 3 columns of pressure sensors. When a human is interacting with the sensor matrix, several sensors in proximity will pick up the touch, but only along a column. The columns are mechanically separated. The sensors have a resistance between 100 Ohm and 1 kOhm. All of these sensors need to be read with a depth of 8 bit, processed and the results need to be sent with a rate of at least 1 kHz. So a single reading/processing needs to take less than a millisecond. The final output per column needs to be: 4 bytes for a float32 and 1 byte for a uint8. The float32 will indicate the averaged position of the first interaction along the column. An interaction is defined as a consecutive cluster of sensors with a pressure above a certain threshold. This is where the processing gets into the mix: the column will be traversed downwards until a reading oversteps a threshold. This will then count as the start of an interaction. The pressure and position of every sensor is memorized up until the first sensor, that falls below the threshold with a maximum of (probably) 4 consecutive sensors. From all the sensors of the recorded interaction, only two sensors will be processed – the one that reads the highest pressure (lowest resistance) and the highest one directly above or below it. The floating point position is calculated by averaging the two sensor positions weighted by their pressures. The overall pressure of the interaction will be just the addition of both pressures clamped between 0 and 255 (add both pressures of unit8 into a uint16 and divide by 2 without rounding, discard the unneeded bits – this should be fast). This needs to happen for every column. The result of the size of 15 bytes will then be sent over SPI to a small computer (Raspberry Pi B3) that acts as a synthesizer. I am not set on the method of transmission. If SPI is not the right tool for the job, I am willing to take any method of communication a Raspberry Pi can handle. Since this is a musical-interactive application, latency is crucial.

My exact questions are: Can this be solved with a single microcontroller without breaking the bank? I can not afford to buy several hundred dollars worth of ICs for a hobby project. What hardware would you recommend? Are there non-obvious caveats I need to be wary off?

The approach I derived from the answers up until now was to power each column individually, then read out the rows with 5 16-channel ADCs (ADS7961) connected to an Arduino over SPI. I am worried that this might not be the easiest/cheapest approach or not fast enough to reach a rate of >1 kHz.

Disclaimer: I'm a normally a theoretical chemist and a terrible amateur when it comes to electrical engineering, everything I know is self taught and without any professional background (which is in turn the reason I'm seeking help from more knowledgeable people). I do know my way around software though. Anything concerning software, I will figure out with enough time. Also, I'm German, so please excuse occasional grammar flaws.

Best Answer

Depending on your price range, you may want to consider using an FPGA between your Raspberry Pi and ADCs, such as the DE0-Nano Board, which has good support as an introductory FPGA dev board. This solution has the advantage of allowing you to write code which will clock multiple/many ADCs at the same time and format your data in a way which is presentable to the Raspberry Pi.

You mentioned that you were considering the MCP3008. This chip is SPI, so you could connect a few devices together on the same bus with different CS pins. Suppose you connected three chips to a bus, so that gives you 24 ADC channels per 6 pins (three data lines and three CS lines). This means 240 channels for 60 pins, which is easily within the capabilities of the FPGA.

If you run the MCP3008 clock line at its max frequency of 2MHz, it would take (15 clocks/channel) * (8 channels/chip) * (3 chips/bus) * (1/2000000 seconds/clock) = 0.18ms to read all 240 sensors, corresponding to sample rate of 5.56kHz.