Hello everyone,
That you can get a picture of what I am trying to achieve, I'll quickly describe my project: I want to achieve magnetic levitation with this design:
So to control the magnet's direction, I have put a motor driver into the circuit. At the beginning, without the flying pencil, I measure the magnetic field and then I give this value to the PID controller as the Setpoint. Now I measure the magnetic field with my hall sensor every ms and give that value to the PID which then gives back a suggested output value.
So far so good. Let's say I attached the MotorIn1 to PIN 10 and MotorIn2 to PIN11. Since the PID calculates with the difference, integral and the derivative I can't simply do what I did here:
//Der Input ist grösser als der Kalibrierungswert
if(Input>Setpoint) {
analogWrite(motorIn1,Output);
analogWrite(motorIn2,0);
}
//Der Input ist geringer als der Kalibrierungswert
if(Input<Setpoint){
analogWrite(motorIn1,0);
analogWrite(motorIn2,255);
Since this would only work for a D controller. Now my question is: How can I make that the PID controller gives me a value between -255 and 255 so I can call the different MotorInputs? (Since the Input can both be lower and higher than Setpoint)
Or if that has been discussed to death, could you give me a google keyword, since looking for bidirectional PID gives no valuable results.
P.S.
I often hear that PID is overkill for such small things, I already did my own, simple controller which only takes the difference to the setpoint and the change per ms into account (derivative). Not the integral and therefore the acceleration. So I felt that maybe a better algorithm may help (Eventhough I most likely will have to adjust the design anyways.)
Thanks for your help!
The entire code for reference:
#include <PID_v1.h>
const int motorIn1 = 11;
const int motorIn2 = 10;
const int analogPin = A0;
int debug = 0;
//Differenzierung zwischen aggresiver Korrektur und konservativer Korrektur
double driftmax = 5.0;
//Erstellung der Variablen für den PID Controller
double Input, Output, Setpoint;
//Tuning Parameter
double aggKp=3, aggKi=1, aggKd=1.2;
//Erstelle den PID Controller
PID myPIDDirect(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
void setup() {
//Schalte den PID Controller an
myPIDDirect.SetMode(AUTOMATIC);
//Tuning Settings
myPIDDirect.SetTunings(aggKp, aggKi, aggKd);
pinMode(motorIn1,OUTPUT);
pinMode(motorIn2,OUTPUT);
//Initzialisiere Debugkonsole zum Auslesen der Werte
Serial.begin(9600);
//Berechne den Kalibrierungswert (Setpoint)
for(int i = 0; i<10; i++) {
Setpoint = Setpoint + measure();
delay(1);
}
Setpoint/=10.0;
}
void loop() {
debug++;
//Messung vornehmen
Input = measure();
//Betrag der Abweichung ermitteln
double drift = abs(Setpoint-Input);
myPIDDirect.Compute();
//Der Input ist grösser als der Kalibrierungswert
if(Input>Setpoint) {
analogWrite(motorIn1,Output);
analogWrite(motorIn2,0);
}
//Der Input ist geringer als der Kalibrierungswert
if(Input<Setpoint){
analogWrite(motorIn1,0);
analogWrite(motorIn2,255);
}
//Debug
if((debug%500)==0) {
Serial.print("Kalibrierung: ");
Serial.println(Setpoint);
Serial.print("Measurement: ");
Serial.println(Input);
Serial.print("Correction: ");
Serial.println(Output);
Serial.println();
}
}
double measure() {
double temp_mes = 0;
int counts = 0;
for (int i = 0; i < 10; i++) {
temp_mes+=(analogRead(analogPin));
counts++;
delay(0.1);
}
return (temp_mes/counts);
}
