Show Posts
Pages: [1] 2 3 4
1  Using Arduino / General Electronics / Re: General book to learn Electronics from zero? on: April 29, 2013, 06:17:49 am
What kind of electronics; analogue, digital? I have been given a load of textbooks as part of the course I'm on (BTEC level 3, kind of what we'd do before going to university (this in the UK, so I guess in the States it would be known as college? A BEng., anyway)) but I have to run now so I can't post the names and ISBNs. They're pretty useful but a few are out of print and hard to find.

If you can find Forrest M. Mims III's "Engineer's Mini Notebook", you should be able to download that for free (legally). I personally haven't looked at it yet but it seems like a handy resource, particularly for analogue electronics; I've heard there are a lot of op amp example circuits in there like integrator and differentiator circuits... That's calculus, right?!
2  Using Arduino / General Electronics / Re: Synaptics T1004 trackpad issues on: April 29, 2013, 06:11:36 am
Thanks, I still have 0022 so I think I'll re-download the library and see if I can get it working in that. I had to change something to make it work with 1.0.4 so I'm wondering if something went wrong, but that wouldn't explain why the mouse works but trackpad doesn't.
3  Using Arduino / General Electronics / Re: Synaptics T1004 trackpad issues on: April 25, 2013, 02:27:34 pm
I have a similar synaptics trackpad with the same pinout. It worked flawlessly with the ps2 library when I last tried it.

Huh. Can you tell me which version of the IDE that was compiled with?

Well I've tried two Synaptics T1004s and one T10048 and none of them have worked, yet the PS/2 mouse I found works fine (with the Arduino sketch). I'm stumped, surely three trackpads - two of which I know for sure used to work and one that was sold to me as fully working - can't all be broken?

I wonder if it's an incompatibility issue because the PS/2 library that exists was written for pre-1.0 versions of the IDE. I'm going to see if my college will let me use an oscilloscope during tomorrow lunch so I can compare whatever the mouse is doing to whatever the trackpad is doing, and if it's doing something, anything, I think I'll pick up a PS/2 - USB active converter and see if that works.

Edit: I found this, it seems pretty comprehensive. It mentions that you need two 10k pull-ups on the clock and data but I've tried them already and they didn't work. Also I haven't seen anyone else mention that they were necessary, most sources say the trackpad was soldered up and it worked right away (with active PS/2 - USB converters and this Arduino library example). I don't know if I mentioned it or not but the trackpad isn't absolutely vital to my project, but as it's near impossible to remove it from my laptop's case (as it's sandwiched between a thick plate and the hyper-thin titanium outer case which is glued in place with something resembling the strongest glue in the known universe) it'll bug me to see the trackpad there but not be able to use it... Even though I almost always forego the trackpad in favour of a mouse. Sigh. It should be so simple, but for some reason isn't.
4  Community / Bar Sport / Re: A Magnet = An Infine Power Source of Energy? on: April 16, 2013, 06:40:02 am
Well that's how generators work, they use kinetic energy to rotate a coil through a magnetic field (or the other way around I guess). So yeah, I guess they are an infinite source of electrical energy provided you have something to move the coil or magnet to induce the current.
5  Using Arduino / General Electronics / Re: Strange SOT23-3 IC on a trackpad FPCB on: April 16, 2013, 06:35:03 am
So I've checked and double checked, there are no short circuits between the 5V, GND, DATA and CLK lines, everything connects up as this highly official pinout suggests:

I'm running this sketch:

#include <ps2.h>

 * an arduino sketch to interface with a ps/2 mouse.
 * Also uses serial protocol to talk back to the host
 * and report what it finds.

 * Pin 2 is the mouse data pin, pin 3 is the clock pin
 * Feel free to use whatever pins are convenient.
PS2Mouse mouse(3, 2);

void setup()

 * get a reading from the mouse and report it back to the
 * host via the serial line.
void loop()
  MouseInfo mouseInfo;
  Serial.print(mouseInfo.status, DEC);
  //X change
  Serial.print(mouseInfo.x, DEC);
  //Y change
  Serial.print(mouseInfo.y, DEC);
  //Scroll change
  Serial.print(mouseInfo.scroll, DEC);
  //Left button down
  Serial.print(mouseInfo.leftClick, DEC);
  //Middle button down
  Serial.print(mouseInfo.middleClick, DEC);
  //Right button down
  Serial.print(mouseInfo.rightClick, DEC);
  //Cumulative X position
  Serial.print(mouseInfo.cX, DEC);
  //Cumulatie Y position
  Serial.print(mouseInfo.cY, DEC);
  //Cumulative scroll postion
  Serial.print(mouseInfo.cScroll, DEC);

