PID Controller to DC motor using MATLAB app designer and arduino
5 次查看(过去 30 天)
显示 更早的评论
Hi all, I'm working on the project to show the effects of PID on DC motor
So I'm using MATLAB app designer and arduino
Hence,I have arduino code to drive the dc motor with encoder with PID Controller,
But the issue is I'm a newbie to MATLAB app designer coding
So I request to help me with MATLAB app code view
I.e I want to send some values of set speed ,P,I,D values via the com port and receive the speed in rpm through the arduino board and display in num box and guage
SO pls help me with the same
To simplify the problem I have to only send values to arduino board and receive the speed of the motor to MATLAB app.
Pls refer the arduino program and please help to run this code using MATLAB gui or MATLAB app designer code view.
/*
Motor - PID speed control
(1) Receive command from Visual Studio (via COM1): set_speed, kP, kI, kD
(2) Control motor speed through PWM (PWM is base on PID calculation)
(3) Send pv_speed to Visual Studio -> show in graph*/
String mySt = "";
char myChar;
boolean stringComplete = false; // whether the string is complete
boolean motor_start = false;
const byte pin_a = 2; //for encoder pulse A
const byte pin_b = 3; //for encoder pulse B
const byte pin_fwd = 4; //for H-bridge: run motor forward
const byte pin_bwd = 5; //for H-bridge: run motor backward
const byte pin_pwm = 6; //for H-bridge: motor speed
int encoder = 0;
int m_direction = 0;
int sv_speed = 100; //this value is 0~255
double pv_speed = 0;
double set_speed = 0;
double e_speed = 0; //error of speed = set_speed - pv_speed
double e_speed_pre = 0; //last error of speed
double e_speed_sum = 0; //sum error of speed
double pwm_pulse = 0; //this value is 0~255
double kp = 0;
double ki = 0;
double kd = 0;
int timer1_counter; //for timer
int i=0;
void setup() {
pinMode(pin_a,INPUT_PULLUP);
pinMode(pin_b,INPUT_PULLUP);
pinMode(pin_fwd,OUTPUT);
pinMode(pin_bwd,OUTPUT);
pinMode(pin_pwm,OUTPUT);
attachInterrupt(digitalPinToInterrupt(pin_a), detect_a, RISING);
// start serial port at 9600 bps:
Serial.begin(9600);
//--------------------------timer setup
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
timer1_counter = 59286; // preload timer 65536-16MHz/256/2Hz (34286 for 0.5sec) (59286 for 0.1sec)
TCNT1 = timer1_counter; // preload timer
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
//--------------------------timer setup
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
analogWrite(pin_pwm,0); //stop motor
digitalWrite(pin_fwd,0); //stop motor
digitalWrite(pin_bwd,0); //stop motor
}
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 = 600.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);
}
}
}
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
if (inChar != '\n') {
mySt += inChar;
}
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
basically at first it was interface with visual studio but now want this to interface with matlab that's it.
回答(1 个)
Kanishk
2024-12-19
To send values for PID controller from arduino and recieve speed in RPM you can use the "MATLAB Support Package for Arduino Hardware".
For controlling the values using App Designer, you can design a simple app which sends and recieves values over serial port using the support package.
Open the appdesigner by typing the following command in command window and create a blank app.
appdesigner
Create a property "ArduinoObj" to store the hardware connection.
Create a startup function to connect with the hardware. Click on "Callback" button in the editor tab in "Code View".
app.ArduinoObj = arduino("COM3", "Uno", "BaudRate", 9600);
Add some edit fields to enter the values to be sent and add a button with callback function to send the values. This is an example callback function to send and recieve values.
function SendButtonPushed(app, event)
setSpeed = app.SetSpeedEditField.Value;
P = app.PEditField.Value;
I = app.IEditField.Value;
D = app.DEditField.Value;
% Send data to Arduino
write(app.ArduinoObj, [setSpeed, P, I, D], "uint8");
% Read the motor speed from Arduino
motorSpeed = read(app.ArduinoObj, 1, "uint16");
% Update the gauge and numeric display
app.SpeedGauge.Value = motorSpeed;
app.SpeedDisplay.Value = motorSpeed;
end
To learn more about MATLAB App designer and Functions in Arduino Support package, you can check the documentation by using these commands.
web(fullfile(docroot, 'matlab/app-designer.html'))
web(fullfile(docroot, 'matlab/arduinoio.html'))
0 个评论
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!