Search code examples
pythonusbpyusb

Multiple reproducible errors with a Brecknell Scale


I'm working on getting a weight from a usb scale using python and PyUSB. Here's my code

import sys
import usb.core
import usb.util
from reports import \
    ReportFactory, STATUSES, ZERO_WEIGHT, STABLE_WEIGHT, DATA_REPORT

device = usb.core.find(idVendor=0x67b, idProduct=0x2303)
if device is None:
    raise ValueError('Device Not Found')

if device.is_kernel_driver_active(0) is True:
    device.detach_kernel_driver(0)
    usb.util.claim_interface(device, 0)

device.set_configuration()

collected = 0
attempts = 50
while collected < attempts:
    ret = device.read(0x2,0x0040)
    sret=''.join([chr(x) for x in ret])
    print "Return Raw: ",ret
    print "Return : ", sret
    print ReportFactory.build(ret)

# release the device
usb.util.release_interface(device, 0)
device.attach_kernel_driver(0)

The first time I run this program I get Resource busy error

enter image description here

The second run I get Operation timed out on the 5th dump.

enter image description here

Subsequent runs after that result in immediate timeouts.

enter image description here

There are several things going on here

  1. Why do I get a resource busy error on first run? I would think the kernel_driver if statement I have should take care of it.

  2. Why do I get data that looks nothing like what a USB scale should produce?

  3. Why the timeout after 4 dumps of data? Everytime!

The device information is thus

enter image description here

Any help would be much appreciated!


Solution

  • Ok, anyone that is struggling to get anything from the GP100 Brecknell scale using PyUSB, switch to PySerial. Since this is one of the cheapest USB scales on the market, I'm guessing this information will help many.

    I emailed the manufacturer for documentation and they've sent me some valuable serial protocol information.

    If you set the protocol of the scale to 7010 you can use python code that looks like this

    import time
    import serial
    
    ser = serial.Serial(
        port='/dev/ttyUSB0',
        baudrate=2400,
        bytesize=8,
        parity='N',
        stopbits=2
    )
    
    while 1:
        x = ser.read(100)
        print(x)
    

    This will stream 8 bytes of data.

    • The first byte is status information that can be interpreted thusly

      • Bits 2-4 enter image description here
      • Bits 5-8 enter image description here
    • Bytes 2 & 3 can be safely ignored.

    • Bytes 4-8 have the weight information, represented by characters 0-9 (e.g. 00023 = 2.3 lbs). This scale is only accurate +- 0.6 lbs and does not work in ounces, perhaps other models using the same serial controller utilize the oz capabilities. The PG100 does not.