I'm trying to build a small Can Bus gauge to my car. I have Feather M4 Can express connected to 2.4" TFT FeatherWing. Screen is working fine, but I don't get Can Bus communication to work.
My car has aftermarket ECU (Ecumaster emu Black). It supports CAN BUS 2.0A and 2.0B. Default ECU ID HEX 600.
Default can stream info: https://filedn.com/lKOo3aQn9ubHtKC7DXLE ... tream.html
From ECU software I have set CAN bus speed to 500 kbps, enabled CAN bus stream and enabled 120ohm termination resistor.
I have checked that termination resistor is ok on Feather with multimeter.
On serial I see line: "Bus state changed to canio.BusState.ERROR_ACTIVE" and after that all the time I'm getting "no message received within timeout".
I have tried changing number of things. I even tried without any kind of message filtering and still nothing. If I try sending message with the loopback it works fine.
Can bus is wired from ECU to OBD port and from there to Feather. I tried plugging in OBD reader and it connected fine and showed sensor data from ECU as it should.
I borrowed Fluke Scopemeter from work and used it to log bus voltages. Ch A is Can High and Ch B is Can low. Ground reference is connected.
Here is video with Feather connected, but NOT powered on: https://youtu.be/eRN3P92qMd0
Looks as it should. Can high voltage changes between 2,5v and 3,5v. Can low voltage changes between 2,5v and 1,5v.
Here is video with Feather connected and power ON: https://youtu.be/PKZ2HQVNnPM
Signal looks strange. Can high voltage changes between 2v and 3,8v. Can low voltage changes between 2,5v and 1,5v.
I tried the silent parameter setting on canio.CAN, but still same problem.
Any ideas what is wrong? I'm starting to believe the transceiver is faulty.
Here is the code I have tried:
Code: Select all
import struct
import time
import board
import canio
import digitalio
# If the CAN transceiver has a standby pin, bring it out of standby mode
if hasattr(board, 'CAN_STANDBY'):
standby = digitalio.DigitalInOut(board.CAN_STANDBY)
standby.switch_to_output(False)
# If the CAN transceiver is powered by a boost converter, turn on its supply
if hasattr(board, 'BOOST_ENABLE'):
boost_enable = digitalio.DigitalInOut(board.BOOST_ENABLE)
boost_enable.switch_to_output(False)
# Use this line if your board has dedicated CAN pins. (Feather M4 CAN and Feather STM32F405)
#can = canio.CAN(rx=board.CAN_RX, tx=board.CAN_TX, baudrate=500_000, auto_restart=True, loopback=True)
can = canio.CAN(rx=board.CAN_RX, tx=board.CAN_TX, baudrate=500_000, auto_restart=True)
# On ESP32S2 most pins can be used for CAN. Uncomment the following line to use IO5 and IO6
#can = canio.CAN(rx=board.IO6, tx=board.IO5, baudrate=250_000, auto_restart=True)
listener = can.listen(matches=[canio.Match(602, mask=604)], timeout=.9)
#listener = can.listen(matches=[canio.Match(603)], timeout=.9)
old_bus_state = None
count = 5
count2 = 10
while True:
bus_state = can.state
if bus_state != old_bus_state:
print(f"Bus state changed to {bus_state}")
old_bus_state = bus_state
now_ms = (time.monotonic_ns() // 1_000_000) & 0xffffffff
# print(f"Sending message: count={count}")
# message = canio.Message(id=602, data=struct.pack("<II", count, now_ms))
# can.send(message)
# message2 = canio.Message(id=603, data=struct.pack("<II", count2, now_ms))
# can.send(message2)
message = listener.receive()
data = message.data
ID = message.id
if len(data) != 8:
print(f"Unusual message length {len(data)}")
continue
if message is None:
print("No message received within timeout")
continue
if ID == 602:
count, now_ms = struct.unpack("<II", data)
print(f"received message: count={count} now_ms={now_ms}")
time.sleep(1)
if ID == 603:
count, now_ms = struct.unpack("<II", data)
print(f"received message: count={count} now_ms={now_ms}")
time.sleep(1)