Differentiating system versus user

I don't, that is a concern of mine also. Other team members aren't as concerned with this and say that clinicians can tell patients to "go along for the ride" for a while, and indicate when to start working. But that is placing a lot of trust in the users. ...


Trying to get valid, useful measurements from a device that cannot be calibrated is going to be ... well ... trying. See item (iii) below.


Good luck.
 
2 questions:
1. Are you using an adding machine (abacus maybe?) as a PLC?
2. What is the period of the sinusoid if you see it with a 5-second scan?

I am using a B&R X20 PLC. And that 5 second scan was an arbitrary value that I'm not fixed to, It just worked well in testing (3 seconds did not capture an accurate minimum, and 10 s was excessive), The period of the sinusoid is dependent on the speed and step length set for the user, but it will be equal to the time it takes to complete one step.

Is there some potential with that? From my understanding, the current sensor, speed, and rpm have not been the most reliable because the linkage system design required more/less torque at certain instances within the revolution, resulting in ranges of values instead of a clean reference point I can compare to. But the overall period or "step time" should be consistent and predictable based on the HMI speed/rpm (even if the rpm/speed fluctuates throughout one step, the period per step should be the same every step in order to maintain that average rpm). Based on the user setting I should be able to determine the period of the step to be my reference. If work is done by user, the speed/rpm should momentarily increase and the step should be completed faster (if StepTimeLive < StepTimeSet -> UserWork). It would eliminate scan times also in theory. Any thoughts on this approach? I'll start testing with this.
 
Last edited:
Let me step back a bit.

Are any or all of the following correct?

  • The is an HMI speed control setting, a speed setpoint.
  • The units of that speed setpoint are the footplates' RPM, or strides per minute, which is half of steps per minute (a stride is a left-step and right-step pair - I expect you know that, I am only writing it here to ensure the terms are defined).
  • The motor control attempts to keep the footplates moving at the setpoint footplates' RPM by varying the current to the motor
  • Even without a user's feet on the footplates, the system's resistance to movement varies throughout the footplates' cycle due to something (linkages? who knows; the details are not important)
  • That resistance is more or less sinusoidal varying at the footplates' step cycle i.e. twice the stride frequency.
  • That sinusoidal resistance induces a sinusoidal variation in the instantaneous speed (as measured by liveRpm?) of the system.
  • If the are no user's feet on the footplate, the current provided by the motor control at a given RPM setpoint will vary throughout each cycle to compensate for the variation in instantaneous speed induced by the variation in resistance.
  • That variation in current will be sinusoidal because it is in effect driven by the sinusoidal variation in resistance.
This is not even close to answering the thread's question; I am only trying to understand the system at this point.
 
Last edited:
2 questions:
1. Are you using an adding machine (abacus maybe?) as a PLC?
2. What is the period of the sinusoid if you see it with a 5-second scan?

Trying to get valid, useful measurements from a device that cannot be calibrated is going to be ... well ... trying. See item (iii) below.


Good luck.

Let me step back a bit.

Are any or all of the following correct?

  • The is an HMI speed control setting, a speed setpoint.

    Yes there is a speed setpoint ranging from 0.1 mph -1.8 mph. This can be adjusted before and while the machine is running.
  • The units of that speed setpoint are the footplates' RPM, or strides per minute, which is half of steps per minute (a stride is a left-step and right-step pair - I expect you know that, I am only writing it here to ensure the terms are defined).

    Yes, 1 revolution = 1 stride = 2 steps
  • The motor control attempts to keep the footplates moving at the setpoint footplates' RPM by varying the current to the motor

    Yes, that is correct. And if you try to "beat" the machine by putting in work, it will force you back down to that setpoint RPM.
  • Even without a user's feet on the footplates, the system's resistance to movement varies throughout the footplates' cycle due to something (linkages? who knows; the details are not important)

    Yes, when the system is unloaded and running empty, there is still system resistance in the footplates cycle and current fluctuation observed due to mechanical design.
  • That resistance is more or less sinusoidal varying at the footplates' step cycle i.e. twice the stride frequency.

    Yes, the resistance throughout the footplate's step cycle results in a relatively sinusoidal outputs. One stride (one step from each foot) is one complete "sin" wave.

  • That sinusoidal resistance induces a sinusoidal variation in the instantaneous speed (as measured by liveRpm?) of the system.

    Yes, that is correct.
  • If the are no user's feet on the footplate, the current provided by the motor control at a given RPM setpoint will vary throughout each cycle to compensate for the variation in instantaneous speed induced by the variation in resistance.

    Yes, that is correct.
  • That variation in current will be sinusoidal because it is in effect driven by the sinusoidal variation in resistance.

    Yes.
