engineer2you
Published

Arduino - Motor PID Speed Control

Make a program for the Arduino Pro Mini in Visual Studio to control motor speed with PID which can archive it exactly.

IntermediateFull instructions provided3 hours92,316
Arduino - Motor PID Speed Control

Things used in this project

Story

Read more

Code

Code snippet #1

Arduino
void loop() {
   if (stringComplete) {
     // clear the string when COM receiving is completed
     mySt = "";  //note: in code below, mySt will not become blank, mySt is blank until '\n' is received
     stringComplete = false;
   }
  //receive command from Visual Studio
   if (mySt.substring(0,8) == "vs_start"){
     digitalWrite(pin_fwd,1);      //run motor run forward
     digitalWrite(pin_bwd,0);
     motor_start = true;
   }
   if (mySt.substring(0,7) == "vs_stop"){
     digitalWrite(pin_fwd,0);
     digitalWrite(pin_bwd,0);      //stop motor
     motor_start = false;
   }
   if (mySt.substring(0,12) == "vs_set_speed"){
     set_speed = mySt.substring(12,mySt.length()).toFloat();  //get string after set_speed
   }
   if (mySt.substring(0,5) == "vs_kp"){
     kp = mySt.substring(5,mySt.length()).toFloat(); //get string after vs_kp
   }
   if (mySt.substring(0,5) == "vs_ki"){
     ki = mySt.substring(5,mySt.length()).toFloat(); //get string after vs_ki
   }
   if (mySt.substring(0,5) == "vs_kd"){
     kd = mySt.substring(5,mySt.length()).toFloat(); //get string after vs_kd
   } 
 }
void detect_a() {
   encoder+=1; //increasing encoder at new pulse
   m_direction = digitalRead(pin_b); //read direction of motor
 }
 ISR(TIMER1_OVF_vect)        // interrupt service routine - tick every 0.1sec
 {
   TCNT1 = timer1_counter;   // set timer
   pv_speed = 60.0*(encoder/200.0)/0.1;  //calculate motor speed, unit is rpm
   encoder=0;
   //print out speed
   if (Serial.available() <= 0) {
     Serial.print("speed");
     Serial.println(pv_speed);         //Print speed (rpm) value to Visual Studio
     }
  //PID program
   if (motor_start){
     e_speed = set_speed - pv_speed;
     pwm_pulse = e_speed*kp + e_speed_sum*ki + (e_speed - e_speed_pre)*kd;
     e_speed_pre = e_speed;  //save last (previous) error
     e_speed_sum += e_speed; //sum of error
     if (e_speed_sum >4000) e_speed_sum = 4000;
     if (e_speed_sum <-4000) e_speed_sum = -4000;
   }
   else{
     e_speed = 0;
     e_speed_pre = 0;
     e_speed_sum = 0;
     pwm_pulse = 0;
   }
  //update new speed
   if (pwm_pulse <255 & pwm_pulse >0){
     analogWrite(pin_pwm,pwm_pulse);  //set motor speed 
   }
   else{
     if (pwm_pulse>255){
       analogWrite(pin_pwm,255);
     }
     else{
       analogWrite(pin_pwm,0);
     }
   }
}

Code snippet #2

Arduino
#pragma endregion
 private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
 serialPort1->Open();
 timer1->Start();
 mStr = "0";
 i=300;
 }
 private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
 serialPort1->WriteLine("vs_set_speed"+textBox1->Text); //send set_speed to Arduino
 serialPort1->WriteLine("vs_kp"+textBox2->Text); //send kP to Arduino
 serialPort1->WriteLine("vs_ki"+textBox3->Text); //send kI to Arduino
 serialPort1->WriteLine("vs_kd"+textBox4->Text); //send kD to Arduino
 }
 private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
 String^ length;
 length=mStr->Length.ToString();
 if(mStr->Substring(0,5)=="speed"){
 speed=mStr->Substring(5,System::Convert::ToInt32(length)-6);
 label1->Text=speed;
 //print motor speed into Chart
 this->chart1->Series["Series1"]->Points->AddXY(i,System::Convert::ToDouble(speed));
 i++;
 this->chart1->ChartAreas["ChartArea1"]->AxisX->Minimum=i-300; //shift x-axis
 }
 }
 private: System::Void serialPort1_DataReceived(System::Object^  sender, System::IO::Ports::SerialDataReceivedEventArgs^  e) {
 mStr=serialPort1->ReadLine();
 }
 private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
 serialPort1->WriteLine("vs_start"); //start motor
 }
 private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {
 serialPort1->WriteLine("vs_stop");  //stop motor
 }

Credits

engineer2you

engineer2you

24 projects • 93 followers
i'm mechatronics engineer who loves making funny project and sharing for you. See me at: https://www.youtube.com/c/engineer2you

Comments