Skip to content

Feature/86dregyk6/can driver #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 50 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
91e76a7
init
XanderHayhoe Feb 16, 2024
97c0250
fix typo
XanderHayhoe Feb 16, 2024
3b9dec2
edits need to review
ishanimunasinghe Feb 19, 2024
ccab068
minor fixes
XanderHayhoe Apr 12, 2024
c409f09
Completed config.py
Apr 13, 2024
669e748
added identifiers for kelly frames
Apr 13, 2024
76fc004
okay Xander
Apr 13, 2024
e55c429
Preliminary CAN driver
Apr 22, 2024
a874e5e
Preliminary commit
Apr 27, 2024
43002d9
second commit
Apr 27, 2024
816b1b2
95% done
Apr 27, 2024
88b32c5
inshallah
Apr 27, 2024
370d1c4
req.txt
Apr 27, 2024
3d0872b
checkpoint
May 3, 2024
d2d2076
cleanup
May 3, 2024
9556e35
cleanup
May 3, 2024
2a6ce5c
cleanup
May 3, 2024
17a633b
cleanup
May 3, 2024
46a1270
cleanup
May 3, 2024
00b0479
cleanup
May 3, 2024
d9a26d2
cleanup
May 3, 2024
9a7418b
cleanup
May 3, 2024
11e6a82
cleanup
May 3, 2024
0b8b6f0
cleanup
May 3, 2024
984f31e
cleanup
May 3, 2024
744d8d6
cleanup
May 3, 2024
f9910f9
cleanup
May 3, 2024
a7659f1
cleanup
May 3, 2024
61cdaf1
cleanup
May 3, 2024
398d867
cleanup
May 3, 2024
1439e1f
cleanup
May 3, 2024
5c1037c
cleanup
May 3, 2024
cc69f2a
cleanup
May 3, 2024
e6254e5
cleanup
May 3, 2024
f52754f
cleanup
May 3, 2024
95d7241
cleanup
May 3, 2024
2e46391
cleanup
May 3, 2024
8bd03a9
cleanup
May 3, 2024
d75fb34
cleanup
May 3, 2024
0e95865
cleanup
May 3, 2024
ccc641a
cleanup
May 3, 2024
19f936d
cleanup
May 3, 2024
345327e
cleanup
May 3, 2024
a836b23
cleanup
May 3, 2024
43bda2e
cleanup
May 3, 2024
1f08e46
cleanup
May 3, 2024
a83ef63
cleanup
May 3, 2024
0f3a2bc
cleanup
May 3, 2024
eb98baa
cleanup
May 4, 2024
d9b73f6
cleanup
May 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added can/__pycache__/config.cpython-312.pyc
Binary file not shown.
Binary file added can/__pycache__/driver.cpython-312.pyc
Binary file not shown.
128 changes: 128 additions & 0 deletions can/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import time
import can
from ctypes import c_uint8, c_uint16

class BMS_DATA:
can_id = 0
temperature = [c_uint8(0), c_uint8(0), c_uint8(0), c_uint8(0), c_uint8(0), c_uint8(0)]
error_code = c_uint8(0)

class SENSORS_1: #CONSISTS OF PRESSURE, LIM1, AND LIM2
can_id = 0
pressure_sensor_data = c_uint16(0)
lim_temperature = [c_uint16(0), c_uint16(0)]
error_code = c_uint8(0)

class SENSORS_2: #CONSISTS OF IMU
can_id = 0
x_acceleration = c_uint16(0)
y_acceleration = c_uint16(0)
x_gyro = c_uint8(0)
y_gyro = c_uint8(0)
z_gyro = c_uint8(0)
error_code = c_uint8(0)

class MOTOR_CONTROLLER_DATA:
can_id = 0
battery_voltage = c_uint16(0)
battery_current = c_uint16(0)
motor_speed = c_uint16(0)
motor_controller_temp = c_uint8(0)
driving_direction = c_uint8(0)
error_code = c_uint8(0) #Note: the error code and driving direction are obtained from the same byte in the config.h datasegment.

