ATtiny Mario handset
This is part 2 of my ATtiny Mario project - part one is here - a Mario-type game I made for the ATtiny85 AVR as a fun way of learning about the chip. After writing the software, I decided I wanted a nice housing for the mass of wires on my breadboards and thought it would cool to put it into a NES-style controller, which is what this post will discuss.
To re-cap briefly, this was a project where program memory and SRAM constraints were constantly on my mind. The limited GPIO pin of the ATtiny85 also offered unique challenges, and a brief summary of the project highlights are below:
- Dual screen scrolling action! Two independently addressed screens run at once, using fast OLED I2C bit banging.
- Simultaneous music and sound effects using Timer0 and Timer1 and a hacked micros() type function implemented.
- 6 digital buttons on two GPIOs, including the RESET pin.
- Fuse settings to internally clock at 16 MHz without a crystal; saves 2 GPIOs
- Procedural level generation
- Jumping, shooting and platforming fun! Bad enemies spontaneously generate off screen and walk around the landscape.
and the software write up is discussed in more detail than you could want here:
For you impatient types, here's the whole thing in action:
I picked up an NES-style USB controller cheaply - no original controllers were harmed in the making of this hack! After unscrewing the back, rather than solder onto the existing PCB, I elected to design a replacement PCB. Given the cost of having a fabrication house run off a custom PCB these days, it was easier than trying to cram everything into the controller and I could position things where I wanted. I also added a volume controller wheel on the board for extra points!
Schematic
The schematic is shown below, and is fairly simple. The ATtiny outputs two tone signals (SPEAKER and SPEAKER2), which are combined with a transistor OR gate, and passed onto the speaker via a wheeled volume control. This is probably overkill and a diode or two might have sufficed. Resistor ladders allow multiple button presses, 3 on the RESET pin and 3 on PB3. In retrospect, the way the controller is used, is to have either left or right held down, with or without jump or fire pressed - rarely other combinations. I could therefore have used a simpler resistor design with a larger dynamic range of ADC signal, but my method allows a way to detect all combinations of button presses and is robust.
Finally, the I2C SCL and SDA signals are broken out, along with VCC and GND, and there is room on the PCB for a wheel volume controller. The interlaced PCB buttons are a quite useful custom part, measured from the original controller PCB.
The PCB - solving a ground plane problem
The PCB is simple and worked pretty much as desired. The button pads lined up nicely with the buttons and I managed to avoid the screw holes and internal parts of the controller.
The biggest problem I came across with was with the button pads - whenever I pressed a button I would get readings that seemed to vary with pressure. I reasoned that since the rubber pad of the buttons had a resistance of 100 Ohm over a few mm, that making more contact with more pressure would in effect change the resistance. This would be useful if I didn't have 3 buttons on the same pin, but otherwise made button deconvolution difficult! To mitigate it therefore, I coated the rubber button pads with adhesive-backed aluminium tape. This time, when some buttons were pressed, the ATtiny85 reset itself! What was going on?
The biggest problem I came across with was with the button pads - whenever I pressed a button I would get readings that seemed to vary with pressure. I reasoned that since the rubber pad of the buttons had a resistance of 100 Ohm over a few mm, that making more contact with more pressure would in effect change the resistance. This would be useful if I didn't have 3 buttons on the same pin, but otherwise made button deconvolution difficult! To mitigate it therefore, I coated the rubber button pads with adhesive-backed aluminium tape. This time, when some buttons were pressed, the ATtiny85 reset itself! What was going on?
The resets were only occurring on buttons that used the RESET pin. This pin is pulled high by a 1k resistor and pulled to GND by a 10k, 22k or 47k resistor (and combinations therefore). This shouldn't cause a problem as RESET is never pulled more than 10% below Vcc, and worked fine on a breadboard. I realised there was a problem with these pads though - the GND plane had been allowed to fill between the interlaced fingers of the PCB button pad, meaning that Vcc and GND are next to each other... when the button pads were pressed, Vcc and GND were effectively connected, the power was shorted, and I was lucky not to break my chip! My work around was to drill two holes in the PCB to isolate the connection between GND plane and the GND in the PCB button pad. There was also a *sliver* of GND plane beside the PCB buttons, which I guarded off with black tape. This solved my reset problems and the button presses could be read robustly and reliably!
Non-conductive black tape was added to the sides of the button, to protect against contact with a thin slice of the GND plane. It's not pretty, but it saved me from having to re-design and re-fabricate the boards, so it counts as a useful hack in a my book!
I have since learned that by drawing a box on the tRestrict layer around the PCB button, I can stop the GND plane from encroaching into the button and causing this problem in the future.
The ground plane had in-filled into the PCB button pads, so had to be isolated by drilling away the connecting copper. Note the thin slice of the GND plane to the sides of the button pads too, particularly noticeable on the left hand side.
Non-conductive black tape was added to the sides of the button, to protect against contact with a thin slice of the GND plane. It's not pretty, but it saved me from having to re-design and re-fabricate the boards, so it counts as a useful hack in a my book!
I have since learned that by drawing a box on the tRestrict layer around the PCB button, I can stop the GND plane from encroaching into the button and causing this problem in the future.
The NES-style controller housing
As you can see in the images below, a panel was cut in the controller for 2 OLED screens to be placed side-by-side. On the back, the ATtiny85 chip is seen, along with the speaker. Perhaps I could have included an ISP programming port for the AVR, but the OLEDs use the same pins and I would have needed to add some programming-selector switch for which I had little appetite to add - easy enough to just remove the thing, but potentially tedious to have to develop in this way.
Forgive the slight ropey nature of the final product! On the back you can see the ATtiny85 for relatively easy removal for programming, and the speaker poking out :-)
So there you have it! I learnt a load about the ATtiny85 through this project and having the constraints in this small AVR definitely forced me to think creatively. I'll be happy to reach for this chip again, but for a similar project in the future, I think I'll elect to go for more GPIOs, more memory and more firepower!
As always, let me know if you have any questions, find my stuff interesting, in the comments below!
Comments
Post a Comment