The Hermes 3000 is back! Sorry for the delay but here is my 2nd post showing my progress on the upcycled typewriter project.
As stated in my introduction post, my initial idea was to place some sort of photo-interrupters under the keys to detect which key was being pressed. However, I soon realized that this could not fit under the top row of the keyboard . So, I decided to go with a more basic approach. I removed the front cover of the typewriter (usually you remove this to change the ribbon). I also removed the carriage (the part that holds the paper) and the ribbon because they were getting in the way. This is what was underneath:
Another view with me lifting up some of the "arms" (I don't know what they are actually called in typewriter lingo):
You can see there are a lot of moving parts inside. When I press a key on the keyboard, one of those many arms will swing up and smack the ink onto the paper giving it a nice clickety-clack sound. However, when I am not pressing any keys, all 44 of those arms rest on that curved black piece. Since the arms are all metal and that curved black piece is some sort of rubbery foam, I decided to add small strips of conductive material onto the black foam part and basically create a lot of "normally-closed" switches.
Here's how the connection is made: each arm is already physically connected to the typewriter chassis. I can connect the chassis itself to 5v. Then, I will wrap some conductive material around the bar that the arms rest on. I will need to ensure that each "strip" of conductive material is in direct contact with the typewriter arm when the arm is down. Also, I need to ensure each strip is not touching the one next to it. All the strips will be individually wired through a 100k pulldown resistor to ground and also to an input on the Intel Edison. The 100k value was selected because if you place 44x100k resistors in parallel the overall resistance is about 2.2k. So the Edison will see 5v at each input and when I press a key, an input will go low.
So that was my basic idea for how to detect key presses. Sounds easy enough, right? Wrong. Turns out there are many issues with this design! First of all, what conductive material could I place that is thin enough to fit next to each other without touching each other? At first I tried wrapping copper wire around the rest bar but there isn't a lot of room to move my hands around it so this was impractical. Next I tried using conductive tape but the tape didn't stick well and it got fairly difficult to even try. Eventually I realized something that would save me... It turns out I can remove that black foam part! It isn't glued in place and because it is foamy it can compress enough to escape the holds of that metal bracket underneath. Wait did I say metal bracket? Yea, that's another problem. If the bracket is metal then I need to ensure my conductive strips aren't touching that either or else they will all short together and the Intel Edison won't know which key is being pressed.
So finally I came up with this: I removed the black foam piece, wrapped 44 small lengths of copper wire around it but spaced each out enough so they weren't touching. Then I covered the metal bracket with black electrical tape. In the end it looked like this (warning, it ain't pretty):
Looks like a mess right? Don't worry, it's not finished yet. I will attach a wire to each copper "winding" and then trim off the excess copper that you see sticking out. Once I finish that, it will be just some loops of copper around the black foam with wires coming off each loop. Each wire will go back to the Edison's GPIO. Although there will be 44 wires and the Arduino breakout board doesn't have 44 GPIO's.... Hmm....
This brings me to my next step. I will use some parallel-in/serial-out shift registers to allow the 44+ inputs to be read by the Edison. As for the inputs, there are 44 arms plus the shift key, space bar, backspace, carriage return, and a "send email" button. This means I can get away with using 6 8-bit PISO shift registers. That's 3 GPIO's for control, 6 for data, plus I will dedicate one GPIO to the shift key and one to the "send email" button. That brings the grand total to 11 GPIO's, which the Arduino breakout board can manage!
Since reading from shift registers is time-sensitive and the host CPU may be busy doing other things, I needed a microcontroller to deal with the registers. I initially was going to use an Arduino to control the shift registers and then have the Arduino tell the Edison which key is being pressed. However, I then learned that the Edison has its own MCU that can talk to the host system. I started experimenting with sending data between the MCU and the host CPU and got a very simple test program working (just something where the MCU turns on an LED when the host system sends it a command). Eventually I managed to get the MCU to read data from a shift register and send it to the host when the host requested it. But unfortunately it doesn't work quite right. Check out my MCU code below:
#include "mcu_api.h" #include "mcu_errno.h" //Data pins are the serial data coming from //shift registers. int data1 = 128; //IO2 //int data2 = 12; //IO3 //int data3 = 129; //IO4 //int data4 = 13; //IO5 //int data5 = 182; //IO6 //int data6 = 48; //IO7 int led = 48; //FOR TESTING PURPOSES //Control signals for shift registers. int SH_LD = 49; //IO8 int CLK_INH = 183; //IO9 int CLK = 41; //IO10 //For receiving a "command" from the host system. //Right now there are no commands unsigned char cmd[255]; unsigned char result[1] = ""; /* * See datasheet for proper operation of shift * register (74HC165). */ void shift_in(int data_pin){ //Assign initial value to result. //Result is 8 bits representing the parallel inputs of register. //unsigned char result = 0; //Load into register gpio_write(SH_LD, 0); gpio_write(SH_LD, 1); //Turn off clock inhibit gpio_write(CLK_INH, 0); //Get data from register int i; for(i = 0; i < 8; i++){ //Cycle the clock gpio_write(CLK, 1); gpio_write(CLK, 0); //Shift data in result[0] <<= 1; result[0] |= gpio_read(data_pin); } //Turn clock inhibit back on gpio_write(CLK_INH, 1); } void mcu_main() { gpio_setup(data1, 0); gpio_setup(SH_LD, 1); gpio_setup(CLK_INH, 1); gpio_setup(CLK, 1); gpio_setup(led, 1); //FOR TESTING gpio_write(CLK_INH, 1); gpio_write(CLK, 1); gpio_write(SH_LD, 0); gpio_write(led, 0); //FOR TESTING while (1){ if(host_receive(cmd, 255) > 0){ gpio_write(led, 1); //FOR TESTING mcu_sleep(100); //FOR TESTING gpio_write(led, 0); //FOR TESTING shift_in(data1); host_send(result, 1); result[0] = 0; } } }
Here's how it works: The MCU has a character called "result". A character is 8 bits long and I am trying to read in 8 bits at a time. When the host CPU sends a "command" (which is just any text, there is no command checking yet) then the MCU will call the "shift_in" function (starts at line 34) and will then send the result back to the host. In the shift_in function, I am basically making my control pins do what is necessary to read the serial data and shift this data into "result". I made this based on the timing diagram provided in the datasheet.
This mostly works. If I log into the host CPU, start a python session, open the file "/dev/ttymcu0" and write a character to it then I will get back a byte that is supposed to represent the 8 bits of the shift register (and for testing purposes right now those 8 bits are manually set, they are not connected to the typewriter yet). However, I have noticed that it seems like I am shifting the bits in one bit too far. When I am expecting a 01100110, I receive a 11001100 which is the expected result but shifted 1 bit to the left! I am not sure why this is happening so I will have to continue troubleshooting, but if you see an obvious reason then please let me know . EDIT: This has been resolved, thanks to jc2048 for helping me figure this one out! See the comments section for more details.
Here's a schematic showing how the shift registers will connect to the typewriter and Edison:
And that's where I am now. Here's what I still need to do for the key-detection mechanism:
- Attach wires to the copper coils, trim the coils.
- Fix this darn shift register problem
- Wire the copper coils to the shift registers
- Finish the programming so the Edison knows which key is being pressed when a specific bit goes low
Stay tuned next week for the continuation of this project! Let me know if you have any questions, comments, concerns, or criticisms.
Top Comments