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).
Parts used:
- Arduino Uno
- Ping))) ultrasonic sensor
- 20 Kg.cm Digital Servo Motor
- 5 V DC power supply
Connections:
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:
https://drive.google.com/folderview?id=0Bx4uoJmyE27YdGRMYi16dnUxVk0&usp=sharing
Documents > arduino > libraries - You must download "PID_v1" library for arduino and move its whole folder to:
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:
LINK 1
LINK 2
The tutorial will teach you how to build a model on simulink for the system and how to tune the Kp, Ki, & Kd values.
Which version you use matlab ?
ReplyDeleteThe m file attached can work fine on Matlab 2010 to Matlab 2013
DeleteWhere is that m file?
Deletehello
ReplyDeleteHow did you obtain those values? P, I and D?
ReplyDeleteCheck out the update at the end of the post.
Deletehii there, could you explain more about the theroical model in SIMULINK?? please
ReplyDeleteCheck out the update at the end of the post.
DeleteHi 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?
ReplyDeleteIt depends on the maximum angle that your servo motor can make.
DeleteMy 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.
what if i used us100 ultrasonic sensor?? what will happen to the codes?? and the connections??
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteWe have arduino mega + arduino R3 motor shield, with the HC-SR04 ultrasonic sensor.
ReplyDeleteWill 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.
I have the same question
ReplyDeleteI solved the problem, the code must be modified just a little :)
DeleteHello, you can share the modified code , With the sensor HC-SR04 :)
DeleteYes please shere it!!
DeleteHi i used ultasonic hc_sr04 . I need code please
DeleteThis comment has been removed by the author.
ReplyDeleteWhat do I need to modify to use the code on arduino mega?
ReplyDeleteI 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.
ReplyDeleteHi there. I just would like to know, what kind of software i need to use other than arduino? I'm interested with your projects.
ReplyDeleteI wanna ask about the servo.. can i use a standard one instead of the digital? + can u give me your servo's serial number?
ReplyDeletehi i would like to knw its practical application i.e. hw this concept can be used in industried n al?
ReplyDeleteHello to everyone!
ReplyDeleteIf 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);
you connect the trigger to pin 8 and leave echo without a connection?
Deletedoes it work?
Deletefor HC-SR04 :
Delete#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;
escuse me, this part of the code
DeletedigitalWrite(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???
Hello.. can you helo me?
ReplyDeleteIm 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?
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º????)
DeleteHow do you got your Horizontal value?
DeleteWhat are the materials of the mechanism?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteCan I use another servo motor? Another which has less torque? And if yes, how powerful? Thanks
ReplyDeletecan you send me modified coding plzz
ReplyDeletech.umer840@gmail.com
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 ???
ReplyDeletehola que sustitutos puedo poner en lugar de ese motor
ReplyDeletefuncionara con un servo motor mg995
ReplyDeleteAmigo.. tu trabajo es genial.. gracias por tu aporte. :)
ReplyDeleteHello i try to make using hc sr 04 anyone can post me ardunio code?
ReplyDeletee_celik93@hotmail.com
it doesnt work for me, it says that 'PID doesnt have a name
ReplyDeleteDid you try with hc sr04 ?
ReplyDeleteconseguiu o código para sr04???
Delete*Note: Trig Pin is connected to 7 and Echo Pin is connected to 8
ReplyDelete#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
Input = readPosition(); //Calls function readPosition() and sets the balls
// 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;
Input = readPosition();
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
}
float readPosition() {
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.
}
BTW this is to use with the HC-SR04
DeleteFeel free to ask any questions
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.
DeleteSir, please send Matlab code for your circuit connection
DeleteI 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??
ReplyDeleteHi
Deletei am facing the same problem, if you had been solved yours could you help me ?
will the code work in matlab R2016a version??
ReplyDeletehello, i can´t see the code in the folders.
ReplyDeletecan someone please share me the whole code for arduino?
ali you are great ...
ReplyDeleteElinize sağlık.Herseyi harika anlatmışsınız.Benim birkaç sorum olucak 5v u arduniodan versek olur mu?
ReplyDeleteThis comment has been removed by the author.
DeleteCould you tell me where to get the links used for building the mechanism
ReplyDeleteWhat is the make and model of servo used?
ReplyDeleteDear Ruben,
ReplyDeletefirts of all: thanks to You for this video and for sharing Ardu-sketch!
Greetings from Germany,
Wolga
I don't understand how to connect everything together, should I include the PID library somewhere?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHello Ruben,
ReplyDeletethanks 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!
This comment has been removed by the author.
ReplyDelete不太懂
ReplyDeleteunsigned long now = millis();
pinMode(pingPin,OUTPUT);
digitalWrite(pingPin,LOW);
delayMicroseconds(2);
digitalWrite(pingPin,HIGH);
delayMicroseconds(5);
digitalWrite(pingPin,LOW);
??? Error using ==> serial.serial at 57
ReplyDeleteThe 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
The matlab program you provided can not be executed。
ReplyDeleteThere 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
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?
ReplyDelete
ReplyDeletegood night I would like to know, how do I perform the servomotor transfer function thanks
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?
ReplyDelete102 degrees is my horizontal , tell me . if i use servo mortor 360 degrees
ReplyDeletehello where did you get the servo arm(horn)
ReplyDeleteHello ,
ReplyDeletethanks 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=1.1,ki=0,kp=2.5
Thanks to anyone can help!
Sir my project model is working ,but sir I can't tune ball on right position can you help me what I do so the ball is fix on right position.
ReplyDeletei cant run the real time plotter i dont know whats the problem .im using matlab 2014a 64bit .any help?
ReplyDeletecan anyone explain me the pid_v1 library codes ?
ReplyDeleteWhat is the weight of the ball?
ReplyDelete