Linklist

14 Aralık 2015 Pazartesi

Circular Buffering

Keywords for a google search about the subject: Data bufferingbufferingqueue implementationFIFO buffer, ...

Lately I come across similar questions about buffering mechanism in automation engineering forums. I've already written a simple introduction to this problem two-three months ago in Turkish. When I see the same question in linked-in, I wanted to translate this blog into English...

The very first introduction is to understand when to decide to use a buffering mechanism.

Assume, there is conveyor and a camera is evaluating parts on the entrance of this conveyor. At the end of the conveyor, there is a gripper to pick&place the incoming parts, and a boxer is taking out the defected products out of the converyor belt. To make it simple, lets assume that any two parts gap distance is fixed. So a conveyor with a limited length can carry a fixed number of parts. Which can simply be calculated as;

iMaxPartNumberOnConveyor := iDistanceBetweenCameraAndConveyorEnd / (iPartLength + iGapLength);

So our buffer should have at least that much empty cells...


I think it will be more clear to describe the solution with some drawings...






Then you may also read the following pseudo-code, in ST language.
R_TRIG_PartSensor(CLK := DI_PartSensor);
PartDetectedPulse := R_TRIG_PartSensor.Q;
(*part recording to buffer*)
if PartDetectedPulse then
(*record position to buffer store cell*)
Buffer[StoreCell] := ConveyorPosition;
(*increase store cell, if buffer size reached then store to the first buffer cell (circular buffer)*)
if (StoreCell < (Buffersize - INT#1))  then
StoreCell := StoreCell + INT#1;
else
StoreCell := INT#0;
end_if;
end_if;
(*part reading - to give an idea how to do it, several needs can cause a part read. For instance; if the part passes over the minimum working area...*)
R_TRIG_ReadPart(CLK := ReadPart);
PartReadPulse := R_TRIG_ReadPart.Q;
if PartReadPulse then
if NOT (StoreCell = UseCell) then
(*Get part position *)
PartPosition := Buffer[UseCell];
(*increase UseCell, if buffer size reached then store to the first buffer cell (circular buffer)*)
if (UseCell < (Buffersize - INT#1))  then
UseCell := UseCell + INT#1;
else
UseCell := INT#0;
end_if;
else
(*warn user*)
NoPartInBuffer := TRUE;
end_if;
end_if;

(*delete user warning*)
if not ReadPart then
NoPartInBuffer := FALSE;
end_if;
NOT: Code seems better in  notepad++ ;)

If you have further questions, feel free to ask.


Hiç yorum yok:

Yorum Gönder