diff --git a/can/__pycache__/config.cpython-312.pyc b/can/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..98deb1f Binary files /dev/null and b/can/__pycache__/config.cpython-312.pyc differ diff --git a/can/__pycache__/driver.cpython-312.pyc b/can/__pycache__/driver.cpython-312.pyc new file mode 100644 index 0000000..9124169 Binary files /dev/null and b/can/__pycache__/driver.cpython-312.pyc differ diff --git a/can/config.py b/can/config.py new file mode 100644 index 0000000..db1b4a4 --- /dev/null +++ b/can/config.py @@ -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 \ No newline at end of file diff --git a/can/driver.py b/can/driver.py new file mode 100644 index 0000000..5214621 --- /dev/null +++ b/can/driver.py @@ -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 + + diff --git a/can/main.py b/can/main.py new file mode 100644 index 0000000..33137ac --- /dev/null +++ b/can/main.py @@ -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() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..42ba688 --- /dev/null +++ b/requirements.txt @@ -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