Heavy time latency in Python script

This forum covers issues concerning multiple software products.
Post Reply
giles
Posts: 9
Joined: Tue 22. Dec 2020, 10:30

Heavy time latency in Python script

Post by giles » Tue 22. Dec 2020, 14:02

Hello,
I try to read CAN msgs and then transmit the processed CAN msgs via PEAK CAN-USB in Python (with the Py) environment, while I found there is a heavy latency communication between PCAN-View and Python environment as shown in below pictures.
IMG_20201222_183551_edit_364196830010052.jpg
IMG_20201222_183551_edit_364196830010052.jpg (1.03 MiB) Viewed 568 times
I simulate the signals from WIN10 PCAN-View and you can see the count number in ubuntu is less than the number in WIN10 PCAN-View
IMG_20201222_184227_edit_364300646205348.jpg
IMG_20201222_184227_edit_364300646205348.jpg (1.33 MiB) Viewed 568 times
and the same situation we can found the Data is also different at the same time

I also tried in ubuntu PCAN-View transmit to ubuntu Python, also occurred the above situation.

Hardware: PCAN-USB Pro FD
And below is the Python code contents:

Code: Select all

from PCANBasic import *
import time

channel = PCAN_USBBUS1
baud = PCAN_BAUD_500K

## The Plug & Play Channel (PCAN-USB) is initialized
##
# objPCAN =# The Plug & Play Channel (PCAN-USB) is initialized
#
objPCAN = PCANBasic()
result = objPCAN.Initialize(channel, baud)
if result != PCAN_ERROR_OK:
    # An error occured, get a text describing the error and show it
    #
    result = objPCAN.GetErrorText(result)
    print(result[1])
    channel = PCAN_USBBUS2
    objPCAN = PCANBasic()
    result = objPCAN.Initialize(channel, baud)
    if result != PCAN_ERROR_OK:
        # An error occured, get a text describing the error and show it
        #
        result = objPCAN.GetErrorText(result)
        print(result[1])
    else:
        print("PCAN-USBx was initialized")
else:
    print("PCAN-USBx was initialized")

    # Check the status of the USB Channel
    #
    result = objPCAN.GetStatus(channel)
if result == PCAN_ERROR_BUSLIGHT:
    print("PCAN-USB (Ch-x): Handling a BUS-LIGHT status...")
elif result == PCAN_ERROR_BUSHEAVY:
    print("PCAN-USB (Ch-x): Handling a BUS-HEAVY status...")
elif result == PCAN_ERROR_BUSOFF:
    print("PCAN-USB (Ch-x): Handling a BUS-OFF status...")
elif result == PCAN_ERROR_OK:
    print("PCAN_USB (Ch-x): Status is OK")
else:
    # An error occured, get a text describing the error and show it
    #
    result = objPCAN.GetErrorText(result)
    print(*result[1])

while (True):
    start = time.perf_counter()

    objPCAN.FilterMessages(channel, 119, 119, PCAN_MESSAGE_STANDARD)

    RecMegs = objPCAN.Read(channel)[1]
    print(RecMegs.ID)
    print(list(RecMegs.DATA))   # extract the data from CAN Read call back module


    # Send the data to CAN bus
    msg = TPCANMsg()
    msg.ID = 0x56
    msg.MSGTYPE = PCAN_MESSAGE_STANDARD
    msg.LEN = 8
    msg.DATA[0] = 0x08
    msg.DATA[1] = 0x00
    msg.DATA[2] = 0x00
    msg.DATA[3] = 0x80
    msg.DATA[4] = 0x00
    msg.DATA[5] = 0x00
    msg.DATA[6] = 0x00
    msg.DATA[7] = 0x00
    time.sleep(0.01)
    #
    result = objPCAN.Write(channel, msg)

    if result != PCAN_ERROR_OK:
        # An error occured, get a text describing the error and show it
        #
        result = objPCAN.GetErrorText(result)
        print(result)
    else:
        print("Message sent successfully")

    end = time.perf_counter()
    duration = end - start
    print(duration)
    print(' ')

# All initialized channgels are released
#
result = objPCAN.Uninitialize(PCAN_NONEBUS)
if result != PCAN_ERROR_OK:
    # An error occured, get a text describing the error and show it
    #
    result = objPCAN.GetErrorText(result)
    print(result)
else:
    print("PCAN-USBx was UN-initialized")


M.Heidemann
Sales & Support
Sales & Support
Posts: 416
Joined: Fri 20. Sep 2019, 13:31

Re: Heavy time latency in Python script

Post by M.Heidemann » Tue 22. Dec 2020, 14:47

Hello,

You do not seem to read until the ReceiveBuffer is empty,
which could be the cause for this.

Please make sure that you read messages in a loop based on the condition that the message-queue is not empty (Using return value TPCANStatus.PCAN_ERROR_QRCVEMPTY).

Otherwise you will only read the next message in the buffer, which might is older.

This is also described in the PCANBasic API documentation:
BASICReceive.PNG
BASICReceive.PNG (23.45 KiB) Viewed 559 times
Furthermore you can take a look at the PCANBasic example for Python included in the PCANBasic package,
the same mechanism is used there:

https://www.peak-system.com/fileadmin/m ... -basic.zip

Code: Select all

 def ReadMessages(self):
        stsResult = PCAN_ERROR_OK

        # We read at least one time the queue looking for messages.
        # If a message is found, we look again trying to find more.
        # If the queue is empty or an error occurr, we get out from
        # the dowhile statement.
        #
        while (self.m_CanRead and not (stsResult & PCAN_ERROR_QRCVEMPTY)):
            stsResult = self.ReadMessageFD() if self.m_IsFD else self.ReadMessage()
            if stsResult == PCAN_ERROR_ILLOPERATION:
                break
Please report back to us if this has solved your issue.

Best Regards

Marvin

giles
Posts: 9
Joined: Tue 22. Dec 2020, 10:30

Re: Heavy time latency in Python script

Post by giles » Wed 23. Dec 2020, 17:36

Thanks very much for your guidance sir, and it indeed help me to have a progress in real-time message receiving and transmitting.
But now some message is lost which I simulated the increasing message with step of 1, marked with red rectangle box.
Screenshot from 2020-12-24 00-25-19.png
Screenshot from 2020-12-24 00-25-19.png (47.31 KiB) Viewed 526 times
And below is the code content:

Code: Select all

from PCANBasic import *
import time

channel = PCAN_USBBUS1
baud = PCAN_BAUD_500K

## The Plug & Play Channel (PCAN-USB) is initialized
##
# objPCAN =# The Plug & Play Channel (PCAN-USB) is initialized
#
objPCAN = PCANBasic()

result = objPCAN.Initialize(channel, baud)
if result != PCAN_ERROR_OK:
    # An error occured, get a text describing the error and show it
    #
    result = objPCAN.GetErrorText(result)
    print(result[1])
    channel = PCAN_USBBUS2
    objPCAN = PCANBasic()
    result = objPCAN.Initialize(channel, baud)
    if result != PCAN_ERROR_OK:
        # An error occured, get a text describing the error and show it
        #
        result = objPCAN.GetErrorText(result)
        print(result[1])
    else:
        print("PCAN-USBx was initialized")
else:
    print("PCAN-USBx was initialized")

    # Check the status of the USB Channel
    #
    result = objPCAN.GetStatus(channel)
if result == PCAN_ERROR_BUSLIGHT:
    print("PCAN-USB (Ch-x): Handling a BUS-LIGHT status...")
elif result == PCAN_ERROR_BUSHEAVY:
    print("PCAN-USB (Ch-x): Handling a BUS-HEAVY status...")
elif result == PCAN_ERROR_BUSOFF:
    print("PCAN-USB (Ch-x): Handling a BUS-OFF status...")
elif result == PCAN_ERROR_OK:
    print("PCAN_USB (Ch-x): Status is OK")
else:
    # An error occured, get a text describing the error and show it
    #
    result = objPCAN.GetErrorText(result)
    print(*result[1])

objPCAN.FilterMessages(channel, 119, 119, PCAN_MESSAGE_STANDARD)
i = 0

while (True):
    start = time.perf_counter()

# Message data receiving module, and as the buffer will store the received data from CAN BUS
# So below 2 steps need to follow:
# Step 1:
#   Check the data in Buffer, if have data, continue to check buffer status
# Step 2:
#   If current buffer is empty, break the while loop and print the last Msgs Data

    while (objPCAN.Read(channel)[0] & PCAN_ERROR_OK) == PCAN_ERROR_OK:
        stsSystem = objPCAN.Read(channel)[0]
        RecMsg = objPCAN.Read(channel)[1]
