2012-09-23

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 :

  1. su to become root
  2. mux pin 14, just to be sure:
    echo 6 > /sys/kernel/debug/omap_mux/gpmc_a2
  3. 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
  4. set the period frequency to 100 (this is the 'pulse' ins Hz):
    echo 100 > /sys/class/pwm/ehrpwm.1:0/period_freq
  5. start the PWM pin running:
    echo 1 > /sys/class/pwm/ehrpwm.1:0/run
  6. 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

#!/usr/bin/env python2
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:
  open("/sys/kernel/debug/omap_mux/gpmc_a2","w")
  f.write("6")
  f.close()
except Exceptione:
  print e.message

def set_runval ):
  try:
    open(run,"w")
    f.writestr(val) )
    f.close()
  except Exceptione:
    print e.message

def set_duty_percent(val):
  try:
    open(duty_percent,"w")
    f.writestr(val) )
    f.close()
  except Exceptione:
    print e.message

def set_period_frequency(val):
  try:
    open(period_freq,"w")
    f.writestr(val) )
    f.close()
  except Exceptione:
      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 statusheaderstext
      
  def run(selfenvironstart_response):
    path environ['PATH_INFO']
    statusheaderscontent self.process_requestpath )
    #begin the response
    start_response(statusheaders)
    #return the content
    return content

app my_wsgi_app()
httpd make_server(''8080app.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.

Comments
2012-10-12 Alison Chaiken:
Just curious . . . which kernel version is running? I know, such a boring question, but I'm curious whether it would be a newer one with devicetree, whose pinctrl with PWM is somewhat complex, but prolly implemented by TI for beaglebone.
2012-10-12 jezra:
Kernel 3.2.21
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
2 minus 2
Answer:
required
subscribe
 
2014
2013
2012
2011
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008