Advertisement
Guest User

Drehzahlmessung/Regelung/PID

a guest
Mar 22nd, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.90 KB | None | 0 0
  1. #include <PID_v1.h>
  2. #include <Wire.h> // Library für I2C-Interface
  3. #include <LiquidCrystal_I2C.h> // LCD i2c Library einbinden
  4.  
  5. LiquidCrystal_I2C lcd1(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
  6. LiquidCrystal_I2C lcd2(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
  7.  
  8. # define PotiPin 0
  9. # define HallPin 2
  10. # define pwmPin  9
  11. int Umax = 1500;
  12. int Prozent;
  13. double UpmSoll;
  14. double upmIst = 0;
  15. char buf[17];
  16. double pwm = 127;
  17. int hpin;
  18.  
  19. const int AVG = 4; // Glättung über mindestens 4 Messwerte
  20. volatile unsigned long dauer = 0; // microsekunden seit dem letzten Interrupt
  21. volatile unsigned long last = 0; // Zählerwert beim letzten Interrupt
  22. volatile unsigned long average = 1; // Integrierte Dauer // =1: divide by 0 vermeiden
  23. volatile int avgcnt = 0;
  24. unsigned long previousMillis;
  25. int diff = 0;
  26. int intervall = 3200;
  27.  
  28. double Kp = 10, Ki = 5, Kd = 1;
  29. PID myPID(&upmIst, &pwm, &UpmSoll, Kp, Ki, Kd, DIRECT);
  30.  
  31. void setup() {
  32.   Serial.begin(9600);
  33.  
  34.   //TCCR0B = (TCCR0B & 0b11111000) | 0x01;
  35.  
  36.   pinMode(PotiPin, INPUT); // lesender Zugriff
  37.   pinMode(HallPin, INPUT_PULLUP); // dito
  38.   pinMode(pwmPin, OUTPUT); // schreibender Zugriff
  39.   digitalWrite(pwmPin, 0); // für definierten Anfangszustand
  40.  
  41.  
  42.   attachInterrupt(digitalPinToInterrupt(HallPin), readmicros, RISING);    // Interrupt
  43.  
  44.   //initialize the variables we're linked to
  45.  
  46.   hpin = analogRead(HallPin);
  47.   UpmSoll = 0;
  48.   upmIst = analogRead(HallPin);
  49.  
  50.   //turn the PID on
  51.   myPID.SetMode(AUTOMATIC);
  52.   myPID.SetTunings(Kp, Ki, Kd);
  53.  
  54.   lcd1.begin(16, 2);
  55.   lcd1.backlight();
  56.  
  57.   lcd2.begin(16, 2);
  58.   lcd2.backlight();
  59. }
  60. void loop() {
  61.   // int Prozent = analogRead(0);
  62.   //UpmSoll = map(Prozent, 0, 1023, 90, 110);
  63.  
  64.   UpmSoll = map(analogRead(PotiPin), 0, 1023, 0, 1500);
  65.   //UpmSoll = map(Prozent, 0, 100, 0, Umax);
  66.  
  67.  
  68.   /*
  69.     UpmSoll = ((UpmSoll + 5) / 10) * 10;
  70.     if (UpmSoll <= 20) {
  71.       UpmSoll = 0;
  72.     } else if (UpmSoll >= 1485) {
  73.       UpmSoll = 1500;
  74.   */
  75.  
  76.  
  77.   myPID.Compute();
  78.  
  79.   UpmIst();
  80.  
  81.   // UpmIstAusgabe();
  82.  
  83.   if (UpmSoll < upmIst) {
  84.     diff = upmIst - UpmSoll;
  85.     //digitalWrite(pwmPin, HIGH);
  86.     pwm = map(diff, 0, UpmSoll, 0, 255);
  87.     pwm = min(pwm, 255); // Begrenzung des PWM - Wertes auf höchstens 255
  88.     Serial.println("BREMSE AN");
  89.   } else {
  90.     diff = 0;
  91.     pwm = 0;
  92.     Serial.println("BREMSE OFF");
  93.   }
  94.   analogWrite(pwmPin, pwm);
  95.  
  96.  
  97.   //Serial.println("EIN");
  98.  
  99.   Serial.print(" UpmSoll: ");
  100.   Serial.print(UpmSoll);
  101.   Serial.print(" upmIst: ");
  102.   Serial.print(upmIst);
  103.   Serial.print(" pwm: ");
  104.   Serial.println(pwm);
  105.  
  106.   int intervall = 3200;
  107.   //Lcd1();
  108.   Lcd2();
  109. }
  110. void UpmIst (void) {
  111.   if (dauer != 0) {
  112.     upmIst = 60000000 / average; // Drehzahl ausrechnen und runden
  113.     //upmIst = ((upmIst + 10) / 10) * 10;
  114.   } else {
  115.     upmIst = 0; // keine Messung? -> Stillstand
  116.     avgcnt = 0;
  117.   }
  118.   sprintf(buf, "%4lu", upmIst);
  119.  
  120.  
  121. }
  122.  
  123. void readmicros() { // Interrupt-Routine
  124.   // detachInterrupt(digitalPinToInterrupt(HallPin)); // Interrupt ausschalten damit er uns nicht beißt
  125.   int avgmax;
  126.   unsigned long us = micros(); // Microsekundenzähler auslesen
  127.   if (last == 0) { // erster Messwert?
  128.     last = us; // merken und nicht weiter bearbeiten
  129.   }
  130.   else {
  131.     if ( us < last ) { // Zählerüberlauf
  132.       dauer = 4294967295 - last + us; // erzeugt einen Fehler von 1µS - vernachlässigbar 4294967295
  133.     }
  134.     else {
  135.       dauer = us - last; // Differenz zum letzten Durchlauf berechnen
  136.     }
  137.     if (dauer > 5000) { // ignorieren wenn <= 5ms (Kontaktpreller)
  138.       average = dauer + average * avgcnt++; // Wert in buffer und mit Faktor avgcnt glätten
  139.       average /= avgcnt; // und zurückrechnen
  140.       avgmax = 1000000 / dauer; // dynamische Größe des Integrationspuffers
  141.       if (avgmax < AVG) avgmax = AVG; // Trägheit mindestens 1 Sekunde
  142.       if (avgcnt >= avgmax) avgcnt--;
  143.       last = us; // und wieder den letzten Wert merken
  144.     }
  145.     else {
  146.       dauer = 0;
  147.     }
  148.   }
  149.   //attachInterrupt(digitalPinToInterrupt(HallPin), readmicros, RISING ); // Interrupt wieder einschalten
  150. }
  151. /*
  152.   void Lcd1(void) { // Ausgabe-Komplett am LCD1
  153.  
  154.   lcd1.clear();
  155.   lcd1.setCursor(0, 0);
  156.   lcd1.print("Force[Nm]:");
  157.   lcd1.setCursor(10, 0);
  158.   lcd1.print(Force, 3); // gewicht ausgabe
  159.   // lcd1.setCursor(0, 1);
  160.   //lcd1.print("Drehzahl ");
  161.   // lcd1.print(Prozent); // UpmSoll ausgabe
  162.   //lcd1.print("%");
  163. */
  164.  
  165.  
  166. void Lcd2(void) { // Ausgabe-Komplett am LCD2
  167.  
  168.   lcd2.clear(); // Soll es BLINKEN ODER NICHT????
  169.   lcd2.setCursor(0, 0);
  170.   lcd2.print("SOLL[U/min]:");
  171.   lcd2.setCursor(12, 0);
  172.   int ausgabeUpmSoll = (int)UpmSoll;
  173.   lcd2.print(ausgabeUpmSoll); // Soll-Umdrehung ausgeben
  174.   lcd2.setCursor(0, 1);
  175.   lcd2.print("IST [U/min]:");
  176.   lcd2.setCursor(12, 1);
  177.   int ausgabeUpmIst = (int)upmIst;
  178.   lcd2.print(ausgabeUpmIst); //Ist-Umdrehung ausgeben
  179.   // lcd2.setCursor(12, 1);
  180.   // lcd2.print(Umax); //Max UPM Schwellwert zum schalten der Bremse
  181. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement