Forum: Digitale Signalverarbeitung / DSP / Machine Learning Drehzahlmessen für Ziegler-Nichols Einstellverfahren


von Vita H. (Firma: FH-Bielefeld) (thevit1989)


Lesenswert?

Hi Leute,

ich hoffe ich könnt mir weiterhelfen.

Ich möchte gerne mit Hilfe von Ziegler-Nichols meinen Drehzahlregler 
Parametrisieren.

Aufbau:

Ich habe einen DC-Motor mit U=12V, I=7A, n= 85 1/min und M=4Nm. Der 
Motor ist über die Welle mit einer Trommel (m= 1,2kg) verbunden. 
Zusätzlich habe ich einen Encoder mit 60 Impulsen pro Umdrehungen an der 
Welle.

Nun zu meiner Frage:

Um ZIegler-Nichols anwendnen zu können muss ich die Drehzahl über der 
Zeit aufnehmen. (Sprungatnwort) (Sprung U=12V)

Dazu habe ich einen Arduino genommen und über die Inkremente des 
Encoders, sowie Interrupt die Drehzahl berechnet. Anschließend habe ich 
das auf dem SeriellMonitor ausgegeben.

Nun brauche ich noch die Zeit. Dies geht wohl am besten die der millis() 
Funktion.

Folgenden Code verwende ich:

#define  INA2  8  //Clockwise
#define  INB2  4  //Counter Clockwise
#define  EN2   A1 //Enable für den zweiten Chip
#define  PWM2  6
#define  Eingang  A0


// read RPM and calculate average every then readings.
const int numreadings = 10;
int readings[numreadings];
unsigned long average = 0;
int index = 0;
unsigned long total;

volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile
unsigned long rpm = 0;
unsigned long lastmillis = 0;
unsigned long time=0;

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

  //Ergänzung Monstershield
  //PWM init für den zweiten Chip
  pinMode(PWM2, OUTPUT);

  //Enable Init für den zweiten Chip
  //pinMode(EN2, OUTPUT);

  //Clockwise Init für den zweiten Chip
  pinMode(INA2, OUTPUT);

   //Clockwise Init für den zweiten Chip
  pinMode(INB2, OUTPUT);

  Timer0_init();

 attachInterrupt(0, rpm_fan, RISING);
}

void loop(){


     if (millis() - lastmillis >= 1000){  /*Uptade every one second, 
this will be equal to reading frecuency (Hz).*/

     detachInterrupt(0);    //Disable interrupt when calculating
     total = 0;
     readings[index] = rpmcount * 60;  /* Convert frecuency to RPM, 
note: this works for one interruption per full rotation. For two 
interrups per full rotation use rpmcount * 30.*/

     for (int x=0; x<=9; x++){
       total = total + readings[x];
     }

     average = total / numreadings;
     rpm = average;

     rpmcount = 0; // Restart the RPM counter
     index++;
     if(index >= numreadings){
      index=0;
     }


    if (millis() > 11000){  // wait for RPMs average to get stable

     time=millis();

     Serial.print(" RPM = \t\t ");
     Serial.println(rpm,'\t');
     Serial.print("time=\t");
     Serial.println(time);
    }

    lastmillis = millis(); // Uptade lasmillis
    attachInterrupt(0, rpm_fan, RISING); //enable interrupt
  }




  digitalWrite(INA2, HIGH);

  delay(100);

  //Serial.print("Hallo");


  OCR0A = 255;

  //OCR0B = 127;
 delay(100);

}


void Timer0_init (void)
{
  /*Prescale*/
  /*
   *
   *
    Setting Divisor Frequency:
    0x01  1 62500
    0x02  8 7812.5
    0x03  64  976.5625
    0x04  256 244.140625
    0x05  1024  61.03515625
   *
   * Um den Prescaler zu setzen einfach die Passende Hexzahl der 
variable
   * setting zuweisen.
  */

 int setting = 0x02;
  // Fast PWM
  TCCR0A |= (1<<COM0A1) | (1<<COM0B1) | (1<<WGM01) | (1<<WGM00);
  TCCR0B = TCCR0B & 0b11111000 | setting;

  //Phase Correct
//  TCCR0A |= (1<<COM0A1) | (1<<COM0B1)| (1<<COM0A0) | (1<<COM0B0)  | 
(1<<WGM00);
//  TCCR0B |= (1<<CS01);//|(1<<CS00);


}
void rpm_fan(){ /* this code will be executed every time the interrupt 0 
(pin2) gets low.*/
  rpmcount++;
}


Leider reicht die Auflösung nicht oder ist Arduino einfach zu Langsam. 
Habt ihr vielleicht eine Idee um diese Kurve aufzeichnen zu können? Habe 
Leider nur die Oben genannten Komponenten.

Kann ich vielleicht über den Strom die Endgültige Drehzahl bestimmen? Im 
Hinblick auf die Ankerzeitkonstante.


