Hi,we are developing a Windows application that aims to Simulate a LIN Pump.
The simulator acts as a Slave and must answer to requests from a Master board.
Master board requests multiple 0x3C packets with different SIDs and DIDs in a small amount of time (up to 10 requests per second)
Our suspect is that, sometimes, answers are wrong, 'cause the software can't update the correct answer to PCAN-USB in time.
Is it possible to 'delay' the response, or make PLIN-USB answer only after the correct message is updated in its memory?
How could we approach this issue?
See below some code excerpts, hoping you can give us some enlightenment.
Initialization
# Initialize hardware as Slave with specified baud rate
result = self.plin_api.InitializeHardware(
self.client_handle,
self.hardware_handle,
TLIN_HARDWAREMODE_SLAVE,
c_ushort(self.baudrate)
)
Frames configuration
for frame_id, direction in map.entries():
entry = TLINFrameEntry()
entry.FrameId = c_ubyte(frame_id)
entry.Length = c_ubyte(8) # Standard LIN frame length
entry.Direction = TLIN_DIRECTION_PUBLISHER if direction == "PUB" else TLIN_DIRECTION_SUBSCRIBER
entry.ChecksumType = TLIN_CHECKSUMTYPE_ENHANCED if frame_id < 0x3C else TLIN_CHECKSUMTYPE_CLASSIC
entry.Flags = FRAME_FLAG_RESPONSE_ENABLE
entry.InitialData = (c_ubyte * 8)(*([0] * 8)) # Initialize with zeros
result = self.plin_api.SetFrameEntry(self.client_handle, self.hardware_handle, entry)
--> Is it possible to use FRAME_FLAG_ONESHOT instead of FRAME_FLAG_RESPONSE_ENABLE here ? How?
Message Receiver and processor:
def run(self):
"""Run the receive loop in Qt thread"""
self.running = True
self.consecutive_errors = 0 # Reset error counter
while self.running:
if self.protocol.is_connected and self.protocol.plin_api:
# Read messages from the LIN hardware
read_msg = TLINRcvMsg()
result = self.protocol.plin_api.Read(self.protocol.client_handle, read_msg)
if result == TLIN_ERROR_OK:
# Success - reset consecutive error counter
self.consecutive_errors = 0
# Process the received message - this will emit signals to UI
self.protocol._process_received_message(read_msg)
Answer Message updater, triggered by Message handler on diagnostic message reception:
lin_msg = TLINMsg()
lin_msg.FrameId = c_ubyte(frame_id & 0x3F) # LIN ID is 6 bits, mask upper parity bits
lin_msg.Length = c_ubyte(len(data))
lin_msg.Direction = TLIN_DIRECTION_PUBLISHER
lin_msg.ChecksumType = TLIN_CHECKSUMTYPE_ENHANCED if frame_id < 0x3C else TLIN_CHECKSUMTYPE_CLASSIC
lin_msg.Checksum = c_ubyte(0) # Let hardware calculate
#if frame_id & 0x3F == 2:
# data = [0xFF]*8
# Copy data
data_array = (c_ubyte * 8)()
for i in range(min(len(data), 8)):
data_array = c_ubyte(data)
lin_msg.Data = data_array
# Send the message -- Master LIN writes directly, SLAVE uses UpdateByteArray
result = self.plin_api.UpdateByteArray(self.client_handle, self.hardware_handle,
c_ubyte(frame_id & 0x3F),
c_ubyte(0), #index
c_ubyte(lin_msg.Length), lin_msg.Data)
Thank you for your help,
L
Troubles using PLIN-USB (via PLinApi from python) as Slave
Re: Troubles using PLIN-USB (via PLinApi from python) as Slave
Hi,
After you have updated the data by calling the UpdateByteArray function, the PLIN-USB will use this data for the next master subscriber frame request.
Further information about LIN frame flags can also be found in the PLIN API documentation under Getting Started => The LIN Frame Entry
Regards
M.Lang
No, the response cannot be delayed directly, if you use UpdateByteArray.Is it possible to 'delay' the response, or make PLIN-USB answer only after the correct message is updated in its memory?
After you have updated the data by calling the UpdateByteArray function, the PLIN-USB will use this data for the next master subscriber frame request.
You must choose the right time to update the data. However, you can watch the subscriber frames requested by the master and determine when another update is necessary.How could we approach this issue?
Do you mean FRAME_FLAG_SINGLE_SHOT, perhaps? Yes, you can only use that with a LIN slave.--> Is it possible to use FRAME_FLAG_ONESHOT instead of FRAME_FLAG_RESPONSE_ENABLE here ? How?
Further information about LIN frame flags can also be found in the PLIN API documentation under Getting Started => The LIN Frame Entry
Regards
M.Lang
Re: Troubles using PLIN-USB (via PLinApi from python) as Slave
Thanks for the reply, but I'm still confused.
In my use case, the response depends on the 3C frame payload.
I.e. Master requests, in a burst:
RX ID: 3C Data: 02 03 22 00 04 FF FF FF CRC: D4
RX ID: 3C Data: 02 03 22 01 04 FF FF FF CRC: D3
RX ID: 3C Data: 02 03 22 03 04 FF FF FF CRC: D1
RX ID: 3C Data: 02 03 22 06 04 FF FF FF CRC: CE
RX ID: 3C Data: 02 03 22 04 04 FF FF FF CRC: D0
RX ID: 3C Data: 02 03 22 05 04 FF FF FF CRC: CF
RX ID: 3C Data: 02 03 22 07 04 FF FF FF CRC: CD
RX ID: 3C Data: 02 06 B2 22 A9 00 00 00 CRC: 79
RX ID: 3C Data: 02 06 B2 00 A9 00 00 00 CRC: 9B
RX ID: 3C Data: 02 03 22 02 04 FF FF FF CRC: D2
So I should be able to
1. receive the request,
2. update the array for the 3D frame, with the correct answer, before PLIN-USB responds,
3. finally, get PLIN-USB respond on the BUS.
How can I achieve this behavior?
Otherwise, if PLIN-USB answers before I had the opportunity to update the array, it will respond with a potentially incorrect payload.
Can FRAME_FLAG_SINGLE_SHOT help?
I actually tried to configure FRAME_FLAG_SINGLE_SHOT on frame 3D, but I get error 0x18 (I guess TLIN_MSGERROR_SLAVE_NOT_RESPONDING | TLIN_MSGERROR_TIMEOUT)
sorry if these are stupid questions, but I-m a newbie in LIN communications and in PEAK products.
In my use case, the response depends on the 3C frame payload.
I.e. Master requests, in a burst:
RX ID: 3C Data: 02 03 22 00 04 FF FF FF CRC: D4
RX ID: 3C Data: 02 03 22 01 04 FF FF FF CRC: D3
RX ID: 3C Data: 02 03 22 03 04 FF FF FF CRC: D1
RX ID: 3C Data: 02 03 22 06 04 FF FF FF CRC: CE
RX ID: 3C Data: 02 03 22 04 04 FF FF FF CRC: D0
RX ID: 3C Data: 02 03 22 05 04 FF FF FF CRC: CF
RX ID: 3C Data: 02 03 22 07 04 FF FF FF CRC: CD
RX ID: 3C Data: 02 06 B2 22 A9 00 00 00 CRC: 79
RX ID: 3C Data: 02 06 B2 00 A9 00 00 00 CRC: 9B
RX ID: 3C Data: 02 03 22 02 04 FF FF FF CRC: D2
So I should be able to
1. receive the request,
2. update the array for the 3D frame, with the correct answer, before PLIN-USB responds,
3. finally, get PLIN-USB respond on the BUS.
How can I achieve this behavior?
Otherwise, if PLIN-USB answers before I had the opportunity to update the array, it will respond with a potentially incorrect payload.
Can FRAME_FLAG_SINGLE_SHOT help?
I actually tried to configure FRAME_FLAG_SINGLE_SHOT on frame 3D, but I get error 0x18 (I guess TLIN_MSGERROR_SLAVE_NOT_RESPONDING | TLIN_MSGERROR_TIMEOUT)
sorry if these are stupid questions, but I-m a newbie in LIN communications and in PEAK products.
Re: Troubles using PLIN-USB (via PLinApi from python) as Slave
Hi,
In most cases, a LIN diagnostic frame (0x3C and 0x3D) should work as follows:
1. LIN master publishes: ID: 3C Data: 02 03 22 00 04 FF FF FF CRC: D4
2. LIN master waits (e.g. 5-10 ms)
3. LIN master subscribes: ID: 3D (header only)
4. LIN master waits for response (e.g. 5-10 ms)
5. Meanwhile, LIN slave publishes: ID 3D (append data)
In the scenario you describe, the steps may look like this:
1. Read all LIN frames you received
2. Check each LIN frame, especially the last received 0x3C
3. Once you have received the desired LIN frame 0x3C, you must immediately update the data of LIN frame 0x3D before the LIN master requests it or the LIN slave responds to it.
Regards
M.Lang
This depends on when (timing) the LIN master publishes and subscribes to the 0x3C and 0x3D LIN frames.So I should be able to
1. receive the request,
2. update the array for the 3D frame, with the correct answer, before PLIN-USB responds,
3. finally, get PLIN-USB respond on the BUS.
How can I achieve this behavior?
In most cases, a LIN diagnostic frame (0x3C and 0x3D) should work as follows:
1. LIN master publishes: ID: 3C Data: 02 03 22 00 04 FF FF FF CRC: D4
2. LIN master waits (e.g. 5-10 ms)
3. LIN master subscribes: ID: 3D (header only)
4. LIN master waits for response (e.g. 5-10 ms)
5. Meanwhile, LIN slave publishes: ID 3D (append data)
In the scenario you describe, the steps may look like this:
1. Read all LIN frames you received
2. Check each LIN frame, especially the last received 0x3C
3. Once you have received the desired LIN frame 0x3C, you must immediately update the data of LIN frame 0x3D before the LIN master requests it or the LIN slave responds to it.
Yes, but the LIN frame is only published once when the data has been updated with UpdateByteArray. After that, you will receive the errors.Can FRAME_FLAG_SINGLE_SHOT help?
I actually tried to configure FRAME_FLAG_SINGLE_SHOT on frame 3D, but I get error 0x18 (I guess TLIN_MSGERROR_SLAVE_NOT_RESPONDING | TLIN_MSGERROR_TIMEOUT)
Regards
M.Lang
Re: Troubles using PLIN-USB (via PLinApi from python) as Slave
I tried various optimizations:
1. response caching to answer to 3D frame as fast as possible
2. 3C request and 3D answer moved into a C library to minimize latency (in case python can't reliably guarantee milliseconds latency)
3. all other frames are forwarded to python and processed there.
Current setup for 3D frame is FRAME_FLAG_RESPONSE_ENABLE / UpdateByteArray().
The issue seems mitigated, but under heavy machine load (i.e. Android Studio opening and project loading timespan....) still present.
I also tried FRAME_FLAG_SINGLE_SHOT / Write() -> errXmtQueueFull (C Api)
I also tried FRAME_FLAG_SINGLE_SHOT / UpdateByteArray() -> errOK (C Api) but cannot see the message reach the bus.
Master response wait time is avg 20ms
I really can't see what I can do; I guess I'm not using FRAME_FLAG_SINGLE_SHOT correctly. Is any example available?
1. response caching to answer to 3D frame as fast as possible
2. 3C request and 3D answer moved into a C library to minimize latency (in case python can't reliably guarantee milliseconds latency)
3. all other frames are forwarded to python and processed there.
Current setup for 3D frame is FRAME_FLAG_RESPONSE_ENABLE / UpdateByteArray().
The issue seems mitigated, but under heavy machine load (i.e. Android Studio opening and project loading timespan....) still present.
I also tried FRAME_FLAG_SINGLE_SHOT / Write() -> errXmtQueueFull (C Api)
I also tried FRAME_FLAG_SINGLE_SHOT / UpdateByteArray() -> errOK (C Api) but cannot see the message reach the bus.
Master response wait time is avg 20ms
I really can't see what I can do; I guess I'm not using FRAME_FLAG_SINGLE_SHOT correctly. Is any example available?
Re: Troubles using PLIN-USB (via PLinApi from python) as Slave
Hi,
By default it is approximately 15–16 ms. This can cause difficulties with an average wait time of 20 ms for LIN master response.
Methods like Sleep(1) will wait at least 1 ms, but the actual delay may be longer.
If you need more precise timing, you can temporarily increase the system timer resolution using native Windows APIs such as timeBeginPeriod(1) and timeEndPeriod(1).
But increasing the timer resolution can impact system performance and power consumption, so it should only be used when necessary and reset afterwards.
Have you combinded the FRAME_FLAG_RESPONSE_ENABLE and FRAME_FLAG_SINGLE_SHOT flags?
You can also filter the reception of LIN frames by first setting a client filter using the SetClientFilter method.
Filter for 0x3C and 0x3D LIN frames:
Regards
M.Lang
Do you change the Windows system timer resolution?Current setup for 3D frame is FRAME_FLAG_RESPONSE_ENABLE / UpdateByteArray().
The issue seems mitigated, but under heavy machine load (i.e. Android Studio opening and project loading timespan....) still present.
By default it is approximately 15–16 ms. This can cause difficulties with an average wait time of 20 ms for LIN master response.
Methods like Sleep(1) will wait at least 1 ms, but the actual delay may be longer.
If you need more precise timing, you can temporarily increase the system timer resolution using native Windows APIs such as timeBeginPeriod(1) and timeEndPeriod(1).
But increasing the timer resolution can impact system performance and power consumption, so it should only be used when necessary and reset afterwards.
As a LIN slave, you cannot use the Write method.I also tried FRAME_FLAG_SINGLE_SHOT / Write() -> errXmtQueueFull (C Api)
I also tried FRAME_FLAG_SINGLE_SHOT / UpdateByteArray() -> errOK (C Api) but cannot see the message reach the bus.
Have you combinded the FRAME_FLAG_RESPONSE_ENABLE and FRAME_FLAG_SINGLE_SHOT flags?
Code: Select all
entry.Flags = PLinApi.FRAME_FLAG_RESPONSE_ENABLE | PLinApi.FRAME_FLAG_SINGLE_SHOT;Filter for 0x3C and 0x3D LIN frames:
Code: Select all
SetClientFilter(client, hw, 0x3000000000000000);Please check out the example of the PLIN API.I really can't see what I can do; I guess I'm not using FRAME_FLAG_SINGLE_SHOT correctly. Is any example available?
Regards
M.Lang
