Video

I used Arduino Uno as a PID controller to balance a small ping-pong ball on a 4-bar mechanism. And used Matlab to plot the position of the ball vs time.

In this video:
• setpoint = 15 cm
• Kp= 2.5
• Ki=0
• Kd=1

Control Loop:

• An ultrasonic sensor detects the actual position of the ball (the "output ball position" in the above figure).
• The output ball position is compared to the "setpoint" (the position where we want the ball to be)
• A PID algorithm on the arduino is used to compute the angle of the servo motor based on the difference between the output ball position and the setpoint (the error).

The dimensions of my 4-bar mechanism

You can change the dimensions of the mechanism, the weight of the ball, or any other parameter. But then you will have to change the Kp, Ki, and Kd values in the code to get a good system performance.

Arduino code, Matlab code and PID library:

• You must download "PID_v1" library for arduino and move its whole folder to:
Documents > arduino > libraries

Update:

How to get the values of Kp, Ki, & Kd?

- You can try to guess the values, then apply it in the code and monitor the performance of the system as you change theses values. Don't worry too much about  Ki in this system, you can set it to zero. Firstly, guess the value of Kp, then keep changing the value of Kd until you reach a satisfying performance for the system. This is called manual tuning and it takes a long time.

- Another thing you can do, is to build a mathematical model on SIMULINK and use its automatic tuner that can give you three values for Kp, Ki, and Kd.  Of course the mathmatical model will not 100% represent the real physical system, therefore, you will have to slightly change  the 3 obtained values, which means you'll have to do some manual tuning anyway.

- If you are familiar with Simulink, you can check out these detailed tutorials:

The tutorial will teach you how to build a model on simulink for the system and how to tune the Kp, Ki, & Kd values.

1. Which version you use matlab ?

1. The m file attached can work fine on Matlab 2010 to Matlab 2013

2. Where is that m file?

2. How did you obtain those values? P, I and D?

1. Check out the update at the end of the post.

1. Check out the update at the end of the post.

4. Hi there, thanks for the response. I have a doubt. In your experience is better a broader outputlimit PID, yours is -80 to 80, or narrower like -50 to 50, which implies one and the other?

1. It depends on the maximum angle that your servo motor can make.

My servomotor's maximum angle is 180 degrees.

In my code, the output limit is -80 to 80 degrees. Which means, the limit of the output servomotor angle will be either (102+80) degrees or (102-80) degrees.

5. what if i used us100 ultrasonic sensor?? what will happen to the codes?? and the connections??

6. This comment has been removed by the author.

7. We have arduino mega + arduino R3 motor shield, with the HC-SR04 ultrasonic sensor.

Will your code still work? How can it be modified ?

I'm trying to accomplish the same task and will be using the same setup that you have built with the same dimensions and everything.

8. I have the same question

1. I solved the problem, the code must be modified just a little :)

2. Hello, you can share the modified code , With the sensor HC-SR04 :)

9. This comment has been removed by the author.

10. What do I need to modify to use the code on arduino mega?

11. I am trying to do same experiment via using dc motor and motor driver, in my driver there are three ping one of them for speed, the others one selecting of direction, how can I implement this experiment, I couldnt set my speed, every time motor turns so fast and damage to the system.

12. Hi there. I just would like to know, what kind of software i need to use other than arduino? I'm interested with your projects.

13. I wanna ask about the servo.. can i use a standard one instead of the digital? + can u give me your servo's serial number?

14. hi i would like to knw its practical application i.e. hw this concept can be used in industried n al?

15. Hello to everyone!

If someone here is using the HC-SR04 sensor you only have to modify a little part of the code. In this case, I add a constant name it pingPin2 (This constant is my new Input) and the the other one (pingPin) is now only an output.

Please, search and find this part of the code and replace it:

const int pingPin = 9;
const int pingPin2 = 8;

long duration, cm;
unsigned long now = millis();
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

pinMode(pingPin2, INPUT);
duration = pulseIn(pingPin2, HIGH);

1. you connect the trigger to pin 8 and leave echo without a connection?

2. does it work?

3. for HC-SR04 :

#define trigPin 12
#define echoPin 11

long duration, cm;
unsigned long now = millis();

digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

cm = duration/58;

4. escuse me, this part of the code
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

cm = duration/58;

is add it in void setup o void loop???

16. Hello.. can you helo me?
Im using an servo (0-180) degrees and my horizontal is 75 degrees, what values of outputlimit PID I can use in my project? If I use iqual to you (-80-80) its correct?

1. I think in your case, you only have to replace the horizontal value (75º) in the code, because the Arduino code add automatically the range. But with that servo you only can go in the "Positive area" 105º more (75º + 80 = 155º [the limit of servo is 180º]) but you can't go in the negative area (75º - 80º = -5º????)

2. How do you got your Horizontal value?

17. What are the materials of the mechanism?

18. This comment has been removed by the author.

19. This comment has been removed by the author.

20. Can I use another servo motor? Another which has less torque? And if yes, how powerful? Thanks

21. I think your mathematical modelling is wrong please check your transfer function , also u have used length of the beam as 1.0m which doesn't match with the figure u have given for the actual model . can you please explain??

22. Dude, how much do the bars weight??

23. can you send me modified coding plzz
ch.umer840@gmail.com

