The HDMIPi driver board is a fairly complex design. I didn’t design it, although I did have some input into the feature list. I don’t fully understand how it works (something to do with the magic white smoke in the chips, I think), but I have messed around with it probably as much as anyone.
— Göran Roseen (@roseeng) January 12, 2015
…and others want to be be able to do it with time or PIR-sensor control.
Can We Use tvservice? No :(
Some monitors allow you to do this using the “tvservice” command. Whilst this will switch off HDMI output from the Pi, it doesn’t turn off the backlight on HDMIPi, which is the greatest power consumer. (It may be that we can get this into a future version. We’ll see.)
So I got to thinking…
Hold on. We have a power button which can toggle the screen on and off without killing power to the Pi. I know this because it was a feature I wanted in the list. Maybe we could hack that switch and use a GPIO port on the Pi to toggle the screen on and off?
So I decided it would be fun to hack my own product and share the process with you. It took a couple of hours getting this to work. It didn’t work the first time, but I did get it working second time and have now figured out how to make it work well.
Measure Twice, Cut Once
It’s an old carpentry saying, but it applies to a lot of other fields too. Taking good measurements and diagnosing the issue is usually the best first step you can take. I needed to understand what “pressing the power button” actually does, so I could see if I could replicate that with a GPIO port on the Pi.
So I took out my trusty multimeter and made some measurements. I quickly established that pressing the power button shorts one side of the circuit to GND. I also probed the button circuit to see what its voltage was. Higher than 3V3 we’d need a transistor to do the switching for us.
Happily the circuit was 3V3, the same as the Pi’s GPIO ports. Even more happily, the current draw on pressing the button switch was ~0.7 mA. This is small enough that we can just hook a wire straight from the positive side of the button to a GPIO port*. Then if we drive that port LOW it shorts that side of the circuit to GND just like if we pressed the power button. That’s the theory anyway.
I Did Get A Couple Of Things Wrong First Time Though
Initially I completely forgot that the button on the HDMIPi driver board had its own pull-up resistor (explanation here) so I tried to use one of the i2c ports on the Pi. These have their own hardware pullups, so I figured they’d be the best ports to use. The trouble is, when the button +ve side was connected to an i2c port, none of the HDMIPi buttons worked. (I’m not quite sure, but I think the Pi’s pullup may have overwhelmed the 3V3 pullup’s source on the HDMIPi board? WJDK.)
But the buttons worked fine again when the wire was disconnected. So I had a little think and decided to try a different GPIO port. I picked GPIO 25 as it’s the same on all models of Pi and I could route the wire underneath the driver board and Pi and connect from the other side, making the wire almost invisible from outside the case.
I soldered the wire on the underside of board as I could wrap it round the button leg before soldering. This ensured a good connection and easier working. It also helped me keep the hot iron away from the board, reducing the chance of damage or shorting. The GPIO25 end was wrapped firmly round the GPIO25 pin. I used solid-core copper wire (from a reel of Cat 5e ethernet cable). It was removed and squeezed slightly to make it a firm ‘push-on’ connection.
It Worked, But Still No Buttons!
Having switched ports and removed the 1.2k resistor*, my little program started working, switching the HDMIPi on and off. YAY! But I soon realised that, while the program was running, all the HDMIPi buttons (apart from the power button) were disabled. When the program finished, they worked again.
OK. So something is happening here because the port is being used as an output. As soon as it’s reset to an input the buttons all work again.
So that was the solution. I tweaked the software so that GPIO 25 is only set up as an output while it’s being used to toggle HDMIPi on or off. The rest of the time it’s set up as an input. This means that the HDMIPi pullup resistor and 3V3 source are not overwhelmed (if that’s what’s happening) and are able to perform correctly.
And now BINGO – it all works just as it should :)
Here’s A Video Showing It In Action
Here’s The Python Code
#!/usr/bin/env python2.7 # HDMIPi_toggle.py by Alex Eames http://raspi.tv/?p=7540 import RPi.GPIO as GPIO from time import sleep GPIO.setmode(GPIO.BCM) GPIO.setup(25, GPIO.IN) # If 25 is set as an input, the hardware pullup on the HDMIPi board # keeps value at HIGH. We only change the port to an output when we # want to toggle the button. # This is because, when set as an output, the HDMIPi buttons are disabled. # So each time we toggle the HDMIPi on or off, we set port back to input def toggle(): GPIO.setup(25, GPIO.OUT, initial=1) GPIO.output(25, 0) # this is our simulated button press sleep(0.2) # hold button for 0.2 seconds GPIO.output(25, 1) # release button GPIO.setup(25, GPIO.IN) # set port back to input (re-enables buttons) for x in range(3): # on for 10s, off for 5s iterate 3 times print "HDMIPi will stay on for 10 seconds" sleep(9) print "HDMIPi is switching off for 5 seconds" sleep(1) toggle() #off sleep(5) toggle() #on print "finished, cleaning up" GPIO.cleanup()
You could condense the code a bit, but I’ve left it like it is so it’s clear to see how it works. For example, this version of the toggle() function works equally well…
def toggle(): GPIO.setup(25, GPIO.OUT, initial=0) # simulate button press sleep(0.2) # hold button for 0.2 seconds GPIO.setup(25, GPIO.IN) # set port back to input (re-enables buttons)
That’s The Basics, Now Make It Your Own!
Obviously this shows just the basic “ON/OFF” functionality. You should probably make it more robust with some exception handling (try: except: finally:) to trap unexpected errors and problems that may arise.
Apart from that, its applications are virtually unlimited. You could use this technique with…
- a cron job for timed switching
- a doorbell and camera
- a twitter app
- a kickstarter tracker
- PIR sensor to detect people
- Light sensor or any other sensor
- An ADC circuit to measure battery voltage and kill power to the screen when battery is low
You Could Even Hack The Other Buttons
While I was writing this article I had a “wow” moment. I realised that if we hacked all the control buttons we could have a programmatically driven OSD menu system. I don’t know if that will ever happen, but it’s nice to think that it could be done. I doubt if I will do it, but anyone who needs or wants it could, if they wanted to. Hackable products for the win!
Will It Affect My Warranty?
I just know that someone will ask that, so I’m pre-empting the question. If your HDMIPi driver board breaks because you have interfered with it, it would be unreasonable to expect a free replacement. But if you know what you’re doing and solder carefully, using the button leg, as I did, there shouldn’t be a problem. (And if there is, we can sell you another one for something in the region of £20.)