Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 23 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
# unit_ut61eplus
Access digtal multimeter UNI-T UT61E+ from Python via CP2110 based USB connection
Access UNI-T UT61E+ Digital Multimeter from Python via CP2110 / CH9329 based USB HID Device
**NOTE:** It seems newer UNI-T UT61x DMMs come with a `CH9329` based HID->UART Adapter.
This project now detects both and automatically chooses which VID/PID to use

It should work also for other models:

This Project should work also for other models, but with adjustments for the unit conversion.
(See `from_vendor/*.json`)
* UT60BT
* UT61B+
* UT61D+
* UT161B
* UT161D
* UT161E

but for this the unit conversion has to be adjusted (see `from_vendor/*.json`)

## Status
> Working with Linux, patches/documentation for Windows are welcome (probably only docs needed to setup the HID library correctly)
> Working with Linux. Patches/Documentation for Windows is welcome
> Tested with UT61E+ and UT61B+


## Example output (see `readDMM.py`)
## Example Output From readDMM.py
```
Opened: VID=0x1A86, PID=0xE429
mode=DCV
range=1
display=8.595
range=0
display=0.0002
display_decimal=0.0002
display_unit=V
overload=False
decimal=8.595
value=0.0002
unit=V
max=False
min=False
hold=False
rel=False
auto=True
battery=False
hvwarning=False
dc=True
peak_max=False
peak_min=False
isMax=False
ismin=False
isHold=False
isRel=False
isAuto=True
hasBatteryWarning=False
hashasHVWarning=False
isDC=False
isMaxPeak=False
```
31 changes: 25 additions & 6 deletions ut61eplus/ut61eplus.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,11 @@ def __str__(self):

class UT61EPLUS:

CP2110_VID = 0x10c4
CP2110_PID = 0xEA80
# List of Possible HID Devices to talk to
TARGETS = [
(0x10C4, 0xEA80), # CP2110
(0x1A86, 0xE429), # CH9329
]

_SEQUENCE_GET_NAME = bytes.fromhex('AB CD 03 5F 01 DA')
_SEQUENCE_SEND_DATA = bytes.fromhex('AB CD 03 5E 01 D9')
Expand All @@ -310,14 +313,30 @@ class UT61EPLUS:
def __init__(self):
"""open device"""
self.dev = hid.device()
self.dev.open(self.CP2110_VID, self.CP2110_PID)
log.debug('device is open')

# Find the Appropriate HID Device
device_vid_pid = self._find_device()
if not device_vid_pid:
raise RuntimeError("No Compatable HID Devices Found")

# Open the HID Target found using path
self.dev.open_path(device_vid_pid['path'])
#self.dev.open(self.CP2110_VID, self.CP2110_PID)
print(f"Opened: VID=0x{device_vid_pid['vendor_id']:04X}, PID=0x{device_vid_pid['product_id']:04X}")

# Send Setup Strings
#self.dev.nonblocking = 1
self.dev.send_feature_report([0x41, 0x01]) # enable uart
self.dev.send_feature_report([0x41, 0x01]) # enable uart
self.dev.send_feature_report([0x50, 0x00, 0x00, 0x25, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00]) # 9600 8N1 - from USB trace
self.dev.send_feature_report([0x43, 0x02]) # purge both fifos
self.dev.send_feature_report([0x43, 0x02]) # purge both fifos
log.debug('feature requests sent')

def _find_device(self):
for dev in hid.enumerate():
if (dev['vendor_id'], dev['product_id']) in self.TARGETS:
return dev
return None

def _write(self, b: bytes):
buf = []
buf.append(len(b))
Expand Down