コード例 #1
0
class frc_can:
    def __init__(self, devid):
        self.can = CAN(2, CAN.NORMAL)
        # Device id [0-63]
        self.devid = devid
        # Mode of the device
        self.mode = 0
        # Configuration data
        self.config_simple_targets = 0
        self.config_line_segments = 0
        self.config_color_detect = 0
        self.config_advanced_targets = 0
        self.frame_counter = 0
        # Buffer for receiving data in our callback.
        self.read_buffer = bytearray(8)
        self.read_data = [0, 0, 0, memoryview(self.read_buffer)]

        # Initialize CAN based on which type of board we're on
        if omv.board_type() == "H7":
            print("H7 CAN Interface")
            self.can.init(CAN.NORMAL,
                          extframe=True,
                          baudrate=1000000,
                          sampling_point=75)  # 1000Kbps H7
            #self.can.init(CAN.NORMAL, extframe=True, prescaler=4,  sjw=1, bs1=8, bs2=3)
        elif omv.board_type() == "M7":
            self.can.init(CAN.NORMAL,
                          extframe=True,
                          prescaler=3,
                          sjw=1,
                          bs1=10,
                          bs2=7)  # 1000Kbps on M7
            self.can.setfilter(0, CAN.LIST32, 0, [
                self.my_arb_id(self.api_id(1, 3)),
                self.my_arb_id(self.api_id(1, 4))
            ])
            print("M7 CAN Interface")
        else:
            print("CAN INTERFACE NOT INITIALIZED!")

        self.can.restart()

    # Set config: This is reported to rio when we send config.
    def set_config(self, simple_targets, line_segments, color_detect,
                   advanced_targets):
        self.config_simple_targets = simple_targets
        self.config_line_segments = line_segments
        self.config_color_detect = color_detect
        self.config_advanced_targets = advanced_targets

    # Update counter should be called after each processed frame. Sent to Rio in heartbeat.
    def update_frame_counter(self):
        self.frame_counter = self.frame_counter + 1

    def get_frame_counter(self):
        return self.frame_counter

    # Arbitration ID helper packs FRC CAN indices into a CANBus arbitration ID
    def arbitration_id(devtype, mfr, devid, apiid):
        retval = (devtype & 0x1f) << 24
        retval = retval | ((mfr & 0xff) << 16)
        retval = retval | ((apiid & 0x3ff) << 6)
        retval = retval | (devid & 0x3f)
        return retval

    # Arbitration ID helper, assumes devtype, mfr, and instance devid.
    def my_arb_id(self, apiid):
        devtype = 10  # FRC Miscellaneous is our device type
        mfr = 173  # Team 1073 ID to avoid conflict with all COTS devices
        retval = (devtype & 0x1f) << 24
        retval = retval | ((mfr & 0xff) << 16)
        retval = retval | ((apiid & 0x3ff) << 6)
        retval = retval | (self.devid & 0x3f)
        return retval

    # Return the combined API number of an API class and index:
    def api_id(self, api_class, api_index):
        return ((api_class & 0x3f) << 4) | (api_index & 0x0f)

    # Send message to my API id: Sends from OpenMV to Rio with our address.
    def send(self, apiid, bytes):
        sendid = self.my_arb_id(apiid)
        try:
            self.can.send(bytes, sendid, timeout=33)
        except:
            print("CANbus exception.")
            self.can.restart()

    # API Class - 1:  Configuration
    # Whenever we set the mode from here we send it to the RoboRio
    def set_mode(self, mode):
        self.mode = mode
        self.send_config_data()

    # Allows us to read back mode in case Rio sets the mode.
    def get_mode(self):
        return self.mode

    # Called by filter when FIFO 0 gets a message.
    def incoming_callback_0(can, reason):
        if reason:
            print("CAN Message FIFO 0 REASON %d" % reason)
        else:
            print("CAN FIFO 0 CB: NULL REASON")

        message = can.recv(0, list=None, timeout=10)

        print("ARBID %d" % message[0])

    # Send our Config data to RoboRio
    def send_config_data(self):
        cb = bytearray(8)
        cb[0] = self.mode
        cb[2] = self.config_simple_targets
        cb[3] = self.config_line_segments
        cb[4] = self.config_color_detect
        cb[5] = self.config_advanced_targets
        self.send(self.api_id(1, 0), cb)

    # Send our camera status data to RoboRio
    def send_camera_status(self, width, height):
        cb = bytearray(8)
        cb[0] = int(width / 4)
        cb[1] = int(height / 4)
        self.send(self.api_id(1, 1), cb)

    # Called to update mode if it is changed.
    def check_mode(self):
        try:
            self.can.recv(0, self.read_data, timeout=10)
            if self.read_data[0] == self.my_arb_id(self.api_id(1, 3)):
                self.mode = self.read_data[3][0]
                print("GOT MODE: %d" % self.mode)
            return True
        except:
            return False

    # Send the RIO the heartbeat message with our mode and frame counter:
    def send_heartbeat(self):
        hb = bytearray(3)
        hb[0] = (self.mode & 0xff)
        hb[1] = (self.frame_counter & 0xff00) >> 8
        hb[2] = (self.frame_counter & 0x00ff)
        self.send(self.api_id(1, 2), hb)

    # API Class - 2: Simple Target Tracking

    # Send tracking data for a given tracking slot to RoboRio.
    def send_track_data(self, slot, cx, cy, vx, vy, ttype, qual):
        tdb = bytearray(7)
        tdb[0] = (cx & 0xff0) >> 4
        tdb[1] = (cx & 0x00f) << 4 | (cy & 0xf00) >> 8
        tdb[2] = (cy & 0x0ff)
        tdb[3] = (vx & 0xff)
        tdb[4] = (vy & 0xff)
        tdb[5] = (ttype & 0xff)
        tdb[6] = (qual & 0xff)
        self.send(self.api_id(2, slot), tdb)

    # Track is empty when quality is zero, send empty slot /w 0 quality.
    def clear_track_data(self, slot):
        # Assume fills with zero.
        tdb = bytearray(7)
        self.send(self.api_id(2, slot), tdb)

    # Line Segment Tracking API Class: 3

    # Send line segment data to a slot to RoboRio.
    def send_line_data(self, slot, x0, y0, x1, y1, ttype, qual):
        ldb = bytearray(8)
        ldb[0] = (x0 & 0xff0) >> 4
        ldb[1] = ((x0 & 0x00f) << 4) | ((y0 & 0xf00) >> 8)
        ldb[2] = (y0 & 0x0ff)
        ldb[3] = (x1 & 0xff0) >> 4
        ldb[4] = ((x1 & 0x00f) << 4) | ((y1 & 0xf00) >> 8)
        ldb[5] = (y1 & 0x0ff)
        ldb[6] = (ttype & 0xff)
        ldb[7] = (qual & 0xff)
        self.send(self.api_id(3, slot), ldb)

    # Send null, 0 quality line to clear a slot for RoboRio.
    def clear_line_data(self, slot):
        ldb = bytearray(8)
        self.send(self.api_id(3, slot), ldb)

    # Color Detection API Class: 4

    # Send the given color segmentation data to the RoboRio
    def send_color_data(self, c0, p0, c1, p1, c2, p2, c3, p3):
        cdb = bytearray(8)
        cdb[0] = c0 & 0xff
        cdb[1] = p0 & 0xff
        cdb[2] = c1 & 0xff
        cdb[3] = p1 & 0xff
        cdb[4] = c2 & 0xff
        cdb[5] = p2 & 0xff
        cdb[6] = c3 & 0xff
        cdb[7] = p3 & 0xff
        self.send(self.api_id(4, 0), cdb)

    # Send empty color data / invalid colors to RoboRio.
    def clear_color_data(self):
        cdb = bytearray(8)
        self.send(self.api_id(4, 0), cdb)

    # Advanced Target Tracking API Class: 5

    # Send advanced target tracking data to RoboRio
    def send_advanced_track_data(self,
                                 cx,
                                 cy,
                                 area,
                                 ttype,
                                 qual,
                                 skew,
                                 slot=1):
        atb = bytearray(8)
        atb[0] = (cx & 0xff0) >> 4
        atb[1] = ((cx & 0x00f) << 4) | ((cy & 0xf00) >> 8)
        atb[2] = (cy & 0x0ff)
        atb[3] = (area & 0xff00) >> 8
        atb[4] = (area & 0x00ff)
        atb[5] = (ttype & 0xff)
        atb[6] = (qual & 0xff)
        atb[7] = (skew & 0xff)
        self.send(self.api_id(5, slot), atb)

    # Send a null / 0 quality update to clear track data to RoboRio
    def clear_advanced_track_data(self, slot=1):
        atb = bytearray(8)
        self.send(self.api_id(5, slot), atb)

    #send LiDar range sensing data to the RIO using API class 6
    #r stands for range
    def send_range_data(self, r, qual):
        atb = bytearray(3)
        atb[0] = (r & 0xff00) >> 8
        atb[1] = (r & 0x00ff)
        atb[2] = (qual & 0xff)
        self.send(self.api_id(6, 1), atb)
