Go Down

Topic: PID does not sense negative values. (Read 3063 times)previous topic - next topic

dvl12

Apr 05, 2013, 01:08 am
Hello. I am trying to set up a system of Servomotor and a combo board (gyro + accelerometers). I am using PID and the setups is such: setpoint is zero degrees, input is angle from the combo board and output is Amplitude of rotation of servo arm on my servo. I made it work, but it only works when incline the combo board in one direction and gives positive angles. however, when incline the other way and it gives negative angles PID does not do anything. Is there any solution to that?

Magician

#1
Apr 05, 2013, 01:15 am
Looks as extract from encrypt comms in CERN, something related to Large Hadron Collider

dvl12

#2
Apr 05, 2013, 01:19 am
Is my question unclear?

Magician

#3
Apr 05, 2013, 01:27 am
Obviously.

http://arduino.cc/forum/index.php/topic,97455.0.html

dvl12

#4
Apr 05, 2013, 01:29 am
I am working on a project, which involves PID controller, Arduino, IMU combo board (gyro + accelerometer) and a servomotor. The aim is to keep IMU horizontal at zero degrees, when it inclines amplitude of oscillation of a servo arm on my servomotor increases and when IMU is back in horizontal position amplitude is zero. I set my PID as such: Input = angles from IMU, Output = Amplitude, Setpoint = 0 degrees. It works fine in one direction when angles from IMU are positive, however, in the other direction when angles are negative PID does not respond. Could anyone help me to find a solution for that problem?

Here is a code to make it easier to understand:
Code: [Select]
#include <PID_v1.h>

#include <FreeSixIMU.h>
#include <FIMU_ITG3200.h>

#include <Wire.h>

double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint,2,5,1, REVERSE);

int Ampl = 0;

float angles[3]; // yaw pitch roll

// Set the FreeSixIMU object
FreeSixIMU sixDOF = FreeSixIMU();

void setup() {
Serial.begin(9600);
Wire.begin();

Input = angles[2];
Setpoint = 0.00;
myPID.SetMode(AUTOMATIC);

delay(5);
sixDOF.init(); //begin the IMU
delay(5);
}

void loop() {

sixDOF.getEuler(angles);

Input = angles[2];
myPID.Compute();
myPID.SetOutputLimits(0, 180);
Ampl = Output;

Serial.print(angles[0]);
Serial.print(" | ");
Serial.print(angles[1]);
Serial.print(" | ");
Serial.print(angles[2]);
Serial.print(" | ");
Serial.println(Ampl);

delay(100);
}

dvl12

#5
Apr 05, 2013, 02:01 am
I managed to solve this problem by introducing two PIDs in the code and multiplying input for one of them by (-1), however, it is not an elegant solution and I am still looking for a solution using single PID?

PeterH

#6
Apr 05, 2013, 02:19 am
I don't think it's related to your problem, but I think the call to SetOutputLimits() should be in setup(), not in loop().

I can't see any reason why that wouldn't work for negative input values. Can you post some examples of the trace output with positive and negative input values?
I only provide help via the forum - please do not contact me for private consultancy.

dvl12

#7
Apr 05, 2013, 03:12 am
For example:

Angle    Amplitude
10        10
20        20
80        80
0          0
-10       0
-30       0
-80       0

I made it up myself, but this is what I see is going on when reading a serial monitor.

PeterH

#8
Apr 05, 2013, 03:39 am
Well, you've set the output limits to 0, 180, so it can't go negative. What do you expect it to do in that case?
I only provide help via the forum - please do not contact me for private consultancy.

dvl12

#9
Apr 05, 2013, 12:18 pm
I did not want getting any negative amplitudes. I was expecting it to increase amplitude when angle is not zero.

PeterH

#10
Apr 05, 2013, 02:01 pm

I did not want getting any negative amplitudes. I was expecting it to increase amplitude when angle is not zero.

It can't 'increase amplitude when angle is not zero' when the angle is negative, because you've prevented it from outputting a negative value. The PID has run into the end stops that you have defined, and it can't go any further.

Please show a real example of where it has produced the wrong behaviour and explain what you wanted it to do.
I only provide help via the forum - please do not contact me for private consultancy.

PaulS

#11
Apr 05, 2013, 05:16 pm
It would seem that you would want the output limits to be -90 to 90. Then, add 90 to the actual output to get a value between 0 and 180 to write to the servo.

What, exactly, is PID doing for you?

Go Up

Please enter a valid email to subscribe