This is not even close to answering the thread's question; I am only trying to understand the system at this point.

Apologies for any confusion, I should have explained the system design more clearly. My answers are above. All your statements are true about the system.

I had poor wording in my last post, the period of a STRIDE (not step) can potentially be considered a reference.
 
Due to the system resistance, the current, RPM/speed is sinusoidal like discussed, so I am working on using the period as an indicator of work being done. There is an observable drop in the period (duration for 1 rev or stride to be completed) when I do work.

Based on the setpoint speed/RPM, I have the theoreticalPeriod to use as my reference (this is a fixed value unless the speed is changed, then it updates accordingly). I would like some input on how to determine the "livePeriod". In the system design, as footplates are moving, there is an encoder wheel with 8 slots (8 pulses = 1 revolution = 2 steps) and a sensor to capture pulses.

One method is to time how long it takes for a counter (counting the pulses) to reach 8 which will tell us when one rev has occurred, then it will reset; the time measured would be livePeriod. However this approach will only spit out a livePeriod value once per revolution. I want the program to be more responsive, at least once per step would be ideal.

The liveRPM is found by taking the duration between pulses and multiplying by 8 (pulsePeriod) to get the period of the revolution, and use that to calculate the RPM. But again, due to the system resistance, that pulsePeriod deviates significantly from one reading to another (within one revolution), which is why the rpm is constantly changing sinusoidally. However, the sum of all 8 pulsePeriod values should equal the theoreticalPeriod for each revoltution (unless work is done of course).

My first attempt at this is to use only the pulse period * 8 pulses to get a more responsive result that could be seen in live time. However, at higher speeds, this resulted in "spikes" of UserWorkDetected occurring, when no work was done, due to the fact that some pulsePeriods are shorter than others due to the mechanical system.

I tried the following in ladder:
60 / setpointRPM = theoreticalPeriod
(pulsePeriod * 8) = livePeriod
if livePeriod < theoreticalPeriod =UserWorkDetected

Example from testing:
setpoint RPM = 32.172 (fixed value unless speed is changed)
TheoreticalPeriod = 1.865 (fixed value unless speed is changed)
livePeriod= ~ 1.83 - 1.904 (values fluctuate within this range with NO WORK)


The overlap of values below 1.865 results in "UserWorkDetected" to momentarily go HIGH inaccurately due to the pulse period being low naturally at that instant. When I do work, I can see livePeriod drop to ~1.7-1.83 with this logic. Is there a better way to determine the livePeriod variable that wont be as sensitive to the device resistance?

I had a thought to store the latest 8 pulsePeriods, and the sum of them is livePeriod, so as one new value comes in, it will be taken into account and updated frequently, but it wont be the only value under consideration, if that makes sense. Any input would be greatly appreciated. Thank you!!
 
Last edited:
Since each pulse from the encoder does not represent exactly one eighth of a revolution, you might need something along the lines of a crank angle sensor to calculate each pulse's contribution. Absent such a sensor, you might be able to generate a table of degree values for each pulse. Then the task will be to keep the pulse count aligned with the correct element in the table.
Also, I don't know what your encoder wheel looks like, but if the on and off times for each lobe of the wheel are the same, you can double your resolution by counting both the leading and trailing edges of the pulses.
 
Yes, unfortunately I am limited with the current hardware. Another challenge I face is that the device can start/stop in any position, there is not an incremental encoder sensor yet, so location of the footplates in its travel path is unknown, otherwise I would be able to identify the regions with higher/lower resistance and do something similar to degree value table you mentioned. But yes, my encoder wheel does have equal on/off lobes, utilizing that for more resolution id an interesting thought. Do you have any suggestions on how I can use that for this application for a more ideal livePeriod value?
 