class GLOBAL:
def __init__(self):
# GENERAL DEFINES
self.MAX_CAN_PAYLOAD_BYTES = 8
self.BUFF_SIZE = 32
self.WARN_OFFSET = 0xFF

#CAN ID DEFINES

# MOTOR CONTROLLER
self.MOTOR_CONTROLLER = 0xFF
self.MOTOR_CONTROLLER_WARN = self.MOTOR_CONTROLLER - self.WARN_OFFSET

# BMS
self.BMS_BOARD = 0
self.BMS_BOARD_WARN = self.BMS_BOARD - self.WARN_OFFSET

# SENSOR BOARD 1
self.SENSOR_BOARD_1 = 0
self.SENSOR_BOARD_1_WARN = self.SENSOR_BOARD_1 - self.WARN_OFFSET

# SENSOR BOARD 2
self.SENSOR_BOARD_2 = 0
self.SENSOR_BOARD_2_WARN = self.SENSOR_BOARD_2 - self.WARN_OFFSET


# THIS IS CONFIG.H FOR CROSS REFERENCE

# #pragma once
# #include "can_driver.h"

# // GENERAL DEFINES
# #define MAX_CAN_PAYLOAD_BTYES 8
# #define BUFF_SIZE 32
# #define WARN_OFFSET 0xFF

# // MOTOR CONTROLLER
# #define MOTOR_CONTROLLER_K1 0x10F8109A
# #define MOTOR_CONTROLLER_K2 0x10F8108D
# #define MOTOR_CONTROLLER 0xFF
# #define MOTOR_CONTROLLER_WARN MOTOR_CONTROLLER - WARN_OFFSET
# // BMS
# #define BMS_BOARD 0xFF
# #define BMS_BOARD_WARN BMS_TEMP - WARN_OFFSET
# // SENSORS
# #define SENSOR_BOARD_1 0xFF
# #define SENSOR_BOARD_1_WARN SENSOR_BOARD_1 - WARN_OFFSET
# #define SENSOR_BOARD_2 0xFF
# #define SENSOR_BOARD_2_WARN SENSOR_BOARD_2 - WARN_OFFSET

# // BEGIN KELLY DEFS
# // FRAME 1
# const Data_Segment_t DRIVING_DIRECTION_K = {MOTOR_CONTROLLER_K1, 1, 1};
# const Data_Segment_t MOTOR_SPEED_K = {MOTOR_CONTROLLER_K1, 2, 3};
# const Data_Segment_t MOTOR_ERROR_CODE_K = {MOTOR_CONTROLLER_K1, 4, 4};
# // FRAME 2
# const Data_Segment_t BATTERY_VOLTAGE_K = {MOTOR_CONTROLLER_K2, 1, 2};
# const Data_Segment_t BATTERY_CURRENT_K = {MOTOR_CONTROLLER_K2, 3, 4};
# const Data_Segment_t MOTOR_TEMP_K = {MOTOR_CONTROLLER_K2, 5, 6};
# const Data_Segment_t MOTOR_CONTROLLER_TEMP_K = {MOTOR_CONTROLLER_K2, 7, 8};
# // END KELLY DEFS

# // BEGIN MOTOR CONTROLLER DEFS
# const Data_Segment_t BATTERY_VOLTAGE = {MOTOR_CONTROLLER, 1, 2};
# const Data_Segment_t BATTERY_CURRENT = {MOTOR_CONTROLLER, 3, 4};
# const Data_Segment_t MOTOR_SPEED = {MOTOR_CONTROLLER, 5, 6};
# const Data_Segment_t MOTOR_CONTROLLER_TEMP = {MOTOR_CONTROLLER, 7, 7};
# const Data_Segment_t DRIVING_DIRECTION = {MOTOR_CONTROLLER, 8, 8};
# const Data_Segment_t MOTOR_ERROR_CODE = {MOTOR_CONTROLLER, 8, 8};
# // END MOTOR CONTROLLER DEFS

