Pyboard D-Series and CAN Bus

The official PYBD running MicroPython, and its accessories.
Target audience: Users with a PYBD
Post Reply
dkeeney
Posts: 6
Joined: Sun May 03, 2020 6:22 pm

Pyboard D-Series and CAN Bus

Post by dkeeney » Sun May 03, 2020 6:30 pm

Hi. Getting pyboard to communicate with a CAN Bus has been challenging. I am hoping someone with experience can look at my effort and identify an omission or error, or ways to diagnose the problem.

Hardware
Pyboard D-Series
WBUS-Dip28
SN65HVD230 CAN Board

Wired as:
WBUS pins Y3 and Y4 to CAN Board also tried Y5 and Y6
Power to CAN Board is off WBUS Pin 1 (VIN) also tried Pin 2 (3.3V) though both seem to measure closer to 2.9V than 3.3

CAN Bus is grounded, shielded twisted-pair cabling, with 120 Ohm resister on each end.
The other bus node is an 8devices Korlan CAN2USB and Linux terminals running Candump and Cansend




The python code is:
import pyb
from pyb import CAN

baud = 125000
bittime = 1/baud
bs1, bs2 = 6, 8

# bittime = (1+ bs1 + bs2) * tq
tq = bittime / (1+bs1+bs2)

PCLK1 = pyb.freq()[2] # 30,000,000

# tq = prescaler/PCLK1
prescaler = PCLK1 * tq # 16

can = CAN(1, CAN.NORMAL, auto_restart=True, prescaler=int(prescaler), bs1=bs1, bs2=bs2)
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))
can.send('message', 123)

An oscilloscope will see square wave signals on the bus (between CANH and CANL) when the linux terminal sends a message, and also on the RX line into the WBUS.
But testing the above code does not result in a message received in the Candump terminal, nor does it put any signal on the TX line observable to the oscilloscope.

On a related note, attempting to create CAN(2) produces an error message, that CAN(2) does not exist. Aren't there two CAN buses on the ST32 chip?

Thanks in advance for any constructive advice.

David

kesterlester
Posts: 12
Joined: Sat Nov 17, 2018 10:04 pm

Re: Pyboard D-Series and CAN Bus

Post by kesterlester » Wed May 06, 2020 9:04 pm

About 4 years ago I tried something similar with a non-D-series pyboard. (I wanted to probe the signals being sent to my car's electric windows and locks which had issues.) I am sorry to report that ultimately I failed. As far as I can remember I was neither able to send nor receive anything on the CAN bus. Alas I haven't even kept any documentation or records sufficient to show you what I did -- but nothing in your code or setup looks considerably off my attempts. Admittedly I tried only for a day or two, but I did have a scope and tried any number of changes but failed to see anything on the lines.

I therefore can't offer you any help. Sorry.

But I *would* be interested to see any answers from others that point you in the right direction. Just in case I need to attempt something similar later.

kesterlester
Posts: 12
Joined: Sat Nov 17, 2018 10:04 pm

Re: Pyboard D-Series and CAN Bus

Post by kesterlester » Thu May 07, 2020 7:57 pm

Just a thought: did you include a line:

Code: Select all

pyb.Pin('EN_3V3').on()
enable the PYBD 3.3V rail for the transceiver to work? I don't see such a line in your code. See discussion here:

viewtopic.php?f=20&t=8137

dkeeney
Posts: 6
Joined: Sun May 03, 2020 6:22 pm

Re: Pyboard D-Series and CAN Bus

Post by dkeeney » Sun May 10, 2020 3:08 am

kesterlester:

Thank you for the input. Yeah, I did provide that Pin('EN_3V3').on() call when I was using the 3V line. I went back to using the VIN as a power source, which does not require enabling.

I found some code on github, by 'hmaerki', and will be testing it this weekend.

David

dkeeney
Posts: 6
Joined: Sun May 03, 2020 6:22 pm

Re: Pyboard D-Series and CAN Bus

Post by dkeeney » Sun May 31, 2020 11:52 pm

Update:

I had it wired wrong. The guidance I was following described the Pyboard v1 board.

The D-Series has one can-bus connection, using the pins X9 and X10. If you use the DIP68 connector, the pins are exposed as pins W55 and W59.

So the working can-bus is as described in my original post, with the wiring changes here. The transceiver can be powered by the 3V3 power out, or by Vin (5V, but it works).

I will include my source code, in case that is useful to anyone.

Code: Select all

import pyb
import time
import machine
import micropython

micropython.alloc_emergency_exception_buf(100)
pyb.Pin('EN_3V3').on()

baud = 1000000  # 125000  # 125000
bittime = 1/baud

#bs1, bs2 should total 10-1   
TqCt = 10
BS1 = int(0.875*TqCt); BS2 = TqCt - 1 - BS1

# bittime = (1+ bs1 + bs2) * tq
tq = bittime / (1+BS1+BS2)
PCLK1 = pyb.freq()[2]   # 30,000,000

# tq = prescaler/PCLK1  (it seems that only integer prescaler values work)
prescaler = PCLK1 * tq

print('tq {}  BS1 {}  BS2 {}  prescaler {}'.format(tq, BS1, BS2, prescaler))  

can = pyb.CAN(1, pyb.CAN.NORMAL, auto_restart=True,   
     extframe=False,prescaler=int(prescaler), bs1=BS1, bs2=BS2)
can.setfilter(0, pyb.CAN.LIST16, 0, (123, 124, 125, 126))

message = b'message'
print('sending ', message)
can.send(message, 123)

ary = [-1,-1,-1,memoryview(buf),buf]
    
def cb(bus, reason):
    
    global ary
    try:
        bus.recv(0, ary)
    except Exception as e:
        print('Exception', e)

    micropython.schedule(cb_sched, None)
        
def cb_sched(_):
    
    msg_id, is_rtr, FMI, _, buf = ary[0:5]
    print('recieved ', buf) 
    print('id {} rtr {} FMI {}'.format(msg_id, is_rtr, FMI))  
     
     
can.rxcallback(0, cb)

print('waiting for message')
while True:
    #time.sleep(1)
    machine.idle()
David

Post Reply