Dear Noah,
I have the very same problem then you.
I can 24 times send a command, then the ligth stucks and plc crashes and tells me, the io link module is offline.
If it is really caused by the library, where to get the updated version from?
Thanks and regards
Lucas
It was not the library that was causing the issue I was having but rather an internal read buffer that overflowed and caused the card to run into an error state. This is fixed by “reading” an acknowledgment from the write cycle of the card to clear that buffer. Here is the code that fixed it for our system. Of course you will need to update the variables to your own but the concept is all the same.
I have two write sequences as I am writing to two different lights. The error happens every 24 write cycles to the combined number of channels that is being used. i.e. 2 channels means 12 total write cycles (2 to each channel). You can copy and reuse the write cycles for the channel 3 or 4 as well.
FLT_WRITE1: (* send data *)
(* set Sender.size of frame *)
Sender.FLT_write.enable := TRUE;
Sender.FLT_write.bufLen := SIZEOF(Sender.send_data);
Sender.FLT_write.pBuf := ADR(Sender.send_data);(* enable the FUB *)
Sender.FLT_write(); (* run FUB *)
IF Sender.FLT_write.status = ERR_OK THEN
Sender.step := FLT_WAIT_ECHO1; (* if data was written, goto start *)
ELSIF Sender.FLT_write.status <> 65535 THEN
Sender.step := FLT_ERROR; (* if something goes wrong -> ERROR *)
END_IF
FLT_WAIT_ECHO1: (* wait for the echo from the other side *)
Sender.FLT_read.enable := TRUE; (* enable the FUB *)
Sender.FLT_read.pBuf := ADR(Sender.recv_data); (* announce recv buffer to the FUB *)
Sender.FLT_read.bufLen := SIZEOF(Sender.recv_data); (* set the recv buffer length *)
Sender.FLT_read(); (* run FUB - acknowledge recveived data *)
Sender.FLT_write.enable := TRUE; (* enable the FUB *)
Sender.FLT_write.pBuf := ADR(Sender.send_data); (* announce frame data to the FUB *)
Sender.FLT_write.readSequ := Sender.FLT_read.readSequ; (* acknowledge the recveived data to the HW-Module *)
Sender.FLT_write.bufLen := 0; (* only acknowledging - no data to send *)
Sender.FLT_write(); (* run FUB - acknowledge recveived data *)
//Sender.step := FLT_READY;
IF Sender.FLT_read.status = ERR_OK THEN
; // no data received run again
ELSIF Sender.FLT_read.status = fltERR_FRAME_FINISHED THEN
Sender.step := FLT_CHECK_ECHO1; //(* frame was completed in the recv buffer
ELSIF Sender.FLT_read.status = ERR_FUB_BUSY THEN
; //(* some frame was insert in the recv buffer, but the frame is not finished
ELSE
Sender.step := FLT_ERROR;
END_IF
FLT_CHECK_ECHO1: (* check the received echo *)
IF (Sender.send_data[0] = Sender.recv_data[0]) AND
(Sender.send_data[1] = Sender.recv_data[1]) AND
((Sender.send_data[2] AND 2#00000111) = (Sender.recv_data[2] AND 2#00000111)) AND
(Sender.send_data[2].7 = Sender.recv_data[2].7) THEN
Sender.step := FLT_WRITE2; (* if the echo match -> reset *)
brsmemcpy(ADR(Sender.command.ioLinkReceive[0]), ADR(Sender.recv_data[3]), SIZEOF(Sender.command.ioLinkReceive[0]));
Sender.command.start := FALSE;
ELSE
// Sender.step := FLT_ERROR; (* if the echo doesnt match -> ERROR *)
END_IF
FLT_WRITE2:
Sender.send_data[0] := Sender.command.Channel2;
Sender.FLT_write.enable := TRUE;
Sender.FLT_write.bufLen := SIZEOF(Sender.send_data);
Sender.FLT_write.pBuf := ADR(Sender.send_data);
Sender.FLT_write();
IF Sender.FLT_write.status = ERR_OK THEN
Sender.step := FLT_WAIT_ECHO2;
ELSIF Sender.FLT_write.status <> 65535 THEN
Sender.step := FLT_ERROR;
END_IF
FLT_WAIT_ECHO2:
Sender.FLT_read.enable := TRUE;
Sender.FLT_read.pBuf := ADR(Sender.recv_data);
Sender.FLT_read.bufLen := SIZEOF(Sender.recv_data);
Sender.FLT_read();
Sender.FLT_write.enable := TRUE;
Sender.FLT_write.pBuf := ADR(Sender.send_data);
Sender.FLT_write.readSequ := Sender.FLT_read.readSequ;
Sender.FLT_write.bufLen := 0;
Sender.FLT_write();
//Sender.step := FLT_READY;
IF Sender.FLT_read.status = ERR_OK THEN
; // no data received run again
ELSIF Sender.FLT_read.status = fltERR_FRAME_FINISHED THEN
Sender.step := FLT_CHECK_ECHO2; //(* frame was completed in the recv buffer
ELSIF Sender.FLT_read.status = ERR_FUB_BUSY THEN
; //(* some frame was insert in the recv buffer, but the frame is not finished
ELSE
Sender.step := FLT_ERROR;
END_IF
FLT_CHECK_ECHO2:
IF (Sender.send_data[0] = Sender.recv_data[0]) AND
(Sender.send_data[1] = Sender.recv_data[1]) AND
((Sender.send_data[2] AND 2#00000111) = (Sender.recv_data[2] AND 2#00000111)) AND
(Sender.send_data[2].7 = Sender.recv_data[2].7) THEN
Sender.step := FLT_READY;
brsmemcpy(ADR(Sender.command.ioLinkReceive[0]), ADR(Sender.recv_data[3]), SIZEOF(Sender.command.ioLinkReceive[0]));
Sender.command.start := FALSE;
ELSE
// Sender.step := FLT_ERROR;
END_IF
Dear Noah,
thanks for sharing your code.
I have tried the B&R example posted here earlier DS438A_example.zip.
Some modifications and working well.
Now I have one LED stripe for testing, later 5 pieces…
I have shifted the tasks for comm libraries from TK#1 2ms to TK#8 and is still working.
Best regards
Lucas