-
When receiving message from CAN, We decode it and send it to Dbus.
-
Install can package
pip install python-can- Connect with CAN bus
can_interface = 'can1'
can_bus = can.interface.Bus(channel=can_interface, bustype='socketcan')- Receive can message by using
.recvfunction. - if CAN connection has error, the function returns
None.
def receive_can_data():
try:
message = can_bus.recv(timeout=0.2) # timeout
if message is not None:
return message.data
else:
return None
except can.CanError:
return None- Change
speedbyte to decimal, and decode it.
def get_speed_can(data):
# get data(index of 0, 1, 2)
byte_0 = data[0]
byte_1 = data[1]
byte_2 = data[2]
# change byte type to hexadecimal
hex_data_0 = format(byte_0, '02X')
hex_data_1 = format(byte_1, '02X')
hex_data_2 = format(byte_2, '02X')
# change hexadecimal to decimal
decimal_data_0 = int(hex_data_0, 16)
decimal_data_1 = int(hex_data_1, 16)
decimal_data_2 = int(hex_data_2, 16)
# decode hexadecimal
speed = (decimal_data_0*256) + decimal_data_1 + (decimal_data_2*0.01)
return speed- Import deque
from collections import deque- Declare deque(size: 4)
queue = deque([0]*4)- In order to follow the most recent speed while reducing noise, weight was given based on the order in which data came into the queue.
- And send the
ave_valueto Dbus.
while 1:
data = receive_can_data()
if data is not None:
queue.popleft()
speed_data = get_speed_can(data)
queue.append(speed_data)
ave_value = queue[0]*0.1 + queue[1]*0.2 + queue[2]*0.3 + queue[3]*0.4
print(speed_data)
car_interface.setSpeed(ave_value) # send data to Dbus
else:
print("No CAN data recieved")- We used
get_battery_voltagefunction which is placed inpiracerpackage. - By using it in
battery_sender.py, we made a function which can calculate battery_percentage.
from piracer.vehicles import PiRacerStandard
def get_battery():
voltage = piracer.get_battery_voltage() / 3
print(voltage)
if(voltage>4.2):
battery_percentage = 100
elif(voltage>=4.1):
battery_percentage = 87 + ((voltage-4.1)/(4.2-4.1))*(100-87)
elif(voltage>=4.0):
battery_percentage = 75 + ((voltage-4.0)/(4.1-4.0))*(87-75)
elif(voltage>=3.9):
battery_percentage = 55 + ((voltage-3.9)/(4.0-3.9))*(75-55)
elif(voltage>=3.8):
battery_percentage = 30 + ((voltage-3.8)/(3.9-3.8))*(55-30)
elif(voltage>=3.6):
battery_percentage = 0 + ((voltage-3.6)/(3.8-3.6))*(30-0)
else:
battery_percentage = 0
return battery_percentage- We got an information about voltage state of charge of lithium battery from an official website.
- With this information, we made a function by using linear interpolation.
- Battery data wasn’t stable, so we collected maximum value to reduce noise data of battery.
- Import deque
from collections import deque- Declare deque (size: 100)
list = deque([0]*100)- Whenever new data comes in to
list, remove first data and append new data. - And then, send maximum data of list to Dbus.
while 1:
list.popleft() # remove first data
now_battery = get_battery()
list.append(now_battery) # append new data
battery = max(list)
car_interface.setBattery(float(battery)) # send data to Dbus- We used
shawan_gamepad.read_data()function which is also placed inpiracerpackage. - When left stick is manipulated, it returns the data by variable of
brake. - But it only gets data when the left stick is manipulated, so if you keep holding the stick, It cannot get data and waits for next manipuliate.
timeoutdecorator is added for preventing long wait for next manipuliation.
@timeout(0.01)
def getBrake():
gamepad_input = shanwan_gamepad.read_data()
brake = gamepad_input.analog_stick_left.y
return brake- If
gamepad_input’s value is less than -0.0038758507034516434, that is, when you’re controlling the backwards, sendTrueto Dbus (Because in stable position,gamepad_inputis - 0.0038758507034516434) - else, send
Falseto Dbus
while True:
try:
gamepad_input = getBrake()
except:
pass
if gamepad_input < -0.0038758507034516434: # to ignore splashing value
print("brake")
car_interface.setBrake(True) # send data to Dbus
else:
print("NO brake")
car_interface.setBrake(False) # send data to Dbus