Viele Grüße

Vit

von Karl (Gast)


Lesenswert?

Vergiss Ziegler Nichols. Es funktioniert für derartiges nur begrenzt 
gut.

Dein Strom gibt mehr oder weniger das Drehmoment wider. Auch nicht 
verkehrt.

Du kannst aber sicher einen timer zum Messen der Zeit zwischen zwei 
Flanken deines Gegners verwenden und daraus die Drehzahl rechnen. Machst 
du das?

von aSma>> (Gast)


Lesenswert?

Servus,
Sprungantwort mithilfe eines Encoders ist ein wenig schwierig, da der 
differenzierende Anteil doch etwas nervös sein wird. Es gibt auch 
bessere Möglichkeiten, wie EMK Spannung messen oder ein Tachogenerator. 
Wollte nur dahin gesagt haben. Es wird auch so gehen mit einen Tiefpass.

> Leider reicht die Auflösung nicht oder ist Arduino einfach zu Langsam.
> Habt ihr vielleicht eine Idee um diese Kurve aufzeichnen zu können? Habe
> Leider nur die Oben genannten Komponenten.

Du hast mehrmals delay(100) in dein main program :(. Weiterhin hast du 
nur 1s du die Berechnung der rmp?! Und noch als Sahnehäufchen hast du 
9600 baud. Was meist du jetzt was dich ausbremst?

> Ich habe einen DC-Motor mit U=12V, I=7A, n= 85 1/min und M=4Nm.
Kommt mir irgendwie aus einen anderen Thread bekannt vor.

Weiterhin formatiere das nächste mal deinen kod_e. Danke.

mfg

von Vita H. (Firma: FH-Bielefeld) (thevit1989)


Lesenswert?

Hi Leute,

erstmal damke für die schnellen Antworten.

Ja aSma ich bin es aus dem anderen Thread:)

Also ich suche eine möglichkeit meine PID-Werte einzustellen. Ich könnte 
es mit BodeDiagramm machen, aber wofür, wenn mein Aufbau beim testen 
keinen schaden verursacht.

Ziegler-Nichols erschien mir am einfachsten. Welches verfahren ist denn 
besser?

Ach und wie messe ich die EMK am Gleichstrommotor. EMK ist doch die 
Induzierte Gegenspannung wenn der Motor hochläuft. Ist das auch die 
Spannung die den Strom Langsam ansteigenlässt? Geschweige den die 
Induktivität. Strom springt ja nciht in einer Induktivität.

Also mein Code oben funktioniert, aber ihr habt recht ich sollte die 
BAUD mal erhöhe und den COde mal aufräumen. Leider bin ihc etwas 
eingespannt wegen der Arbeit daher kann es etwas dauern.

Ach und Tachogenerator habe ich auch schon gesucht,daber die sind so 
Teuer:(

Viele Grüße Vit

von aSma>> (Gast)


Lesenswert?

Servus,
normalerweise, mit Verlaub, ist es angebracht die gewünschte Regelgüte 
zu nennen. Nur dann kann man konkret helfen. Positionsregelung werden 
mithilfe einer Kasadenregelung geregelt...

Vita H. schrieb:
> Also ich suche eine möglichkeit meine PID-Werte einzustellen. Ich könnte
> es mit BodeDiagramm machen, aber wofür, wenn mein Aufbau beim testen
> keinen schaden verursacht.

Bau dir ein Endstop rein. Entweder mechanisch oder induktiv mit 
Magneten.

Stell den Regler nach der gewünschten Winkelgeschwindigkeit und Dämpfung 
ein. Fang erstmal an mit einen PI-Regler an. Eine Pt1-Strecke mit einen 
PI-Regler gibt wiederum eine PT1 Übertragung. Du kannst somit eine 
gewünschte Zeitkonstante wählen... Dann kannst du einen PID-T1 Regler in 
Angriff nehmen.


> Ziegler-Nichols erschien mir am einfachsten. Welches verfahren ist denn
> besser?
In der Realität kann man die ganzen heuristischen Verfahren vergessen, 
da diese nicht die physikalischen Grenzen des Systems 
mitberücksichtigen.

Deswegen ist eine Simulation das A und O. Sprungantwort gefolgt von der 
Rampenantwort.

> Ach und wie messe ich die EMK am Gleichstrommotor. EMK ist doch die
> Induzierte Gegenspannung wenn der Motor hochläuft. Ist das auch die
> Spannung die den Strom Langsam ansteigenlässt? Geschweige den die
> Induktivität. Strom springt ja nciht in einer Induktivität.

Die Drehzahl ist proportional zur EMK. Diese triviale Geschichte ergibt 
sich aus der DC Motorgleichung. Es gab neulich eine gute Diskussion hier 
im Forum. Ich bin am falschen Rechner und finde es nicht gleich auf 
anhieb.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.