PID Funktion optimieren Multiplikation "eliminieren".

Gast #1552713
Lesenswert?
• ▲
▼
Hallo,
ich habe folgende PID Funktion, die ich auf einem Mega88 laufen lassen 
will:
1
unsigned char PIDunsigned(unsigned char x, unsigned char w)
2
{
3
 ue = w-x;
4
 if(uy < MAXSCHWELLE && uy > MINSCHWELLE)
5
 {
6
  uesum+=ue;
7
 }
8
 uy=(uKp*ue)+(uKi*uTa*uesum)+(uKd*((ue-uealt)/uTa));
9
 uealt=ue;
10
 if(uy >= MAXSCHWELLE)
11
  return MAXSCHWELLE;
12
 if(uy <= MINSCHWELLE)
13
  return MINSCHWELLE;
14
 return uy;
15
}
Soweit so gut, doch der Mega88 hat keinen Multiplikator.
Gibt's eine Möglichkeit das mittels Shift o.ä. schneller und kleiner zu 
machen ?
Danke.
Gast #1552756
Lesenswert?
• ▲
▼
Der Multiplizierer braucht zum Multiplizieren aber einen Multiplikator,
sonst kann er nichts multiplizieren. Aber auch mit dem Multiplikator
kann der Multiplizierer nichts multiplizieren, wenn nicht auch ein
Multiplikand da ist, mit dem der Multiplikator multipliziert werden kann
ist. Da ber alles da ist, der Multiplizierer, ein Multiplikand und ein
Multiplikator, steht dem Multiplizieren nichts mehr im Wege.

Warum also Eliminieren? Da braucht's dann erst wieder einen Eleminator
... (ok, ok ich hör schon auf :))
Gast #1552788
Lesenswert?
• ▲
▼
> es geht mir aber allgemein darum wie ich so etwas realisieren kann.
> Denn dann läuft's auch auf kleineren µCs.

Welchen Grund sollte man haben sich soetwas anzutun?

Du kannst natuerlich grundsaetlich deine Koeffizienten so skalieren
und runden das sie binaer kompatibel werden und dann shiften anstatt
zu multiplizieren. Allerdings ist die Frage ob die Aufloesung dann
noch reicht. Wenn du die Koeffizienten deines Reglers so veraenderst,
dann moechtest du da auch fein genug machen um halt vernuenftig Regeln 
zu koennen.

Wenn man etwas sehr langsames regelt, wie z.B Temperatur, dann kannst
du sicher einen beliebigen Controller nehmen und alles den Compiler
machen lassen. Wenn man sich aber Gedanken machen muss ob es zeitlich
knapp wird dann wuerde ich mindestens einen 16Bit Controller nehmen.
Fuer die meisten Sachen reicht ja ein 8Bit Wert als Ein und 
Ausgangsgroesse aus. Aber im Regler selber haettest du sicher gerne 16 
oder gar 32Bit damit du eben deine Koeffizienten gut skalieren kannst 
und damit es zu keinem Ueberlauf kommt.
Und da bietet es dich dann halt an z.B mit 128, 256 usw. zu skalieren 
damit man beim zurueckrechnen nur shiften muss.

Ein anderes Beispiel. Nehmen wir mal an du brauchst einen Koeffizient
Kp=0.453. Wandel da erstmal in eine Bruch um, also 453/1000. Den rundest
du etwas, und schon werden daraus 113/250. Jetzt skalierst du das ganze
auf 116/256. Dann bemerkst du das man das noch gut kuerzen kann, auf
29/64.
Nun sind aber 29/64 eigentlich 0.453125. Du hast jetzt also eine kleine
Abweichung mit der du wahrscheinlich leben kannst. Dafuer musst du
nur noch mit 29 multiplizieren und 6mal shiften. Damit wird das doch 
schon einfacher und dein Zwischenwert passt sicher in ein 16Bit 
Register.
Du koenntest natuerlich noch weiter vereinfachen auf Kp=0.5, aber
dem sind leider Grenzen gesetzt. Irgendwann laeuft dein Regler dann 
nicht
mehr vernuenftig.

Aber gerade bei der Auswahl eines Controllers fuer einen Regler wuerde
ich darauf achten das man ordentlich Reserven hat!

Olaf
Gast #1680170
Lesenswert?
• ▲
▼
hallo alle

> unsigned char PIDunsigned(unsigned char x, unsigned char w)
> {
>  ue = w-x;
>  if(uy < MAXSCHWELLE && uy > MINSCHWELLE)
>  {
>   uesum+=ue;
>  }
>  uy=(uKp*ue)+(uKi*uTa*uesum)+(uKd*((ue-uealt)/uTa));
>  uealt=ue;
>  if(uy >= MAXSCHWELLE)
>   return MAXSCHWELLE;
>  if(uy <= MINSCHWELLE)
>   return MINSCHWELLE;
>  return uy;
> }

könnte jemand mir gut erklären der vorteil hier ein unsigned int zu 
nutzrn statt int?
und ein zweite Frage : wie könnte ich die AD_wandler Werte normieren bzw 
durch schieben statt multiplikation oder division?  mit float brauch die 
routine viel zeit und mit integer geht das schneller, aber wie soll jetz 
diese int werte mit festkomma skalieren werden

Annahme nach der wandlung

sollwert= 4000
istwert=3530
error=soll - ist
kp=0,403,    Ta=50ms

wie kann ich meine integer  Werte durch multiplikation und/oder schieben 
normieren zb beim rechnen  von

error;  yp=kp * e,  yi= ki  Ta  Esum

 Hilfe bitte

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.