- HEMS Solar Speicher Tutorial    Werbung      
Ergebnis 1 bis 10 von 10

Thema: RP6 Gleichlauf der Motoren

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Neuer Benutzer
    Registriert seit
    17.04.2012
    Beiträge
    4
    Zitat Zitat von SlyD
    Läuft los ja, aber hält er bei 46 auch wieder an?
    Das ist nämlich meistens nicht der Fall
    Wenns mal läuft dann läufts leichter...
    Danke für den Hinweis, hab ich ganz vergessen, aber wär mir bestimmt bald aufgefallen Bild  
    Mit der Hyterese sollte das dann auch kein Problem sein.

    Zitat Zitat von SlyD
    Einfacher wäre es natürlich, wenn man dem Motor der später losläuft beim Start direkt etwas mehr Power gibt.
    (also nur beim Start z.B. dem Integrierer eine Konstante hinzuaddieren... )
    Zitat Zitat von SlyD
    Ich meinte damit die Integral Variablen left_i und right_i beim standard I Regler in der Lib.
    Also da muss ich jetzt ein bissl was erzählen. Und zwar habe ich einen völlig eigenen Regler programmiert und den anderen Regler aus dem Code entfernt. Grund: Eingreifen in das Regelgeschehen war nicht einfach, wegen dem Soft-PWM etc. und ich wollte nicht Speed und Direction getrennt angeben. Ich habe jetzt die Funktion runSpeedController(int left, int right) und da kann ich die Geschwindigkeit in mm/s von -300mm/s bis +300mm/s eingeben. Was bei einer Positionsregelung dann auch von Vorteil ist, weil wenn die Dirfferenz negativ ist, ich nicht die Richtung ändern muss sondern der zweite Regler einfach mit Minus weiterrechnen kann.
    Deshalb brauch ich auch eine Hyterese um den Nullpunkt, da happerts im Moment noch.

    Ich stell mal den Code hier rein. Im Code siehst du auch den Grund, warum ich das mit einer Voreinstellung des I-Wertes nicht machen kann, weil mein Regler nicht einen I-Wert speichert sondern immer zur momentan eingestellten Stellgröße dazurechnet oder abzieht. Der Korrekturfaktor ist der Wert, wo ich die maximale Pulsweite(180, eigentlich 210 aber von meinem Programm begrenzt auf 180) durch die daraus resultierende Geschwindigkeit in [mm/s] dividiere.
    Der Code läuft im Timer0 Interrupt ab:

    Code:
    if(speedController == 1)
    	{
    		if(speedControllCounter++ >= speedControllTimer)
    		{
    			//Linke Raupe
    			speedControllCounter = 0;
    			sclE = sclW - getLSpeed();
    			
    			if(speedKp > 0)
    			delta_y = speedKp * (180/267.0) * ((sclE - sclE1) + speedKi * sclE * speedControllTimer/10000.0 + 
    					  speedTv * (sclE - 2*sclE1 + sclE2)/(speedControllTimer/10000.0));
    			else
    			delta_y = (180.0/267.0) * (speedKi * sclE * speedControllTimer/10000.0 + 
    					  speedTv * (sclE - 2*sclE1 + sclE2)/(speedControllTimer/10000.0));
    			
    			difE2 = difE1;
    			difE1 = difE;
    
    			if(delta_y > scMaxUp)
    				delta_y = scMaxUp;
    			
    			if(delta_y < scMaxDown)
    				delta_y = scMaxDown;
    
    			
    			if((PORTC & 0x04) >= 1) //BWD?
    				y1 = OCR1BL * (-1);  //=>y ist dann eigentlich negativ
    			else
    				y1 = OCR1BL;		    //sonst positiv
    
    
    			//Umwandeln von PW 46 bis 180 auf 0 bis 180 zur Kompatibilität zum Regler
    			//bzw. bei Rückwärtlauf von PW -42 bis -180 auf 0 bis -180
    			if(y1 >= 46)
    				y1 = (y1-46) * (180.0/(180.0-46.0));
    			else if(y1 <= (-42))
    				y1 = (y1-(-42)) * ((-180.0)/((-180.0)-(-42.0)));
    			else
    				y1 = 0;
    
    			//neues delta_y einfließen lassen und Signal in den vorgegebenen Grenzen halten
    			y1 += delta_y;
    
    			if(y1 > 180)
    				y1 = 180;
    			
    			if(y1 < -180)
    				y1 = -180;
    
    			//Zurückrechnen auf Werte zwischen 46 und 180 bzw. -42 bis -180
    
    			if(y1 > 0 || (y1 == 0 && delta_y >= 0))
    				y1 = 46 + y1 * ((180.0-46.0)/180.0);
    			else if(y1 < 0 || (y1 == 0 && delta_y < 0))
    				y1 = -42 + y1 * (((-180.0)-(-42.0))/(-180.0));
    
    			if(y1 < 0)
    			{
    				PORTC |= (1<<PORTC2); //BWD
    				y1 *= (-1); //y muss wieder positive Zahl sein weils auf OCR geschrieben wird
    			}
    			else
    			{
    				PORTC &= ~(1<<PORTC2); //FWD
    			}
    
    			sclE2 = sclE1;
    			sclE1 = sclE;
    
    			OCR1BL = y1;
    
    
    
    
    
    
    
    			//Rechte Raupe
    			
    			scrE = scrW - getRSpeed();
    			
    			if(speedKp > 0)
    				delta_y = speedKp * (180.0/284.0) * ((scrE - scrE1) + speedKi * scrE * speedControllTimer/10000.0 + speedTv * (scrE - 2*scrE1 + scrE2)/(speedControllTimer/10000.0));
    			else
    					delta_y = (180.0/284.0) * (speedKi * scrE * speedControllTimer/10000.0 + speedTv * (scrE - 2*scrE1 + scrE2)/(speedControllTimer/10000.0));
    			
    
    			if(delta_y > scMaxUp)
    				delta_y = scMaxUp;
    			
    			if(delta_y < scMaxDown)
    				delta_y = scMaxDown;
    
    			if((PORTC & 0x08) >= 1) //BWD?
    				y2 = OCR1AL * (-1);  //=>y ist dann eigentlich negativ
    			else
    				y2 = OCR1AL;		    //sonst positiv
    
    			//Umwandeln von PW 20 bis 180 auf 0 bis 180 zur Kompatibilität zum Regler
    			//bzw. bei Rückwärtlauf von PW -18 bis -180 auf 0 bis -180
    			if(y2 >= 20)
    				y2 = (y2-20) * (180.0/(180.0-20.0));
    			else if(y2 <= (-18))
    				y2 = (y2-(-18)) * ((-180.0)/((-180.0)-(-18.0)));
    			else
    				y2 = 0;
    
    			//neues delta_y einfließen lassen und Signal in den vorgegebenen Grenzen halten
    			y2 += delta_y;
    
    			if(y2 > 180)
    				y2 = 180;
    			
    			if(y2 < -180)
    				y2 = -180;
    
    			//Zurückrechnen auf Werte zwischen 20 und 180 bzw. -18 bis -180
    
    			if(y2 > 0 || (y2 == 0 && delta_y >= 0))
    				y2 = 20 + y2 * ((180.0-20.0)/180.0);
    			else if(y2 < 0 || (y2 == 0 && delta_y < 0))
    				y2 = -18 + y2 * (((-180.0)-(-18.0))/(-180.0));
    
    			if(y2 < 0)
    			{
    				PORTC |= (1<<PORTC3); //BWD
    				y2 *= (-1); //y muss wieder positive Zahl sein weil auf OCR geschrieben wird
    			}
    			else
    			{
    				PORTC &= ~(1<<PORTC3); //FWD
    			}
    
    			scrE2 = scrE1;
    			scrE1 = scrE;
    
    			OCR1AL = y2;
    		}	
    	}
    Mit freundlichen Grüßen

    Schwammi

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    41
    Beiträge
    1.516
    Ah OK Bild  

    Ich würde jedoch sowieso empfehlen das etwas aufzusplitten also P und I getrennt vom Reset berechnen in eigenen Variablen dann wäre das auch kein Problem. Den Integrierer separat limitieren.

    So eine lange Rechnung hier in einer einzigen Zuweisung:

    delta_y = speedKp * (180/267.0) * ((sclE - sclE1) + speedKi * sclE * speedControllTimer/10000.0 +
    speedTv * (sclE - 2*sclE1 + sclE2)/(speedControllTimer/10000.0));


    ist nicht optimal da der Compiler aus sowas oft ineffizienten Code produziert.
    Bei 8 Bit Controllern immer alles schrittweise auseinanderbrechen und die Codegröße beim Übersetzen beachten.


    Insbesondere auch: 180/267.0
    ist böse weil große Teile der Rechnung ggf. mit Floatingpoint durchgeführt werden (auch da wo nicht notwendig).
    Alles was nicht float sein muss auf int umstellen!
    Divisionen sind auch böse, wenn möglich anders skalieren.

    Das aber nur nebenbei Bild  


    MfG,
    SlyD

  3. #3
    Neuer Benutzer
    Registriert seit
    17.04.2012
    Beiträge
    4
    Ok über Codeeffizienz hab ich mir noch sehr wenig Gedanken gemacht. Hab eigentlich auch keine Ahnung davon. Die Divisionen müssen so sein 180/267 wäre sonst 0, und die Kommazahl jetzt schon anschreiben mag ich nicht, weil ich den Code dann schwerer nachvollziehen kann. Aber gut Codeoptimierung ist jetzt ein anderes Thema, jedoch würde mich interessieren, welchen Sinn es hat den I-Regler getrennt zu limitieren bzw. warum überhaupt?

    Mit freundlichen Grüßen

    Schwammi

  4. #4
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    09.04.2008
    Beiträge
    384
    Zum code efficienz und 8-bit µ : wen moglich mit eine 8bit int rechnen, dan 16 bit int, dan 32 bit int und allerletze float. Die Rechenaufwand geht sehr schnell ind die Hohe !! Dividieren durch 2, 4, 8.. geht sehr schnell : ist eine reine Schieb operation von binaire Zaehlen. Alles andere kostet mehr Rechenzeit.
    Limitieren von I-regler ist standard bei jeden PI(D) Regelung : Wen die Regelung aus irgendeine Grund die "Error" nicht ausregelen kan, bleibt der I-regler bei jeden Durchlauf seine Wert erhohen, selbst wen das absolut kein Sinn mehr macht (Beispiel : PWM Wert schon 100 %). Wen das Regelen dan wieder Sinn macht, muss das I-Anteil erst wieder abgebaut werden, und das kan sehr lange daeuern... Dafur werd meistend das I-Anteil begrenzt (anti Wind up). Auch wen sie iher Setpoint anderen (Beispiel : RP6 : STOP !), macht ess Sinn das I-Anteil zu nullen.

Ähnliche Themen

  1. Gleichlauf bei DC Motoren???
    Von Teslafan im Forum Motoren
    Antworten: 14
    Letzter Beitrag: 28.03.2012, 11:19
  2. Motoren und RCX
    Von firestorm_ im Forum Motoren
    Antworten: 0
    Letzter Beitrag: 08.06.2008, 08:45
  3. Antworten: 2
    Letzter Beitrag: 16.04.2007, 05:22
  4. Ct-Bot Motoren
    Von Sven04 im Forum Motoren
    Antworten: 2
    Letzter Beitrag: 23.03.2006, 11:29
  5. DC Motoren und PWM
    Von cavegn im Forum Motoren
    Antworten: 5
    Letzter Beitrag: 02.08.2005, 20:35

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

    Werbung      fchao-Sinus-Wechselrichter AliExpress