MojoScale Studio Docs
API Reference

can

Raw CAN 2.0 bus access over the ESP32 TWAI controller.

Studio Docs Buses & Protocols

import can

The can module sends and receives raw 11-bit or 29-bit CAN frames. Use it when you want protocol-level control, custom CAN payloads, or a protocol that is not covered by a higher-level module. For SAE J1939 engine data, use the j1939 module instead. ESP32 and ESP32-S3 include the TWAI controller used here. You still need an external CAN transceiver between the ESP32 TX/RX pins and CANH/CANL.

Quick example

import can
import system

bus = can.CAN(tx=5, rx=4, bitrate=can.BITRATE_500K)
bus.begin()

bus.send(0x123, [1, 2, 3, 4])

def poll():
    frame = bus.receive(timeout_ms=0)
    if frame != None:
        print(frame["id"], frame["data"])

system.schedule("can_poll", 20, 0, -1, poll)

import can

bus = can.CAN(tx=5, rx=4, mode=can.MODE_LISTEN_ONLY)

def on_frame(frame):
    print(frame["id"], frame["dlc"], frame["data"])

bus.set_filter(id=0x100, mask=0x700)
bus.on_receive(on_frame)
bus.begin()

importcan

Raw CAN 2.0 bus access over the ESP32 TWAI controller.

The can module sends and receives raw 11-bit or 29-bit CAN frames. Use it when you want protocol-level control, custom CAN payloads, or a protocol that is not covered by a higher-level module. For SAE J1939 engine data, use the j1939 module instead. ESP32 and ESP32-S3 include the TWAI controller used here. You still need an external CAN transceiver between the ESP32 TX/RX pins and CANH/CANL.

API 20 available

can.CAN(tx: int, rx: int, bitrate: int = None, mode: str = None, rx_queue: int = None, tx_queue: int = None) -> can_bus

Create a raw CAN bus object.

Creating the object does not start the TWAI controller. Call ``begin()`` before sending or receiving frames. Only one raw CAN/J1939 TWAI owner should run at a time because the hardware controller is shared.

Parameters
Name Type Pass as Required Description
tx int positional or keyword Yes ESP32 TWAI transmit GPIO connected to the CAN transceiver TXD pin.
rx int positional or keyword Yes ESP32 TWAI receive GPIO connected to the CAN transceiver RXD pin.
bitrate int positional or keyword No Optional CAN bitrate in bits per second. Defaults to can.BITRATE_500K.
mode str positional or keyword No Optional controller mode. Use can.MODE_NORMAL, can.MODE_LISTEN_ONLY, or can.MODE_NO_ACK.
rx_queue int positional or keyword No Optional receive queue depth for polling frames. Defaults to 32.
tx_queue int positional or keyword No Optional transmit queue depth for outgoing frames. Defaults to 16.
Returns

can_bus can_bus object.

can.CAN().begin() -> bool

Start the TWAI controller and receive task.

can.CAN().stop() -> bool

Stop the bus, receive task, and TWAI driver.

can.CAN().is_running() -> bool

Return True when the TWAI controller is active.

can.CAN().send(id, data, extended=False, rtr=False, timeout_ms=0) -> bool

Send one raw CAN frame. data may be a list of 0 to 8 byte values or a byte-like string.

Parameters
Name Type Pass as Required Description
id any positional or keyword Yes Required value.
data any positional or keyword Yes Required value.
extended bool positional or keyword No Optional value. Defaults to False.
rtr bool positional or keyword No Optional value. Defaults to False.
timeout_ms int positional or keyword No Optional value. Defaults to 0.

can.CAN().send_frame(frame, timeout_ms=0) -> bool

Send a frame dict created by can.Frame() or returned by receive().

Parameters
Name Type Pass as Required Description
frame any positional or keyword Yes Required value.
timeout_ms int positional or keyword No Optional value. Defaults to 0.

can.CAN().receive(timeout_ms=0) -> dict

Return the next received frame dict, or None when no frame arrives before the timeout.

Parameters
Name Type Pass as Required Description
timeout_ms int positional or keyword No Optional value. Defaults to 0.

can.CAN().available() -> int

Return the number of queued frames available for polling.

can.CAN().on_receive(callback) -> bool

Register a callback that receives each frame dict. Pass None to clear it. Do not mix callback and polling for the same bus.

Parameters
Name Type Pass as Required Description
callback callback positional or keyword Yes Required value.

can.CAN().set_filter(id, mask, extended=False) -> bool

Accept frames where (frame_id & mask) equals (id & mask).

Parameters
Name Type Pass as Required Description
id any positional or keyword Yes Required value.
mask int positional or keyword Yes Required value.
extended bool positional or keyword No Optional value. Defaults to False.

can.CAN().set_filters(filters) -> bool

Replace software filters with a list of filter dicts containing id, mask, and optional extended.

Parameters
Name Type Pass as Required Description
filters any positional or keyword Yes Required value.

can.CAN().clear_filters() -> bool

Accept all incoming frames again.

can.CAN().flush(timeout_ms=1000) -> bool

Wait for the transmit queue to drain.

Parameters
Name Type Pass as Required Description
timeout_ms int positional or keyword No Optional value. Defaults to 1000.

can.CAN().clear_rx() -> bool

Drop queued receive frames.

can.CAN().state() -> str

Return stopped, running, warning, passive, bus_off, or recovering.

can.CAN().recover(timeout_ms=2000) -> bool

Attempt TWAI bus-off recovery and wait for running state.

Parameters
Name Type Pass as Required Description
timeout_ms int positional or keyword No Optional value. Defaults to 2000.

can.CAN().stats() -> dict

Return tx_sent, tx_failed, rx_received, rx_dropped, rx_filtered, tx_queued, rx_queued, tx_error_count, rx_error_count, bus_errors, arbitration_lost, bus_off_count, state, running, bitrate, mode, tx, and rx.

can.CAN().reset_stats() -> bool

Reset module-level counters.

can.CAN().on_state(callback) -> bool

Register a callback that receives the state string when it changes. Pass None to clear it.

Parameters
Name Type Pass as Required Description
callback callback positional or keyword Yes Required value.

can.Frame(id: any, data: list = None, extended: bool = None, rtr: bool = None, dlc: any = None) -> dict

Create a raw CAN frame dict.

Parameters
Name Type Pass as Required Description
id any positional or keyword Yes CAN identifier. Use 0x000 to 0x7ff for standard frames or 0x00000000 to 0x1fffffff for extended frames.
data list positional or keyword No Optional payload list containing 0 to 8 byte values. Defaults to [].
extended bool positional or keyword No Optional bool. Use True for 29-bit CAN identifiers.
rtr bool positional or keyword No Optional bool. Use True for a remote transmission request frame.
dlc any positional or keyword No Optional data length code. Defaults to the payload length.
Returns

dict dict with id, data, dlc, extended, rtr, and timestamp_ms.