LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

PID controller with Arduino (Hardware in the loop)

Solved!
Go to solution

hi.
i am new with forum part of labview, so i wish that i am on the right place and excuesme because of my language 🙂
i have a transfer function (dc motor) in bview. i want to design a PID controller on arduino for that transfer function. I know that it's possible to design the controller in labview too but i need the controller on Arduino.
so i have the PID codes for arduino and i use VISA to connect arduino to labview. (i attached them). my problem is that it doesn't work correctly. what's the reason?
it's because of the codes?
or because of the VISA?
i tried this code for a real dc motor and it worked correctly. but it doesn't work for the transfer function.

 

 

double sampletime = 0.12;
double eror, sumeror = 0 , input , buff;
float feedback ;
byte speedref = 100;
byte output;
double Kp = 19 , Ki = 36 , a = 0 ;

void setup() {
Serial.begin(115200);
Serial.println( a);
while (!Serial) {}
}

int bytesToRead = 0;
char msg[64];

void loop() {

if (Serial.available())
{

getMessage();
float feedback = atof (msg);
output = (double) feedback;
//PID:
eror = speedref - output;
sumeror = sumeror + (sampletime * eror);
input = (Kp * eror) + ( Ki * sumeror) ;

Serial.println(input );

delay(1000);
}

 

}
//Serialread:
void getMessage()
{
int i;

bytesToRead = Serial.available();

for (i = 0; i < bytesToRead; i++)
{
msg[i] = (Serial.read());

}
msg[i] = '\0';
}


Thank you...

0 Kudos
Message 1 of 12
(2,134 Views)

i need this.

please answer

0 Kudos
Message 2 of 12
(2,124 Views)

It's hard to read your code without indents, can you use the "insert code" formatting button to fix it? Can you be a lot more specific than just "it doesn't work correctly"? One common mistake which might cause problems is using "bytes at port" to tell the VISA Read how much to read, that's usually not the right way to do it and can lead to missed bytes. If your transmission from the Arduino to LabVIEW could either be of a fixed length or have a termination character at the end, that would make communications it more reliable.

0 Kudos
Message 3 of 12
(2,092 Views)

Thanks my friend.

this is the code:

double sampletime = 0.12;
double eror, sumeror = 0 , input , buff;
float feedback ;
byte speedref = 100;
byte output;
double Kp = 19 , Ki = 36 , a = 0 ;

void setup() {
Serial.begin(115200);
Serial.println( a);
while (!Serial) {}
}

int bytesToRead = 0;
char msg[64];

void loop() {

if (Serial.available())
{

getMessage();
float feedback = atof (msg);
output = (double) feedback;
//PID:
eror = speedref - output;
sumeror = sumeror + (sampletime * eror);
input = (Kp * eror) + ( Ki * sumeror) ;

Serial.println(input );

delay(1000);
}

 

}
//Serialread:
void getMessage()
{
int i;

bytesToRead = Serial.available();

for (i = 0; i < bytesToRead; i++)
{
msg[i] = (Serial.read());

}
msg[i] = '\0'; 
}

when i run the code, labview can read and write from serial. but the output should be 100 and stop on 100 (Vref in arduino code) but it increase and never stop.

what should i use instead of "byte as port"?

0 Kudos
Message 4 of 12
(2,078 Views)

Hi 

I am sorry if I misunderstood your problem,

However my take on your code is the following 

You are using double variables that gives you a wide range and no where in your PID code I see where you set the limits on the PID output(anti-windup ).This means to me as long as your error does to become zero your output will keep growing until the limit range of your double variable is reached , with out seeing your labVIEW code and a better understanding of your dc motor and system(is it running is it swinging or speedup and run at full speed) it hard to help (I can not open your Vi my LV is older than yours )

Then also in my experience with motors and PID a 1 sec Delta T for the PID is huge ,

 

Regards 

QMESAR

 

---------------------------------------------------------------------------------------
Learning is an endless process but needs to start some where
Message 5 of 12
(2,066 Views)

Thanks my friend...

your right...

i put a condition for "error" but it never become zero. even i use pid library for arduino but it does not work

0 Kudos
Message 6 of 12
(2,048 Views)

 I think labview and Arduino are not synchronous.

Is it necessary to use real-time module in labview?

I attached my vi picture to this post 

0 Kudos
Message 7 of 12
(2,036 Views)
Solution
Accepted by topic author mojafari74

Hi mojafari,

 

using a serial communication between DAQ <-> PID-loop <-> actuator is quite tricky as you need to account for transmission delays…

Why don't you put the PID control on the Arduino and just transfer all data to your PC host for plotting (pv, sp, output)?

 

On your code:

- There is a delay of 1s in your Arduino code: is this intended? Is the control loop acting that slow?

- Your LabVIEW code is missing a loop: how will you ever read and write more than just one value?

- You open the serial port in LabVIEW, but you never close that port. Did you even check the very basic example VIs coming with LabVIEW?

- You still use the BytesAtPort function: replace it by a simple numeric constant with a value of 999 (value larger than the expected number of bytes in a message)! You already configured the serial port to use a TermChar, which uses the very same default value as is used in the Arduino with the "Serial.println" command!

 

Btw. in your "code formatting" you still missed those requested indents…

Best regards,
GerdW

using LV2011SP1 + LV2017 (+LV2020 sometimes) on Win10+cRIO
0 Kudos
Message 8 of 12
(2,023 Views)

Thanks alot

0 Kudos
Message 9 of 12
(2,009 Views)

hi

i have problem with my topic yet...

i change my codes an VI but it doesnt work...

please say what should i do

#include <PID_v1.h>
double Setpoint, Input, Output;
double Kp = 36, Ki = 19, Kd = 0;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
void setup()
{
  Serial.begin(115200);
  while (!Serial) {}
  Setpoint = 100;
  myPID.SetMode(AUTOMATIC);
}
int bytesToRead = 0;
char msg[64];
void loop()
{

  if (Serial.available())
  {

    getMessage();
    float feedback = atof (msg);
    Input = (double) feedback;
    myPID.Compute();
    Serial.println (Output);
  }
}

void getMessage()
{
  int i;

  bytesToRead = Serial.available();

  for (i = 0; i < bytesToRead; i++)
  {
    msg[i] = (Serial.read());

  }
  msg[i] = '\0';
}
0 Kudos
Message 10 of 12
(1,882 Views)