How not to count



  • So, you have a PLC and want to count something, for example the number of times a day a ball rolls through a tube of some kind. Simple? Well, depends on how you go about it. You could just use a counter and add 1 each time a ball rolls by, but that's only like five minutes of work and all too easy. Here is how the professionals do it:

    Declare three arrays of the datatype word (which is 16 bits in this case) of length 150:

    monthday AT %MW100 : ARRAY [1..150] OF WORD;
    hourminute AT %MW200 : ARRAY [1..150] OF WORD;
    secondnuffin AT %MW350 : ARRAY [1..150] OF WORD;

    Now, every time a ball rolls by and we get a signal from the sensor you just have to take the current month, day, hour, minute and second and put that in the appropriate place in the array! To make this human readable you should make sure to assign it like this, assuming a ball rolled by on August 5th at 14:10:11:

    monthday[currentIndex] := 16#0805;
    hourminute[currentIndex] := 16#1410;
    secondnuffin[currentIndex] := 16#1100;
    currentIndex := currentIndex + 1;

    IF currentIndex > 150 THEN
    currentIndex := 1;
    ENDIF

    See the pattern? That's professional simplicity at work! Screw the datatypes specifically made for handling time and dates, nobody should use them anyway. When the index counter reaches 150 we'll just reset it to 1 and all will be good. At a specific time of day an external system will reach into the PLC and count the amount of non-zero entries and present the summarized ball droppings in a nice chart. To make this coding exercise even more exciting make sure to overlap two of the arrays.

    (I have not yet seen the piece of code that translates the decimal dates/times into the obscene hexadecimal counterpart nor the other way around, and I am not sure I want to. The PLC controls pieces of heavy machinery, and yes, the rest of it is just as fucked up.)


  • Notification Spam Recipient

    They obviously wanted to make sure the PLC wasn't vulnerable to a timing attack.



  • @phnom said in How not to count:

    At a specific time of day an external system will reach into the PLC and count the amount of non-zero entries and present the summarized ball droppings in a nice chart.

    After a while, won’t this simply always add 150 to the total any time it polls the PLC?



  • @Gurth true, the external system will also need to zero out the arrays right after it reads them. Although that may have just been an oversight in the explanation.



  • @phnom said in How not to count:

    datatypes specifically made for handling time and dates

    Does the PLC have any? Most of the ones I've used did not.

    Overall, that sounds like a fairly reasonable approach if we have these assumptions:

    • the system needs to record the exact date/time every time a ball passes the sensor -- maybe the designer thought that the HMI was going to allow the user to view this raw data, or that it could be useful as a future improvement
    • there will always be fewer than 150 events in whatever interval of time the external system polls the PLC and resets the arrays

    So yeah, it's probably over-designed, but I can see what the designer might have been thinking which caused it.

    The arrays overlapping is the only real bug. I'm guessing the original design was to have only monthday and hourminute arrays, with room for 100 events, and the fact that there wasn't enough space wasn't noticed when the array sizes were increased to 150 and another array for seconds was added.


  • area_can

    How not to count something: nodebb page numbers



  • @phnom said in How not to count:

    I have not yet seen the piece of code that translates the decimal dates/times into the obscene hexadecimal counterpart nor the other way around

    It's packed BCD. Likely the PLC has built-in instructions to convert between decimal and BCD.



  • @anotherusername said in How not to count:

    @phnom said in How not to count:

    I have not yet seen the piece of code that translates the decimal dates/times into the obscene hexadecimal counterpart nor the other way around

    It's packed BCD. Likely the PLC has built-in instructions to convert between decimal and BCD.

    I'm just gonna crawl into a corner and hide now, of course you are correct... Have a 🍪 !



  • @anotherusername said in How not to count:

    Does the PLC have any? Most of the ones I've used did not.

    It does as far as I can tell, there actually is a DATE_AND_TIME datatype in the IEC-standard, but it seems like all the different brands just go with whatever the hell they want sometimes.

    Overall, that sounds like a fairly reasonable approach if we have these assumptions:

    • the system needs to record the exact date/time every time a ball passes the sensor -- maybe the designer thought that the HMI was going to allow the user to view this raw data, or that it could be useful as a future improvement

    No, it does not, which is why I find the array a peculiar choice. The external systems just sums up the data and shows it per day.

    • there will always be fewer than 150 events in whatever interval of time the external system polls the PLC and resets the arrays

    Yeah, the event count in this case would stay under the limit (unless something extraordinary happened), though the wrap-around did not actually work which is why we started looking at the code in the first place.



  • @phnom said in How not to count:

    It does as far as I can tell, there actually is a DATE_AND_TIME datatype in the IEC-standard, but it seems like all the different brands just go with whatever the hell they want sometimes.

    Only the newer ones that I've seen supported it, as far as I know. Most of the ones I've actually used had separate hour, minute, and second registers.


Log in to reply