How to add data from a TP9605BT multimeter to apcupsd rrd and graphs.

WARNING: All liability is yours: this procedure involves handling of potentially lethal electrical currents.

This describes how to add Voltage Output data to the apcupsd RRD database.
I did this because the APC BackUps ES-500 I have does not report a value I was interested in: “OUTPUTV - The voltage the UPS is supplying to your equipment” ( http://www.apcupsd.org/manual/manual.pdf ).

The plan was simple:

  • Get a multimeter that could output voltage readings to my router.
  • Add the readings to the apcupsd RRD database.
  • Verify the readings appear in the appropriate graph.

I found a multimeter that worked and was cheap enough, the Tekpower TP9605BT ( This an affiliate link from Louis Rossmann's work with this meter at: Multimeter Overlay in OBS ).

The physical attachment of the multimeter involved:

  • Connecting the meter's USB cable to the router USB, which further required a small USB hub.
  • Experimenting until I found the correct button-press combination that put the meter into always-on mode.
    • The documentation had an incorrect sequence.
    • The correct sequence is: hold down the [Range] button while turning on the meter.
  • Switching to probes that would stay in a mains socket
  • Cobbling up a 9 volt battery eliminator.
  • Making sure I used the same circuit on the battery-backed-up side of the UPS for both the meter probes, and the battery eliminator. This minimizes the chances of a ground loop destroying the multimeter.

The next step was to establish communication between the meter and the router:

  • opkg install kmod-usb-serial-ch341
  • Make sure the communication worked.
  • Write some code that periodically took a value from the meter, and dumped it in the apcupsd RRD database.

From looking at logread, I determined that the meter's port is on /dev/ttyUSB0. So, I did:

# cat /dev/ttyUSB0

and got some very reasonable results:

+1227 3)�

+1227 3)�

Now, came the analysis part. The “)?” characters tell us what range the meter is set to. This didn't matter to me in this application, because I already knew the settings.

  • “+1227” are the numbers on the meter display.
  • “3” is where to put the decimal point.
  • So, “+1227 3)�” = 122.7 Volts AC.

Below is some code I whipped up. I'm sure it can be improved. Note that it has custom locations for the RRD files, and the port for the meter.

I added these lines to the crontabs/root:

# get AC Volts from the multimeter once every minute
*/1 * * * * /usr/share/bobvolts_TP9605BT_usb.sh

This runs the program every minute, and seems to work well when I look at the graph:

Now for some cleanup. Add this line to /etc/sysupgrade.conf, which preserves this new script across upgrades:

/usr/share/bobvolts_TP9605BT_usb.sh

And, here is the script, to add to /usr/share/bobvolts_TP9605BT_usb.sh:

##!/bin/bash

# bobvolts_TP9605BT_usb.sh, Copyright 2017 Bob Meizlik, license: CC Attribution-Noncommercial-Share Alike 3.0.
# All liability is yours: this code presumes handling of dangerous tools and electricity.
#
# Purpose:
# Collect and store AC Voltage Output readings, when your UPS does not. 
#
# Usage:
# Connect your meter appropriately, to the output AC of the UPS, and the (USB or RS232 or Bluetooth) of your computer or access point.
# Hold down RANGE button, and turn meter on, to defeat the auto-power-off timer.
# Set meter range to Volts, AC.
# Set meter to RS232 output (this enables, RS232, USB and Bluetooth)
# Install drivers 
# Set this script to run periodically, perhaps with a cron script, or a daemon.
#
# Code Process:
# Get AC Voltage readings from a TekPower TP9605BT multimeter, and 
# send them to the apcups, collectd RRD file meant for these readings.
# 
# get the latest voltage reading from a TekPower TP9605BT multimeter
# set to AC Volts range
# set to RS232 output
#
# We get 4 readings per second.
# each reading is 14 bytes long
# the lines look like this: 2b 31 32 31 38 20 33 29  20 20 80 20 0a 0a 2b 31  |+1218 3)  . ..+1|
# if we start in the middle of a line, ignore the line, and go to the next line, which is presumably complete.
# the x0a characters look like new lines in this processing, resulting in a data line that is 12 bytes long.
#
# Known issues:
# The input will hang, when there is no device at /dev/ttyUSB0.
# The input will hang, when the meter is turned off.

inputfile="/dev/ttyUSB0"

rrdfile="/mnt/share/tmp/mydigitemp.rrd"
rrdfile="/mnt/share/stats/rrd/g70outside/apcups/voltage-output.rrd"
# todo: get the rrdfile name from /etc/config/luci-statistics option DataDir '/mnt/share/stats/rrd'

# translate 0 to space, because the length is our checksum
dat=$(dd bs=1 count=50 if=$inputfile | tr \\000 \\040 )

line1=$(echo -en "$dat" | sed --quiet '1p')
line2=$(echo -en "$dat" | sed --quiet '2p')
line3=$(echo -en "$dat" | sed --quiet '3p')

line1len=${#line1} 
line2len=${#line2}
line3len=${#line3}

# todo, this would be nicer if it was a loop
if [ 12 -eq "$line1len" ]; then
   theline=$line1
else
   theline=$line3 
fi

# extract the data from the line, and convert it to a form that rrd can use.
set -- junk $theline
val=$2 # the value, like +1234

dec=`expr "$3" : '\([0-9]\)'` # the decimal place, like 3
decp1=`expr 1 + $dec`         # add 1 to get past the sign
theValue=${val:0:$decp1}.${val:$decp1} # put the value together with the decimal place

# generate and run a line like: rrdtool update .rrd $(date +%s):+122.5 
theSeconds=$(date +%s)
rrdcmd='rrdtool update '$rrdfile' ''N:'$theValue   
$rrdcmd
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2018/03/04 07:46
  • by bobafetthotmail