Forum: Mikrocontroller und Digitale Elektronik Funktion mit INOUT Variablen


von STM Neuling (Gast)


Lesenswert?

Hallo, wie die Überschrift schon sagt suche ich einen Weg, einer 
Funktion (hier im speziellen einen von mir programmierten PID-Regler) 
ein globales Struct zu übergeben. Innerhalb der Funktion soll ein 
lesender, sowie schreibender Zugriff auf diese Variablen möglich sein.

Hintergrund:
PID Regler Funktion hat Eingangsvariablen (Gain, I_Rate, I_Reset etc.) 
als Rückgabewert kommt ein float, nämlich die Regelgröße zurück. 
Innerhalb der Funktion "PID" benötige ich jedoch statische Variablen 
(z.B. für die zyklische Aufaddierung des I-Anteils) Wenn ich diese 
innerhalb der Funktion definiere werden ihre Werte nicht über mehrere 
Zyklen gespeichert, sondern bei jedem Aufruf neu initialisert oder?

Gibt es sowas wie ein Schlüsselwort, mit dem ein Übergabewert lesend und 
schreiben beeinflusst werden kann?

vgl (out int Variable... bei C#)?

von B. S. (bestucki)


Lesenswert?

STM Neuling schrieb:
> Gibt es sowas wie ein Schlüsselwort, mit dem ein Übergabewert lesend und
> schreiben beeinflusst werden kann?

Welche Sprache? Üblicherweise werden dafür Zeiger oder Referenzen 
verwendet.

STM Neuling schrieb:
> Innerhalb der Funktion "PID" benötige ich jedoch statische Variablen
> (z.B. für die zyklische Aufaddierung des I-Anteils) Wenn ich diese
> innerhalb der Funktion definiere werden ihre Werte nicht über mehrere
> Zyklen gespeichert, sondern bei jedem Aufruf neu initialisert oder?

Schlüsselwort static in C/C++. Ansonsten kannst du diese Werte auch in 
deiner Struktur speichern.

von STM Neuling (Gast)


Lesenswert?

Schlüsselwort static innerhalb der Funktion ermöglicht es, dass die 
Werte statisch sind, d.h. nach einem erneuten prozessorzyklus (erneuter 
Aufruf der Funktion) noch zur Verfügung stehen? Das wäre genau das was 
ich suche...


Wie sieht es dann aus wenn man diese Funktion 5 mal aufruft für 
verscheidene Regelaufgaben?

von B. S. (bestucki)


Lesenswert?

STM Neuling schrieb:
> Wie sieht es dann aus wenn man diese Funktion 5 mal aufruft für
> verscheidene Regelaufgaben?

Eine mit static definierte Variable behält ihren Wert während der 
gesamten Programmlaufzeit. Wie eine globale Variable, nur dass nur die 
eine Funktion darauf zugreifen kann (ausser über Zeiger). Wenn du 
verschiedene Regelstrecken hast, empfehle ich, die Werte in eine 
Struktur zu packen und der Funktion einen Zeiger darauf zu übergeben. 
Dann kannst du so viele Regelstrecken haben wie du willst und immer die 
gleiche Funktion benutzen.

von STM Neuling (Gast)


Lesenswert?

Hi,

ok das klingt sehr einleuchtend.

Kannst du mir hierzu für den Aufruf ein kleines Beispiel geben, da ich 
Pointermäßig noch nicht wirklich bewandert bin.

Aufruf wäre ja in etwa sowas


struct PI_Control
{
  float P_Part;
  float OutValueRamp;
  float OutValue;
  u8 LimitOnLow;
  u8 LimitOnHigh;
  float I_PartZwErg;
  float I_Part;
  float deltaInputLC;
  float deltaInput;
} PI_Motor;


float PIRegelung(float Gain, float I_Time, POINTER PI_Control)
{
PI_Controll++;
...
}




Aufruf:

meineSchöneRegelgöße = PIRegelung(1.1,3.5, POINTER PI_Motor);





Edit: Ich weiß, eher abstrakt gehalten :-). Könntest du dieses Beispiel 
"korrigieren" was die Verwendung des Pointers betrifft?

von chris (Gast)


Angehängte Dateien:

Lesenswert?

STM Neuling schrieb:
> Wie sieht es dann aus wenn man diese Funktion 5 mal aufruft für
> verscheidene Regelaufgaben?

Pack doch den Integralanteil / die Summe einfach mit ins Reglerstruct. 
Dann kannst du beliebig viele Regelstrecken mit der selben Funktion 
regeln, indem du einfach jeweils das zugehörige struct übergibst.

Da gibts auch von Atmel eine AppNote dazu, anhand derer ich meinen 
PID-Code geschrieben habe, siehe Anhang (mit kleinem Beispielprogramm) 
Ursprünglich für AVR geschrieben, deshalb hab ich die hardwareabhängigen 
Teile mal rausgeworfen. Das Prinzip sollte aber klar werden denke ich.

lg
Chris

von B. S. (bestucki)


Lesenswert?

Funktion:
1
float PIRegelung(float Gain, float I_Time, struct PI_Control * Control)
2
{
3
  Control->PI_Controll++;
4
  ...
5
}

Aufruf:
1
meineSchoeneRegelgoesse = PIRegelung(1.1, 3.5, &PI_Motor);


EDIT:
Siehe auch hier:
https://www.mikrocontroller.net/articles/Zeiger

von STM Neuling (Gast)


Lesenswert?

Vielen Dank...ich probiers aus...schönen Abend noch

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.