Hallo,
ich habe es nun endlich geschafft, einen PID Controller auf dem Arduino laufen zu lassen. Sieht man von etwas Feintuning von Kp, Ki und Kd einmal ab.
Nun möchte ich gerne 2 PID's auf einem Arduino laufen lassen. Ich habe mir dazu das Beispiel angesehen, wie man 2 LCD Displays auf einem Controller anspricht
Nur wie bringe ich den beiden PID Instanzen bei, das sie unterschiedliche Kp, Ki und Kd Werte verwenden sollen? Die beiden Instanzen im Programm dann in verschiedenen Unterprogrammen in geschweiften Klammern zu verwenden, leuchtet mir auch ein.
Ich habe aber kein Beispiel finden können, wie ich 2 PIDs erst mal initialisiere.
Kann mir da bitte mal jemand auf die Sprünge helfen?
Sie sieht es mit einem PID aus:
/*
Arduino Tutorial 4.2 - Drehzahl mit Potisteuerung
by Scynd 2014
In diesem Tutorial geht es darum, die Lüftergeschwindigkeit mit Hilfe eines Drehpotenzometers einzustellen.
*/
//Konstanten
const int ledPin = 3;
const int FanPin = 9; // Lüfter an Pin 9 angeschlossen
const int PotiPin = A0 ; // Potenzometer am analogen Eingang Pin 0 angeschlossen
const int TachoPin = 2; // Pin des Tachosignals des Lüfters
// Variablen
int ledBright = 0;
int ledPercent = 0;
int Temp = 0;
#define KRITISCH 40.00
int FanSpeed = 0; // Variable für die Lüftergeschwindigkeit
int FanMin = 50; // Minimaler PWM Wert für den Lüfter. Kommt auf den Lüfter an
int PotiVar = 0 ; // Variable zum speichern des Potentiometereingangs
int AbfrZeit = 5000; // Zeitabstand für die Abfragen des Tachosignals
long TachoMillis = AbfrZeit; // Zeitabstand für Pulse Stretching Funktion
float RPS = 0; // Variable mit Kommastelle für die Berechnung der Umdrehungen pro Sekunde
int RPM = 0; // Variable für die gemittelte Drehzahl
float UmdrZeit = 0; // Variable mit Kommastelle für die Zeit pro Umdrehung des Lüfters
float FlankenZeit =0; // Variable mit Kommastelle für die Zeit pro Puls des Lüfters
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <PID_v1.h>;
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
//PID SETUP
double Setpoint, Input, Output; //I/O for PID
double aggKp=40, aggKi=2, aggKd=10; //original: aggKp=40, aggKi=2, aggKd=10, Aggressive Turning,50,20,20
double consKp=10, consKi=0.5, consKd=2.5; //original consKp=20, consKi=1, consKd=5, Conservative Turning,20,10,10
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, REVERSE); //Initialize PID
LiquidCrystal_I2C lcd(0x20,16,4); // set the LCD address to 0x20 for a 16 chars and 2 line display
void setup() {
lcd.init(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
sensors.begin();
Setpoint = 35.00; //Eingestellte Temperatur
myPID.SetMode(AUTOMATIC);
TCCR1B = TCCR1B & 0b11111000 | 0x01; // Setzt Timer1 (Pin 9 und 10) auf 31300Hz
// Serial.begin(9600);
pinMode(ledPin, OUTPUT) ;
pinMode(FanPin, OUTPUT) ; //Setzt den Lüfter Pin als Ausgang
pinMode(PotiPin, INPUT) ; //Setzt den LEDPin als Ausgang
pinMode(TachoPin, INPUT); //Setzt den Tacho Pin als Eingang
}
void loop() {
//lcd.clear();
sensors.requestTemperatures(); // Send the command to get temperatures
PotiVar = analogRead(PotiPin) ; // Liest das Potentiometer aus
Temp = (sensors.getTempCByIndex(0)) ;
if ((Temp) > -127.00) { Input = Temp;
}
//Input = Temp;
double gap = abs(Setpoint-Input); //entfernung zur eingestellten Temperatur
if(gap < 1)
{
//nah am Setpoint --> KONSERVATIVES REGELN
myPID.SetTunings(consKp, consKi, consKd);
}
else
{
//weit weg vom Setpoint --> AGGRESSIVES REGELN
myPID.SetTunings(aggKp, aggKi, aggKd);
}
myPID.Compute();
if (Input < KRITISCH)
analogWrite(FanPin,Output);
else
analogWrite(FanPin,255);
lcd.setCursor(0, 0);
//lcd.print("Poti");
lcd.print("Temp");
lcd.setCursor(5, 0);
//lcd.print(PotiVar);
lcd.print((Input),1);
lcd.write(0xD0 + 15);
//lcd.setCursor(9, 0);
lcd.print("C ");
lcd.setCursor(-4, 2);
lcd.print("Fan Out ");
//lcd.setCursor(1, 2);
lcd.print((Output),0);
//lcd.setCursor(6, 3);
lcd.print(" ");
//FanSpeed = map(PotiVar, 50, 1023, FanMin, 255); // Verteilt den PWM Wert über den Messbereich des Potis
ledBright = map(PotiVar, 0, 1023, 255, 0);
ledPercent = map(PotiVar, 0, 1023, 0, 100);
lcd.setCursor(-4, 3);
lcd.print("LED ");
//lcd.setCursor(1, 2);
lcd.print(ledPercent);
//lcd.setCursor(6, 3);
lcd.print(" % ");
// Unterer Potenziometerbereichs (0-50) = Lüfter aus
//if(PotiVar < 50) {
//FanSpeed = 0;
//}
//analogWrite(FanPin, FanSpeed); // Gibt die Variable mit PWM aus
analogWrite(ledPin, ledBright);
// Alle 2000ms pulse_stretch starten um die Drehzal auszulesen
if((millis() - TachoMillis) >= AbfrZeit) {
pulse_stretch();
}
}
void pulse_stretch() {
// Nur wenn PotiVar größer als 50 ist, wird die RPM ausgelesen
if(Output == 255) {
//analogWrite(FanPin, 255); // Den Lüfter konstant mit Strom versorgen damit das Tachosignal funktioniert
FlankenZeit = pulseIn(TachoPin, HIGH); // Abfrage der Zeit pro Puls in Mikrosekunden
//analogWrite(FanPin, FanSpeed); // Setzt die Lüftergeschwindigkeit zurück
UmdrZeit = ((FlankenZeit * 4)/1000); // Berechnung der Zeit pro Umdrehung in Millisekunden
RPS = (1000/UmdrZeit); // Umrechnung auf Umdrehungen pro Sekunde
RPM = (RPS*60); // Umrechnung auf Umdrehungen pro Minute
lcd.setCursor(0, 1);
lcd.print("Fan ");
//lcd.setCursor(4, 1);
lcd.print(RPM);
//lcd.setCursor(8, 1);
lcd.print(" RPM ");
}
// Wenn der Lüfter nicht angesteuert wird, schreibe Drehzahl 0
//else{
//lcd.setCursor(0, 1);
//lcd.print("Fan 0 RPM ");
//lcd.setCursor(4, 1);
//lcd.print(RPM ,0);
//lcd.setCursor(8, 1);
//lcd.print("RPM");
//Serial.println("0");
//}
//lcd.setCursor(12, 1);
//lcd.print(FanSpeed);
TachoMillis = millis(); // Die TachoMillis werden aktualisiert um die nächsten 2000ms zählen zu können
//delay(1000);
}
Das ganze ist noch im Rohzustand. Es soll ein Temperaturmanagment für eine Power-LED werden. Ein DS18B20 klebt am Kühlkörper und misst die KK Temperatur. Erwärmt sich der KK, versucht der 1. PID den KK auf 40°C mittels Lüfter zu halten. Gelingt das nicht, soll der 2 PID dann ab 45°C zwangsweise die LED runterdimmen. Die KSQ hat einen 0-10V Eingang. Wenn das Ganze funktioniert, werde ich die Hardware hier vorstellen, denn dieses Projekt kann vielleicht noch für andere Leute interessant sein und läßt sich recht easy an andere Hardware anpassen.