Problem with actuators.

Hello
I have a problem with synchronization of two actuators. They has to raise or lower one platform (electric linear actuator with potentiometers, controlled by two H-bridges and one Arduino Mega). One actuator is a master, another one is a slave( follower). To raise actuator it is required to press and keep one button, and to lower actuators we need to press and keep another button. Regardless of the weight that is put on the platform, slave must be always on the same position as master (platform has to be leveled). For this moment i have a code, which reads values from potentiometers of two actuators and after that, by comparison, tries to position slave in one level with master. However, its not a perfect method, because there is no continuously regulation of speed (PWM) and also the inertia of the actuator causes that the slave doesnt stop immediately at the same point as the master. Im new with programming, so here is my question: what do i need to change in my code to make a smooth regulation of speed (when slave is near the position of the master, he should start braking and eventually stop at the same level) I know that the best way to achieve that is to use PID regulator. However, my programming level is not so advanced, so is there any chance that some of you may help?
I’ve been searching a lot how to implement PID in my code, however there were no good resolutions for me :confused:
Thanks (and sorry for my english!)

code:
int wartosc; //value of master potentiometer
int wartosc1; //–/-- slave
const int buttonPos = 42; //button for extension of actuator
const int buttonPos2 = 43; //button for retract of actuator
int wartosc_pop; //value of pot. which will be sclaed (master)
int wartosc1_pop; //value of pot. which will be scaled(slave)
void setup() {
pinMode (2,OUTPUT); //PWM master
pinMode (3,OUTPUT); //PWM follower
pinMode (22,OUTPUT); //extension master
pinMode (23,OUTPUT); //retract master
pinMode (24,OUTPUT); //extension follower
pinMode (25,OUTPUT); //retract follower
pinMode (42,INPUT); //button pin for extension
pinMode (43,INPUT); //pin retract
analogWrite(2,255); //speed of master
//analogWrite(3,255); //slave
Serial.begin(9600);
}
void loop()
{
wartosc = analogRead(A0); //read value of master potentiometer
wartosc1 = analogRead(A1); //read value of slave potentiometer

wartosc_pop = map(wartosc, 992, 56, 100, 0); //scale the value of master pot.
wartosc1_pop= map(wartosc1, 994, 60, 100, 0); //scale the value of slave pot.

//controlling master

if(digitalRead(buttonPos) == HIGH) //extension if we press and keep button(pin42
{
digitalWrite(22,HIGH); //extension
digitalWrite(23,LOW); //retract
}
else if(digitalRead(buttonPos2) == HIGH) //retract if…(pin 43)
{
digitalWrite(22,LOW);
digitalWrite(23,HIGH);
}
else //dont move if there is no button pressed
{
digitalWrite(22,LOW);
digitalWrite(23,LOW);
}
//-----------------------------------------------------------

//controlling the slave
if(wartosc_pop > wartosc1_pop) //if value of master pot. is higher than value of slave, then:
{
analogWrite(3,50);
digitalWrite(24,HIGH); //extension
digitalWrite(25,LOW); //retract
}
else if(wartosc_pop < wartosc1_pop) //if value of master pot. is lower than value of slave, then::
{
analogWrite(3,50);
digitalWrite(24,LOW);
digitalWrite(25,HIGH);
}
else //if the values are the same, dont move
{
analogWrite(3,0);
digitalWrite(24,LOW);
digitalWrite(25,LOW);
}
//------------------------------------------------

delay(50);
}

ang.ino (2.18 KB)

Google "PID Controller". PID stands for "Position, Integral, Derivative". You base the speed of the actuator on the amount of error, the rate at which the error is changing, and the integral of the error - error in this case being the amount by which the slave is different to the master.

Getting the parameters right is a bit of a matter of fiddling with the numbers until you get acceptable behaviour. The "position" effectively gives you a spring, "integral" a mass, and "derivative" a damper - together they form a (hopefully) correctly damped system.