Although I realise posting it is kind of useless as most of the work is done by the library itself, but still; it's the exact code from the example.

So I'm at a loss, I'm guessing the trackpad is dead. Any ideas anyone? I don't have an oscilloscope to test the DATA line with, unfortunately, so is there another way I could check and see if anything is going on, maybe?
6  Using Arduino / General Electronics / Re: Strange SOT23-3 IC on a trackpad FPCB on: April 15, 2013, 07:34:19 pm
I had to burn them off to solder them, I've tested the continuity and it seems fine. I've also checked there are no shorts either but I'll double check it tomorrow, I can't be sure I haven't made some ridiculously obvious mistake due to tiredness.
7  Using Arduino / General Electronics / Re: Strange SOT23-3 IC on a trackpad FPCB on: April 15, 2013, 07:13:54 pm
Ah, thanks. So that means I might have a dead controller chip, I guess? Sigh...
8  Using Arduino / General Electronics / Synaptics T1004 trackpad issues on: April 15, 2013, 05:45:55 pm

So I have a trackpad I'm trying to interface with my Arduino. It has a Synaptics T1004 IC and I've seen people getting these working elsewhere on the internet, so I figured this would be quite straightforward, clearly I was wrong! I'm not sure what the problem is; I've cut a chunk of the donor laptop's motherboard off to get the trackpad connector solderable, soldered it all up, checked for continuity where there shouldn't be and there is none. So far, there's nothing to suggest it shouldn't work.

I've wired it all up to my Uno (also tried on a Leonardo), loaded up the PS/2 library's Mouse example and I get nothing on the serial monitor. I've tested it with other sketches and they work fine, just this gives absolutely no response.

Looking at the trackpad, the only thing that strikes me as odd is the SOT23-3 IC that's soldered about halfway along the trackpad's FPCB connector. It has the code '12E' printed on it so I looked it up and it's supposed to be a ZC2812E, "dual series RF schottky15V 20mA", but that doesn't tally with what my multimeter is telling me, which is that it has a common anode connected to the trackpad's GND line and there are two cathodes which go up to the motherboard connector and stop there. One cathode reads 600mV and the other 550mV. Quite why the anode is on the GND line I have no idea.

A rough drawing:

I'm totally stumped. I've tried swapping the CLK and DATA over when connected to the Uno but I still get no signal... Maybe it's dead? The test points on the trackpad seem to be ok, though, they sit at about 4.4V and when you touch the trackpad and move your finger that goes up to 4.55V until you take your finger off. Obviously I have no idea whether it's supposed to do that or not, but it's better than not responding at all. Maybe. I don't know. I'm just grasping at straws because I'd really like to be able to use this trackpad.

Oh actually it may be worth noting that I had to use uber-thin headphone wire to solder this thing up, but it's only a short piece (about 5-10cm). Maybe it's too resistive to give a good signal? I'll check it with my meter and report back ASAP. --- Edit: Checked both CLK and DATA, roughly one whole ohm. Probably not the issue.

Any ideas please?
9  Using Arduino / Project Guidance / Re: Keyboard/mouse controller for ThinkPad X41 keyboard on: April 12, 2013, 02:57:33 pm
Sorry, I was going to reply earlier on but I thought I'd just get on with the coding, you know when you get excited about something and can't stop thinking about it? I kind of had that.

The end result is that my keyboard now works, in so far as all but the modifier keys respond correctly (I do actually need to check this). I need to wire the modifiers and caps lock LED, slow down the repeat rate and whatever else, but I think I've cracked a few key (no pun intended) problems.

First of all, I had my keyboard sort-of working earlier on today. I had rows A-E and G working but F and H were all mixed up. This was when I was still using a 595 to cycle the rows. I think the rows were confused because of the log2() thing I mentioned; I was using that to convert the byte I was shifting out to the 595 to a digit between 0 and 7 which correlated to the rows in the software array. I wasn't happy with the polling rate, though, and the 595 was the easiest thing to swap out so I'm now using a 4017 decade counter to cycle the rows.

