Is it possible to read 218 independent inputs?

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.

Sorry for the delay... So I rechecked the reading of a bit from shift register and the scope showed pulses of 14us. This is absolutely compatible with AWOL's measurement and 10 x faster than I had in mind. What I did formerly was reading out the whole 8 bit register with some complex bit manipulations, which then altogether took 150 us... :-[

Analogue reading: Dont compare apples and oranges! The analogue method will give you 8 readings at a time, so the time for I/O is absolutely comparable!

Remember that the main concern was the mass of chips involved to connect 200+ lines. There is no diference between shift registers and multiplexers. Only the analogue method can reduce that hardware complexity....

The analogue method will give you 8 readings at a time, so the time for I/O is absolutely comparable!

On a ten bit A/D?
Explain please, I'm all ears.

The PISO SRs will work just fine, the only thing is the speed using user C code and that seems to be open to conjecture at present. Certainly if the function was written in assembler it would be fast enough.

Unfortunately the Arduino doesn't have a shiftin() function (I think) to match shiftout() as it's possible a library function like this would be written in assembly (OK unlikely but possible).

So what about using the hardware SPI on the chip. It's little more than a shift register itself, if you organize the 28 external SRs as mentioned, pulse one ditgital pin to latch data into all SRs, then send 28 bytes out the SPI, the data will appear on the MOSI line but that is not even connected. However the output of SR #28 is connected to MISO, so every byte you write causes a byte to be read and you grab it before sending the next byte.

See page 167 of the 328 spec sheet for details.

This will run blindingly fast (up to 4Mbps but probably a bit slower if your line lenghts are long) and should solve the "to slow" problem.

Whatever you do this is going to be a large wiring job though.

Is it possible to detect simultaneous events this way?

Yep.

Explain please, I'm all ears.

I think I explained this in my posting #11 - and also the issue... 8 values are tight...

The PISO SRs will work just fine, the only thing is the speed using user C code and that seems to be open to conjecture at present. Certainly if the function was written in assembler it would be fast enough.

Unfortunately the Arduino doesn't have a shiftin() function to match shiftout() as it's possible a library function like this would be written in assembly (OK unlikely but possible).

The PISO approach is NOT fine as A LOT of hardware is involved. There is no need to improve the speed, as I miscalculated the time due to a slip of my memory, and the situation is quite favourable.

The ShiftOut is slow, it is NOT coded in assembly. Have a look at all that C-code in the Arduino directory from time to time...

A lot of cheap hardware though, shift registers are as cheap as, well, chips.

I would just write the SR read and write code using direct port manipulation, much faster.

The ShiftOut is slow, it is NOT coded in assembly

Then maybe it should be.

There is no need to improve the speed

Our posts crossed here so I was working on the 150uS.

The PISO approach is NOT fine as A LOT of hardware is involved

Granted your idea uses only 5 chips and that's a big plus, but there's no need to shout.

Anyway I'm just presenting an idea that 2stl may (or may not) feel more comfortable with, after all despite needing 28 chips there is still only 3 wires involved.

Sorry for shouting :cry: It had been late night here. (On second thought one should never shout at late nights...)

Well, you are right WRT to connecting to the Arduino itself (3 wires against 4 (plus ground)) A PISO approach can also abandon the latch line, as no exact sychonicity is required.

However I should be concerned with all the wiring at the interface to the 200+ key with 25+ chips. This will need good PCB design..

To my surprise the analogue approach has been discussed in length in this thread already
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226896251/
That elaborates the general idea...

I think a simpler explanation is this.
You implement a classical R-2R DAC, but the input is done from the keys rather than from the controller.

The decoding from the ADC then mirrors the bit pattern of the input! I did not think of this yesterday, but all the bits will become correctly reproduced automatically without any transformation!

This however it bound to the fuzziness of the analogue world... So best not use the lowest 2 bits, which gives you 8 keys to connect to one ADC channel - more or less reliably.

This will need good PCB design..

Not to mention a BIG design :), Eagle free version won't handle it.

Not to mention a BIG design Smiley, Eagle free version won't handle it.

or just protoboard and LOTS of wire. ;D

Many thanks guys!

Sorry for my previous post because I just noticed it doesn't make much sense, as I tried (unsuccesfully) to translate a commom term in my native language :).

Whatever you do this is going to be a large wiring job though.

As a noob, this isn't a big problem, because it seems pretty much easy to understand the functioning of the 'apparatus'. The massive wiring isn't very bad because after that everything will work for sure (i think). I want to avoid the possible unpredictable problems of using a more 'advanced' (complex) method. I know that I will not be able to deal with such problems. I plan to study electronics a little more after this project and then I will try to 'enter the analog world'.

Therefore, correct me if i'm wrong, but if I understand correctly, the whole circuit will be as simple as this:


(scaled to 28 shift registrérs)

And it will be possible to read all the switches into one array at a very high frequency.

This sounds pretty much like a dream to me, because I thought it was going to be much harder. :slight_smile: Will it be possible to use any register on the market? (or should I search for a particular brand/specification?)

Thank you very much guys. You have no idea how much it is important to me! :wink: