Troubles using PLIN-USB (via PLinApi from python) as Slave
Posted: Thu 27. Nov 2025, 11:24
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
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