Host Engineering Forum

General Category => Do-more CPUs and Do-more Designer Software => Topic started by: Bobby Tables on March 26, 2026, 01:05:52 PM

Title: Ring buffer for fault logging
Post by: Bobby Tables on March 26, 2026, 01:05:52 PM
I've been lurking for a while but this is my first post.

Background for the issue:
I want to record the machine state as a file that is able to be loaded into DmDesigner on the simulator so I can troubleshoot the machine state remotely. The BACKUP instruction takes multiple scans to complete so machine states may change before it is done.

I would also like to log important state history leading up to the fault in a ring buffer to be logged in the event of a fault. So as to not bog down the system and the log with writing non important events.

I want to log fault bits being turned on at rungs that trigger them 0->1. The machine itself has a fault reset switch that will turn off the faults when the cause has been resolved. But I want to use FILELOG or DMLOGGER as an event log so I know what rung caused the fault, important machine state bits, etc. so errors can be reproduced.

To solve the multi scan BACKUP issue I would like to similarly buffer the machine state of the last few scans before the fault occurred.

The issue is FILELOG and DMLOGGER do not have a ring buffer to allow the order and time to be preserved. And I have had trouble finding example of implementing a ring buffer for an event log on here.


Question for the forum:



The implementation I want is
Event logging rough idea:

---|state_variable1 rising contact|---(write to buffer)

---|write_complete_bit|----(MATH: buffer_length=buffer_length+1)

---|state_variable1 falling contact|---(write to buffer)

---|write_complete_bit|----(MATH: buffer_length(V###)=buffer_length+1)

---|fault_on_bit|----(read_from_buffer_trigger_bit)

[fault handling logic follows and the machine enters a stopped state]

----|machine_is_stopped_state_bit|------[logic to read from buffer in order using for loop and/or buffer read instruction for FIFO into FILELOG or DMLOGGER]
 
Or creating an image reading from a different larger buffer with the whole machine state in the last few scans
 
---|read_1_buffer_entry_complete_bit|----(MATH:  buffer_length=buffer_length-1)

---|EQU buffer_length=0|-----(buffer_length_is_full_bit)

The FIFO buffer by default doesn't seem to necessarily be a ring buffer implementation. Is there a way to modify it to work like one?
for reference
https://en.wikipedia.org/wiki/Circular_buffer (https://en.wikipedia.org/wiki/Circular_buffer)tcplclib_tc2_utilities/35413643.html&id= (https://infosys.beckhoff.com/english.php?content=../content/1033/tcplclib_tc2_utilities/35413643.html&id=)
Title: Re: Ring buffer for fault logging
Post by: BobO on March 26, 2026, 01:51:07 PM
A ring buffer is just a simple fast implementation of a FIFO that allows addition of records without copying/shifting the data. A FIFO isn't always implemented as a ring buffer, but a ring is generally considered to be a FIFO.

If you are intending the FIFO to store the last N records, losing the oldest as you add a new record, just call FIFOUNLOAD before FIFOLOAD when MyFifo.Full is true. A ring buffer implementation would need to bump the tail to accomplish the same thing.

If you would prefer to implement this as ring buffer, it's really quite simple. Make your buffer size a power of 2. Use one V location as the head pointer and another as the tail pointer. Create a bit mask of the buffer size - 1. If the buffer is 256 elements, the mask is 0x00FF. For 1024, it would be 0x03FF.

Empty = Head == Tail
Full = (Head+1)&Mask == Tail

Add a record (if !Full):
Buffer[Head] = NewVal
Head = (Head+1)&Mask

Remove a record (if !Empty):
OldVal = Buffer[Tail]
Tail = (Tail+1)&Mask

But honestly, just use the FIFO.