# // BEGIN BMS DEFS
# const Data_Segment_t MUX1_TEMP = {BMS_BOARD, 1, 1};
# const Data_Segment_t MUX2_TEMP = {BMS_BOARD, 2, 2};
# const Data_Segment_t MUX3_TEMP = {BMS_BOARD, 3, 3};
# const Data_Segment_t MUX4_TEMP = {BMS_BOARD, 4, 4};
# const Data_Segment_t MUX5_TEMP = {BMS_BOARD, 5, 5};
# const Data_Segment_t MUX6_TEMP = {BMS_BOARD, 6, 6};
# const Data_Segment_t BMS_ERROR_CODE = {BMS_BOARD, 8, 8};
# // END BMS DEFS

# // BEGIN SENSORS BOARD DEFS
# //FIRST FRAME
# const Data_Segment_t PRESSURE_SENSOR_DATA = {SENSOR_BOARD_1, 1, 2};
# const Data_Segment_t LIM_ONE_TEMP = {SENSOR_BOARD_1, 3, 4};
# const Data_Segment_t LIM_TWO_TEMP = {SENSOR_BOARD_1, 5, 6};
# const Data_Segment_t SENSORS_ERROR_CODE_1 = {SENSOR_BOARD_1, 8, 8};
# //SECOND (IMU) FRAME
# const Data_Segment_t X_ACCEL = {SENSOR_BOARD_2, 1, 2};
# const Data_Segment_t Y_ACCEL = {SENSOR_BOARD_2, 3, 4};
# const Data_Segment_t X_GYRO = {SENSOR_BOARD_2, 5, 5};
# const Data_Segment_t Y_GYRO = {SENSOR_BOARD_2, 6, 6};
# const Data_Segment_t Z_GYRO = {SENSOR_BOARD_2, 7, 7};
# const Data_Segment_t SENSORS_ERROR_CODE_2 = {SENSOR_BOARD_2, 8, 8};
# // END SENSORS BOARD DEFS
145 changes: 145 additions & 0 deletions can/driver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import time
import can
from ctypes import c_uint8, c_uint16, c_uint32
import struct
from config import *

#instantiate objects of all classes
global_vars = GLOBAL()
bms_data = BMS_DATA()
sensors_1 = SENSORS_1()
sensors_2 = SENSORS_2()
motor_controller_data = MOTOR_CONTROLLER_DATA()

#assign CAN_IDs to all instantiated objects
bms_data.can_id = global_vars.BMS_BOARD
sensors_1.can_id = global_vars.SENSOR_BOARD_1
sensors_2.can_id = global_vars.SENSOR_BOARD_2
motor_controller_data.can_id = global_vars.MOTOR_CONTROLLER

#define send and receive functions
"""
FUNCTION: RECEIVE_MESSAGE
@ARG can_bus: passed can object
RETURN: none
WHAT IT DO? receives a message on the bus. Writes message data to the correct
instantiated object based on the message's arbitration ID
"""
def RECEIVE_MESSAGE(can_bus):
rx_msg = can_bus.recv()
print (rx_msg)
# rx_msg = can_bus.Message
# print(rx_msg)

# rx_data = rx_msg.data

# if (rx_msg.arbitration_id == global_vars.BMS_BOARD) or (rx_msg.arbitration_id == global_vars.BMS_BOARD_WARN):
# bms_data.temperature[0]=rx_data[0]
# bms_data.temperature[1]=rx_data[1]
# bms_data.temperature[2]=rx_data[2]
# bms_data.temperature[3]=rx_data[3]
# bms_data.temperature[4]=rx_data[4]
# bms_data.temperature[5]=rx_data[5]
# bms_data.error_code = rx_data[6]