24. I have a servo motor 17 kg.cm High torque servo 1501 MG. But this motor is not digital servo motor. Can I use this motor for this project ???

25. hola que sustitutos puedo poner en lugar de ese motor

26. funcionara con un servo motor mg995

27. Amigo.. tu trabajo es genial.. gracias por tu aporte. :)

28. Hello i try to make using hc sr 04 anyone can post me ardunio code?
e_celik93@hotmail.com

29. it doesnt work for me, it says that 'PID doesnt have a name

30. Did you try with hc sr04 ?

1. conseguiu o código para sr04???

31. *Note: Trig Pin is connected to 7 and Echo Pin is connected to 8

#include
#include

const int servoPin = 9; //Servo Pin

float Kp = 2.5; //Initial Proportional Gain
float Ki = 0; //Initial Integral Gain
float Kd = 1.1; //Intitial Derivative Gain
double Setpoint, Input, Output, ServoOutput;

PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); //Initialize PID object, which is in the class PID.

Servo myServo; //Initialize Servo.

void setup()
{

Serial.begin(9600); //Begin Serial
myServo.attach(servoPin); //Attach Servo

// position as the input to the PID algorithm

myPID.SetMode(AUTOMATIC); //Set PID object myPID to AUTOMATIC
myPID.SetOutputLimits(-80,80); //Set Output limits to -80 and 80 degrees.
}

void loop()
{

Setpoint = 15;

myPID.Compute(); //computes Output in range of -80 to 80 degrees

ServoOutput=102+Output; // 102 degrees is my horizontal
myServo.write(ServoOutput); //Writes value of Output to servo

}

delay(10); //Don't set too low or echos will run into eachother.

const int pingPin = 7; //Trig Pin Arduino 7
const int pingPin2 = 6; //Echo Pin Arduino 6

long duration, cm;
unsigned long now = millis();
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

pinMode(pingPin, INPUT);
duration = pulseIn(pingPin2, HIGH);

cm = duration/(29*2);

if(cm > 30) // 30 cm is the maximum position for the ball // make 35
{cm=25;} // make 30

Serial.println(cm);

return cm; //Returns distance value.
}

1. BTW this is to use with the HC-SR04

Feel free to ask any questions

2. Sir, can you please provide me the connections for the HC SR04 sensor as because I am getting great difficulty in making the connections for the HC SR04 sensor and the ping sensor is not available in my country. Please reply sir. Thanks in advance.

32. I have a problem with real time plotting. Plot is not updating. Still is the straight line even when PID action is running. It can be a problem if i use matlab 2015??

33. hello me can you please pass me all documents related to the project of the bar in equilibrium with pid I need sabar as encontrastes all variables kp, ki, kd.
this is my mail jd.edu15.08@hotmail.com

34. will the code work in matlab R2016a version??

35. hello, i can´t see the code in the folders.
can someone please share me the whole code for arduino?

36. ali you are great ...

37. Elinize sağlık.Herseyi harika anlatmışsınız.Benim birkaç sorum olucak 5v u arduniodan versek olur mu?

1. This comment has been removed by the author.

38. Could you tell me where to get the links used for building the mechanism

39. There is no link, it should be easy to construct if you are mechanically inclined. I made mine out of wood, screws, bolts, and washers. I can sell you mine if you like. \$200

40. What is the make and model of servo used?

41. Dear Ruben,
firts of all: thanks to You for this video and for sharing Ardu-sketch!
Greetings from Germany,
Wolga

42. I don't understand how to connect everything together, should I include the PID library somewhere?

43. This comment has been removed by the author.

44. Hello Ruben,

thanks for the useful tutorial, my setup isn't working and I have no idea where to start the debug.
It looks it's moving without any relation to the ball position.
I tried to slow it adding a delay(1000) at the bottom but the servo keeps moving even if I fix the ball with the tape.

kd,ki,kp=0

Thanks to anyone can help!

45. This comment has been removed by the author.

46. 不太懂
unsigned long now = millis（）;
pinMode（pingPin，OUTPUT）;
digitalWrite（pingPin，LOW）;
delayMicroseconds（2）;
digitalWrite（pingPin，HIGH）;
delayMicroseconds（5）;
digitalWrite（pingPin，LOW）;

47. ??? Error using ==> serial.serial at 57
The serial port object is supported on the Solaris, 32-bit Windows and 32-bit Linux platforms only.
我arduino是用com8為何會有錯誤

Error in ==> Matlab_realtime_plotter at 19
arduino=serial('COM8','BaudRate',9600); % create serial communication object on port COM18

48. The matlab program you provided can not be executed。
There are mistakes

??? Error using ==> serial.serial at 57
The serial port object is supported on the Solaris, 32-bit Windows and 32-bit Linux platforms only.

Error in ==> Matlab_realtime_plotter at 19
arduino=serial('COM8','BaudRate',9600); % create serial communication object on port COM18

49. if I want to run a ball and beam system on a bicopter with arduino mega and mpu6050.... can u help me with programming code?

50. good night I would like to know, how do I perform the servomotor transfer function thanks

51. Hello, I have a problem with the langlarian formula in the simulink, So it cannot run. It says "syntax error". Do you know whats the problem?

52. 102 degrees is my horizontal , tell me . if i use servo mortor 360 degrees

53. What are the practical applications of this project?