Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 1255

Python • Help with reading multiple CAN messages with python

$
0
0
Goal of the project: I am using a raspberry pi and MCP2515 dual CAN board to read broadcasted 1MB CAN data from a standalone ECU in my car. The Pi will interpret the incoming CAN messages from the ECU, perform a math function so that it is discernible data. Convert that data to be within a range of values. Convert that range of values to a 0 to 100% duty cycle output on a GPIO pin. That GPIO output is read by an ESP32 board controlling a GC9A01 screen and converts the 0 to 100% duty cycle to move a needle for data monitoring (gauges). Currently I have the code working exactly as intended for one individual CAN message and GPIO output. The struggle I am having with the python code on the Pi is, how to read and perform a math function on multiple individual CAN messages, and convert each message to a specific GPIO pin.

I will post two separate working scripts, only difference being the CAN message that is being transformed.

First script is for the Oil Pressure message. Second script is for the water temperature message.

If I uncomment the remainder of the monitorlist (which is all of the messages I'm trying to read) I get errors when compiling and cannot figure out how to interpret a message individually from that list.

Code:

#import cursesimport canimport RPi.GPIO as GPIOimport timeimport osoil_pin = 17GPIO.setwarnings(False)GPIO.setmode(GPIO.BCM)GPIO.setup(oil_pin, GPIO.OUT)oil_pwm = GPIO.PWM(oil_pin, 1000)oil_pwm.start(0)oil_DC = float()canFilter = list()bus = can.interface.Bus('', bustype='socketcan', filter=canFilter)can = "can0"# defined types to process the data. x = can message , a = byte 1 , b = byte 2def temp(x,a):    return(round((x[-a])*(9/5)) + 32)        def volt(x,a,b):    return(((x[a]<<8) + x[b]) * .01)def press(x,a):    return(x[a])def oilpres(x,a):    return((x[-a]))def flvl(x,a):    return(x[a])def speed(x,a):    return(x[a])def rpm(x,a,b):    return(x[a] + x[b])def wrapper(msg,name,func,output,colum,*args):    return(func(msg,*args))# list of can ID's and details to monitor in this order:# (ID, Channel, [("name", process, type, colum, byte1, byte2)])monitorlist=[#(0x118,#              can,#              [("Coolant", temp, str, 0, 2),#              ("Volts", volt, str, 0, 4, 3),#              ("AirTemp", temp, str, 0, 1)]),#             (0x101,#               can,#               [("FuelPressure", press, str, 0, 4)]),             (0x110,               can,               [("OilPressure", oilpres, str, 0, 4),#             (0x164,#               can,#               [("FuelLevel", flvl, str, 0, -7)]),#             (0x102,#               can,#               [("NonDriven_WheelSpeed", speed, str, 0, 4)]),#             (0x108, #              can, #              [("RPM", rpm, str, 0, 5, 6)])])]# setupfor monitor in monitorlist: # build out the can bus filtering list. only receive messages that we care about. canFilter.append({"can_id": monitor[0], "can_mask": 0xFFF, "can_channel": monitor[1]}) # Process every single message received from the canbustry: for msg in bus:  for monitor in monitorlist:   if msg.arbitration_id == monitor[0] and msg.channel == monitor[1]:     for detail in monitor[2]:      oil_value = (wrapper((msg.data),*detail))      oil_DC = (((oil_value)/90) * 100)      oil_pwm.ChangeDutyCycle(oil_DC)      time.sleep(0)           except:   bus.shutdown()  curses.nocbreak()  stdscr.keypad(0)  curses.echo()  curses.endwin()  raise

Code:

#import cursesimport canimport RPi.GPIO as GPIOimport timeimport oscoolant_pin = 17GPIO.setwarnings(False)GPIO.setmode(GPIO.BCM)GPIO.setup(coolant_pin, GPIO.OUT)coolant_pwm = GPIO.PWM(coolant_pin, 1000)coolant_pwm.start(0)coolant_DC = float()canFilter = list()bus = can.interface.Bus('', bustype='socketcan', filter=canFilter)can = "can0"# defined types to process the data. x = can message , a = byte 1 , b = byte 2def temp(x,a):    return(round((x[-a])*(9/5)) + 32)        def wrapper(msg,name,func,output,colum,*args):    return(func(msg,*args))# list of can ID's and details to monitor in this order:# (ID, Channel, [("name", process, type, colum, byte1, byte2)])monitorlist=[(0x118,              can,              [("Coolant", temp, str, 0, 2),])]# setupfor monitor in monitorlist: # build out the can bus filtering list. only receive messages that we care about. canFilter.append({"can_id": monitor[0], "can_mask": 0xFFF, "can_channel": monitor[1]}) # Process every single message received from the canbustry: for msg in bus:  for monitor in monitorlist:   if msg.arbitration_id == monitor[0] and msg.channel == monitor[1]:     for detail in monitor[2]:      coolant_value = (wrapper((msg.data),*detail))      coolant_DC = (((coolant_value - 60)/180) * 100)      coolant_pwm.ChangeDutyCycle(coolant_DC)      time.sleep(0.25)           except:   bus.shutdown()  curses.nocbreak()  stdscr.keypad(0)  curses.echo()  curses.endwin()  raise

Statistics: Posted by CPD — Wed Jun 26, 2024 1:26 am



Viewing all articles
Browse latest Browse all 1255

Trending Articles