Practical Arduino Cool Projects for Open Source Hardware- P10 potx

10 488 0
Practical Arduino Cool Projects for Open Source Hardware- P10 potx

Đang tải... (xem toàn văn)

Thông tin tài liệu

CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT With both sockets connected up the end result should look something like Figure 5-6. Figure 5-6. PS/2 sockets wired to power and data on the shield That’s it. The shield is done. Mount it on your Arduino, plug in a keyboard or mouse as appropriate, and proceed to the software section. PS/2 Extension Cable A simple alternative to mounting sockets on the shield is to cut one end off a PS/2 extension cable and attach it. Before you do any cutting, plug your PS/2 extension cable into your keyboard or mouse just to make sure you chop off the correct end. With the cable plugged in, cut off the connector at the other end to leave you with a nice long lead with a PS/2 socket attached. Then strip back about three or four centimeters of the outer insulation and you should be left with a set of four or possibly six color-coded wires plus a foil or braid shield. Even if there are more wires inside the cable, there are actually only four that you need to care about: ground, +5V, DATA, and CLOCK. You can ignore the others because we won’t be using them. Don’t be fooled by the color-coding on the wires, though, because the colors might not be what you expect them to be. For example, in the PS/2 extension cable we used for this project the red wire is the ground connection—quite deceiving if you’re the trusting type who assumes red always means positive! In our case, the color codes were as shown in Table 5-2. 69 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT Table 5-2. Typical color codes in PS/2 extension cable. Varies between manufacturers. Pin Purpose Color 3 Ground Red 4 +5V Green 1 DATA Orange 5 CLOCK Brown To identify which wire is which you can use a multimeter as a continuity tester by setting it to a low Ohms range, with one multimeter probe connected to one of the wires and the other inserted into each of the socket connections in turn to find which pin that wire connects to. If your multimeter probe won’t fit into the tiny holes in the PS/2 connector, you can use a resistor leg or other piece of thin wire held against the multimeter probe and pushed inside the socket to make contact as shown in Figure 5-7. Figure 5-7. Using a thin resistor leg to reach inside a socket Once you’ve identified the four important connections make sure you write down the color codes for reference so you don’t lose track of which is which. Other than those four connections there is one more you need to care about: the foil or braid “shield” connection that wraps around the central conductors to minimize electrical noise that might be induced by nearby electromagnetic fields. The shield needs to be connected to ground as well. Strip back about 3mm of insulation from each of the four important wires, then twist the bare end of each wire between your fingers so the conductors make a tight little spiral before “tinning” them with a small amount of solder as shown in Figure 5-8 so they are all ready to connect to Arduino pins. You should also tin the end of the shield connection. 70 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT Figure 5-8. Wire ends “tinned” and ready to connect Since there are only four connections to be made, and they’re all directly to Arduino pins, you might not even need to use a prototyping shield. The connections could be made just as easily to two pairs of breakaway male header pins (one pair for power/ground and another pair for clock/data), and the headers inserted directly into your Arduino. However, we assembled ours on a prototyping shield because it allowed us to add more mechanical support to the cable and reduce the likelihood of the connections being ripped off the Arduino if the keyboard or mouse is moved. Lay the end of the PS/2 cable over the prototyping shield and anchor it in place with cable ties so it is firmly fixed to the shield as shown in Figure 5-9. The prototyping shield we used for this version of the project came from Little Bird Electronics and has a couple of handy oversize holes that are perfect for threading small cable ties through, but if your prototyping shield doesn’t have holes in the right place you might need to use a small drill bit to expand a couple of the tiny component lead holes so you can fit a cable tie through them. Figure 5-9. PS/2 extension cable attached to shield 71 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT Bend the ground and +5V leads around to the matching power rails on the prototyping shield and solder them in place. Also take the shield lead over to the same area and solder it onto a ground connection. Next, bend the CLOCK and DATA leads across in the opposite direction toward the digital I/O lines. For a keyboard connection solder the CLOCK lead onto digital I/O pin 3, and the DATA lead onto digital I/O pin 4. For a mouse connection solder the CLOCK lead onto digital I/O pin 6, and the DATA lead onto digital I/O pin 5. These specifications are given in Table 5-3. Table 5-3. Arduino pin assignments for PS/2 connections Lead Digital I/O Line Keyboard CLOCK 3 Keyboard DATA 4 Mouse CLOCK 6 Mouse DATA 5 If your extension cable has more conductors in it that you aren’t using, you can either bend them back out of the way and tuck them inside a cable tie to keep them neat or cut them off short near where the insulation is stripped back. If you prefer to save a few dollars you can make a very simple DIY shield using some breakaway male headers and a piece of prototyping board. Techniques for building DIY shields discussed in Chapter 16 are perfect for projects like this where you have a small number of parts and a professionally produced prototyping shield would be overkill. In this project it’s preferable to have some kind of shield, even if it is a DIY shield, because mechanically anchoring the cable is very important. Figure 5-10 shows a version we made on a cheap DIY shield with just a keyboard connector and no mouse input. Make sure you clearly label which socket is which. Nothing will be damaged if you plug a keyboard into a mouse socket or vice versa, but you can save yourself some annoyance by marking each socket. That’s it. You’re done. Mount the shield on your Arduino, plug in a keyboard or mouse, and proceed to the software. 72 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT Figure 5-10. PS/2 keyboard interface assembled on a DIY shield Keyboard Software All the hard work of understanding the PS/2 communications protocol for reading keypresses from a keyboard is taken care of by an Arduino library called PS2Keyboard. The latest version of the library is linked to from the project page on the Practical Arduino web site, or you can download it directly from www.arduino.cc/playground/Main/PS2Keyboard. Make sure you download the latest version (called PS2Keyboard014 at the time of writing) because that page also contains links to other variants of the library. If in doubt use the link from the Practical Arduino web site which goes to the correct version. Once you have downloaded PS2Keyboard.zip to your computer, it needs to be decompressed and installed. Note, however, that the folder inside the archive has the wrong name: the folder in the archive is called “zip and submit as PS2Keyboard014,” so you need to rename it to “PS2Keyboard” when installing it into your Arduino environment. Make a directory called “libraries” inside your sketchbook directory if it doesn't already exist, move the PS2Keyboard directory inside it, and restart the Arduino IDE to activate the new library. The basic PS2Keyboard library handles the low-level PS/2 communications, but it doesn’t contain all the mappings to convert every possible raw PS/2 scancode to useful ASCII characters and it also doesn’t take care of detecting whether SHIFT is being held down and changing to upper-case automatically. In fact it even maps all the letter keys to their uppercase equivalent all the time, even when you’re not holding down SHIFT. That’s because a scancode sent by the keyboard is not quite as simple as an indication of a single keypress, as you might expect. PS/2 keyboards are remarkably dumb and offload a lot of the work of interpreting user action onto the host computer, rather than processing it internally. For example, they don’t send a different scancode for a press of a key based on whether SHIFT is currently held down. They 73 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT leave it up to the host computer to figure out that SHIFT has been depressed, but not yet released, at the time the next character is pressed. For example, consider the sequence of typing a lowercase letter a followed by an uppercase letter A. It’s not just two codes sent from the keyboard, but is rather more complex and goes something like this: 1. You press the A key. The keyboard sends scancode 0x1C, which represents a “make” (keydown) event on the A key. 2. You release the A key. The keyboard sends scancode 0xF01C, which represents a “break” (keyup) event on the A key. 3. You depress the SHIFT key. The keyboard sends scancode 0x12 (if it’s the left SHIFT key) or 0x59 (if it’s the right SHIFT key) to represent a make event on SHIFT. 4. You depress the A key. The keyboard sends scancode 0x1C (make on A). 5. You release the A key. The keyboard sends scancode 0xF01C (break on A). 6. You release the SHIFT key. They keyboard sends scancode 0xF012 (break on SHIFT). What this means is that the host computer can’t simply receive one code that represents a lowercase letter a and another that represents an uppercase letter A. The scancode for the keypress is exactly the same in both cases. What’s different is that the SHIFT key was depressed prior to the A key being depressed, and not previously released. Supporting modifier keys, such as SHIFT, therefore requires the host computer to implement a state-machine that switches to different states based on modifier-key events. The state of each modifier key must be maintained independently and then the current state combined to determine the action to take on a keypress: for example, SHIFT-A may need to cause an uppercase A to be sent, but CONTROL- SHIFT-A may need to cause a “select all” event. This all sounds unnecessarily complicated, but there is a good reason for it. By taking this approach the host computer has far more control over what each key represents, and allows it to control things such as auto-repeat rate rather than having the keyboard determine when auto-repeat needs to begin and sending a stream of identical characters. Once you get your head around it you can understand why it was done this way, but it may not be intuitive first time you come across it. If you’re not intending to use the keyboard for character input, and don’t care about mapping scancodes to specific characters, then the PS2Keyboard library will do everything you need and you can do your own interpretation of the codes it sends through. That might sound a bit strange, but a keyboard can be very handy in situations other than as a text-input device. For example, home automation hacker Scott Penrose uses a modified PS/2 keyboard as an input multiplexer. He connects the outputs of devices, including motion detectors and reed switches, across the contacts for individual keys inside a gutted PS/2 keyboard, so that events around the house cause scancodes to be sent to an Arduino which then processes them to determine the state of each device. Very clever, because it means he can connect about a hundred sensors to an Arduino using only two digital I/O lines and an old spare keyboard! You can find out more about Penroses’s home automation work at his web site, linux.dd.com.au/wiki/Rainbow_House.The basic example sketch provided on the Practical Arduino web site simply watches for keypresses and sends them straight on to the serial connection so you can see them using the Serial Monitor mode in the Arduino IDE. It starts by including the PS2Keyboard library, then defines which pin to use for the DATA pin connection. We don’t have to define the CLOCK pin connection because it’s hard-coded inside the library to use Arduino digital I/O pin 3 so it can trigger an interrupt defined by the library. 74 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT #include <PS2Keyboard.h> #define DATA_PIN 4 Next, it creates a PS2Keyboard object simply called “keyboard.” This is the object that our sketch will use to interact with the PS/2 keyboard. PS2Keyboard keyboard; The setup function configures the keyboard object by telling it which Arduino digital I/O pin to use for the PS/2 DATA connection. It then sets up a serial connection to the host and announces that it’s alive. void setup() { keyboard.begin(DATA_PIN); Serial.begin(38400); Serial.println("Initialised PS/2 reader"); delay(1000); } The main program loop checks the event buffer in the keyboard object to see if there are any keypress events queued up for processing. If there are, it calls the keyboard.read() method to fetch the next keypress and stores it in a single-byte variable called “data.” void loop() { if(keyboard.available()) { byte data = keyboard.read(); The keyboard can send either normal alphanumeric keys or special keys such as SHIFT and BACKSPACE. The PS2Keyboard library defines a list of mappings from raw scancodes to these special keys so you can simply refer to the name rather than the scancode. As of version .14 of the library, the special key codes it supports are as follows: PS2_KC_BREAK PS2_KC_ENTER PS2_KC_ESC PS2_KC_KPLUS PS2_KC_KMINUS PS2_KC_KMULTI PS2_KC_NUM PS2_KC_BKSP The example sketch checks the key value for matches against each of these special keys and displays appropriate output. if(data == PS2_KC_BREAK) { Serial.print("[BREAK]"); } else if(data == PS2_KC_ENTER) { Serial.println(""); } else if(data == PS2_KC_ESC) { Serial.print("[ESC]"); } else if(data == PS2_KC_KPLUS) { 75 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT Serial.print("+"); } else if(data == PS2_KC_KMINUS) { Serial.print("-"); } else if(data == PS2_KC_KMULTI) { Serial.print("*"); } else if(data == PS2_KC_NUM) { Serial.print("[NUMLOCK]"); } else if(data == PS2_KC_BKSP) { Serial.print("[BACKSPACE]"); } else { If the check makes it through to this point it means the keycode hasn’t matched any of the known special keys, so the sketch then prints it directly to the host. Serial.println(data, HEX); } } } Load up the sketch, compile it, upload it to your Arduino, make sure your keyboard is plugged in, and activate the serial monitor in the IDE at 38400bps. Pressing keys on the keyboard should then cause the matching value to be sent through to your computer and displayed in the IDE. Mouse Software Just as with the keyboard example, our mouse example uses a library to do most of the heavy lifting so that the sketch itself can be very small and simple. The PS2Mouse library needs to be downloaded and installed into your Arduino environment. A link to the latest version of the library is included on the project page on the Practical Arduino web site, so grab a copy and make sure the library folder is named “PS2Mouse” (rename it if necessary) and is placed inside the libraries folder in your sketchbook directory where your Arduino environment can see it. The example sketch first includes the PS2Mouse library, then defines which pins will be used for the CLOCK and DATA connections as per the wiring on your shield. #include <PS2Mouse.h> #define MOUSE_DATA 5 #define MOUSE_CLOCK 6 Next the sketch creates a PS2Mouse object simply called “mouse,” and passes in the defined CLOCK and DATA pin values as the first and second arguments. The third argument sets the mouse mode to STREAM, which tells the mouse to send updates to the host whenever there are values to send. The other mode supported by the PS2Mouse library is REMOTE, in which the mouse only sends updates in response to requests from the hosts. PS/2 mice also support a third mode called ECHO in which it simply echoes back any values sent to it, but that mode isn’t very useful unless you’re testing the mouse so the PS2Mouse library doesn’t implement it. PS2Mouse mouse(MOUSE_CLOCK, MOUSE_DATA, STREAM); The setup function is trivial. It just opens a serial connection to the host to report the X and Y values from the mouse, and calls a special method called “initialize()” on the mouse object. Calling initialize() 76 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT forces the library to set up the I/O lines appropriately and then send a reset command to the actual physical mouse so it will start sending data. void setup() { Serial.begin(38400); mouse.initialize(); } The main program loop is also quite simple. It starts by defining a three-element array to hold the mouse status and X/Y movement data, then calls the report() function and passes in the array. The report() function then performs some magic within the library to talk to the mouse and populates the array so the values can be accessed by the program. void loop() { int data[2]; mouse.report(data); Next the sketch sends the status value to the host, followed by the X and then the Y movement values. Serial.print(data[0]); Serial.print(":") Serial.print(data[1]); Serial.print(","); Serial.print(data[2]); Serial.println(); delay(200); } Connect a mouse to your shield, load up the sketch in the Arduino IDE, compile and upload it, and open the serial monitor with the baud rate set to 38400bps. You should then see a stream of values that change as you move the mouse around. The X and Y values should be fairly obvious, but the status value can be very useful as well. It’s a bitwise representation of the state of various things in the mouse including the sign bits for the X and Y values and the state of the three buttons, so by processing the status value it’s possible to detect mouse button presses. Each bit in the status byte represents something specific. Bit 3 is always set high so the status value will always be at least 8, or a binary value of b00001000. The left mouse button asserts bit 0, the right mouse button asserts bit 1, and the middle button asserts bit 3. This should be fairly obvious if you hold the mouse still and click the left mouse button while running the previous sketch and watching the serial console, because the status value will increase from 8 to 9. Clicking the right mouse button sets the status value at 10, and the middle mouse button puts it at 12. Clicking the left and right buttons together sets it to 11, and so on. The meaning of each of the bits in the status byte is given in Table 5-4. 77 CHAPTER 5  PS/2 KEYBOARD OR MOUSE INPUT Table 5-4. Status byte values Bit 7 6 5 4 3 2 1 0 Value 128 64 32 16 8 4 2 1 Purpose Y overflow X overflow Y sign bit X sign bit Always high Middle button Right button Left button A bitwise comparison of the status byte can, therefore, tell you whether any of the buttons are currently being pressed. Checking for a specific bit can be done using the logical “&” bit comparison operator and an appropriate mask value that sets only the bit you want to check. For example, to modify the previous example sketch to report when buttons are pressed you could add the following lines right before the delay(200) at the end of the main loop. if(data[0] & 1) { Serial.println("Left"); } if(data[0] & 2) { Serial.println("Right"); } if(data[0] & 4) { Serial.println("Middle"); } You’ll then see the effect of clicking the buttons reflected in the serial monitor. Using a mask value of 1 sets bit 0, a mask value of 2 sets bit 1, and a mask value of 4 sets bit 2, all neatly matching up with the status byte valuess shown in Table 5-4. Most of the time you won’t care about the other bits in the status byte, but something to be careful of is getting updates from the mouse quickly enough to prevent the X and Y values from overflowing the buffer. The previous example sketch has a delay(200) at the end of the main loop so that as you’re watching the serial monitor you get a chance to see what the numbers are, but if the mouse is moved very fast you might find it overflows one of the axis values and sets the matching overflow bit. You can check for this situation by adding the following lines just before the delay(200) and watching the serial monitor while you zip the mouse around really fast. if(data[0] & 64) { Serial.println("X OVERFLOW"); } if(data[0] & 128) { Serial.println("Y OVERFLOW"); } If you’re using the mouse to sense motion on something like a robot it’s unlikely that it would move fast enough to overflow, but if your sketch spends a lot of time busy doing other things and doesn’t process the mouse data very often you might need to pay attention to the overflow bits and restructure things to decrease the time between samples. 78 . protocol for reading keypresses from a keyboard is taken care of by an Arduino library called PS2Keyboard. The latest version of the library is linked to from the project page on the Practical Arduino. provided on the Practical Arduino web site simply watches for keypresses and sends them straight on to the serial connection so you can see them using the Serial Monitor mode in the Arduino IDE breakaway male headers and a piece of prototyping board. Techniques for building DIY shields discussed in Chapter 16 are perfect for projects like this where you have a small number of parts and a

Ngày đăng: 03/07/2014, 20:20

Từ khóa liên quan

Mục lục

  • Prelim

  • Contents at a Glance

  • Contents

  • About the Author

  • About the Technical Reviewers

  • Acknowledgments

  • Introduction

  • Introduction

    • Fundamentals

    • Sharing Your Work

    • Practical Electronics for Software Developers

      • Current, Voltage, and Power

      • Mains Is Nasty

      • Reading Schematics

      • Resistance and Resistors

      • Ohm’s Law and Current Limiting

      • Choosing Wire

      • Diodes

      • Power Supplies

      • USB Power

      • Batteries

      • Wall Warts/Plugpacks

Tài liệu cùng người dùng

Tài liệu liên quan