Pneumatic Cylinder position Control. Need feedback on my Structured Text code

Use a servo controller like Peter recommends or a rod lock cylinder.
Yes but just because you can, it doesn't mean you should. I would prefer small electric servos or steppers.

To make the OP's system work he need outputs that will extend stops to stop the actuator at the proper position. Moving to a mechanical stop is easy. Precision isn't required.
 
I agree with stops (solenoid operated can work), however, I have done what the OP is trying, this was for a press (low pressure), however, this was 4 position using sensors on a pneumatic cylinder, it worked well without problems, the biggest problem that the system had was when the seals on the cylinder dried out (for some reason they would not allow lubrication even though all lube was food safe). Yes a failed sensor would mean not stopping in position but that was rare, the cylinder would naturally stop at 0 or 100%.
We used high speed timers for alarm states based on average time from one position to another, although I would rather have used a check for rising & falling sensor transition for alarm should the cylinder go past the required point.
I have also done a pipe cutting system Extruded concrete pipe where the cutter was adjusted again using pneumatics however, that did have an encoder on it.
It's ok to say it needs such & such, however, as many of these systems are probably designed by engineers that do not do the programming, In actual fact I can write on a postage stamp where I have been able to have an influence on the physical equipment used. How many times can a programmer say I had to create software solutions to overcome the mechanical short comings.
 
One thing the OP has never commented on is how accurate the stops have to be. Is it ok if the system gets to a stop +/- 10% or do they need +/-0.5%, something in between?

That quantification of stop accuracy is what will determine if the system is possible, needs some type of stop (rod lock…) or can work right from valves.
 
One thing the OP has never commented on is how accurate the stops have to be. Is it ok if the system gets to a stop +/- 10% or do they need +/-0.5%, something in between?

That quantification of stop accuracy is what will determine if the system is possible, needs some type of stop (rod lock…) or can work right from valves.

Accuracy is not that important for the current application.
The Cylinder is controlling a sliding gate on a Silo for unloading wheat into trucks.
Cylinders and the magnetic switches are already installed as somebody else started the job and i was called in to finish it.
 
So I created a simulation of what I think the OP is talking about. Except now it sounds like this may be a vertical system. If that is the case and people are going to walk under the system you need a locking device. Period, end of story.

This code below is for educational purposes only. It includes no error checking, no debouncing of signals, etc. and is not intended to be used on a real system.

So anyway, here's a link to me running the simulation:
https://youtu.be/4E14bBbjRT8

Here's the Global Variable file:
Code:
{attribute 'qualified_only'}
VAR_GLOBAL
	
	SOL_EXT:	BOOL;	// Represents Solenoid to Extend the Cylinder
	SOL_RET:	BOOL;	// Represents Solenoid to Retract the Cylinder
	
	JOG_EXT:	BOOL;	// Represents a Jog Extend Pushbutton
	JOG_RET:	BOOL;	// Represents a Jog Retract Pushbutton
	
	// In these arrays 0..4 represent the position 0,25%, 50%, 75%, 100% Respectively
	
	BTN:		ARRAY [0..4] OF BOOL; // Array of Buttons
	SW: 		ARRAY [0..4] OF BOOL; // Array of Mag Switch Position [0]=0% [1]=25% etc..
	
	// In the POS and GOAL words, there are 9 positions.
	// The positions at the mag switches and the positions between the mag switches
	// 000000001 - Mag Switch 0%
	// 000000010 - Between 0% and 25%
	// 000000100 - Mag Switch 25%
	// 000001000 - Between 25% and 50%
	// 000010000 - Mag Switch 50%
	// 000100000 - Between 50% and 75%
	// 001000000 - Mag Switch 75%
	// 010000000 - Between 75% and 100%
	// 100000000 - Mag Switch 100%
	POS:		WORD;	// Represents the current position by which bit is set on
	GOAL:		WORD;	// Represents the Goal positoin by which bit is on
	
END_VAR

And Here is the program
Code:
PROGRAM PLC_PRG
VAR
	Last_EXT:	SR; // Set Block to remember if last motion was Extend
	Last_RET:	SR; // Set Block to remember if last motion was Retract

	// In these arrays 0..4 represent the position 0,25%, 50%, 75%, 100% Respectively
	
	SW_ON:		ARRAY [0..4] OF R_TRIG;	// Rising Triggers of Mag Switches
	SW_OFF:		ARRAY [0..4] OF F_TRIG;	// Falling Triggers of the Mag Seitches
	
	BTN_ON:		ARRAY [0..4] OF R_TRIG; // Rising Triggers of the Goto % Pushbuttons
	
	index:		INT;	// An index value to use in loops
	
	Auto_Move:	BOOL;
