Reading a Dymo USB scale using Python

For an experimental project I’m working on, I wanted to read the weight from a  DYMO M10 digital postal scale with USB support. I expected the scale to show up as a virtual COM port, since older digital scales used RS232 for their computer interface,but the scale shows up as a USB HID (Human Interface Device) in Windows.

I found Micah Carrick’s site which shows how to read from a MagTek credit card reader in Linux using PyUSB 1.0. Like the DYMO M10, the MagTek reader uses the USB HID device class so the basic method for getting data from the device is the same.

The first step is to install PyUSB 1.0. Unzip the contents of the archive from the PyUSB sourceforge page and run python setup.py install.

Using PyUSB on Windows requires installing a suitable backend such as libusb-win32. After installing libusb-win32, it’s necessary to install a device filter for the scale. Connect the USB scale to the computer and press the power button. Windows should detect the scale and install the device driver automatically. The DYMO M10 shows up in Device Manager as a “USB Input Device” with vendor ID 0922 and product ID 8003.

Using the libusb-win32 Filter Wizard, install a device filter for the scale. It will show up in the list as “vid:0922 pid:8003 rev:0100 USB Input Device”.

Now it’s possible to read data from the scale using the usb module in Python:

import usb.core
import usb.util

VENDOR_ID = 0x0922
PRODUCT_ID = 0x8003

# find the USB device
device = usb.core.find(idVendor=VENDOR_ID,
                       idProduct=PRODUCT_ID)

# use the first/default configuration
device.set_configuration()
# first endpoint
endpoint = device[0][(0,0)][0]

# read a data packet
attempts = 10
data = None
while data is None and attempts > 0:
    try:
        data = device.read(endpoint.bEndpointAddress,
                           endpoint.wMaxPacketSize)
    except usb.core.USBError as e:
        data = None
        if e.args == ('Operation timed out',):
            attempts -= 1
            continue

print data

The data packet is a 6-element array; for example:

array('B', [3, 2, 11, 255, 0, 0])

The 1st element has always had the value 3 in my tests, so I’m not sure what it does.

The 2nd element indicates whether the value is stable.

The 3rd element (value 11 in the example above) is probably a flag byte. The only values I have observed so far are 2 and 11. A value of 2 indicates that the scale is in kg mode, and a value of 11 indicates that the scale is in lbs/ounces mode. Curiously, whenever the scale reads 0, it seems to indicate lbs/oz mode.

Thanks to Daniel Rice (see his comment below), we now know what the 4th element (index 3) is for; it’s for calculating the scaling factor when reading in ounces. In the above example it has a value of 255. This is in fact the signed value -1, which indicates that the raw value is in tenths, due to a scaling factor of 10^-1 or 0.1. For a value of 254, the scaling factor is 10^-2, or 0.01. I’ll refer to this value as scaling_factor below.

The elements at indices 4 and 5 are used to calculate the weight.

In kg mode:

grams = data[4] + (256 * data[5])

In pounds/ounces mode:

ounces = scaling_factor * (data[4] + (256 * data[5]))

If you check the mode, you can just convert to whatever unit you need no matter what mode the scale is in.

DATA_MODE_GRAMS = 2
DATA_MODE_OUNCES = 11

raw_weight = data[4] + data[5] * 256

if data[2] == DATA_MODE_OUNCES:
    ounces = raw_weight * scaling_factor
    weight = "%s oz" % ounces
elif data[2] == DATA_MODE_GRAMS:
    grams = raw_weight
    weight = "%s g" % grams

print weight

The scale is capable of reading negative values if you zero it and then remove the weight, but I haven’t yet figured out how to get negative weight values yet. The scale itself displays the correct value, but the data packet reads as if it were zero, except the second array element has a value of 5 instead of 2.

I also haven’t figured out how to determine when the reading has stabilized. Nicholas Piasecki’s article on reading a Stamps.com USB scale in C# says that the 2nd element in that scale’s data packet reads 4 when the value is stable, but 4 is all I observe when reading a positive non-zero weight value, even when the values are changing rapidly.