#        if stsSystem == 0:
#            print('Status of system is:', stsSystem)
        if (objPCAN.Read(channel)[0] & PCAN_ERROR_QRCVEMPTY) == PCAN_ERROR_QRCVEMPTY:
            break
    if RecMsg.ID != 0:
        print('CAN BUS Data is: ', list(RecMsg.DATA)[0])

'''
    # Send the data to CAN bus
    msg = TPCANMsg()
    msg.ID = 0x56
    msg.MSGTYPE = PCAN_MESSAGE_STANDARD
    msg.LEN = 8
    msg.DATA[0] = 0x08
    msg.DATA[1] = 0x00
    msg.DATA[2] = 0x00
    msg.DATA[3] = 0x80
    msg.DATA[4] = 0x00
    msg.DATA[5] = 0x00
    msg.DATA[6] = 0x00
    msg.DATA[7] = 0x00
    time.sleep(0.05)
    #
    result = objPCAN.Write(channel, msg)

    if result != PCAN_ERROR_OK:
        # An error occured, get a text describing the error and show it
        #
        result = objPCAN.GetErrorText(result)
        #print(result)
    else:
        i = 2
        #print("Message sent successfully")

    end = time.perf_counter()
    duration = end - start
    #print(duration)
    #print(' ')
'''

# All initialized channgels are released
#
result = objPCAN.Uninitialize(PCAN_NONEBUS)
if result != PCAN_ERROR_OK:
    # An error occured, get a text describing the error and show it
    #
    result = objPCAN.GetErrorText(result)
    print(result)
else:
    print("PCAN-USBx was UN-initialized")

giles
Posts: 9
Joined: Tue 22. Dec 2020, 10:30

Re: Heavy time latency in Python script

Post by giles » Fri 25. Dec 2020, 01:55

And below is the relevant code about the message status checking:

Code: Select all

 while (objPCAN.Read(channel)[0] & PCAN_ERROR_OK) == PCAN_ERROR_OK:
        stsSystem = objPCAN.Read(channel)[0]
        RecMsg = objPCAN.Read(channel)[1]
#        if stsSystem == 0:
#            print('Status of system is:', stsSystem)
        if (objPCAN.Read(channel)[0] & PCAN_ERROR_QRCVEMPTY) == PCAN_ERROR_QRCVEMPTY:
            break
    if RecMsg.ID != 0:
        print('CAN BUS Data is: ', list(RecMsg.DATA)[0])

but as I descript in above last replay, some messages are lost when Python script receiving. Could you please help to check it what's happened ?
M.Heidemann wrote:
Tue 22. Dec 2020, 14:47
Hello,

You do not seem to read until the ReceiveBuffer is empty,
which could be the cause for this.

Please make sure that you read messages in a loop based on the condition that the message-queue is not empty (Using return value TPCANStatus.PCAN_ERROR_QRCVEMPTY).

Otherwise you will only read the next message in the buffer, which might is older.

This is also described in the PCANBasic API documentation:

BASICReceive.PNG

Furthermore you can take a look at the PCANBasic example for Python included in the PCANBasic package,
the same mechanism is used there:

https://www.peak-system.com/fileadmin/m ... -basic.zip

Code: Select all

 def ReadMessages(self):
        stsResult = PCAN_ERROR_OK

        # We read at least one time the queue looking for messages.
        # If a message is found, we look again trying to find more.
        # If the queue is empty or an error occurr, we get out from
        # the dowhile statement.
        #
        while (self.m_CanRead and not (stsResult & PCAN_ERROR_QRCVEMPTY)):
            stsResult = self.ReadMessageFD() if self.m_IsFD else self.ReadMessage()
            if stsResult == PCAN_ERROR_ILLOPERATION:
                break
Please report back to us if this has solved your issue.

Best Regards

Marvin

giles
Posts: 9
Joined: Tue 22. Dec 2020, 10:30

Re: Heavy time latency in Python script

Post by giles » Fri 25. Dec 2020, 11:05

Dear Sir,
I found the CAN bus empty status checking code may be the root cause for the messages lost
Is this sentence need more time to process in your basic software?