One method is to time how long it takes for a counter (counting the pulses) to reach 8 which will tell us when one rev has occurred, then it will reset; the time measured would be livePeriod. However this approach will only spit out a livePeriod value once per revolution. I want the program to be more responsive, at least once per step would be ideal.


With an eight- or sixteen- element FIFO array, containing the last eight or sixteen times of transition, the PLC would be able to calculate how long it was for the past 8 or 16 transitions, and update that value at each transition, so there would be a one-cycle period updated every quarter or eighth of a second. Since the transitions being compared are one complete cycle apart, any irregularities between blocker lengths would not affect the calculation.
 
With an eight- or sixteen- element FIFO array, containing the last eight or sixteen times of transition, the PLC would be able to calculate how long it was for the past 8 or 16 transitions, and update that value at each transition, so there would be a one-cycle period updated every quarter or eighth of a second. Since the transitions being compared are one complete cycle apart, any irregularities between blocker lengths would not affect the calculation.


That was my initial thought as well, I think this is the best option I have now given my hardware limitations and system nature. So... I want use the pulse encoder wheel sensor going HIGH to be my trigger to to capture the pulsePeriod into the FIFO sized for 8 (or 16) elements. Then livePeriod = sum of all FIFO elements, so I'll get a new livePeriod value to compare against my reference theoreticalPeriod 8 (or 16) times per rev while accounting for pulse period irregularities the best that I can currently.

I haven't worked with FIFOs much before, and haven't seen it being called that in Automation Studio in ladder function blocks, I've tried looking into these a lot but haven't found one. Is there equivalent FB that is used in AS? Does anyone have experience with using FIFOs in AS or input on how to approach this?

I will be adding a reference sensor/incremental encoder in a future project, but this task has to be completed given the existing hardware, which is why I've been trying to exhaust all my options. Thank you all!
 
Last edited:
I haven't worked with FIFOs much before, and haven't seen it being called that in Automation Studio in ladder function blocks, I've tried looking into these a lot but haven't found one. Is there equivalent FB that is used in AS? Does anyone have experience with using FIFOs in AS or input on how to approach this?

There are at least two ways to implement a FIFO. But first, to define a FIFO:

  • A FIFO is an array that contains a series of measurements, usually from a series of events.
  • Each element in the array has two properties:
    • Its value, i.e. the measurement, at the time of the event represented by the element.
    • Its position, i.e. the element's index, within the array
      • This is the property of the element that is unique to the FIFO and that makes it useful
      • The sequence of positions in the array represent the sequence of events that placed their values into the array
In the current case,

  • the value of each element in the array is a time measurement of a encoder wheel sensor input transition event; it could be
    • the relative time since the previous event, or
    • the absolute time of the event
  • the index of each element represents which of the most recent 16 transitions generated that value, relative to the most recent transition.