END_VAR

// Create Triggers from the Hardware Switches and Auto Move Buttons
FOR index := 0 TO 4 DO
	SW_ON[index](CLK := GVL.SW[index]);
	SW_OFF[index](CLK:= GVL.SW[index]);
	BTN_ON[index](CLK:= GVL.BTN[index]);
END_FOR

// Set latches based on the last solenoid energized
// to remember direction
Last_EXT(SET1:= GVL.SOL_EXT, RESET:= GVL.SOL_RET);
Last_RET(SET1:= GVL.SOL_RET, RESET:= GVL.SOL_EXT);

// Loop through the 5 switch positions
FOR index := 0 TO 4 DO
	//Falling Edge of a switch - set in betwen position 
	IF SW_OFF[index].Q THEN
		// Reset the pos
		GVL.POS := 0;
		IF Last_Ext.Q1 THEN 
			GVL.POS := SHL(1,2*index+1);
		ELSIF Last_Ret.Q1 THEN
			GVL.POS := SHL(1,2*index-1);
		END_IF
		
	END_IF
	
	// Rising edge of a switch, clear inbetween positon
	// The position for actual mag switches is set
	// at the bottom of this POU
	IF SW_ON[index].Q THEN
		GVL.POS := 0;
	END_IF
	
	// Check if a goto % Button is pressed
	IF BTN_ON[index].Q THEN
		GVL.GOAL	:= SHL(1,index*2);
		Auto_Move	:= TRUE;
	END_IF
END_FOR

IF Auto_Move THEN
	IF GVL.POS =  GVL.GOAL THEN
		Auto_Move	:= FALSE;
		GVL.GOAL	:= 0;
	END_IF
END_IF

// Set the positions based based on  physical switches
GVL.POS.0	:= GVL.SW[0];
GVL.POS.2	:= GVL.SW[1];
GVL.POS.4	:= GVL.SW[2];
GVL.POS.6	:= GVL.SW[3];
GVL.POS.8	:= GVL.SW[4];

// Control the Solenoid valves
GVL.SOL_EXT := GVL.JOG_EXT OR (Auto_Move AND (GVL.GOAL > GVL.POS));
GVL.SOL_RET := GVL.JOG_RET OR (Auto_Move AND (GVL.GOAL < GVL.POS));
 
Norm: sweet! Let's see how many likes that video can get.

Norm implemented an idea I have been toying with: keeping track of the last valve used. It would not be needed if the existing system does not overshoot, however, when an initial move is initiated (i.e. via a new button-pressed HMI event), knowing the direction of the move would be useful if the sensor is not, as I said before, "wide" enough and the sliding gate overshoots the target truck position, in which case the targeted sensor changes from 1 back to 0.

[Sidebar]

N.B. That concept of "wide" enough is a combination of the detection extent of the sensor plus the dynamics of the pneumatic cylinder (friction, stiction, hose and cylinder volumes, etc.).

[/Sidebar]


There could be a special case added, representing an overshoot, where none of the sensors are 1 but the target equals the index position. In that case, the last valve active indicates the direction of the overshoot, and could be checked to automate activation of the opposite valve to push the system back a bit. However, in order to not overshoot again in that opposite direction, when in this "overshoot mode," use some form of PWM to move more slowly.

@PeterN et al.: yes, I freely accept the eye roll; yes it's a cobb-job/Rube-Goldberg/Heath-Robinson, but the employer/customer has decided it is cheaper to pay for a software fix than a physical fix for any system deficiencies, and I for one am happy for OP for that.

Caveats

  • Of course, this could lead to cycling
  • The PWM could shorten the valve life, although if that motivated a fix to the problem in the physical design, is that such a bad result ;)?
Anyway, here is an attempt at coding that approach; it is an add-on that would follow the code from Post #7.
Code:
(*******************************************************************)
(* Calculate direction to bump index on anticipated next overshoot *)
(*******************************************************************)

   IF VALVE_A THEN bumpit := +1;  (* Valve A increases index *)