I hope this information has been useful to you. If you have any questions or have anything to add, please post a comment!

DRIVE channel made a film about my Fiero project car

A few months back, The Smoking Tire posted a request for interesting local cars and I posted a photo of my car. I guess they liked it, because in late September, Matt Farah of The Smoking Tire and /DRIVE channel spent the day track-testing my Fiero at a Speed District event at Buttonwillow Raceway. They were originally going to film it up Angeles Crest or another canyon road, but I insisted on taking the car out to a racetrack so it could be driven to the limit.

It was awesome seeing my car covered in cameras, and nice to hear that the car was fun to drive from someone who has driven everything from Lamborghini Aventadors to the Hennessey Venom GT.

The resulting footage was turned into full-length 10-minute video on /DRIVE+ for subscribers, and a 5-minute version (not trailer, just a shorter edit) on the free /DRIVE channel.

The videos turned out AWESOME. I didn’t think I spoke well during the interview, but I guess I did alright. With clever editing, I narrate a large portion of the film!

For once I came home from a track day and didn’t have to edit any videos myself!

Here’s the full length version for /DRIVE+ subscribers:

… and the free, shorter version:

Big thanks to Matt, Thaddeus,  Zack and Nino for making the film, to Speed District for hosting the track day, and to my friend Chris for long hours spent helping to make the car ready for a flawless day at the track!

Here are a few pics of my car covered in cameras:

Extended wheel studs for the 1988 Fiero

With aftermarket wheels and/or thicker brake rotors, the Fiero’s stock wheel studs don’t provide much thread engagement with the lug nuts. I found that on the front of my ’88 Fiero I was only getting 8 turns with the C4 12″ rotors and my Motegi wheels. That’s 12 mm of thread engagement on a 12mm stud. Marginal at best. With the 3mm spacers I wanted to add behind my rotors to get some control arm clearance, I would be down to a dangerous 6 turns or 9mm.

I scoured the ARP and Dorman catalogs to find a good candidate. The 1988 front hub holes are about 0.490″ with the stock studs removed. Dorman recommends a hole size between 0.017″ and 0.027″ under the knurl OD, while ARP recommends 0.005″ for iron and steel hugs and 0.007″ for aluminum. It’s not clear why there’s such a big range or difference between the recommended interference.

The closest longer studs that would fit are ARP 100-7708 and Dorman 610-323. The ARP 100-7708 studs have an 0.509″ knurl,  making a 1/2″ reamer the closest common size to the correct hole size (0.504″ by ARP’s recommendation). When installed, these studs increase the thread length by 0.84″ (21.4mm) over the stock studs.

The Dorman 610-323 studs have a 12.80 mm (0.504″) knurl, which fit in the original hub holes based on Dorman’s specifications. They are 54 mm long, thus increasing the thread length by 12mm over the stock studs.

I pressed the lug studs out of a brand new Rodney Dickman 88 front hub and measured the hole size as about 0.490″ at the smallest and around 0.50″ at the largest. I went ahead and pressed the ARP studs in without reaming the hole to 0.503″,  and they pressed in without too much trouble. The hub didn’t split, but a few metal shavings were produced by the knurl pushing through the hole. This fit exceeds the ARP recommendation for the interference fit, but is within spec if Dorman’s recommendation is followed.

1988 Fiero hub with ARP 100-7708 studs installed
1988 Fiero hub with ARP 100-7708 studs installed

Since these studs are so much longer than stock, open-ended lug nuts must be used. For GM wheels the stock ones should work. In the aftermarket, I found some inexpensive Gorilla lug nuts on Amazon.com. The part number is 20033SD for a set of 20 lug nuts and the spline drive socket. These nuts are narrow enough to fit in aftermarket wheels. I tried some White Knight lug nuts but they were too large in diameter to fit in the lug but counterbores in my wheels.

