Login
Start Free Trial Are you a business? Click Here

USB to CAN Adapter Reviews

3.7 Rating 6 Reviews
Read The Pi Hut Reviews
Visit Product Page

Email:

contact@thepihut.com

Ben S
Verified Reviewer
Incentivized
Awesome bit of kit that deos exactly what I need! It would be good if they could make the USB smaller so it's wasier to package neatly
Helpful Report
Posted 5 months ago
Anonymous
Verified Reviewer
Incentivized
Author didn't leave any comments.
Helpful Report
Posted 9 months ago
It works fine once you realise it is speaking a proprietary binary protocol! For anyone who comes next: #!/usr/bin/env python3 import argparse import serial import struct import sys import time from datetime import datetime # Defaults from the C code DEFAULT_UART_BAUD = 2_000_000 CANUSB_INJECT_SLEEP_GAP_DEFAULT = 200 # ms # ----------------------- # Speed code translation # ----------------------- SPEED_MAP = { 1_000_000: 0x01, 800_000: 0x02, 500_000: 0x03, 400_000: 0x04, 250_000: 0x05, 200_000: 0x06, 125_000: 0x07, 100_000: 0x08, 50_000: 0x09, 20_000: 0x0A, 10_000: 0x0B, 5_000: 0x0C, } MODE_NORMAL = 0x00 MODE_LOOPBACK = 0x01 MODE_SILENT = 0x02 MODE_LOOPBACK_SILENT = 0x03 FRAME_STANDARD = 0x01 FRAME_EXTENDED = 0x02 # (not really supported by this short demo format) def checksum(buf): """Sum of bytes & 0xFF (like C code).""" return sum(buf) & 0xFF def build_settings_frame(speed_code, mode=MODE_NORMAL, frame_type=FRAME_STANDARD): """ 20-byte command frame: 0: 0xAA 1: 0x55 2: 0x12 3: speed_code 4: frame_type (1=std,2=ext) 5..8: filter id (ignored -> 0) 9..12: mask id (ignored -> 0) 13: mode 14: 0x01 15..18: 0 19: checksum(data[2..18]) """ frame = bytearray(20) frame[0] = 0xAA frame[1] = 0x55 frame[2] = 0x12 frame[3] = speed_code frame[4] = frame_type frame[5:13] = b"\x00" * 8 frame[13] = mode frame[14] = 0x01 frame[15:19] = b"\x00" * 4 frame[19] = checksum(frame[2:19]) return bytes(frame) def frame_is_complete(buf): """ Reproduces the C logic: - If first byte != 0xAA, treat as junk (complete to resync) - Command frames: 0xAA 0x55 ... always 20 bytes - Data frames: 0xAA 0xC? DLC in low nibble, total len = DLC + 5 """ if not buf: return False, 0 # If doesn't start with 0xAA, we consider that a "frame" to skip if buf[0] != 0xAA: return True, 1 if len(buf) < 2: return False, 0 b1 = buf[1] # Command frame if b1 == 0x55: if len(buf) >= 20: return True, 20 return False, 0 # Data frame: high nibble is 0xC if (b1 >> 4) == 0xC: dlc = b1 & 0x0F need = 1 + 1 + 2 + dlc + 1 # 0xAA + info + 2-byte ID + data + 0x55 if len(buf) >= need: return True, need return False, 0 # Unknown ? treat as single byte to skip return True, 1 def parse_data_frame(frame): """ C prints: Frame ID: %02x%02x, Data: ... Layout: 0: 0xAA 1: 0xC? (upper nibble 0xC, low nibble DLC) 2: ID LSB 3: ID MSB 4..N-2: DATA N-1: 0x55 """ info = frame[1] dlc = info & 0x0F id_lsb = frame[2] id_msb = frame[3] can_id = (id_msb = 6 and frame[0] == 0xAA and ((frame[1] >> 4) == 0xC): can_id, dlc, data = parse_data_frame(frame) ts = time.time() print(f"{ts:.6f} ID: 0x{can_id:04X} DLC: {dlc} DATA: {' '.join(f'{b:02X}' for b in data)}") else: # Unknown / sync loss ? print if you want to debug print("Unknown:", frame.hex()) pass def send_data_frame(ser, can_id, data): """ Matches send_data_frame() in C. Only handles 11-bit IDs (2-byte ID field). """ if not (0 0: send_data_frame(ser, can_id, data) remaining -= 1 time.sleep(gap_s) else: # -------- DUMP MODE ---------- print("Dumping frames? (Ctrl+C to stop)") dump_frames(ser) except KeyboardInterrupt: pass finally: ser.close() if __name__ == "__main__": main()
1 Helpful Report
Posted 11 months ago
Easy to order. Quick delivery. Well packed. Will order again.
Helpful Report
Posted 2 years ago
A simple device - appears as a USB Serial port and prints received CAN frames has hex strings. You can send it hex strings back to configure some CAN settings, or to send frames. One thing to be aware of - it contains an actual USB to UART chip, not just a microcontroller acting as a USB Device. This means the baud rate for the USB Serial interface is very important because if it is wrong the microcontroller won't be able to communicate with the USB Serial chip. Unfortunately the default baud rate is 2,000,000 baud, which is not supported by the default USB Serial driver on macOS. I had to plug the USB to CAN Adapter into a Raspberry Pi instead.
2 Helpful Report
Posted 2 years ago
The adapter itself is very easy to use. It comes with enough documentation and a C example. The data itself arrives in serial format (It's a CAN to Serial converter), so it (obviously) won't work with SocketCAN. There are no included Python code examples, however, it's incredibly easy to write something with PySerial with the documentation Waveshare provides.
5 Helpful Report
Posted 2 years ago