ELSIF VALVE_B THEN bumpit := -1;  (* Valve B decreases index *)
 ELSE              bumpit := 0;

(*******************************************************)
(* Detect overshoot:                                   *)
(* - None of position sensors are 1                    *)
(* - Neither valve is 1                                *)
(* - Last detected position (index) is target position *)
(*******************************************************)

IF NOT (position_0 OR position_25 OR position_50
        OR position_75 OR position_100 OR VALVE_A OR VALVE_B)
   AND (index = target) THEN

  (* Overshoot detected                                               *)
  (*                                                                  *)
  (* i. Indicate an inferred overshoot position as the smallest       *)
  (*    non-zero offset, i.e. 1, and less than the 25 between sensors *)
  (*                                                                  *)
  (*    N.B. this makes the IF expression above a one-shot, i.e. true *)
  (*         for one scan only                                        *)

  index := index + bumpit;             (* Model the assumed overshoot *)

  (* ii. Start the pseudo-PWM counter                            *)
  (* ii.a. Does nothing i.e. is disabled if less than zero       *)
  (* ii.b. Counts from 0 to 999 repeating                        *)
  (* ii.c. Valves will be off when recovering from overshoot and *)
  (*       counter is greater than 499                           *)
  (*                                                             *)
  (* N.B. the 999 and 499 values are guesses here and will need  *)
  (*      to be tuned for the physical pneumatic system; the     *)
  (*      values use the scans a poor man's clock and            *)
  (*      assume the mean scan time is small - of order 1ms;     *)
  (*      it may make sense to implement those values as         *)
  (*      variables/global tags with initial estimates, but      *)
  (       adjustable from the HMI                                *)

  iPWM := 0;

ELSIF (index = target) THEN

  iPWM := -1;                              (* Disable pseudo-PWM *)

END_IF;

(* Pseudo-PWM - override open valve for latter part of cycle  *)
(* N.B. there is an off-by-1 error here:  on the scan when    *)
(*      the overshoot is detected, the valve bits will both   *)
(*      be 0 so these IF expressions will evaluate to FALSE   *)

IF VALVE_A AND ((target - index) < 2) AND (iPWM > 499) THEN VALVE_A := 0;
IF VALVE_B AND ((index - target) < 2) AND (iPWM > 499) THEN VALVE_B := 0;

IF iPWM > -1 THEN iPWM := iPWM + 1;  (* Increment iPWM when active *)
IF iPWM > 999 THEN iPWM := 0;        (* Reset iPWM to 0 from 1000  *)
N.B. the [(target - index) < 2] and [(index - target) < 2] tests could be replaced by [target = (index*2)] and [index = (target*2)] in the bit-wise @parky approach as extended by Norm, where index and target are the integers containing the bits. We may need to test for non-zero values, although target should never have all of its bits be zero.

Disclaimer


Norm raises an excellent point about safety that must not be ignored; I will do the same and say this is only a conceptual approach to solve the smaller problem i.e. overshoot that may not even be present; whether it is safe, or even works at all, is up to the OP and/or other local engineers to determine.
 
Last edited:
I would like to thank everyone's feedback, i very much appreciate it. i will take in consideration all the feedbacks.
Any new feedbacks or comments are welcome
 
It's good to be smart but it's better to be lucky. In this case, as inferred by Peter and others, your success will more likely be dependent on the latter, so we wish you good luck (you were already smart enough to come here and ask ;)).
 

Similar Topics

Hey everyone i know this is somewhat unrelated to PLC discussion but I couldnt find anything online to answer my question. My cylinders are...
Replies
19
Views
5,598
I need to ramp up the psi on a pnuematic cylinder until the force on the piston, measured by a load cell, is met. Then I need the air pressure to...
Replies
9
Views
4,541
Hello All, I am no expert in valves, Cylinders, or any sort of Pneumatic controls, and in need of some help as to type of control valve that is...
Replies
9
Views
4,903
Hello All, I have a pneumatics question for the group; I need the behavior of a single-acting cylinder with spring return, but I need more force...
Replies
27
Views
8,961
There seems to be plenty of different manufacturers of pneumatic cylinders with 4-20mA position indication. I need one with 2" bore, 24" stroke...
Replies
3
Views
3,549
Back
Top Bottom