and now I will filter the messages ID which I want in main loop while out of the while loop.
to check if the code receive the messages via if the ID of message is 0.

with above process, code now can work normally and messages also can be received completely.

But no CAN status check information now in code, so if you have a better solution with CAN status judgement, could you please inform me and thanks very much for your great support.

Code: Select all

   while (True):
#        stsSystem = objPCAN.Read(channel)[0]
        RecMsg = objPCAN.Read(channel)[1]
        if RecMsg.ID != 0:
            print(list(RecMsg.DATA))
            break

M.Heidemann
Sales & Support
Sales & Support
Posts: 416
Joined: Fri 20. Sep 2019, 13:31

Re: Heavy time latency in Python script

Post by M.Heidemann » Fri 25. Dec 2020, 19:20

Hello,

i noticed you use the return of "PCAN_ERROR_OK" as your condition for the read loop, which might leads to
the behaviour you have seen, as you will break the condition as soon as something else is returned, wether or not the queue
is actually empty at this point.

The ideal implementation is shown in the PCANBasic Python example,
which is exactly the reverse order:

The function read messages will either call "ReadMessageFD" or "ReadMessage" (Depending on the messagetype) as
long as "PCAN_ERROR_QRCVEMPTY" is not returned.

Look for the function "ReadMessages" in the Python example of the PCANBasic Package:

Code: Select all

  def ReadMessages(self):
        stsResult = PCAN_ERROR_OK

        # We read at least one time the queue looking for messages.
        # If a message is found, we look again trying to find more.
        # If the queue is empty or an error occurr, we get out from
        # the dowhile statement.
        #
        while (self.m_CanRead and not (stsResult & PCAN_ERROR_QRCVEMPTY)):
            stsResult = self.ReadMessageFD() if self.m_IsFD else self.ReadMessage()
            if stsResult == PCAN_ERROR_ILLOPERATION:
                break
The called functions will check for "PCAN_ERROR_OK" and will only
process the message if it is returned (Processing could be printing the message, for example):

Code: Select all

def ReadMessage(self):
        # We execute the "Read" function of the PCANBasic
        #
        result = self.m_objPCANBasic.Read(self.m_PcanHandle)

        if result[0] == PCAN_ERROR_OK:
            # We show the received message
            #
            self.ProcessMessage(result[1:])
            
        return result[0]
The "ReadMessages"-function itself is called by either on timer-tick,with a receive event or manually on call.

In your case you might want to implement a timer based version of the read,
please see the provided example for Python in the PCANBasic-Package to see how this can be implemented.


Please let us know, if this was helpful to you.

Best Regards

Marvin

giles
Posts: 9
Joined: Tue 22. Dec 2020, 10:30

Re: Heavy time latency in Python script

Post by giles » Mon 4. Jan 2021, 12:19

Dear Sir,
Thanks very much for your swift response, and the main reason maybe out of I invoke the Read function twice, so lead the data update in buffer, now I update the code as below, all issues are killed now.

Besides, do we have the .dbc file decode file example for python or cpp which can realize the data decoding in real-time from CAN bus with the .dbc file application?

Thanks very much and have a nice day and happy new year.

Code: Select all

    while (True):
#        stsSystem = objPCAN.Read(channel)[0]
        RecMsg = objPCAN.Read(channel)
        sysStatus = RecMsg[0]
        RecData = RecMsg[1]
        #if RecMsg.ID != 0:
        if sysStatus != PCAN_ERROR_QRCVEMPTY:
            print(list(RecData.DATA))
            i = i + 1
            print(i)
            break

M.Heidemann
Sales & Support
Sales & Support
Posts: 416
Joined: Fri 20. Sep 2019, 13:31

Re: Heavy time latency in Python script

Post by M.Heidemann » Mon 4. Jan 2021, 12:25

Hello,

We are glad that you were able to resolve your issue.

We do not offer examples to implement a DBC-file parser, you'll need to implement
this yourself.

For further questions feel free to contact me again.

Best Regards

Marvin

giles
Posts: 9
Joined: Tue 22. Dec 2020, 10:30

Re: Heavy time latency in Python script

Post by giles » Wed 6. Jan 2021, 15:31

Thanks very much for your great support!

Post Reply