# elif (rx_msg.arbitration_id == global_vars.SENSOR_BOARD_1) or (rx_msg.arbitration_id == global_vars.SENSOR_BOARD_1_WARN):
# sensors_board_data.temperature[0] = rx_data[0]
# sensors_board_data.temperature[1] = rx_data[1]
# sensors_board_data.imu_data = rx_data[2]
# sensors_board_data.pressure_sensor_data = rx_data[3]
# sensors_board_data.error_code = rx_data[4]

# elif (rx_msg.arbitration_id == global_vars.SENSOR_BOARD_2) or (rx_msg.arbitration_id == global_vars.SENSOR_BOARD_2_WARN):
# sensors_board_data.temperature[0] = rx_data[0]
# sensors_board_data.temperature[1] = rx_data[1]
# sensors_board_data.imu_data = rx_data[2]
# sensors_board_data.pressure_sensor_data = rx_data[3]
# sensors_board_data.error_code = rx_data[4]

# elif (rx_msg.arbitration_id == global_vars.MOTOR_CONTROLLER) or (rx_msg.arbitration_id == global_vars.MOTOR_CONTROLLER_WARN):
# motor_controller_data.battery_voltage = rx_data[0]
# motor_controller_data.battery_current = rx_data[1]
# motor_controller_data.motor_speed = rx_data[2]
# motor_controller_data.motor_controller_temp = rx_data[3]
# motor_controller_data.driving_direction = rx_data[4]
# motor_controller_data.error_code = rx_data[5]

"""
FUNCTION: CREATE_SEND_DATA
@ARG arbitration_id
RETURN: data packet. Bytearray.
WHAT IT DO? Creates 'data' based on the arbitrationID
of the frame we wish to send. Reveals the current state of
the instantiated objects.
"""
def CREATE_SEND_DATA(arbitrationID):
# define data object
data = []
if (arbitrationID == global_vars.BMS_BOARD) or (arbitrationID == global_vars.BMS_BOARD_WARN):
data = [bms_data.temperature[0],
bms_data.temperature[1],
bms_data.temperature[2],
bms_data.temperature[3],
bms_data.temperature[4],
bms_data.temperature[5],
bms_data.error_code,
0]

elif (arbitrationID == global_vars.SENSOR_BOARD_1) or (arbitrationID == global_vars.SENSOR_BOARD_1_WARN):

msb_pressure = (sensors_1.pressure_sensor_data & (0b11111111 << 8))
lsb_pressure = (sensors_1.pressure_sensor_data & 0b11111111)
msb_lim_temp_0 = (sensors_1.lim_temperature[0] & (0b11111111 << 8))
lsb_lim_temp_0 = (sensors_1.lim_temperature[0] & (0b11111111))
msb_lim_temp_1 = (sensors_1.lim_temperature[1] & (0b11111111 << 8))
lsb_lim_temp_1 = (sensors_1.lim_temperature[1] & (0b11111111))

data = [msb_pressure,
lsb_pressure,
msb_lim_temp_0,
lsb_lim_temp_0,
msb_lim_temp_1,
lsb_lim_temp_1,
sensors_1.error_code,
0]

elif (arbitrationID == global_vars.SENSOR_BOARD_2) or (arbitrationID == global_vars.SENSOR_BOARD_2_WARN):

msb_x_accel = (sensors_2.x_acceleration & (0b11111111 << 8))
lsb_x_accel = (sensors_2.x_acceleration & (0b11111111))
msb_y_accel = (sensors_2.y_acceleration & (0b11111111 << 8))
lsb_y_accel = (sensors_2.y_acceleration & (0b11111111))

data = [msb_x_accel,
lsb_x_accel,
msb_y_accel,
lsb_y_accel,
sensors_2.x_gyro,
sensors_2.y_gyro,
sensors_2.z_gyro,
sensors_2.error_code]

elif (arbitrationID == global_vars.MOTOR_CONTROLLER) or (arbitrationID == global_vars.MOTOR_CONTROLLER_WARN):