The thing is, it still wasn't that fast. It was faster than it was with the 595 but not by much. Initially when I tested the 595's loop rate (without any code to do anything that wasn't cycle a bit through the 595) I got 793Hz, with the 4017, with just the code need to count from 0 to 7, I got 6KHz. It seemed promising, but as soon as I added the rest of the code it slowed right down to 6.25Hz!

So I wasn't sure what to do, that's clearly too slow to be useful. Then I thought: What if I could ignore the for loop that read the inputs completely while they weren't being used? That would speed the cycle rate right up because it wouldn't waste time scanning for inputs when there weren't any on the row. So I added diodes to all of the columns, commoned them together and added simple if statement to check that pin; if it was low, ignore it, if it was high, read the inputs. Bingo, the polling rate went right up to 6KHz. The problem is, typing with the keyboard looks like this:

hhhheeeeellllooo    wwwoooorrrrrllllddddd

- Sent from my zombie PowerBookDuino Keyboard

Naturally, it needs some work still, but I've got a nice high polling rate to work from so I'm confident I can apply the same if statement 'trick' to the modifier keys. Here's the code:

/*  Keyboard matrix reader V2

    This program is designed for an Apple PowerBook G4 Titanium (DVI, 2002) keyboard matrix.
    Good luck following this without a schematic, I don't have one yet but I will soon.
    Notes: Pull downs are required on all inputs.
           Pins 2-11 are the column inputs, in order of column number.
           You need a 4017 decade counter. Ignore Q0 (start from Q1)
                                           Pin 13 is pulled low
                                           Pin 14 is the clock (this sketch > Arduino pin 13)
                                           Pin 15 is the reset (this sketch > Arduino pin 12)
           Pin A0, inputDetect: This is pulled down. The input is all column inputs joined
                                together, with diodes, and it is very, very important!
    Author: Neema T
    Date: 12/04/2013
const int clockPin = 13; //declare 4017 clock pin

const int resetPin = 12; //declare 4017 reset pin

const int inputDetect = A0; //declare your input detect line

int count = 0; //initialise the row tracking count variable

char keyboardArray [8] [10] = { //initialise the keyboard char array [rows] [columns]
       //1    2    3    4    5    6    7    8    9   10  < These are the column numbers to you and I, can be helpful reference
/*0*/  {194, 195, 196, 197, 198, 199, 200, 201, 202, 203}, //Row A << Over the other side are the row numbers according to the Arduino
/*1*/  {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}, //Row B << Over here are the row letters according to me
/*2*/  {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'}, //Row C
/*3*/  {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l',  59}, //Row D
/*4*/  {'z', 'x', 'c', 'v', 'b', 'n', 'm',  44,  46,  47}, //Row E
/*5*/  {204, 177, ' ', ' ',  45, ' ', ' ', ' ',  92, 176}, //Row F
/*6*/  {205,  96, '§', 193,  91, ' ', ' ', 215, 218,  61}, //Row G
/*7*/  {178, 179, ' ', ' ',  39,  32, ' ', 216, 217,  93}  //Row H
      // 0    1    2    3    4    5    6    7    8    9 < These are the column numbers as the Arduino sees them

void setup() {
  pinMode(clockPin, OUTPUT); //set clock as an output
  pinMode(resetPin, OUTPUT); //set reset as an output
  Keyboard.begin(); //begin keyboard!

void loop(){
  for(int count = 0; count < 8; count ++){ //this for loop makes the 4017 count to eight and checks the inputDetect pin.
    digitalWrite(clockPin, HIGH); //tick
    digitalWrite(clockPin, LOW);  //tock - 4017 counts up one
    //   delay(500); //commented out, but left in place for testing purposes - probably not required.
    if (digitalRead(inputDetect) == 1){ //Checks inputDetect. If no voltage is found, it is ignored - this massively boosts the polling rate.
        for (int pin = 2; pin < 12; pin ++){ //2 - 12 refer to the actual pins on the Arduino the columns are connected to.
          if (digitalRead(pin) == 1){ //reads each pin one at a time
            int col = pin - 2; //gets the 2D array column address by subtracting 2 from pin; this is because pins 0 and 1 cannot be used.
            int row = count; //this is not strictly necessary, but it doesn't really matter.
            Keyboard.print(keyboardArray [row] [col]); //prints the relevant 2D array address.
          } else { //otherwise,
            Keyboard.releaseAll(); //release all keys.
  digitalWrite(resetPin, HIGH); //tick
  digitalWrite(resetPin, LOW);  //tock - 4017 resets so that it agrees with the Arduino's soft counter (i.e. 'count' variable).

Hope that helps! I'm afraid I won't be around to discuss anything until Monday, so have a great weekend and I'll check in when I can.
10  Using Arduino / Project Guidance / Re: Keyboard/mouse controller for ThinkPad X41 keyboard on: April 12, 2013, 10:26:15 am
I guess it's also correct, but according to, INPUT_PULLUP also activates the internal pull ups. I believe it was added in Arduino 1.0.1 so it's a relatively recent addition.

If I could work out how to do log2(variable) I could probably have my keyboard 'working' in about five minutes, but - naturally - I can't! I'm going to have to do some digging.
11  Using Arduino / Project Guidance / Re: Keyboard/mouse controller for ThinkPad X41 keyboard on: April 12, 2013, 08:50:53 am
Thanks for letting me know. This shouldn't be a big issue, however, as the Arduino has software configurable pull-up resistors for every input pin: digitalWrite(inputPin, HIGH)

I think you'd use pinMode([name], INPUT_PULLUP, if you write a high (5V) to something it's supposed to be reading it's not going to have a particularly good time. I didn't use that in my code (there was that one line that was made redundant that I forgot to remove) because I was using pull down resistors instead, but if you include _PULLUP when you're declaring the inputs you should be good to go.

Without the diodes, if - in my example - you press C5 and E5 at the same time, then you short circuit C (0V) and E (5V). Or am I missing something?

Right you are, I knew it was just me being slow. I'll have to try it for myself and see what happens but it looks good, of course with the code I have now they wouldn't be necessary but we'll see what happens when I've got the high/low thing flipped over.

I don't fully understand that. Anyhow, it's something outside of our control: We both work with an existing key matrix.

Yeah, most keypads have them but keyboards tend not to for cost reasons, from what I've seen. My keyboard has different resistances for each key and I initially thought that could be a sort of safeguard against phantom keys (also known as 'ghosting', if it's the same thing), an analogue to digital converter may have been used to read the specific resistances of the keys being pressed so it could differentiate, but I'm not too sure about that. It's not something I'm going to look in to further, I never press more than one key at once unless I'm in a game. This might be of interest:

Not? You would gain free pins (8 rows vs. 10 columns) at the expense of scan speed, which should be negligible.

Oh of course, I didn't think about what you'd gain in pins, but I don't think the scan speed would be affected according to which axis you chose to be the inputs and which were the outputs because either way you'd cycle an output, read all the inputs, cycle to the next output, read the inputs... So you end up with 8x10 or 10x8 either way. That's how I see it, anyway. It can't hurt to try both and see which is faster.

I am worried that there is more voodoo necessary when designing the circuit. In fact, I would like to just concentrate on the software, and - perhaps at a later time - on the design of the keyboard case (as compact as possible). At least, the Arduino seems to black box a lot of the dirty things.

At most it'll be some resistors, some diodes and a couple of ICs, for me anyway. The Arduino is a very versatile device but you would never be able to design this application to work with just the Arduino, you're going to need to get your hands slightly dirty when it comes to the hardware side but it'll be nothing major, the only things to look out for are the polarity of the diodes (silver band = cathode) and the wiring of the ICs, which can be tricky at first. Nothing a datasheet can't fix, though.

Why don't you use I assume this should solve the problem.

I'm not 100% but I think that might loop the command anyway since I'm only monitoring one column, but the rows are cycling. Therefore the column is going '10000000 10000000 10000000' so the code is pressing the key, releasing seven times, pressing, releasing seven times and so on, so the key repeats anyway. In fact it'll be tricky to work out a way around this without having the Arduino wait for as long as the key is held before continuing, because if you hold a key down and the rows continue to cycle the Arduino will see the voltage go up and down, as if you weren't holding the key down, and would therefore repeat the stroke at whatever the polling rate is, which is what this code does. This would be a good reason to have the modifier keys outside of the rest of matrix because if the Arduino were to stop polling whenever a modifier key is held, you wouldn't be able to press any other key... Well, you would, but the Arduino wouldn't scan it. This would mean you can't hold two printable keys at once but I can't think of the last time I did that outside of a game, but you should still be able to hold two or more modifier keys at once. There is most likely a better way around this, as all other keyboards seem to manage it.

The problem is that for any given key you'll only get a signal on one row, right? So if you hold, say, h, the code will read that there was a signal on column 6 when row D was selected, but when it checks again when row E is high, it won't see the signal. Then when row D comes around again it'll see the signal again and think 'Oh hey, he's pressing it again! Better repeat it', and therefore the key will repeat at the keyboard's polling rate. A way around this would be to have a 'previous row D column 6 state' variable, and if it was 1 and is 1 again, then do nothing, if it was 0 and is 0 again, do nothing. If it was 0 and is now 1, do something, and if it was 1 and is now 0, do the opposite. Maybe this could be done with hardware, you could have a flip flop which simply records whether a key is being pressed or not and is polled on every cycle, independent of the rows. If it stays high then don't issue a Keyboard.release command, if it goes low then do release the key. Seems like an archaic way to do it, though.
12  Using Arduino / Project Guidance / Re: Keyboard/mouse controller for ThinkPad X41 keyboard on: April 12, 2013, 05:53:29 am
As far as I can see, the modifier keys can be wired into the matrix just like any other key. See attached image.

Ah I think I follow you now, I'll have to give it some thought. I'm a bit cautious because of the fact that the modifier keys' common is shared with the LED cathodes, but I'll draw up some schematics and work it out eventually.

Also I'm pretty sure (but not 100% because I can't work out why this would be the case right now) you need an individual pull up on every column. Every device I've ever pulled apart that has had pull up resistors they've always had one for every input; an old Sega Mega Drive controller has them, as does the Logitech G25 gear shifter I have on my desk right now, so there must be a reason for that. As for the diodes, I think my brain must be asleep still because I can't work out what they'd do! I'm guessing it's so that if you were to press a key that's on the row that is being polled (0V) at the same time as a key on a row that isn't being polled (5V) the Arduino would just get the 0V signal and not the 5V lack of one?

Looks perfect! I didn't know that something like this exists. It's also nice that it counts to ten, and I imagine there are ones that count even higher.

Well they're called decade counters for a reason! If you need to count higher you just chain them together, using Q9 of one counter as the input clock of the next counter. You might be able to get hex counters or something but I'm not sure you'd need it, if you only have 8 rows then a decade counter would be able to cycle through them with just one IC and I don't think you'd gain anything from cycling the columns and polling the rows instead, because you (well, I'd) still have to poll 76 inputs either way.

I understand the problem. But with one additional pin, as you have suggested, this could be solved. One further possibility that I see is to connect one of the counter's pins to an Arduino input pin. That way, the Arduino simply could wait until the counter is in sync.

Yeah, maybe. The problem is that if you don't have the counter and Arduino connected on every step then you can't guarantee that it'll stay in sync, but if it's properly designed then it shouldn't be a problem. It's something to think about, anyway, when you're using every single pin anything you can do to save one can make all the difference.

That's the voodoo in electronics to me. smiley-wink

I don't completely understand it myself, I just see it as standard practice, and it must be standard practice for a reason so I'm happy to play along!

Ah, I didn't know you could access the ports directly, I kind of assumed we'd have to program in C to get access to them. At college we have MikroC dev boards which use Port A, B, C and D and the pins are numbered 0-7 within them, rather than the Arduino's 0-13, A0-A5 and so on.

Another method to save on pins; I think the SCL and SDA pins are -- Never mind, I thought to check before I posted and it turns out they're just duplicates of pins 4 and 5, I thought they were dedicated SPI pins. I wonder if it's possible to change pin functions during a sketch? Maybe it would be possible to wire the shift register and some of the columns in parallel and change a pin from an output (for the shift register clocks an data) to an input between shifting the bits out and reading the inputs. Might be something to try, but I might do it on my old Uno just in case something blows up.

I don't think I've posted this, but this also works. As you'll see it's just a test to make sure that the electrical connection works, but it also highlights the need for variable tracking; if you press a key on column 5 it'll just print '1', and it will do so for as long as you hold your finger down. It's quite a good indicator of the polling rate as it is now, even if I tapped the key as quickly as possible it would still print four or five 1s. That would mean it's looping four or five times in whatever the duration would be, I would guess it would be on the order of the average 135wpm typist keystroke duration, so maybe 80ms? (Source:

Anyway, yeah, the code:

Keyboard matrix interface

Interfaces the keyboard matrix from a 2002 PowerBook G4 Titanium DVI (15in, no
backlight) with an Arduino Leonardo to create a functioning USB keyboard.

- Pull down resistors required on all column inputs, 10K preferable.
- Pins 2-11 are the columns.

Author: Neema T
Date: 10/04/2013


const int latchPin = A0; //set 595 latch pin assignment

const int clockPin = 13; //set 595 clock pin assignment

const int dataPin = 12; // set 595 serial data pin assignment

int count = 1; //initialise row cycling bit to be shifted through 595

//2D array containing key data
char keyboardArray [8] [10] = {
       //1    2    3    4    5    6    7    8    9   10  < These are the column numbers
/*0*/  {194, 195, 196, 197, 198, 199, 200, 201, 202, 203}, //Row A
/*1*/  {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}, //Row B
/*2*/  {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'}, //Row C
/*3*/  {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l',  59}, //Row D
/*4*/  {'z', 'x', 'c', 'v', 'b', 'n', 'm',  44,  46,  47}, //Row E
/*5*/  {204, 177, ' ', ' ',  45, ' ', ' ', ' ',  92, 176}, //Row F
/*6*/  {205,  96, '§', 193,  91, ' ', ' ', 217, 218,  61}, //Row G
/*7*/  {178, 179, ' ', ' ',  39,  32, ' ', 216, 215,  93} //Row H
      // 0    1    2    3    4    5    6    7    8    9

void setup() {
  pinMode(latchPin, OUTPUT); //declare latch as an output
  pinMode(dataPin, OUTPUT); //declare data as an output
  pinMode(clockPin, OUTPUT); //declare clock as an output
  pinMode(4, INPUT); //declare pin 4 as an input
  pinMode(2, INPUT_PULLUP); //declare pin 2 as an input with pull up resistor - change this
  Keyboard.begin(); //begin keyboard!

void loop() {
  count = count << 1; //shift count bit once to the left: 0000 0001 becomes 0000 0010, etc.
  if (count >255){ //if statement to make sure the shifted bit loops from 1000 0000 to 0000 0001
    count = 1; //this is where the bit is looped back to the start of the byte
  digitalWrite(latchPin, LOW); //lowers latch for transmission
  shiftOut(dataPin, clockPin, MSBFIRST, count); //transmits 'count' to 595. This is designed to scroll the outputs of the 595.
  digitalWrite(latchPin, HIGH); //raises latch to push transmitted byte to the outputs.
  if (digitalRead(4) == 1){ //if statement to read key input, this is a test statement; it works right now.
    Keyboard.print('1'); //prints '1'
  } else { //in any other condition,
    Keyboard.releaseAll(); //release all keys. This is not ideal because of the high key repeat rate, a variable should be tracked instead.
  //this if statement should be replaced with a for loop which would have a nested if, using the for loop's variable as a digitalRead, er, variable?
  //don't forget: to print a char from the array, you'd use:
  //Keyboard.print(keyboardArray [row] [column]);
  //delay commented out, included for testing purposes.

I should point out that this is currently working the opposite way to what I think I'll end up with, I've got pull down resistors on every column and the Arduino is looking for a high voltage rather than a low one. In the end I'll add a line to toggle (i.e. bitwise NOT) the byte going to the shift register so that all the outputs are high except the one being cycled through and look for a '0' rather than a '1' on the inputs, and change the pull downs for pull ups.
13  Using Arduino / Project Guidance / Re: Keyboard/mouse controller for ThinkPad X41 keyboard on: April 11, 2013, 10:10:37 am
Thanks, I just trust you on this.

Eh, that might not be the wisest decision!

It's a surprise to me that you worry about this. After all, the keyboard itself is just composed of some push buttons and wires/lines which I wouldn't expect to be too sensitive to a little more current.

Well, you're probably right, but if it's a simple case of using a 4xxx IC instead of a 74xx IC while retaining the same code then I see no reason not to choose the lower voltage, but I need to look into datasheets and such to investigate operating currents and all the rest of it. I'm almost certain a CMOS device will use less current so that's another reason to go for that, but as I say I have to look into it. They're also more sensitive to ESD, though I don't expect that to be much of a problem once it's actually being used. It may also be that you can limit the logic voltage of a 595 by reducing the supply voltage, but that's either going to be inefficient (a resistor voltage divider) or more expensive (voltage regulator). A Zener diode might do the trick though.

The modifier keys should not need more than one additional pin, though. One could put them all into the matrix, in a new column: 11

If you look at my pinout you'll see that the modifier keys have their own pads, separate from the eight rows and ten columns. That wouldn't be a problem if you were to use PISO shift registers to read the columns, but if you're not then you'll need an additional five pins, or three for a PISO register solely for the modifiers (which is what I'm thinking I'll do). It may also be a problem (for me) that the common for the modifier keys must be 0V as it's also the cathode connection for the LEDs, but as your keyboard doesn't have built in LEDs I guess that won't be a consideration for you.

As I showed in the (oversimplified) circuit diagram, my idea is to have the latch pin (ST_CP) always high so that data gets pushed to output right away. If the latch pin needs to be cyled (low, high), then I could connect it to the clock pin (SH_CP).

I might be wrong but I don't think that will work, clocking both from the same source like that. I don't know, I think you'd end up with an unpredictable result. If you don't shift in eight bits before you push them to the outputs, you'll effectively end up with a serial in serial out register where Q0 is an exact copy of DS, and the other seven Qs would be the relevant number of steps behind, so I don't really know how that will help. I guess you just have to try it and see what happens.

You have just made me realise that you could probably cycle the outputs with a simple decade counter instead of a shift register, but keeping track of which output is active would be tricky as you'd effectively end up with an asynchronous situation where the decade counter is just going '+1' '+1' '+1' in a relative fashion while the microcontroller keeps track without actually knowing for sure which row is high, but a shift register is actively taking the absolute value and shifting that out specifically so the microcontroller can just read that absolute value too and they stay in sync no matter what happens. If you could get it to work, though, you'd save on pins because I think a decade counter only needs one clock pulse and that's it. You could even have it automatically reset when it reaches a certain number by feeding that output to the reset, or maybe with an AND gate which uses the clock and a given number as the input and the reset as the output. Alternatively you could use a pin on the Arduino to reset it, that would be one way to keep them in sync. Sure, you only save one pin, but it would probably save on processor time: Instead of 16 clock pulses to shift data out and then two more to shift them to the 595's outputs to cycle through the outputs, you could just have a decade counter ticking along at two clock pulses per cycle. It's still not ideal having the counter and processor out of sync though.

Interesting thought.

I can't really think why else they'd be on their own like that, it's as if the keyboard's original controller would poll them in each cycle (i.e. regardless of where it was in polling the matrix) instead of waiting for the keyboard to loop back. It could also be a difference in the operating voltage or simply some other physical necessity of the original communication method, I have no idea.

Indeed. A char is simply one byte. A character literal (e.g. 'a') is of type char. Its numeric value is the ASCII code of the character.

Oh yeah, I forgot you said you were a software guy!

As for the difference between having all but one Y line high and having all but one Y line low: You'll generally see that an Arduino's inputs for a digitalRead() command are high at all times until a low input signal comes in. This is for noise prevention because if you're at 0V and waiting for a positive voltage to act on, there is a chance a noise source can give a false positive. If I'm honest I've been using the terms interchangeably (because they are interchangeable, really; you can even set definitions in your code so that you can write 'HIGH' but the code will replace it with a 0) but my final code will probably work this way too.

Edit: Apologies if my posts are making little sense, I've been writing this one over the course of several hours and I keep coming back to it, changing it a little, going away and coming back to change more and forgetting what I was saying. Hardly ideal but it can't be helped, unfortunately.
14  Using Arduino / Project Guidance / Re: Keyboard/mouse controller for ThinkPad X41 keyboard on: April 11, 2013, 06:54:42 am
If processor time is an issue...

As illustrated above, with the SIPO I can shift the active bit with every clock cycle, then do a measurement. Perhaps naively, I was expecting that something similar is possible with a PISO. If it is really necessary to do one full byte per shift register before being able to do a measurement, then my previous calculation needs to be revised.

Well, the thing is you can't actually tell what the active bit is until you've shifted the whole byte or bytes in, which is why I'm hoping to have the inputs on unique pins on the Leonardo so it can access them in parallel rather than serial.

I would need to inform myself about the CMOS vs. TTL part, but 5V is of course what I need for the Leonardo. smiley

So you've connected a 4xxx SIPO to a Leonardo and it worked? It's an interesting option, but you and Pylon said there are the 74597 and similar TTL devices. So using a 4xxx seems to be more of academic interest.

It was an Uno I had working with the 4021 before, but that's 5V too, I think the Due is the only official 3.3V board. I'd just feel better about putting 3.3V through the keyboard's FPCB traces because I don't want to burn anything out, I'm sure it won't make too much difference but I'm betting the keyboard was designed for 3.3V signals in the first place, and if it's easy enough to substitute a 74595 for a 4xxx equivalent then I think that's what I'll do.

What would be really interesting: Can you post the final keyboard matrix (somewhere)? I guess it would be of general interest to many.

I certainly can, here's what I ended up with:

You'll note the modifier keys aren't included on this matrix, that's because they don't really have a matrix as such. As I mentioned previously (I think, might've been in my own thread) there were five pads on the keyboard connector that corresponded to one modifier key each (both shifts and GUI keys counted as the same button, Apple doesn't distinguish between left/right shift and all that) and they use the LED cathode pads as their common.

Here's a pinout I made for the connector:

A brief doodle showing the columns (messy, but I did say it was brief!):

A photograph of the keyboard templates and how I used them to work out the matrix, each illustration of the keyboard corresponds to one connector pad that was being tested at the time:

And the rest of the spreadsheet work I did:

Bonus shot of the keyboard connector soldered up and breadboarded:

Am I missing something?

Something else concerning the keyboard. I am not sure if it is possible to have the Leonardo receive information from the computer about which keyboard LEDs to light.

One thing that stands out is that you've got two pins allocated to the 595 but you need three (clock, latch and data), and you might find that your modifier keys are outside of the regular matrix. I imagine this is because they might be on interrupts or are generally polled differently to the regular matrix, but I would not be surprised if your keyboard was the same as mine in that respect.

Also I was just going to have the Leonardo light the LEDs itself. Well, actually, I only really want it to do the caps lock LED because I don't think I've ever used num lock in my life and I want to use the num lock LED for something else (not sure what yet), but I was thinking of having caps lock as a toggle rather than a momentary thing and there would be a line to check the status of the caps lock variable and toggle the LED on or off accordingly.

Finally, I made a short code to test how a 2D matrix might work.

//2D array containing key data

char keyboardArray [8] [10] = {
  //1    2    3    4    5    6    7    8    9   10  < These are the column numbers
/*0*/  {194, 195, 196, 197, 198, 199, 200, 201, 202, 203}, //Row A
/*1*/  {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}, //Row B
/*2*/  {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'}, //Row C
/*3*/  {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l',  59}, //Row D
/*4*/  {'z', 'x', 'c', 'v', 'b', 'n', 'm',  44,  46,  47}, //Row E
/*5*/  {204, 177, ' ', ' ',  45, ' ', ' ', ' ',  92, 176}, //Row F
/*6*/  {205,  96, '§', 193,  91, ' ', ' ', 217, 218,  61}, //Row G
/*7*/  {178, 179, ' ', ' ',  39,  32, ' ', 216, 215,  93} //Row H
      // 0    1    2    3    4    5    6    7    8    9 < These are the numbers you have to use (since it starts at 0, not 1)

void setup() {
  pinMode(2, INPUT_PULLUP); //sets pin 2 high
  Keyboard.begin(); //begins... Keyboard?

void loop() {
  while (digitalRead(2) == HIGH) {
    delay(500); //do nothing while pin 2 is high
  delay(1000); //when pin 2 goes low,[1] [0]); //'press' the key in location 1, 0 (row B, column 1: '1')
  Keyboard.releaseAll(); //release 'all' keys (it's just easier than specifying which key to release)

This works and it's worth noting that although I've used chars for all of the numbers and letters you can use ASCII codes instead. You can also use them interchangeably, I made another code to test that last night and you can have:


Which is perfectly valid.

Some resources I used:,44228.0.html //Thread on 2D arrays //Example code I edited //ASCII codes for modifier keys and other unprintables like the cursor keys.
15  Using Arduino / Project Guidance / Re: Keyboard/mouse controller for ThinkPad X41 keyboard on: April 10, 2013, 08:26:37 am
Why can't you just swap inputs and outputs? Does it matter in which direction current is flowing through the keys?

I could swap them as the matrix isn't polarised (no diodes) and really it makes no difference, it's just that I have a load of 595s to hand (I don't have any 597s or 165s) and they're suitable as outputs only, and as they're 8-bit and there are 8 rows it kind of just fits. If I used the 10 columns as outputs I'd have to have two 595s daisy chained together and then 6 outputs of one of the 595s would be wasted, which also adds to wasted processor time and wasted space too, come to think of it.

Can you recommend some good reading explaining how a typical PISO works, with examples?

I managed to get a 4021 working with just the information here:, but the 4021 is a different logic family to the 74595; a 4xxx code indicates CMOS, 74xx indicates TTL. They work at different voltages (4xxx at 3.3V, 74xx at 5V), so it's better to match the logic family, hence why I mentioned the 74597 and 74165 instead of the 4021.

I understand your rationale: ... At first sight this looks good.

Yeah, that's basically it. If you have the inputs connected in parallel to the microcontroller it can access any given input at any time. In serial (via a parallel in serial out shift register), it has to shift in two full bytes to read the keys before it can do anything with the information. As for your assessment, I hadn't even thought about it that way yet. Hmm. 16KHz seems quite high given that commercial keyboards poll at 1KHz (or so I've read) though. I think older keyboards worked at 200Hz, based on a few comments I read on a forum somewhere, I'd be happy with that. If my average keystroke is a little over 120ms I think I could get away with a fairly slow polling rate... 1 / 120ms = 8Hz, surely that can't be right?!

Problematic are probably not many key presses in quick succession, but detecting a quick down-up of a single key.

With an average keystroke of 120ms at 90wpm it's unlikely that the Arduino would miss it. With eight rows being cycled I think that means you just need an 8Hz (1 / 0.120 sec = 8Hz) * 8 row = 64Hz polling rate to capture any keystroke, but I'm probably wrong about that as maths isn't my strong point. I suppose quickly tapping backspace or something would be a problem, but for normal, considered typing it's about 120ms.

That calls for the Due, which operates at 3.3V, but I need 5V to communicate by PS/2.

Not necessarily, if I were to operate a CMOS SIPO register (i.e. replace the 74595 with a 4xxx equivalent) with a Leonardo, I think that would mean the matrix would operate at 3.3V as that would be the 'high' voltage of the register's Q0-Q7 pins. Not sure why the lower CMOS logic level isn't a problem for the 5V Leo, but it isn't.

I want to implement that in hardware.

Oh I see, well I really hope my trackpad works without any of that, because frankly I can't be bothered with it! Also for reliability it would be helpful to at least have the trackpad hard-wired, if my Leonardo were to die and render my keyboard AND pointing device useless that would be a bit of a pain.

That would be awesome!

I'll get on it ASAP.
Pages: [1] 2 3 4