コード例 #2
0
# CAN Shield Example
#
# This example demonstrates CAN communications between two cameras.
# NOTE: you need two CAN transceiver shields and DB9 cable to run this example.

import time, omv
from pyb import CAN

# NOTE: Set to False on receiving node.
TRANSMITTER = True

can = CAN(2, CAN.NORMAL, baudrate=125_000, sample_point=75)
# NOTE: uncomment to set bit timing manually, for example:
#can.init(CAN.NORMAL, prescaler=32, sjw=1, bs1=8, bs2=3)
can.restart()

if (TRANSMITTER):
    while (True):
        # Send message with id 1
        can.send('Hello', 1)
        time.sleep_ms(1000)

else:
    # Runs on the receiving node.
    if (omv.board_type() == 'H7'): # FDCAN
        # Set a filter to receive messages with id=1 -> 4
        # Filter index, mode (RANGE, DUAL or MASK), FIFO (0 or 1), params
        can.setfilter(0, CAN.RANGE, 0, (1, 4))
    else:
        # Set a filter to receive messages with id=1, 2, 3 and 4
        # Filter index, mode (LIST16, etc..), FIFO (0 or 1), params
コード例 #3
0
ファイル: can.py プロジェクト: DanielO/micropython
CAN.initfilterbanks(14)
can = CAN(1)
print(can)

# Test state when de-init'd
print(can.state() == can.STOPPED)

can.init(CAN.LOOPBACK)
print(can)
print(can.any(0))

# Test state when freshly created
print(can.state() == can.ERROR_ACTIVE)

# Test that restart can be called
can.restart()

# Test info returns a sensible value
print(can.info())

# Catch all filter
can.setfilter(0, CAN.MASK16, 0, (0, 0, 0, 0))

can.send('abcd', 123, timeout=5000)
print(can.any(0), can.info())
print(can.recv(0))

can.send('abcd', -1, timeout=5000)
print(can.recv(0))

can.send('abcd', 0x7FF + 1, timeout=5000)