msb_voltage = (motor_controller_data.battery_voltage & (0b11111111 << 8))
lsb_voltage = (motor_controller_data.battery_voltage& (0b11111111))
msb_current = (motor_controller_data.battery_current & (0b11111111 << 8))
lsb_current = (motor_controller_data.battery_current & (0b11111111))
msb_motor_speed = (motor_controller_data.motor_speed & (0b11111111 << 8))
lsb_motor_speed = (motor_controller_data.motor_speed & (0b11111111))

data = [msb_voltage,
lsb_voltage,
msb_current,
lsb_current,
msb_motor_speed,
lsb_motor_speed,
motor_controller_data.motor_controller_temp,
motor_controller_data.driving_direction]

else:
data = [0, 0, 0, 0, 0, 0, 0, 0]

return data


88 changes: 88 additions & 0 deletions can/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# # import can
# # import time
# # import os
# # from config import *
# # from driver import RECEIVE_MESSAGE, CREATE_SEND_DATA

# # def main():

# # #CANBUS init
# # os.system("sudo /sbin/ip link set can0 up type can bitrate 500000") #bring up can0 interface at 500kbps
# # time.sleep(0.05)
# # try:
# # CAN0 = can.interface.Bus(channel='can0', bustype='socketcan') #instantiate CAN object
# # except OSError:
# # print('Cannot find PiCAN board.')
# # exit()
# # print('Ready')

# # #create listener and notifier
# # #(TODO: configure CAN connection (masks, etc))
# # CAN0_listener = RECEIVE_MESSAGE
# # CAN0_notifier = can.Notifier(CAN0, [CAN0_listener]) #assign listener to notifier

# # #send and receive messages
# # # 1. send
# # msg_data = [0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0]
# # msg = can.Message(arbitration_id = 0x57, data = msg_data)
# # CAN0.send(msg)
# # os.system("sudo ip link set can0 down")

# # if __name__ == "__main__":
# # main()


import can
import time
import os
from config import *
class MessageListener(can.Listener):
def on_message_received(self, msg):
print(f'Received message: {msg}')

def main():
os.system("sudo ip link set can0 up type can bitrate 500000") # Bring up can0 interface at 500kbps
#os.system("sudo ip link set can1 up type can bitrate 500000")
time.sleep(0.05)
try:
CAN0 = can.interface.Bus(channel='can0', bustype='socketcan', loopback = True, receive_own_messages=True ) # Instantiate CAN object
except OSError:
print('Cannot find PiCAN board.')
exit()
print('Ready')

CAN0_listener = MessageListener()
CAN0_notifier = can.Notifier(CAN0, [CAN0_listener]) # Assign listener to notifier

msg_data = [(0xF0), (0xF0), (0xF0), (0xF0)]
msg = can.Message(arbitration_id = 0x57, data = msg_data, is_extended_id = False)
print(f"MESSAGE: {msg} \n")
CAN0.send(msg)
time.sleep(0.001) # Allow some time for message handling

CAN0_notifier.stop()
CAN0.shutdown()

os.system("sudo ip link set can0 down")
os.system("sudo ip link set can1 down")

if __name__ == "__main__":
main()

# import can
# def main():
# # Setup the CAN bus in loopback mode
# can_interface = 'can0'
# bus = can.interface.Bus(channel=can_interface, bustype='socketcan', loopback=True)
# # Send a message
# message = can.Message(arbitration_id=0x123, data=[0x11, 0x22, 0x33], is_extended_id=False)
# bus.send(message)
# # Receive the message
# received_message = bus.recv(10) # Timeout in seconds
# if received_message:
# print(f"Received message: {received_message}")
# else:
# print("No message received.")
# bus.shutdown()
# if __name__ == "__main__":
# main()
6 changes: 6 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
can==0.0.0
msgpack==1.0.8
packaging==24.0
python-can==4.3.1
typing_extensions==4.11.0
wrapt==1.16.0