Send and receive database signals

  • February 15, 2018
  • check-paym check-pay

This is the second post in a 2-part series about how to manage DBC databases using the Kvaser database library (kvadblib) and Python:

  1. Handling CAN databases in Python
  2. Send and receive database signals

 

In the first post we created a DBC database and took a peek inside to verify that we got what we asked for. Now we will use the database to send signals with physical values set from Python.


Send and receive CAN messages

Before sending signals using our database, let us first remind ourselves on how to write and receive a raw CAN message using Python.

from canlib import kvadblib
from canlib import canlib
from canlib import Frame

def open_channel(channel):
    ”””Open a new channel, set bitrate 1Mbit/s and go bus on.”””
    ch = canlib.openChannel(channel, canlib.canOPEN_ACCEPT_VIRTUAL)
    ch.setBusOutputControl(canlib.canDRIVER_NORMAL)
    ch.setBusParams(canlib.canBITRATE_1M)
    ch.busOn()
    return ch


def close_channel(ch):
    ”””Go bus off and close channel.”””
    ch.busOff()
    ch.close()

def send_receive_raw(ch0, ch1):
    # send a CAN frame without using kvadblib
    frame = Frame(id_=4,data=bytearray(b ’\x00\x00\x00\x00\xd8\x00\x1e\x00 ’))
    print(”Sending frame : %s” % frame)
    ch0.write(frame)

    # read message back
    print(”Receiving frame: %s” % str(ch1.read()))


ch0 = open_channel(0)
ch1 = open_channel(1)

send_receive_raw(ch0 , ch1)

close_channel(ch0)
close_channel(ch1)

Listing 1: Code sample showing how to write and receive a CAN message.

There should be no big surprises here1, sending the CAN message on channel zero is done with ch0.write(), receiving is done on channel one using ch1.read(). Running this small sample shows the following on standard out:

Sending frame: Frame(id=4, data=bytearray(b’\x00\x00\x00\x00\xd8\x00\x1e\x00’), dlc=8, flags=0, timestamp=None)
Receiving frame: Frame(id=4, data=bytearray(b’\x00\x00\x00\x00\xd8\x00\x1e\x00’), dlc=8, flags=2, timestamp=4)

Binding CAN messages

The first step when sending CAN signals is to open a database and associate a CAN frame with a message that is defined in the database.

# open the database we would like to use
db = kvadblib.Dbc(filename=’db_histogram.dbc’)

# fetch the message we are going to use from the database
lim_002 = db.get_message_by_name(’LIM_002’)

# create a BoundMessage, containing an empty frame with the correct
# id and dlc.
bmsg_0 = lim_002.bind()

When we bind a database message, we get a new object with space allocated for ID, DLC and Data, and at the same time the ID and DLC has been set according to the message specification. Now we can use the newly created BoundSignal to access our signals as attributes.

# We set the raw value of our signal ’Load ’ using attributes
bmsg_0.Load.raw = 0xff

print(”The bound message now looks like:\n%s” % bmsg_0)

print(”Load signal as raw value: %s” % bmsg_0.Load.raw)
print(”and as physical value: %s” % bmsg_0.Load.phys)

# More often we are interested in setting the physical value of the signal
bmsg_0.Load.phys = 75

print(”Load signal as raw value: 0x%x” % bmsg_0.Load.raw)
print(”and as physical value: %s” % bmsg_0.Load.phys)

Running the above code results in the following on standard output:

The bound message now looks like:
Frame: message_name:LIM_002, data:bytearray(b’\xff\x00\x00\x00\x00\x00\x00\x00’)
Load signal as raw value: 255
and as physical value: 3.5733110840282835e-43
Load signal as raw value: 0x42960000
and as physical value: 75.0

Send and receive CAN frames

Now that we have our bound message with the correct content, we use ._frame to extract the frame in a format suitable for the call to write().

# send a CAN frame using standard write () method
ch0.write(bmsg_0._frame)

# create another BoundSignal, this time containing a frame read from
# channel 1
bmsg_1 = lim_002.bind(ch1.read(timeout=100))

Taking the this new code and combining it with our first code sample, we end up with the following final result:

from canlib import canlib
from canlib import kvadblib

def open_channel(channel):
    ”””Open a new channel, set bitrate 1Mbit/s and go bus on. ”””
    ch = canlib.openChannel(channel, canlib.canOPEN_ACCEPT_VIRTUAL)
    ch.setBusOutputControl( canlib.canDRIVER_NORMAL)
    ch.setBusParams( canlib.canBITRATE_1M)
    ch.busOn()
    return ch

def close_channel(ch):
    ”””Go bus off and close channel.”””
    ch.busOff()
    ch.close()

def send_receive_sig(ch0, ch1):
    # open the database we would like to use
    db = kvadblib.Dbc(filename=’db_histogram.dbc’)

    # fetch the message we are going to use from the database
    lim_002 = db.get_message_by_name(’LIM_002’)

    # create a BoundMessage, containing an empty frame with the correct
    # id and dlc.
    bmsg_0 = lim_002.bind()

    # Set signal value
    bmsg_0.Load.phys = 75

    print(’Sending: %s’ % bmsg_0.Load)
    # send a CAN frame using standard write() method
    ch0.write(bmsg_0._frame)

    # create another BoundSignal, this time containing a frame read from
    # channel 1
    bmsg_1 = lim_002.bind(ch1.read(timeout=100))

    print(’Received signal Load: %s %s’ % (bmsg_1.Load.phys, bmsg_1.Load.unit))

ch0 = open_channel(0)
ch1 = open_channel(1)

send_receive_sig(ch0, ch1)

close_channel(ch0)
close_channel(ch1)

Running our last code sample gives the following result.

Sending: <BoundSignal: name=’Load’, phys=75.0>, unit:metric ton
Received signal Load: 75.0 metric ton

We have now scratched the surface on how to take advantage of the Kvaser database library (kvadblib) in order to use signals instead of creating and sending CAN messages manually.


Footnotes

1 The usage of canlib.Frame is new in v1.5 so that could have been a small surprise… 😉

Author Image

check-paym check-pay

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. abc