python-can icon indicating copy to clipboard operation
python-can copied to clipboard

Python-CAN script receiving half of the expected CAN messages

Open lhpluke opened this issue 3 years ago • 4 comments

Hello all,

I have written a Python script utilizing the Python-CAN library which records received CAN messages at a 1 second rate for 5 minutes, before logging all the messages into a file and exiting. The computer has a CAN module which is connecting to the CAN bus. (The other device on the bus is an engine) I communicate with it using the SocketCAN interface.

The test engine system that this computer is connected to is sending around 114 messages at what I believe is a 250kb baud rate. I am expecting to see 114 messages recorded in the file for each 1 second period, but instead I'm seeing about half that count. (~65 messages)

Could it be possible that the engine's ECU is set to a 500kb baud rate, and that's why I'm not getting the count I am expecting? I would think there would be no communication if the baud rates do not match, but I do not have physical access to the system because I'm sending the script remotely through an OTA update and not running it myself. (The device is headless, but is setup to run the script on startup) I just see the log files that are generated.

Here is the python code:

(A note, I have code parsing the received messages into the contained signals, but I did not include this code here because it happens at the end, and it is not relevant)

class logging:

        def __init__(self):
            #Dictionary to hold received CAN messages
            self.message_Dict = {}

            #List to hold queued dictionaries
            self.message_Queue = []

            #A "filters" object is also created here, but I did not include it
            #I have verified the filters are correct on my test system

        def main(self):

            #Record the current time
            currentTime = datetime.datetime.now()

            #Record the overall start time
            startTime = datetime.datetime.now()

            #Record the iteration start time
            lastIterationStartTime = currentTime

            #Create the CanBus that will be used to send and receive CAN msgs from the MCU
            canbus = can.interfaces.socketcan.SocketcanBus(channel='can0', bitrate=250000)
            #These filters are setup correctly, because all the messages come through
            #on my test system, but I did not include them here
            canbus.set_filters(self.Filters)
    
            # Creating Listener filters and notifier
            listener = can.Listener()

            #Main loop
            while 1:        

                #create a variable to hold received data
                msg2 = canbus.recv()

                #Record the current time
                currentTime = datetime.datetime.now()

                #If a valid message is detected
                if(msg2 != None):
                   if(len(msg2.data) > 0):
                       try:                                
                           #Save the message data into a queue (will be processed later)
                           self.message_Dict[msg2.arbitration_id] = msg2.data

                       except:
                           print("Error in storing CAN message")

                #If 1 second has passed since the last iteration, 
                #add the dictionary to a new spot in the queue
                if((currentTime - lastIterationStartTime) >= datetime.timedelta(seconds=1)):

                    #Add the dictionary with messages into the queue for later processing
                    messageDict_Copy = self.message_Dict.copy()
                    self.message_Queue.append(messageDict_Copy)

                    print("Number of messages in dictionary: " + str(len(self.message_Dict)) + " 
                       Number of reports in queue: " + str(len(self.message_Queue)))

                    #Clear the dictionary for new messages for every iteration
                    self.message_Dict.clear()

                    #Record the reset time
                    lastIterationStartTime = datetime.datetime.now()
                
                #Once 5 minutes of data has been recorded, write to the file
                if((currentTime - startTime) > datetime.timedelta(minutes=5)):
                    
                    #Here is where I write the data to a file. This is too long to include

                    #Clear the queue
                    self.message_Queue = []

                    #Clear the dictionary for new messages for every iteration
                    self.message_Dict.clear()

#When the script is run, execute the Main method
if __name__ == '__main__':  
    mainClass = logging()
    mainClass.main()

I appreciate any ideas or input you have. Thank you

lhpluke avatar Nov 10 '21 18:11 lhpluke

Hi, in case you get another message with same arbitration id in your receive window of one second, it will be overwritten by the previous one.

self.message_Dict[msg2.arbitration_id] = msg2.data

Check if your incoming message have really different arbitration ids, otherwise you cannot use a dict. Use a list or queue and remove duplicate messages later in your processing. René

rliebscher avatar Nov 10 '21 18:11 rliebscher

Hi, in case you get another message with same arbitration id in your receive window of one second, it will be overwritten by the previous one. self.message_Dict[msg2.arbitration_id] = msg2.data Check if your incoming message have really different arbitration ids, otherwise you cannot use a dict. Use a list or queue and remove duplicate messages later in your processing. René

Hello, my thought process for using a dictionary was so I could obtain the most up-to-date messages within that one second window. I figured overwriting the older messages in the dictionary would be faster than checking to see if it is already in the dictionary as well. Am I incorrect in my assumption?

lhpluke avatar Nov 10 '21 18:11 lhpluke

It was not completly clear. Do you have 114 messages (with possible some the same arbitration id) or many more messages with 114 different arbitration ids?

rliebscher avatar Nov 10 '21 21:11 rliebscher

It was not completly clear. Do you have 114 messages (with possible some the same arbitration id) or many more messages with 114 different arbitration ids?

Oh, yes, apologies that I didn't explain that part well. I am trying to monitor 114 distinct messages. They all have unique arbitration id's. Since it is connected to a live engine/ECU, I believe there are a lot more than 114 messages transmitting across the bus. My filters have cut down the messages to just 114.

lhpluke avatar Nov 10 '21 21:11 lhpluke