With those definitions in place, here are two common implementations:

  • An linear array that shifts the values through the array and maintains a constant relationship between event ordinal and array index.
    • The oldest (first stored) event's value is always in array element 0
    • The newest (last stored) event value is always in array element N-1.
    • The arrival of a new event's value triggers two operations, which are often implemented by two FIFO instructions, unload and load
      • A FIFO unload operation will
        • "Pop" the oldest (FO "First Out") event's value from of the array at index (position) 0.
        • Shift the array element's values at indices (positions) 1 through L-1 by one position "down," i.e. into indices 0 through L-2
          • L is the number of elements (events) currently stored in the FIFO array
          • N.B. this overwrites the oldest (first stored) value in the array, which is why it was "popped" in the previous step.
        • Decrease the length, L, of the array by 1
      • A FIFO load operation will
        • "Push" a new event's value onto the array at index L
        • Increment the length, L, of the array by 1
    • How those two operations, load and unload, are implemented, e.g. as two separate instructions or as one instruction, is up to the vendor. Usually they are separate instructions as that allows a variable FIFO array length.
    • Note that, because popping the oldest value (FO; First Out) from, and pushing a new value (FI; First in) the FIFO array will not occur on every scan cycle, vendor-supplied FIFO instructions have a one-shot built in, so the FIFO shift is triggered on the single scan cycle only when an event signal becomes 1, and further shifts are prevented by the one-shot mechanism on subsequent scan cycles while that event signal is still 1.
  • A circular array that leaves each event's value at the index in the array into which it is first written, and has a variable relationship between event ordinal and array index.
    • The oldest (first stored) event's value is in array element at index , where I is a variable tag, with the value of I maintained by the program that varies from 0 to L-1.
      [*]The newest (last stored) event value is always in array element I-1 (or I+L-1, if I is 0).
      [*]The arrival of a new event's value triggers a few operations:
      • The oldest event's value is "popped" from array element at index
        [*]The newest event's value is written to array element at index , which overwrites the oldest events' value.
        [*]I is incremented by 1, and if that resulting incremented value is L, then I is assigned a value of 0
        • or apply a MODULO instruction if available, using L as the divisor
        • This is the origin of the phrase "circular" array: the index "increments" from the end of the array (index L-1) back to the beginning (index 0), as if the array elements were laid out in a circle.

        [*]N.B. this description does not include the case where the FIFO array length (L in the other implementation) changes; that can be covered but is not relevant to the current case of footplate encoder sensor transition timings.


      [*]I have not seen any vendor-supplied FIFO instructions using this implementation. So you would have to do it yourself, which would be the case anyway if Automation Direct does not have built-in FIFO instruction(s).
      [*]However, it is straightforward and applicable to the current case:
      • Move array value to a tag e.g. to "OLD"
        [*]Move the new event value to array
        [*]Add 1 to value of I, assign that result value to I
        [*]If incremented value of I is 16 (L), then assign a value of 0 to I
        [*]You would also need explicit one-shot logic.





Either of those implementations provides the oldest and newest values from the event transitions at the same phase point of a footplate cycle, i.e. from two events exactly one revolution apart. If those values are some form of absolute times or free-running time, then subtracting* oldest from newest yields the period of the most recent full revolution starting and ending at that phase.

* Depending on the meaning of those time values and where they come from, there could be rollover issues in the subtraction, but that is not difficult to deal with, and you were dealing with them anyway when calculating the time differences in your current system.
 
There are at least two ways to implement a FIFO. But first, to define a FIFO:

  • A FIFO is an array that contains a series of measurements, usually from a series of events.
  • Each element in the array has two properties:
    • Its value, i.e. the measurement, at the time of the event represented by the element.
    • Its position, i.e. the element's index, within the array
      • This is the property of the element that is unique to the FIFO and that makes it useful
      • The sequence of positions in the array represent the sequence of events that placed their values into the array
In the current case,

  • the value of each element in the array is a time measurement of a encoder wheel sensor input transition event; it could be
    • the relative time since the previous event, or
    • the absolute time of the event
  • the index of each element represents which of the most recent 16 transitions generated that value, relative to the most recent transition.
