As you may have seen in previous posts, I have this fancy steering wheel on the Go-Kart. It's from a Logitech force feedback steering wheel, it was USB and was meant to be used with a computer for playing video games. One day I decided to take it apart and use it on this go-kart instead. As you can see below, it's got 6 push buttons, 2 LED's, and 2 paddle switches. I'm going to use those for various features on the go-kart.
When planning out this implementation, I had a couple of different options. The first option was, I could run wires back from all of them to the Teensy++ in the rear, pretty much 11 wires (one common ground, 8 buttons, 2 LEDs). This is pretty clearly a bad idea simply because that's a lot of wires to have to route that far.
The next option was shift registers. These are nice, you can use 3 CPU pins to get 8+ outputs, or inputs. And this is great if I were dealing with one or the other. Since I'm doing both, I'd pretty much have to run 8 wires (power, ground, 3 for output, 3 for input), not to mention I don't have the parallel to serial (input) shift register, so I'd have to place an order specifically for one.
The final option, that I decided to go with, was to just put another microcontroller up front IN the steering wheel. I can network it with the one in back via i2c (sometimes called Two wire interface) which is well supported in Arduino. This means I only need FOUR wires.. Power, Ground, Clock and Data.
First up, I needed to get the steering wheel back off and have a look inside. It had been awhile since I looked in there last. Looks like a tight space, but that square cavity in the center is a perfect fit for a Teensy. I have a Teensy++ in the rear controlling the motors and reading the pedals. I had a Teensy hanging around just asking to join his big brother on this go-kart project.
Normally, the Teensy would be used either in a breadboard, or in a CPU socket (22 pin in this case). I have the Teensy++ in a 40 pin socket in the rear. But there just isn't room for a CPU socket and a circuit board in the steering wheel. I also didn't want to solder wires directly to the CPU, if I could avoid it.
Necessity being the mother of invention, this is what I came up with. Digging around in the garage, I cut some cables out of old computer cases. These fit nice and snug onto the pins of the Teensy board, and give me convenient wires to route to the switches.
Fits like a glove into that little center pocket on the steering wheel. And don't worry, if you think that's a rats nest, you ain't seen nothin yet! hehe. It gets worse.
Here it is wired up to the two side boards with the buttons and LED's. Figuring out the pinout was a breeze, the boards are very simplistic. They have a common lead, ground, that goes to every switch and the negative side of the LED. Then 5 more pins clearly go to each item one by one. Had it wired up in no time. You can see I made an effort to keep things tidy, the wires for each side are twisted together.
Here's everything connected and tucked back in. The unused CPU pin wires are left bundled up at the top, for future use. I plan to put a dual 7 segment LED display in the middle, maybe a bargraph display too. I did extensive software testing at this point, confirming all the buttons were working as expected, and both LED's worked. We'll get to the code in a minute though.
At the bottom of the above picture you can see a white plastic "thing". That's a telephone jack. I decided to go with phone cord, it's got 4 conductors, it's designed to be flexible (allowing the steering wheel to rotate back and forth), and it's easy to get.
Here's the phone cord coming out the bottom/side of the steering wheel. I drilled a hole JUST big enough to get the connector through, it goes in and plugs into that jack. When I install it back on the kart, I'll post pictures of how it routes on there, and how it looks.
And yes, the cover fits back over top of everything, despite the rats nest within. Hides it nicely, really. And no, I do not have ready access to the USB port on the Teensy to reprogram it. I will make sure it's communicating properly with the rear before I bolt the steering wheel on.
Now on to the code I wrote for the steering wheel:
I'm mighty proud of this code. I think it's a very elegant and efficient way of handling the buttons. I commented it pretty thoroughly, so you should be able to follow it. But let me give you a bit of a quick summary. There are 8 buttons on this steering wheel, the 6 push buttons, and 2 paddles. There are 8 bits in a byte. i2c sends one byte per packet, so I decided to just send all of the button states in one simple packet. This required using what are called "bitwise" operands to manipulate one bit at a time without touching any of the other bits. So it checks each button, if that button is pressed, the particular bit that that button is assigned to will be set high, otherwise it's set low. The paddles are persistent, so when one is pushed, it turns off the other paddle and leaves that paddle high, as I'm using the paddles for forward/backward, and nothing else.
When the rear controller (the master) calls up to this controller (the slave) and asks for the state of the buttons, it simply transmits that one byte with the status of all 8 buttons.
And finally, there's a routine to receive a byte from the rear controller. This uses the two LED's as a direction indicator. The reason I did it this way, is that if you hit the reverse paddle while the motors are being driven, it will ignore the direction change request until you at least get off the throttle.
That's it for now, I have code written to use the data on the rear controller, but I wait to post that along with pictures of the phone cord routing and probably some video of it in action.