I purchased these inexpensive Gorilla brand  open-end lug nuts on Amazon.com
I purchased these inexpensive Gorilla brand open-end lug nuts on Amazon.com. p/n 20033SD

The Gorilla lug nuts fit perfectly in my aftermarket Motegi MR116 wheels. The only disadvantage of these nuts is that the require the use of Gorilla’s spline drive key. Some hex drive lug nuts are available from Vorshlag that look like they might fit, since they are small enough to use a 17mm hex instead of the 19mm hex on the White Knight lug nuts that were too large for my wheels.

After installing the extended studs and open-ended lug nuts, I had plenty of thread engagement while running a 3mm rotor spacer
After installing the extended studs and open-ended lug nuts, I had plenty of thread engagement while running a 3mm rotor spacer

The same studs will work just as well on the rear bearings as on the front.

Fiero Harness Bar

IMPORTANT NOTE: I am not a professional safety equipment builder, and I do NOT recommend building your harness bar the same way I built mine! This bar isn’t legal for any wheel-to-wheel racing, and race harnesses are not legal for use on the street. I just needed a way to put harnesses in the car for autocross and track days, since there’s no way to lock the stock seatbelts on a Fiero. Use a professional race shop to build a roll bar/cage if you intend to use a race harness. Race harnesses, harness bars and roll bars are NOT to be used on the street.

I recently finished building and installing a harness bar in my ’88 Fiero. I designed it so no parts need to be removed from the car except the B-pillars, the stock seatbelt can still be used, and no holes need to be drilled in the chassis.

Existing holes in the b-pillar can be used to pass bolts through for the harness bar.
Existing holes in the b-pillar can be used to pass bolts through for the harness bar.

I designed a bracket to go over two existing holes in the B-pillar. I mock up all my brackets in cardboard, then trace them onto the material to be cut on a bandsaw, and bend it using my vice and a hammer or adjustable wrench. Obviously a sheet metal brake would be a lot easier and more precise, but I don’t have room for one in my shop right now.

This is a mockup of the backing plate which goes on the inside of the B-pillar. It will have two M12 nuts welded to it for attaching the harness bar.
This is a mockup of the backing plate which goes on the inside of the B-pillar. It will have two M12 nuts welded to it for attaching the harness bar.

There is a hole at the bottom of the B-pillar that’s big enough to fit my arm through to feed the inner backing plate into place. I had two M12 nuts welded to the backing plate so I don’t have to fumble with nuts on the inside.

I bent the harness bar from 1.5″ OD, 0.120″ thickness 4130 “chrome moly” steel using a JD Squared Model 32 manual bender:

The harness bar cross beam was bent using a JD Squared Model 32 manual bender.
The harness bar cross beam was bent from 1.50″ OD 0.120″ wall thickness 4130 “chrome moly” steel tubing using a JD Squared Model 32 manual bender.

Schroth shoulder harnesses

The brackets (inner and outer) were cut from 3/16″ 4130 steel plate and bent in my vice:

The brackets are made from 3/16" thickness 4130 steel plate. They were cut on a bandsaw and bent on a vice. Precise fitup is extremely important for strong welds with 4130. There should ideally be NO gap between the tube and bracket plate.
The brackets are made from 3/16″ thickness 4130 steel plate. They were cut on a bandsaw and bent on a vice.
Precise fitup is extremely important for strong welds with 4130. There should ideally be NO gap between the tube and bracket plate.

I may add another M8 or M12 bolt in the 3rd hole, but haven’t done so yet.

Anti-rotation brackets mockup
Anti-rotation brackets can be tied into the harness bar by welding in additional tubes. This can help prevent the main harness bar from rotating forward when the shoulder harnesses pull on it in a collision.

If anti-rotation bars are desired, the main harness bar can be tied into plate bolted to the OE shoulder belt mounting points.

The bracket shown mocked up in cardboard would be made from 3/16″ 4130 steel plate and would be tied into the main harness bar with 1.5″ OD 0.120″ wall thickness tubes. This can help prevent the main harness bar from rotating forward when the shoulder harnesses pull on it in a collision.

