-1

enter image description hereThis is a kind of an experiment, I just have a question on how Arduino ports work. Consider this sample: there is this target device that I'm trying to control with Arduino. The device uses a typical scanned keyboard (8 output columns and 5 input rows which make contact whenever a user presses a key). I am trying to emulate that keyboard with Arduino. Of course, a standard way to do it would be to read 8 columns and produce appropriate output on the 5 rows. However, Arduino is not fast enough to make it work. So, I am going with multiplexer idea. 8 Arduino's digital pins are connected to columns and 5 Arduino digital pins are connected to rows. GND rail is NOT connected.

So the idea is this. By default all Arduino pins are set to INPUT in init() routine. Whenever I need to emulate a key press, I just set a corresponding row pin to OUTPUT and LOW, same for the column pin. So, that should work as some kind of a multiplexer, since Arduino pins are driven by Mosfets and input state is high impedance, and during output state both pins would be tied to Arduino's GND which makes a hardlink connection between them (setting to HIGH should work to, there's no difference).

Here is the test code which should make a keypress every 5 seconds:

pinMode(ROW0_PIN,OUTPUT);
digitalWrite(ROW0_PIN,LOW);
pinMode(COLUMN0_PIN,OUTPUT);
digitalWrite(COLUMN0_PIN,LOW);
Sleep(5000);

pinMode(ROW0_PIN,INPUT);
pinMode(COLUMN0_PIN,INPUT);
Sleep(5000);

Now, the thing IS working. However, it only works if one column pin is connected. When I connect any two pins, the target device stops responding. What I found is that actually, when I do

pinMode(COLUMN0_PIN,OUTPUT);digitalWrite(COLUMN0_PIN,LOW);,

the neighboring pins somehow get activated too, which results in all column outputs connected together and sending signal to row inputs.

If all pins are set to INPUT, it works fine, meaning, no connection between rows and columns.

My qustion is: why is it happening? Let me rephraze it: somehow setting a digital pin to OUTPUT makes other digital pins lose their high impedance state, although all of them are set to input. I haven't checked if this is happening within a hardware port or not, just consider schematics, please.

Jimmy Falcon
  • 101
  • 3
  • 1
    it is unclear what you are trying to do ... emulating a keyboard does not involve using a matrix ... are you trying to programmatically "press keys" on a real keyboard? – jsotola Jan 06 '22 at 15:58
  • There is a vintage device that uses a typical keyboard matrix circuit. I am trying to emulate keypresses on that keyboard with Arduino. Usually you do this by following outputs and producing data on inputs. But Arduino is too slow in this case and that approach is not working. So, I'm looking for a simple way to do it. Of course, I can use add-on multiplexers, but the point is to keep it "Arduino only." – Jimmy Falcon Jan 06 '22 at 16:11
  • 3
    The Arduino is probably plenty fast enough - you just have to be more clevererer with your programming. – Majenko Jan 06 '22 at 16:19
  • the device activates only one of the column lines at a time ... it reads the status of the row lines to determine if any of the keys are pressed in the selected column .... your code has to determine which of the column lines is being read and it has to activate only one of the row lines for the duration of the time the column is being addressed – jsotola Jan 06 '22 at 16:23
  • I am not looking for advice or explanation on how keyboard matrix works or how to program it, it's textbook simple. I am trying to implement a crossbar-matrix multiplexer with Arduino. The keyboard matrix was just an example to illustrate the idea, forget the keyboard matrix. :) The actual quesion is about pinMode() behavior and why changing pin state to OUTPUT somehow affects other pins. – Jimmy Falcon Jan 06 '22 at 16:37
  • The difficulty is in the internal circuitry of the AVR, I don't think that your idea will work. So this is more an [X-Y-problem](https://en.wikipedia.org/wiki/XY_problem).-- Would you mind to [edit] your question and add some timing information, please? Did you measure the times the device activates its scanning outputs? A diagram of a complete cycle would be optimal. And did you measure the times your program needs? Hint: the standard Arduino library's pin function are quite slow because of the "universal" pin numbers. – the busybee Jan 06 '22 at 17:56
  • Thanks for elaborating, actually, I am talking about ZX Spectrum keyboard, the outputs are address lines of the Z80 CPU. Many people attempted doing it programmatically already, the Atmega 328 is not fast enough. It *will* work if Xtal is replaced by 24 Mhz, also using interrupt to read the IORQ line (which is active exactly when the CPU reads the keyaboard). What I'm trying to do here is achieve all this with bare Arduino. Just trying to find new simpler ways. Apparently the best way to do it is use a bunch of CD4051BE's. – Jimmy Falcon Jan 06 '22 at 18:30
  • 1
    How fast would be fast enough? What do you mean by "the neighboring pins somehow get activated too" Maybe they need some small physical pull-up resistors? You could speed things up by writing to your row pins in parallel with PORTC/DDRC/PINC and reading in parallel using PIND & PINB. Changing the pinMode on A0-A4 to OUTPUT, or not is just fiddling with bits in DDRC and PORTC -- see https://arduino.stackexchange.com/a/81338/6628 and https://arduino.stackexchange.com/a/22985/6628 – Dave X Jan 06 '22 at 18:50

1 Answers1

4

I have no certainty about what is happening, but I suspect you are seeing the effects of the input clamping diodes. Each digital pin has clamping diodes that keep its potential between GND and Vcc, ±the diode threshold.

  • As long as all pins are set to INPUT, they can freely float with respect to one another, provided the potential differences stay within Vcc+2×diode_threshold.

  • When you set one pin to OUPUT LOW, you are tying to to GND. The other pins can still float above this one, but only very slightly below it. The clamping diodes provide unidirectional current paths from this pin (which is now GND) to every other pin.

Edgar Bonet
  • 39,449
  • 4
  • 36
  • 72
  • Yes, that must be it. Any idea how to get around it, please? Maybe add external diodes to create voltage offset? – Jimmy Falcon Jan 06 '22 at 17:07
  • 1
    @JimmyFalcon: Sorry, but no idea. Connecting nodes to GND of a floating IC is a very unconventional way of achieving electrical contact. – Edgar Bonet Jan 06 '22 at 19:02