With those definitions in place, here are two common implementations:

  • An linear array that shifts the values through the array and maintains a constant relationship between event ordinal and array index.
    • The oldest (first stored) event's value is always in array element 0
    • The newest (last stored) event value is always in array element N-1.
    • The arrival of a new event's value triggers two operations, which are often implemented by two FIFO instructions, unload and load
      • A FIFO unload operation will
        • "Pop" the oldest (FO "First Out") event's value from of the array at index (position) 0.
        • Shift the array element's values at indices (positions) 1 through L-1 by one position "down," i.e. into indices 0 through L-2
          • L is the number of elements (events) currently stored in the FIFO array
          • N.B. this overwrites the oldest (first stored) value in the array, which is why it was "popped" in the previous step.
        • Decrease the length, L, of the array by 1
      • A FIFO load operation will
        • "Push" a new event's value onto the array at index L
        • Increment the length, L, of the array by 1
    • How those two operations, load and unload, are implemented, e.g. as two separate instructions or as one instruction, is up to the vendor. Usually they are separate instructions as that allows a variable FIFO array length.
    • Note that, because popping the oldest value (FO; First Out) from, and pushing a new value (FI; First in) the FIFO array will not occur on every scan cycle, vendor-supplied FIFO instructions have a one-shot built in, so the FIFO shift is triggered on the single scan cycle only when an event signal becomes 1, and further shifts are prevented by the one-shot mechanism on subsequent scan cycles while that event signal is still 1.
  • A circular array that leaves each event's value at the index in the array into which it is first written, and has a variable relationship between event ordinal and array index.
    • The oldest (first stored) event's value is in array element at index , where I is a variable tag, with the value of I maintained by the program that varies from 0 to L-1.
      [*]The newest (last stored) event value is always in array element I-1 (or I+L-1, if I is 0).
      [*]The arrival of a new event's value triggers a few operations:
      • The oldest event's value is "popped" from array element at index
        [*]The newest event's value is written to array element at index , which overwrites the oldest events' value.
        [*]I is incremented by 1, and if that resulting incremented value is L, then I is assigned a value of 0
        • or apply a MODULO instruction if available, using L as the divisor
        • This is the origin of the phrase "circular" array: the index "increments" from the end of the array (index L-1) back to the beginning (index 0), as if the array elements were laid out in a circle.

        [*]N.B. this description does not include the case where the FIFO array length (L in the other implementation) changes; that can be covered but is not relevant to the current case of footplate encoder sensor transition timings.


      [*]I have not seen any vendor-supplied FIFO instructions using this implementation. So you would have to do it yourself, which would be the case anyway if Automation Direct does not have built-in FIFO instruction(s).
      [*]However, it is straightforward and applicable to the current case:
      • Move array value to a tag e.g. to "OLD"
        [*]Move the new event value to array
        [*]Add 1 to value of I, assign that result value to I
        [*]If incremented value of I is 16 (L), then assign a value of 0 to I
        [*]You would also need explicit one-shot logic.





Either of those implementations provides the oldest and newest values from the event transitions at the same phase point of a footplate cycle, i.e. from two events exactly one revolution apart. If those values are some form of absolute times or free-running time, then subtracting* oldest from newest yields the period of the most recent full revolution starting and ending at that phase.

* Depending on the meaning of those time values and where they come from, there could be rollover issues in the subtraction, but that is not difficult to deal with, and you were dealing with them anyway when calculating the time differences in your current system.


Thank you for the descriptions of each implementation method. Id like to implement a linear FIFO. So for my application, I want to trigger a one-shot when the pulse sensor is high to capture the pulsePeriod to store as an element in the FIFO array. Once all elements are filled, the load and unload commands will empty(pop out) the oldest element, shift each array element up in the array, and load in the newest pulsePeriod. I want to take the sum of all array elements continuously to have a livePeriod to compare to the theoreticalPeriod at all times (or technically at every new pulse).

But again, I have been having a difficult time with array building in automation studio as its new to me. I haven't been able to find a FIFO, FFU, and FFL commands in ladder unless there are equivalent ones I am unaware of. This has been making it difficult for me to approach this new logic.
 
Last edited:
Unfortunately, there aren't many B&R gurus on the site. If you search the forum using "B&R" as a keyword you'll find a number of threads without any responses. You might try messaging capinwinky and asking him to take a look at this thread and chime in. I'm pretty sure he's been able to offer B&R advice in the past.
Here's his profile page. (https://www.plctalk.net/qanda/member.php?u=894870)
 
Yeah sadly AS resources are limited, but I'll reach out to him, thank you for his info. I will continue to look into similar commands in the mean time because I think this is the best option I have given my hardware. If anyone else has input I would appreciate it, Thanks!
 

Similar Topics

Hello, I have no training in maintaining potable water systems, so forgive me if some of my terminology is far off the mark or if I'm focusing on...
Replies
0
Views
96
I have a redundant ControlLogix being set up. This program reads a value from a remote site which happens to be SLC PLC. Rockwell mentions SLC...
Replies
2
Views
96
Hi all, This is going to be a long post apologies. I'm also a complete beginner to the world of PLCs. I'm currently working on my first ever...
Replies
10
Views
457
Hello everyone, I'm working on a project that involves controlling an array of nozzles within a CNC environment, where the nozzles travel along a...
Replies
5
Views
186
I am utilizing both HMI and SCADA for my project. Both HMI and SCADA have identical tags. When I modify the tag value on HMI, it is reflected in...
Replies
2
Views
157
Back
Top Bottom