CAN Support on N6

Hi, I am having trouble trying to get CAN working with the N6. I have tried both the pyb and machine libraries and neither have the CAN module present. Is this going to be released in the firmware at some point to have this enabled?

Currently have firmware 4.8.0 (as a side note the latest dev release seems to not allow my IDE to connect to the board and simply says “busy”).

Hi, you need the latest dev firmware. You have to install the newest version of the IDE for it to work with your camera: Download – OpenMV

CAN is merged into the dev release, and it’s working.

Hi, I have updated my IDE and downloaded the latest release from github on the N6. It still doesn’t seem to be available. This is what I am running

import pyb
import machine

print(f"pyb contents \n {dir(pyb)}“)
print(f"machine contents \n {dir(machine)}”)

"pyb contents
[‘class’, ‘name’, ‘main’, ‘ADC’, ‘ADCAll’, ‘ExtInt’, ‘Flash’, ‘LED’, ‘Pin’, ‘RTC’, ‘SDCard’, ‘SPI’, ‘Timer’, ‘UART’, ‘dict’, ‘country’, ‘disable_irq’, ‘enable_irq’, ‘fault_debug’, ‘repl_info’, ‘repl_uart’, ‘rng’, ‘wfi’]
machine contents
[‘class’, ‘name’, ‘ADC’, ‘DEEPSLEEP_RESET’, ‘HARD_RESET’, ‘I2C’, ‘LED’, ‘PWM’, ‘PWRON_RESET’, ‘Pin’, ‘RTC’, ‘SOFT_RESET’, ‘SPI’, ‘Signal’, ‘SoftI2C’, ‘SoftSPI’, ‘Timer’, ‘UART’, ‘USBDevice’, ‘WDT’, ‘WDT_RESET’, ‘dict’, ‘file’, ‘bitstream’, ‘bootloader’, ‘deepsleep’, ‘dht_readinto’, ‘disable_irq’, ‘enable_irq’, ‘freq’, ‘idle’, ‘info’, ‘lightsleep’, ‘mem16’, ‘mem32’, ‘mem8’, ‘os’, ‘reset’, ‘reset_cause’, ‘rng’, ‘sleep’, ‘soft_reset’, ‘time_pulse_us’, ‘unique_id’]

OpenMV e86106720c; MicroPython 0f831e89f0; OpenMV N6 with STM32N657X0
Type “help()” for more information."

Hi George,

firmware.zip (1.2 MB)

Upstream MicroPython doesn’t enable the N6 CAN, just the H7. I’ve gone through the codebase and enabled it… however, didn’t have time to test it yet. Just got it to compile. Probably broken, but the modules appear now.

I’ll give it a test tomorrow. However, if it’s working already, let me know.

Note that only CAN1 is operational. CAN3 is not.

Okay, I got N6 CAN working.

Here’s a binary:

firmware.zip (1.2 MB)

There are a bunch of changes needed for this. It will be a while before this passes PR review in upstream MicroPython is mergedable into OpenMV.

from machine import CAN
import time

can = CAN(1, 500_000)
can.set_filters(None)
while True:
    can.send(123, b"\xDE\xAD\xBE\xEF")
    msg = can.recv()
    if msg:
        print(msg)
    time.sleep(0.01)

Hello, I upgraded the firmware according to the firmware library you provided and used the example you offered. However, I didn’t receive any messages sent by the OpenMV N6. I used the P2 (can1 TX) and P3 (can2 RX) pins on the OpenMV N6, then connected a CAN transceiver module. P2 was connected to the TX of the CAN transceiver module, and P3 was connected to the RX of the CAN transceiver module. VIN (5V) was connected to the 5V of the CAN transceiver module, GND was connected to the GND of the CAN transceiver module. After that, I connected the CAN transceiver module to the USB-CAN module. CANH of the CAN transceiver module was connected to CANH of the USB-CAN module, CANL was connected to CANL of the USB-CAN module, and GND was connected to GND of the USB-CAN module. Then, I observed the received data information through PCAN-view on the computer. The code I used was the example program you provided:

from machine import CAN
import time

can = CAN(1, 500_000)
can.set_filters(None)
while True:
can.send(123, b"\xDE\xAD\xBE\xEF")
print(111)
msg = can.recv()
if msg:
print(msg)
time.sleep(0.01)

I added the line “print(111)” to check the data transmission status. As a result, I saw a row of “111” outputs in the output terminal of the OpenMV IDE, but I did not receive the information I sent (can.send(123, b"\xDE\xAD\xBE\xEF") at the receiving end).

Hi, VIN doesn’t supply 5V. From the picture, there’s no power to the CAN transceiver.

Connect the power pin for the transceiver to RAW, which supplies 5V from the USB on the camera.

Hello, I have followed the method you suggested to connect the power pin of the transceiver to N6’s RAW. In my PCAN-View software, I did receive the sent ID number, but the sent data was not received. What could be the reason for this?

Hi,I tested the OpenMV N6 CAN firmware you provided, and I found an issue with CAN transmission.The OpenMV N6 can transmit the CAN ID successfully, and PCAN-View can receive the frame with ID 0x125. However, the received frame always has DLC/Length = 0, and the Data field is empty.

Test setup:

  • Board: OpenMV N6
  • Firmware: the firmware.bin you provided
  • CAN tool: PCAN-USB + PCAN-View
  • Bitrate: 1 Mbps
  • CAN ID: 0x125

Test code:

from machine import CAN
import time

can = CAN(1, bitrate=1_000_000)
can.set_filters(None)

while True:
data = bytes([0x10, 0x12, 0x12, 0x12, 0x12, 0x21, 0x21, 0x02])
ret = can.send(0x125, data, 0)
print(“send ret =”, ret, “len =”, len(data), “data =”, data.hex())
time.sleep_ms(1000)

The serial output is:

send ret = 0 len = 8 data = 1012121212212102

So the Python layer is definitely passing an 8-byte payload to can.send(), and send() does not return None.

But in PCAN-View, the received frame is:

CAN-ID = 125h
Length = 0
Data = empty

Also, when PCAN-View sends a CAN frame to the OpenMV N6, the OpenMV can correctly receive both the CAN ID and the payload data. Therefore, the CAN wiring, transceiver, termination, and bitrate should be correct. The problem seems to be in the OpenMV N6 firmware CAN transmit path.

I suspect this may be a DLC encoding issue in the STM32N6 FDCAN HAL.

Please check this file:

lib/stm32/n6/src/stm32n6xx_hal_fdcan.c

Specifically, the function:

FDCAN_CopyMessageToRAM()

In the MicroPython FDCAN layer, DataLength appears to already be encoded as:

txmsg->DataLength = (dlc << 16)

However, in the STM32N6 HAL, if FDCAN_CopyMessageToRAM() does this again:

(pTxHeader->DataLength << 16U)

then the DLC field will be shifted twice, which would make the actual transmitted DLC become 0. This matches the behavior observed in PCAN-View: correct CAN ID, but Length = 0 and no data.

Suggested fix:

Change this:

TxElementW2 = ((pTxHeader->MessageMarker << 24U) |
pTxHeader->TxEventFifoControl |
pTxHeader->FDFormat |
pTxHeader->BitRateSwitch |
(pTxHeader->DataLength << 16U));

to:

TxElementW2 = ((pTxHeader->MessageMarker << 24U) |
pTxHeader->TxEventFifoControl |
pTxHeader->FDFormat |
pTxHeader->BitRateSwitch |
pTxHeader->DataLength);

And change this:

for (ByteCounter = 0; ByteCounter < DLCtoBytes[pTxHeader->DataLength]; ByteCounter += 4U)

to:

for (ByteCounter = 0; ByteCounter < DLCtoBytes[pTxHeader->DataLength >> 16U]; ByteCounter += 4U)

This should make the STM32N6 FDCAN HAL behavior consistent with the STM32H7 FDCAN HAL implementation.Could you please help rebuild a fixed firmware.bin for me?If possible, please also provide the corresponding .elf and .map files, so that future firmware-level issues can be located more easily.

Hi Robin,

I made the change you suggested, and that was the fix. Here are the updated files. I am also updating my PR to micropython.

bootloader.zip (15.8 MB)

Here’s the PR for that and a link to the upstream micropython commits required: lib/stm32: Enable N6 CAN. by kwagyeman · Pull Request #3189 · openmv/openmv · GitHub

Thank you, kwagyeman, my friend. The OpenMV communication issue has been resolved.What a rewarding day!