When I have enough parts ready to fill a large batch, I’ll probably have the harness bar powdercoated. I’ve read that some race teams don’t powdercoat or paint their roll cages or harness bars, so that it’s easier to inspect for cracks. However, some surface rust will develop over time if it isn’t protected.

Repairing Fiero Coolant Tubes

With its mid-engine layout, the Fiero needs to shuttle coolant from the rear to the front of the car, where the radiator is located. The coolant flows through tubes located just inboard of the rocker panels. Since this is a common location for modern cars to be lifted for maintenance and repair, shops often damage the coolant tubes by using them as jackpoints. All it takes is one careless mechanic or tire shop employee to crush the pipes and render the cooling system ineffective.

The damage is often hidden, as shown below:

Damaged coolant pipe, viewed from below
Damaged coolant pipe, viewed from below where the damage is not visible
The same pipe, removed and viewed from above
The same pipe, removed and viewed from above
Damaged coolant pipe, viewed from the side
Damaged coolant pipe, viewed from the side

Replacement coolant tubes for the 1984 to 1987 Fieros are available from The Fiero Store. However, they are expensive, and tubes for 1988 Fieros are not available.

With access to a welder, it’s possible to repair kinked/crushed tubing.

First, cut the tubing at the narrowest part of the kink. A hacksaw will make quick work of the thin stainless steel tubing.

Coolant tubing cut into two pieces at the narrowest part of the kink
In the cross-section, you can see the magnitude of the restriction. This tube had about 30% less cross sectional area than it should have. It wasn’t enough to cause overheating in normal driving, but on the track coolant temps were very high.

When not suffering from damage, the coolant tube should have an inner diameter of ~1.236″. A socket with approximately the same outer diameter can be used as a mandrel to bend the tube back into shape.

A 1/2"-drive socket with the right outer diameter can be used as a mandrel to reshape the coolant tube
A 1/2″-drive socket with the right outer diameter can be used as a mandrel to reshape the coolant tube. This socket has a stepped region with a smaller diameter so it fits in the bent tube.

To facilitate removal, insert a long bolt through the drive hole in the socket. Later, a slide hammer can be used to remove the socket.

Insert a bolt through the socket and install a nut so it can be used to pull the socket. A nylock nut was used here to prevent it from accidentally loosening during removal.
Insert a bolt through the socket and install a nut so it can be used to pull the socket. A nylock nut was used here to prevent it from accidentally loosening during removal.

It may be necessary to bend the coolant tube with pliers or a vice to make room for the stepped smaller diameter of the socket.

It will be necessary to secure the coolant tube in a vice to prevent it from moving while knocking the socket into the tube.

After making the small diameter of the socket fit by bending the tube with pliers or the vice, carefully hammer the socket evenly into the tube. Make sure to wear safety glasses! The chrome plating of the socket or the hammer itself may chip. Using a piece of wood to drive the socket is also a good idea, as it can help prevent the hammer and socket from chipping, and help distribute load.

After the socket is fully inserted into the tubing, remove it using a slide hammer or channel locks (see photo below).

If you don't have a slide hammer, grab the bolt with channel locks and use it to remove the socket.
If you don’t have a slide hammer, grab the bolt with channel locks and use it to remove the socket.

Repeat the socket-reshaping procedure described above fro the other piece of the cut tube.

This Fiero coolant tube has been reshaping by hammering a socket into it.
This Fiero coolant tube has been reshaping by hammering a socket into it.

Finally, prepare the tube for welding by sanding the inside and outside, and grind or deburr the faces if necessary to get the best fit.

This tube was welded back together using a TIG welder and stainless steel filler rod.
This tube was welded back together using a TIG welder and stainless steel filler rod.

If you don’t have access to a welder, a muffler shop should be able to weld the tube back together. Make sure they know it’s stainless steel, and tell them to line up the welded seam of the tubing.