Friday 31 January 2014

41. PS/2 Keyboard Test

Now a computer is no good, unless you can type something into it.  Although it is possible to read a USB keyboard you need additional hardware if you are just using an Arduino UNO.  However there is an Arduino library for PS/2 Keyboards. I found it at http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html.  You'll need to add it to the Arduino IDE Libraries. Click on Sketch->Import Library->Add Library...

All I needed now was a PS/2 Keyboard as all my keyboards are USB these days.  Fortunately they can still be found in plentiful supply at your favourite online stores.

Of course, with s PS/2 keyboard you need a PS/2 socket to plug it in.  I had an old motherboard and a hot air gun soon melted the solder to free it from the main board.  Now to make it breadboard friendly.

You only need 4 pins.  +5V, GND, Clock and Data.  See http://en.wikipedia.org/wiki/PS/2_port for details of the pin outs.  I used a continuity tester to check which pins underneath matched which ps/2 port inputs and soldered on four jump wires.



Using just the LiquidCrystal library and the PS2Keyboard library, I was able to write all over my 20x4 LCD display.

The PS2Keyboard library defaults to US layout doesnt have the UK layout defined so I might tweak that later.

Heres the code:
#include <LiquidCrystal.h>

#include <PS2Keyboard.h>

LiquidCrystal lcd(10,9,8,7,6,5,4);
PS2Keyboard keyboard;
const int DataPin = 3;
const int IRQpin =  2;

int row=1;
int col=0;

void setup() {
  // put your setup code here, to run once:
  delay(1000);
  keyboard.begin(DataPin, IRQpin);
  lcd.begin(20,4);
  lcd.print("Keyboard Test");
  //lcd.cursor();
  lcd.blink();
  lcd.setCursor(col,row);

}

void loop() {
  // put your main code here, to run repeatedly: 
  if (keyboard.available()) {
    
    // read the next key
    char c = keyboard.read();
    
    // check for some of the special keys
    if (c == PS2_ENTER) {
      col=0;
      row=row+1;
    } else if (c == PS2_ESC) {
      lcd.clear();  // clear screen if ESC is pressed.
      col=0;
      row=0;
    } else if (c == PS2_LEFTARROW) {
      col=col-1;
    } else if (c == PS2_RIGHTARROW) {
      col=col+1;
    } else if (c == PS2_UPARROW) {
      row=row-1;
    } else if (c == PS2_DOWNARROW) {
      row=row+1;
    } else if (c == PS2_DELETE) {
      col=col-1;
      lcd.setCursor(col,row);
      c=32;
      lcd.print(c);
      lcd.setCursor(col,row);
    } else {
      
      // otherwise, just print all normal characters
      lcd.print(c);
      col=col+1;
   }
   if (col>19) {
     col=0;
     row=row+1;
   }
   if (col<0) {
     col=19;
     row=row-1;
   }
   if (row>3) row=0;
   if (row<0) row=3;
  }
  lcd.setCursor(col,row);
}

Monday 20 January 2014

40. A foray with I²C

It's been a while since I built something that didn't come in a kit.

I've had a RTC (Real Time Clock) chip (PCF8563) in my collection for a while as I wanted to get to grips with I²C.

I²C is a protocol for allowing ICs to communicate via a 2 wire interface.  One wire is the clock (SCL) and the other is the data (SDA).  This saves on the number of connections and also simplifies circuit design.

My early experiments writing bit bashing code on a PIC to speak I²C ended up fruitless and I thought I had missed some vital information.  Needless to say, it put me off for a bit.  I got other people's code to work on the PIC but I wanted to understand it because I thought it might be cool to get the Z80 to talk to a RTC.

However, the Arduino boards have a dedicated I²C interface and library code that makes it a piece of cake to get started.  So I dug out the PCF8563 and started coding.  Fortunately there was even code examples for Arduino using the PCF8563. Once you've seen how the code should be written its a lot easier to roll your own.

So I got the RTC clock wired up, and added my 16x2 LCD and in no time had a clock working.  It seemed a bit too easy, so I wondered what else I could connect to the I²C bus.  I found the DS1631 temperature/thermostat IC.

Each I²C device has a different address.  I don't know how unique they are as there are only 128 addresses available.  Bit 0 is used to signify read or write.  Luckily the RTC and Temp IC are different.

Needless to say it wasn't to hard to talk to the DS1631 as well using the Wire library and display the temperature.

To spice things up a bit more I wanted to divorce the ATMega328P from my Arduino Uno and put it directly on the breadboard.  This needed an additional 16MHz crystal and 2x 22pF capacitors.

Lastly a battery backup for the RTC clock which is quite easy to connect by using diodes to make sure the current goes in the right direction.

The software allows you (via the 2 buttons) to set the date and time and set a thermostat temperature, which when reached lights the red LED via a 1K resistor at the bottom.  In fact the DS1631 will operate on its own once configured to control a heating system.

Update: somehow the 1K resistor was a 47 ohm.  I noticed that when the thermostat temperature was reached and the LED lit up the temperature would go back up again.  It seems without much resistance on the output it causes the IC to warm up due to the current flow.  What I have done now it put a 10k resistor and fed that into a BC548B transistor to light the LED.


39. Time on my hands.

I bought this watch kit from Cool Components.  Easy to solder and assemble.  I realised afterwards that I could customize the PIC chip as the source code is available.   I prefer a 24 hour clock, and this is programmed just to display the 12 hour clock.  But its still a great watch and wearing it about at work has become a conversation piece.