Hello everybody, this is my first post and I would like to thank everyone in advance for the help and for making this forum such a rich resource.
I'm using the PID_v1 library to control a dual acting pneumatic cylinder via 5 way 3 position 12 volt solenoid valves. The board I'm using is an Elegoo MEGA 2560 (I'm having the same issue on an UNO) and the relay board is a SainSmart 8-channel relay board independently powered with 5 volts. I'm fairly certain that I'm not having any issues with hardware/wiring.
The issue I'm having is intermittent. It happens most often when the input overshoots the setpoint but it also happens often when the input is near the setpoint in general. The control signal will go from steadily ramping down its frequency to a sudden spike sending the cylinder far beyond the setpoint. I've spent many hours playing with the PID tunings and nothing seems to get rid of that spike from occuring, nor does anything seem to make the problem more repeatable. I've removed power from the JD-VCC portion of the relay board to isolate the electro-mechanical aspect of the relays from the equation and I can still see it happening just by watching the led's blinking that correspond to the channel being used. So I think I must have missed something in the code.
A few notes on the code: The input comes from a string pot that I made using a ten turn 10k pot. The max value I receive from these pots is 406
I've also adjusted the pwm output on the MEGA to 30.64 Hz and then further limited the pwm ouput to 165 from 255 to put the frequency in a usable range for the solenoid valves.
I'm running both a DIRECT and REVERSE PID on each cylinder.
Here is the code:
#include <PID_v1.h>
//Center Drum
double aSetpoint;// Setpoint for top cylinder
double aInput;// Stringpot for top cylinder
double aOutput;// Output for top cylinder
double aOutputr;// Reverse Output for top cylinder
// PID parameters
double Kp = .80, Ki = .0005, Kd = 0.00;
//create PID Instances
PID aPID(&aInput, &aOutput, &aSetpoint, 0, 0, 0, DIRECT);
PID aPIDr(&aInput, &aOutputr, &aSetpoint, 0, 0, 0, REVERSE);
void setup()
{
TCCR3B = TCCR3B & B11111000 | B00000101; // for PWM frequency of 30.64 Hz for pins 2,3, 5
Serial.begin(9600);
//Center Drum
aSetpoint = analogRead(6);
aInput = analogRead(0);
aOutput = 0;
aOutputr = 0;
//Turn the PID on
aPID.SetMode(AUTOMATIC);
aPIDr.SetMode(AUTOMATIC);
aPID.SetTunings(Kp, Ki, Kd);
aPIDr.SetTunings(Kp, Ki, Kd);
aPID.SetOutputLimits(-165, 165);
aPIDr.SetOutputLimits(-165, 165);
}
void loop() {
aInput = map(analogRead(0), 0, 406, 0, 165);
aSetpoint = map(analogRead(6), 0, 1023, 0, 406);
//ROCK
if (aInput >= aSetpoint) {
aPID.Compute();
analogWrite(2, aOutput);
digitalWrite(3, HIGH);
}
else if (aInput <= aSetpoint) {
aPIDr.Compute();
analogWrite(3, aOutputr);
digitalWrite(2, HIGH);
}
Serial.println(aOutput);
Serial.println(aOutputr);
Serial.println(aSetpoint);
Serial.println(aInput);
// delay(100)
}