PID Controller w/ two digital outputs



I am working on a PID controller project. The project is based on the PID Controller software from GitHub at In particular I am using the PID Relay output version however I need to make some modifications:

I need to fire two relays based on the set point. If the new desired set point is lower, fire one relay. If the new desired set point is higher, fire the other relay.



What are you needing help with? Conceptualizing what you need to do? Implementing? Code Changes?

When you fire either relay, do you want them to both be subject to the PID? are you wanting the same PID instance but firing relays based on previous set point?


I need help with all of the above. Never programmed anything before like this.

I am controlling a hydraulic cylinder using relays. The relays control Solenoids. In this example:

Let’s call it 0 (closed) and 100 (Open)
Two relays 1 for open and 1 for close. Each controls a solenoid on either end of the hydraulic cylinder.
Starting point is 0.

I change the set point to say…30. The feedback shows that the current point is 0 therefore 30 is a positive integer and it needs to “open” so it fires the open solenoid. As it settles at 30 the relay switches to 0 the hydraulic actuator is now at the position desired.

If I ask it to open further to say 80 from 30 by changing the set point, it would fire the same open relay as before but what if I want to go the other way?

I am currently at 30 and change the set point to 10. 10 is below 30 meaning it has to move the opposite way therefore it has to fire the “close” solenoid also adhering to the same PID.

I could get fancy and say I want to have controls to move faster one way or the other but the basic premise is as described.

This does not work exactly like a simple PID heater or AC system which just stays on till it gets to the temp and them turn off. It has to know the current setpoint and relative position based on the sensor feedback and know which direction to go.

I think it might also require a deadband to control the overshoot and correction factor to keep it from hunting back and forth forever.


Here is the code provided as an example (Starting point)

#include "pid.h"
#define RelayPin 6

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, PID::DIRECT);

int WindowSize = 5000;
unsigned long windowStartTime;
void setup()
  windowStartTime = millis();
  //initialize the variables we're linked to
  Setpoint = 100;

  //tell the PID to range between 0 and the full window size
  myPID.SetOutputLimits(0, WindowSize);

  //turn the PID on

