Skip to content

kevinnassery/pybtmeter

Repository files navigation

BTMETER Python Decoder

This is a python decoder for BTMETER BT-90EPC (and others) implemented by Kevin Nassery of RTXSecurity.

About

The BTMeter is an inexpensive multimeter that provides an RS232 mechanism via a USB FTDI cable. The meter speaks an RS232 protocol that correlates bits to the various LCD segments. btmeter

Reference material

There is a windows application, but I had no windows machine for testing so I used trial an error and then was eventually able to make sense of the brief description of the protocol provided by Voltcraft.

"Message" format

Initially, it was unclear to me how to determine the boundaries of the 14-byte message as there is no 'sync/start/stop' sequence.

Other serial decoders for older Voltcraft multimeters I looked at leveraged a delay from the meter to sync, however, my meter generated a regular stream of bytes.

Eventually, I understood that the protocol used an ordering mechanism with the first hex digit of each byte to indicate it's placement in the message. This means you can scan for a "1" to find the first "segment" of the 14-byte message or an E for the last byte.

A few points of clarity regarding that description:

  • "Segments" means individual bytes of the 14 byte message.
  • "COM4->1" describes 4 bits (the second digit). Each nibble is 1 if "high" and 0 if "low" and each bit corresponds to a physical LCD segment element.
  • It's unclear what PINs are.

The most relevant usage of these two terms is in the message description:

pdu

  • It's unclear what the first "4" greyed segments are,or PINS for that matter. Perhaps an older VC RS232 implementation used these.

The documentation described this as: 1X1,2X1,..EX1

-at first- I thought that indicated a multiplication rather than a concatenation. It is in fact, concatenation.

For example a byte: 0x17 is broken into two parts: 1 indicates the start of a message and segment 1

7 then provides 4 bits of details "known as coms" which are "1" if that part of the LCD is energized and "0" if not.

A more useful PDU model might be:

sequence + data bit view

0 1 2 3
0001 ABCD 0010 ABCD 0011 ABCD 0100 ABCD
0101 ABCD 0111 ABCD 1000 ABCD 1001 ABCD
1010 ABCD 1011 ABCD 1100 ABCD 1101 ABCD
1110 ABCD

Where each left nibble corresponds to a "segment" aka byte id of the 14 byte message and ABCD is a nibble mapping to LCD segments as described above as "COM4-1."

Byte "1" bit A for instance maps to the polarity indicator "-" represented above as <S>.

Based on known the map of LCD positions (provided above) you can decode the "screen" for logging or bench analysis:

lcd

The image above describes 4 digits of a seven segment LCD display with each segment lettered A-G (as notated) on digit 1.

For example a 0 in a 7 segment LCD has all elements energized except the "G" element so it could be described as "1111110" given string ABCDEFG. This is essentially what the Voltcraft protocol does, but the bits are scattered around the array and you have to collect them to decode the digit:

  self.digit4 = getdigit(
                        "%s%s%s%s%s%s%s" % (
                        signals[7][3],
                        signals[8][3],
                        signals[8][1],
                        signals[8][0],
                        signals[7][1],
                        signals[7][2],
                        signals[8][2])
                )

This code above does just this, it's plucking the correct bits for a digit and sends it to a function that will return the number that corresponds. The correct bits are notated above as A1 which resides at COM1 of Segment 8. In the signals array that is the 7th element, and COM1 is the 4th bit. Again, I don't know why the call these "COMs." There is very little text provided in the pdf.

Serial interaction is done using Pyserial which seems quite good.

ser = serial.Serial(
    port='/dev/cu.usbserial-221320',
    baudrate=2400,
    timeout=0,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    dsrdtr=True,
    rtscts=False,
)
  • You will need to adjust the device to your com port.
  • These devices use 2400 baud.
  • Some folks reported RTS off and DTS on being important.
  • Timeout indicates that the serial read will "block" until a byte is found. This worked well in testing.

Conclusions

I specifically purchased the BTMeter as an inexpensive way to "log" measurements over time. Alternative solutions exist such as building a custom monitor from an arduino and ADC but ADC ranges are limited, so a voltage divider circuit would also be necessary in many applications.

Advanced instruments like an Analog Discovery 2 also provide good telemetry but there are many situations where leaving one for logging might not be viable.

In addition to the BTMeter, several instruments are also available such as a clamp AC/DC ammeter.

Usage

usage: meter.py [-h] [--port PORT] [--baud BAUD] [--samples SAMPLES]

Decode RS232 Voltcraft protocol.

options:
  -h, --help         show this help message and exit
  --port PORT        Serial port to read from
  --baud BAUD        Baud rate to use
  --samples SAMPLES  Number of readings to take

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages