Is it possible to read 218 independent inputs?

Serial/USB is how to send the data to the PC and a different issue to decoding the switches.

I know, but I would connect the cables directly into the PC if i had enough ports.

Do you have access to two wires from each switch?

Nope, one wire is common (don't know if is correct to say this) for all the switches. I have acces to only one wire from each switch.

Nothing immediatey springs to mind except 30 shift registers Smiley but there's bound to be some keyboard decoder chips out there.

Maybe there's a simple way to "expand" the io ports in Arduino :D.

Thanks.

Maybe there's a simple way to "expand" the io ports in Arduino Cheesy.

..Parallel in - Serial Out shift registers. Lots of them.

..Parallel in - Serial Out shift registers. Lots of them.

What? Sorry, but i'm software programmer. I know almost nothing about electronics :(. I wonder if this is the right way for me... I'm not giving up though.

Thanks.

Parallel In Serial Out (PISO) shift registers take 8 inputs and shift them serially out from one pin. You can hook as many as you like together, so in your case you would connect 28 of them in a line, pulse one of the Arduino pins 28*8 times while reading another pin and saving a byte every 8 pulses.

At the end of this you have 28 bytes in RAM that represent the state of 224 inputs.

It's easy to do and will only need 3 pins, but presumably you will be playing music so the only problem is that as a C function it might be too slow if you are expecting an instant response.

No need to speculate...Using standard Arduino techniques takes 150us to shift in one bit. The whole lot thus will need 36 ms = 1/28 sec which is a noticeable time for the ear (and even for the eye). It can be done faster, but there will be a lot of processing involved anyhow, not to speak of sending the data, though you will send the differences only of course....

The build-up and wiring of 28 chips on a PCB is also not an easy task for someone with little experience.

There are 16 bit PISOs though (http://www.unicornelectronics.com/ftp/Data%20Sheets/74ls674.pdf) but a little bit difficult to find...

Alas, the common ground of the switches prevents any sensible matrix design....


Edit some hours after..
Sorry this was a slip of my memory. I checked it with a scope: It takes 14 us only for 2 digitalWrite and 1 digital Read

All right, there is another not so well known appproach, using an analogue technique. You can add a resistor to each of the keys to a common voltage, adding the current through them. As you have to identify multiple keys, the values have to be logarithmic which limits this approach to less than 10 keys

1MOhm - 470k - 220k- 100k - 47k - 22k - 10k - 4k7 - 2k2 - 1k

You can use 6 ADC lines to have 60 keys.....

Critically viewed the 10 bit resolution of the ADCs will not really suffice to cover that range reliably...


Second thought: It is easy to expand the ADC to more lines, as the 6 provided lines are multiplexed anyhow. This needs a quite popular chip as 74HC4051 (1to8-analogue multiplexer). So by using 5 of them to 5 Arduino analogue ports you have 40 lines, each connected to a resistor network of 8 (from 470k to 2k2) giving you 320 inputs.

I have not yet calculated what time the decoding will take. Most likely not so much, as most of the time most keys will be open which can be easily detected....

Search the board for "multiplex" for ideas for inputting a large number of inputs. You can read the switches this way, but only one at a time.

Parallel In Serial Out (PISO) shift registers take 8 inputs and shift them serially out from one pin. You can hook as many as you like together, so in your case you would connect 28 of them in a line, pulse one of the Arduino pins 28*8 times while reading another pin and saving a byte every 8 pulses.

At the end of this you have 28 bytes in RAM that represent the state of 224 inputs.

It's easy to do and will only need 3 pins, but presumably you will be playing music so the only problem is that as a C function it might be too slow if you are expecting an instant response.

Thanks for the detailed explanation.

Too bad it doesn't fit my needs though.

Second thought: It is easy to expand the ADC to more lines, as the 6 provided lines are multiplexed anyhow. This needs a quite popular chip as 74HC4051 (1to8-analogue multiplexer). So by using 5 of them to 5 Arduino analogue ports you have 40 lines, each connected to a resistor network of 8 (from 470k to 2k2) giving you 320 inputs.

I have not yet calculated what time the decoding will take. Most likely not so much, as most of the time most keys will be open which can be easily detected....

Wow! Seems the way to go... I even found something similar using this method:
http://blog.makezine.com/archive/2008/05/build_the_arduino_pocket.html

However, as a beginner, I would like to study some tutorial-style documentation about this, so, if anyone can point me some good ones (i'm interested about the "piso" also) i'll be very gateful.

Thank you very much guys!

Does it really take 150us to clock in a single bit from a shift register?
That's an awful long time, and of the order of the same sort of time between analogue readings.

I once tested the loop:

digitalWrite(clock, LOW)
digitalRead(data)
digitalWrite(clock, HIGH)

There is a lot of overhead in the underlaying C-Code...
As this was some time ago my memory might be unprecise - I shall repeat the meassurement and report here again :slight_smile:

It's a lot easier to speed up a digital read than it is to speed up an analogue one

Wow... Thanks guys.

However, the ability to detect simultaneous presses is very essential. And 36ms isn't very good, but is much more acceptable than 'non-simultaneosity'. Including the pedals and effects, sometimes it will be necessary to detect 5 simultaneous events or more.

Maybe the "PISO" method, even if a little bit "delayed", is the best bet in this case. Is it possible to detect simultaneous events this way?

Also, I planned to do this while i'm on vacation, as a hobby, however, I don't know if 1 month will be enough to finish this, because it looks way harder than I thought.

Is there a noob tutorial teaching in details how to do this (PISO) in practice?

Thanks guys. :wink:

All right, there is another not so well known appproach, using an analogue technique. You can add a resistor to each of the keys to a common voltage, adding the current through them. As you have to identify multiple keys, the values have to be logarithmic which limits this approach to less than 10 keys

this will take far too long, the arduino only has a single ADC (that is multiplexed already) and it is a very slow ADC. It could work with banks of flash ADCs, but that would be expensive.

Latches and encoders could work, it would be much faster than shift registers anyway. Just tri-state all the latches apart from the one you want to read. The encoder isn't necessary but saves port space.

You could also use the Intel 8255, which gives you 3 GPIO ports from one, but it is rather an old chip, I don't know if the is a more modern alternative.

What's the practical difference between the digital and analog inputs?

Speed

Thanks AWOL.

I've found some nice documentations about parallel shifting, including a nice official example (http://www.arduino.cc/en/Tutorial/ShiftIn), however, i must know if any 8-bit parallel-to-serial register will do the job, and if the procedure to add more than 2 register is simply to reproduce the same arrangement as the second register.

I did a quick and only moderately representative test, of digital reads vs analogue reads.
The test is simplified in that neither case assembles readings into storable bytes, but the overhead would be minimal, and fairly constant in either case.

const int N_INPUTS = 218;
const int clockPin = 2;
const int dataPin  = 3;
const int analoguePin = 0;

void setup ()
{
  pinMode (clockPin, OUTPUT);
  digitalWrite(clockPin, LOW);
  pinMode (dataPin, INPUT);
  Serial.begin (9600);
  time ();
}

void loop () {}

void time ()
{
  unsigned long start = micros ();
  unsigned long elapsed;

  start = micros ();
  for (int i = 0; i < N_INPUTS; ++i) {
    singleDigitalRead ();
  }  
  elapsed =  micros () - start;
  Serial.print ("digital loop ");
  Serial.println (elapsed);

  start = micros ();
  for (int i = 0; i < N_INPUTS; ++i) {
    singleAnalogueRead ();
  }  
  elapsed =  micros () - start;
  Serial.print ("analogue loop ");
  Serial.println (elapsed);
  
}

void singleDigitalRead ()
{
  digitalWrite(clockPin, LOW);
  (void)digitalRead (dataPin);
  digitalWrite (clockPin, HIGH);  
}

void singleAnalogueRead ()
{
  (void)analogRead (analoguePin);
}

And the results are:

digital loop 2856
analogue loop 24516

Times in microseconds.

As predicted, the digital read is considerably quicker than the analogue one (better than 8x faster), and could be quicker still with some simple modifications.

Again, add in a small overhead for setup and byte packing, but you're still heading for a whole keyboard scan rate of two or three hundred Hertz.

Wow... Am I wrong, or this is something like 3 milliseconds?? (for the digital input)

Even the analog input is fast enough to me... btw I just found a incredibly nice tutorial on how to use Python to talk to Arduino (http://www.stealthcopter.com/blog/2010/02/python-interfacing-with-an-arduino/) and i'm going to use Python instead of C++ to actually "play" the songs on PC. Zynaddsubfx is 'massive'.

I wonder if the use of parallel to serial registers has some bad limitation though.

Thank you.

Even the analog input is fast enough to me

< 40Hz?

Oh... I forgot that the analog input is 'at the mercy' of the clock frequency.