(EDIT: maybe it's actually the integral that acts as a spring, and derivative as a damper. Whatevs.)

There's a fair bit of literature on the topic, plenty of existing ardiuino projects based around the idea. There are also off-the-shelf PID controllers with trimpots that might be suitable for your job. Look into that.

slave must be always on the same position as master (platform has to be leveled)

How is the slave supposed to know where the master is?

analogWrite(2,255); //speed of master
//analogWrite(3,255); //slave

Why are you starting the master at full speed in setup()? Why are you not starting the slave at the same (or some) speed?

wartosc = analogRead(A0); //read value of master potentiometer
wartosc1 = analogRead(A1); //read value of slave potentiometer

Numbering one variable of a set sure looks dumb.

You need some separation between the reads from different analog pins, or you need to throw away the first value read from a given pin.

if(wartosc_pop > wartosc1_pop) //if value of master pot. is higher than value of slave, then:
{
analogWrite(3,50);
digitalWrite(24,HIGH); //extension
digitalWrite(25,LOW); //retract
}
else if(wartosc_pop < wartosc1_pop) //if value of master pot. is lower than value of slave, then::
{
analogWrite(3,50);
digitalWrite(24,LOW);
digitalWrite(25,HIGH);
}

This is where the problem is. The speed of the slave needs to be proportional to the difference in potentiometer readings, NOT a constant.

@PaulMurrayCbr
Thanks for clues :slight_smile: to be honest i know how PID works. I even tried already to implement some examples in my code, however there weren't satisfying effects (probably because of my not well programming.

How is the slave supposed to know where the master is?

Thats the problem, my first thought was to use the values from potentiometers.

Why are you starting the master at full speed in setup()? Why are you not starting the slave at the same (or some) speed?

Speed of master actuator has to be constant. I didnt start the slave with the same speed, because i wanted to simulate synchronization (when master achieve some position, slave follows him to the same level and stop when he reach position of the master).

Numbering one variable of a set sure looks dumb.
You need some separation between the reads from different analog pins, or you need to throw away the first value read from a given pin.

You're right, but these variables are not the same, the second has "1" at the end.

This is where the problem is. The speed of the slave needs to be proportional to the difference in potentiometer readings, NOT a constant.

The speed of the slave has to change when following the master. When he is far from the master, he extends with a great speed, but when he is about to reach the same level as the master, he shall start braking and stop smoothly. The problem is, i have no idea how to implement that regulation.

Thanks for the answers and information, i will still try to find resolution with PID implementation.

You're right, but these variables are not the same, the second has "1" at the end.

I don't understand how this statement addresses my concern(s). You read from pin A0 and store the result in wartosc. Then, you read from pin A1 and store the result in wartosc1. You'll notice that you didn't read from pins A and A1. So, why are you storing data in wartosc and wartosc1?

And, you ignored the fact that if you read from A0 and then read from A1 IMMEDIATELY afterwards that the value returned for pin A1 will be junk.

You need something like:

   int junk0 = analogRead(A0);
   int wartosc0 = analogRead(A0);

   int junk1 = analogRead(A1);
   int wartosc1 = analogRead(A1);

When he is far from the master, he extends with a great speed

Are you sure that the actuators are boys? Maybe they are girls...

The actuators should never be far apart, but, you are right in that the farther apart they are, the faster the slave should move. So, why is your code NOT written that way?

If the master is running flat out (255 as the second argument to analogWrite() means full speed), how can the slave ever catch up? You need to run the master at something less than balls-to-the-wall, so that the slave CAN run a bit faster if needed.

The problem is, i have no idea how to implement that regulation.

   analogWrite(slavePin, masterSpeed - (scaledMasterReading - scaledSlaveReading));

If the master value is higher than the slave value, then the scaled readings (scaled to the 0 to 255 range), will result in a negative value, so the slave's speed will be higher than the master's speed.

If the master value is lower (the slave passed the master), then the scaled readings result in a positive value, and the slave's speed will be lower than the master's speed.

Hi

My journey towards PID controllers started by watching these two videos:

Video1
Video2

They are great examples to get basic information about PID controlling method.

After those you should see attached example Arduino PID library to learn how they work as written code…

Basicly your master potentiometer will be as “Setpoint” and slave potentiometer will be as “Input”. In the beginning you should set output limits to 0 - 255 (analogWrite range). Also you have to find out which way you should move your actuator, in other words, is your slave actuator ahead or behind compared to master.

Basic Idea:

#include <PID_v1.h>

double Kp = 0, Kd = 0, Ki = 0;

//Specify the links and initial tuning parameters
PID myPID(&pidInput, &pidOutput, &pidSetpoint, Kp, Ki, Kd, DIRECT);

void setup()
{     
     myPID.SetTunings(Kp, Ki, Kd);	
     myPID.SetOutputLimits(0, 255);
     myPID.SetMode(AUTOMATIC);
}

void loop()
{
     // first you should drive master actuator

     // ..and after that you should get slave actuator to follow it..
     int pot1 = analogRead(A0); //read value of master potentiometer
     ...
     int pot2 = analogRead(A1); //read value of slave potentiometer

     myPID.Compute();

     if (pot1 > pot2) // slave is for example ahead, can't say are they this way
     {
          pidOutputValue--; // slow slave down
	  		
	  // write pwm for controlling what ever you use for controlling your actuator (like L298N) by pwm and two pins
          analogWrite(2, pidOutputValue); 
          
          // write another pwm for 0 to get dc motor rotate
          analogWrite(3, 0);  
     }
     else if (pot1 < pot2) // slave is for example behind, can't say are they this way but opposite than first one
     {
          pidOutputValue++; // speed slave up
	  		
	  // write another pwm for 0 to get dc motor rotate
          analogWrite(2, 0); 

          // write pwm
          analogWrite(3, pidOutputValue);
     }
     else
     {          		
          // write both pwm signals to zero to stop actuator
          analogWrite(2, 0); 
          analogWrite(3, 0);
     }
}

You should get it work quite well only with some Kp-value (1.0 - 2.0), rest of those (Ki, Kd) could be set as 0. After when you’ve found correct enough value for Kp, then you should start to adjust Kd. I think that you shouldn’t need to adjust Ki at all…

Also to avoid slave actuator oscillation you have to write to the code so called deadBand which means hysteresis gap (in this case ±3) between thos two if statements above… Principle for that is like this code below:

#define pwmOutput1 2
#define pwmOutput2 3

int pidZeroLimit = 3;

void setup()
{
          pinMode(pwmOutput1, OUTPUT);
	  pinMode(pwmOutput2, OUTPUT);
}

void loop()
{
     
     ...

     myPID.Compute();

     ..


     if (pidOutput >= pidZeroLimit)
     {
	  analogWrite(pidOutput , 0);
	  analogWrite(pidOutput , pidOutputValue);
     }
     else if (pidOutput <= -pidZeroLimit)
     {
	  analogWrite(pidOutput , pidOutputValue);
	  analogWrite(pidOutput , 0);
     } 
     else
     {
  	  analogWrite(pidOutput , 0);
	  analogWrite(pidOutput , 0);
     }
}

Much information at one time but if you first look those two videos to get know terminogy, maybe it will open to you. Let’s hope the best, that’s the way I learned to use it while back. :slight_smile:

Try it first with 10k potentiometer and one actuator to get it work and after that try to add another one to follow master. Then it’s easy to change controls for the master how you want it.

TommiP

PID_v1.zip (754 KB)