Earlier this month, I received a 3V Voltmeter that I purchased on Amazon. The reason for the purchase was so that I could write some code to control the voltmeter from my beaglebone. Well hey! Guess what I finally got around to doing?
Before I get to the code, let me explain how this works, and I'd like to give a big shout out to gigamegablog for being such a great resource.
Controlling the voltmeter with the beaglebone requires a bit of understanding of Pulse-Width Modulation (PWM). The pins on the beaglebone are capable of outputting 3.3V of power. By using PWM we can send the 3.3V of power in pulses, and when these pulses are spaced apart properly, we give the illusion of a lower voltage.
The Pin Layout
According to the beaglebone documentation, pins 14 and 16 of pin header P9 on the beaglebone are PWM pins. It should be possible to use other pins as PWM pins by "muxing" the pins, but for my needs, pin 14 will do just fine.
The positive probe of the voltmeter was connected to pin 14 on P9 and the ground was connected to pin 2 on P9.
The First Test
Since I am runnin Arch Linux on my beaglebone, PWM is not only supported in the kernel, it is also enabled. Rad, that is one less step to take. Thank you Arch Linux!
The test went like this :
- su to become root
- mux pin 14, just to be sure:
echo 6 > /sys/kernel/debug/omap_mux/gpmc_a2 - set the duty_percent to 0 (this is the percent of the 3.3V that we want to emit):
echo 0 > /sys/class/pwm/ehrpwm.1:0/duty_percent - set the period frequency to 100 (this is the 'pulse' ins Hz):
echo 100 > /sys/class/pwm/ehrpwm.1:0/period_freq - start the PWM pin running:
echo 1 > /sys/class/pwm/ehrpwm.1:0/run - start increasing the duty_percent until the voltmeter is at 3V. For me, this was when the duty_percent was 92
Sweet!
Getting Data To Process
Since I didn't want to do any web server configuration in order to get data, I decided to write a very small WSGI app in python and serve it up using the wsgiref.simple_server class.
Enter the Python
from wsgiref.simple_server import make_server
#define some stuff
max_val = 92
pin_path = "/sys/class/pwm/ehrpwm.1:0"
run = pin_path+"/run"
duty_percent = pin_path+"/duty_percent"
period_freq = pin_path+"/period_freq"
#mux the pin
try:
f = open("/sys/kernel/debug/omap_mux/gpmc_a2","w")
f.write("6")
f.close()
except Exception, e:
print e.message
def set_run( val ):
try:
f = open(run,"w")
f.write( str(val) )
f.close()
except Exception, e:
print e.message
def set_duty_percent(val):
try:
f = open(duty_percent,"w")
f.write( str(val) )
f.close()
except Exception, e:
print e.message
def set_period_frequency(val):
try:
f = open(period_freq,"w")
f.write( str(val) )
f.close()
except Exception, e:
print e.message
#set some PWM values
set_run(0)
set_duty_percent(0)
set_period_frequency(100)
set_run(1)
def got_value(val):
val = val.strip("/")
val = int(val,10)
percent = (max_val * val/100)
set_duty_percent(percent)
class my_wsgi_app:
def process_request(self,text):
got_value(text)
status = '200 OK' # HTTP Status
headers = [('Content-type', 'text/html')] # HTTP Headers
return status, headers, text
def run(self, environ, start_response):
path = environ['PATH_INFO']
status, headers, content = self.process_request( path )
#begin the response
start_response(status, headers)
#return the content
return content
app = my_wsgi_app()
httpd = make_server('', 8080, app.run)
print "Serving on port 8080..."
# Serve until process is killed
httpd.serve_forever()
For ease of copy, the code is also available at http://hoof.jezra.net/snip/o3
The code starts serving on port 8080 and sets the percent of the PWM based on the URL used to access the server. For example, to set the voltmeter to 25%, one would need to point a browser at http://NAME_BEAGLEBONE:8080/25. My beaglebone is mounted on the wall and is named "wallbone", yea original. Anyway, if I want to set the voltmeter to 77%, I would access http://wallbone:8080/77
Face to Face
It's a shame that the voltmeter as a big "V" on it, as well as 0, 1, 2, 3, and some useless text.
One would think that I could just take apart the voltmeter, make a compass from a pin and a twist-tie, draw a new face, and re-assemble the meter. Oh, don't mind if I do!
How about some video?
Well... it was far too dark and the pin isn't really visible. What a shame.
http://www.youtube.com/watch?v=ldcwMYj5AIc
http://www.youtube.com/watch?v=SdbBgiZn1UM
Now What?
There are plenty of uses for this meter.
- analog progress or volume meter for muttonchop
- add a few more meters and create a neat clock
With the pulse-width modulation, I could connect and control a fan from the beaglebone.
The possibilities are only limited by my imagination.
Now quit reading, and go send me some ideas.