Forum: Mikrocontroller und Digitale Elektronik PID Funktion optimieren Multiplikation "eliminieren".


von Optimierer (Gast)


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.

von andreas r. (Gast)


Lesenswert?

der atmega88 hat einen multiplikator

von Optimierer (Gast)


Lesenswert?

Uups,
sorry ist im falschen Forum gelandet, bitte ins GCC verschieben.
Danke.

von Dieter (Gast)


Lesenswert?

>der atmega88 hat einen multiplikator


Nö. Aber einen Multiplizierer hat er.

von Optimierer (Gast)


Lesenswert?

OK,
es geht mir aber allgemein darum wie ich so etwas realisieren kann.
Denn dann läuft's auch auf kleineren µCs.
Und stimmt muß Multiplizierer heißen :-P

von yalu (Gast)


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 :))

von Olaf (Gast)


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

von gertro (Gast)


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

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.