void loop()
  Input = analogRead(0);

   * turn the output pin on/off based on pid output
  if(millis() - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  if(Output < millis() - windowStartTime) digitalWrite(RelayPin,HIGH);
  else digitalWrite(RelayPin,LOW);



My #1 question is why would you bother using a PID controller for this?

If you only have control over the valve open or close position it seems like you are not learning anything about PID control and also wasting your time messing with it for the application.

If you MUST use a signals approach, use a “P” controller and set a very large gain and some hysteresis.

But… um…

if (position < setpoint) { goForward(); }
else if (position > setpoint) { goBackward(); }

would work great based on your description…

(edit: adding deadband to this is trivial, and left as an exercise to the reader)


Just for completeness:
In your description I failed to see you mentioned the need to make the two relays mutually exclusive on. Whenever one is triggered, you need to make sure the other is first switched off.

And I second @HEng’s point. PID would possibly make sense if you’d start pulsing the relays when you approach the desired endpoint to slow down the motion, but if you just keep it on till you are there and then go off, a simple approach like above should suffice - however, I guess a certain tolerance value would be required to prevent getting trapped in a permanent cycle of over-shooting.


Normally a hydraulic cylinder is controlled by a 4-way or spool valve. This is valve that does allow for proportional control and is not just on or off. There is a floating area in the middle where no pressure is applied to either end of the cylinder and the pump high pressure side (on the P port) is returned to the return port (T). Moving the valve to left (say) allows pressure to go to one end of the cylinder (A port on the value) and allows the other end to return its pressure to the return port. Move the lever to the right and the opposite end of the cylinder gets pressure (B port on the valve) and the other end returns pressure.

The valve is made so that as you move the control more, more area in the valve is opened and more pressure can be delivered up to the pump max. This type of valve is why you can do very delicate and precise movements with hydraulics.

This valve has a safety feature built in that won’t allow you to pressurize both sides at the same time which your proposed design does not.

I think you need to do more research on your project before designing your system.


Thank you for your comments. We already have a “modulating” design that uses solenoids valves to do exactly this setup and it works. We have been using it for 25 years. The difference is that it is done with an analog controller, not a digital one. It has a span, dead band and endpoints available as pot screws and uses old fashioned through hole components and a few surface mount ones to do the job. I want to develop this design to be able to control it digitally AND be able to do more with the controls and how it actually works. I can add more features over time.


It is actually a total of 4 solenoids. Two of them are fired from one relay. One is N.O. 1 N.C. Does thayt make more sense?

The analog system does NOT pulse. It merely opens, travels, closes. It usually ends up being off by about 2% when properly adjusted. We don;t move blistering fast, we move pretty slowly with it as this is ONLY used for control applications.

I want to design a digital version with more features .


It sounds like you might have proportional control solenoid valves.

But as others have said, PID will be over-kill if you don’t have modulating/proportional valves.

If your only control is on/off solenoids, then your best approach is what’s been suggested. Travel to the target and then make a few corrections if needed.

If your “solenoids” are proportional valves, You may want to look at the AdaptiveTunings Example instead of the Relay Example. It uses an Aggressive Tune when the position is far away from the setpoint, and transitions to a conservative Tune as you approach the target setpoint.

Getting back on track: How do you plan on sending the Target Input and Current Position to your Photon/Electron? Is your cylinder feedback an Analog Voltage, variable resistance, external physical measurement, or other ?


Setting the record straight a little, what’s being described isn’t PID control. Since it’s an all or nothing input (0% or 100%), it’s bang-bang control. Of course there are several methods you can to trigger the bangs, but I suggest looking into sliding mode control. Just make sure you don’t beat the crap out of your solenoids.

If your model is exceedingly accurate, and since it’s in slow hydraulics it sounds like it might be, you could try making an optimal control. On a two dimensional system, you stand a decent chance of being able to make an optimal synthesis. If you enjoy math, check out the PMP (Pontryagin Maximum Principle). If your state observation is spot on, PMP will give you decent real-world results and considering the cost of actuating solenoids it can save a lot of money in hardware by reducing twitchiness.


Thank you to everyone for your input. After some time mulling this over and Learning, I’ve realized exactly what this, why and how to do it. This is indeed a PID loop. It is PID and not “P” because you do not want to overshoot as you approach the position desired.

Feedback is provided by a position indicator, no different than a thermocouple reporting temperature. The difference is accelerating mass of a piston, rod and fluid in a hydraulic system. Unless your controller can compensate you will overshoot resulting in hunting. That’s what a PID loop does, it dampens the overshoot. Here are the specs.

  1. For the input (feedback of position), 4-20ma, 0-5v, 0-10v, potentiometer etc. It can be any of these and you must condition the input signal.

  2. Particle Xenon, Boron, Photon, etc. Software for PID control. The loop can use proportional valves to throttle flow of hydraulic fluid OR simple on/off valves and pulse them as you approach your desired position to slow the approach and eliminate overshoot. Fidelity is important here because you want position control of the piston/hydraulic cylinder.

  3. Input for desired position can come from a very large number of input sources. 4-20ma, potentiometer, 0-5v, 0-10v, pwm, digital, over specialized protocols like HART, MODBUS, CANBUS, ETC. A signal conditioner can convert input signals but adds cost/complexity/calibration.

It would be nice to have proportional control to travel fast, slow down and then as you approach your final position slow way down and settle exactly where you want. With on/off valves you would pulse them faster as you get close until they are more closed than open % of time-wise.

This would enable you to open or close a gate at home, automate things, etc.

The standard PID loop code is easy but how do I add loops for pulsing solenoids (relays) and throttling proportional valves into the loop?

Is anyone aware of simple signal conditioning boards that can do lots of protocols? Easy to make one?

This is a more complex project, I realize but any direction, code, advice would be helpful.


Did you look at the Adaptive Tune Example ?


I have had time to mull this over more. I am now using a proportional valve and controller that accepts
0-32vdc digital
60hz-10khz frequency
PWM 60hz-10khz.

The particle device (if I’m correct) has 0-5v out, PWM, digital, serial i2c. Not sure about others.

If I can get two channels of pwm or 0-5v out, I can use it to control the proportional valves through their controller input.

I need the PID loop to provide feedback and control ramping/directional control based on input setpoint.

Unfortunately I have to have 4-20ma input to the particle photon because industry standard is 4-20ma for position input feedback so I have an ic2 board from control anything to provide this functionality.

Any input on implementation or advice?

Ultimately I am going to use a boron too and remotely control the proportional valve setpoint wirelessly and get wireless feedback on position.


Did the project succeed? Can you share the arduino code? Here is my running code- Maybe there is room for improvement.