Forum: Mikrocontroller und Digitale Elektronik STM Pointerproblem


von STM Neuling (Gast)


Lesenswert?

Hallo liebe Forumgemeinde,

ich versuche seit einiger Zeit meinen PID Regler ans Laufen zu bekommen. 
Da ich den Regler mehrfach aufrufen will und ich innerhalb des Reglers 
statische Variablen benötige habe ich diese per Pointer angebunden.
(siehe nachfolgenden Code für PID Regler)

[c]float PI_Regler(struct PI_Control *PI, float P_Gain, float Out_min, 
float Out_max, float I_Time, bool I_Reset, float cycle_time, float 
control_value, float actaul_vaule)
{

float delta_input, P_part, I_Part_Zw_Summe;

//Regeldifferenz berechnen
delta_input = (control_value - actaul_vaule);

//P-Regler beschreiben
P_part = delta_input * P_Gain;

//I_Regler beschreiben
if (I_Time > 0)
{
  I_Part_Zw_Summe = ((((delta_input * P_Gain) + 
((*PI).delta_input_last_cycle * P_Gain)) / 2.0) * (cycle_time / 
I_Time));
  if (! (*PI).limit_on_low && (I_Part_Zw_Summe <0))
      (*PI).I_part =  (*PI).I_part + I_Part_Zw_Summe;
  else if (! (*PI).limit_on_high && (I_Part_Zw_Summe >0))
      (*PI).I_part =  (*PI).I_part + I_Part_Zw_Summe;
}
else if (I_Time <= 0.0)
  (*PI).I_part = 0.0;

//I_Regler zurück setzen
if (I_Reset)
  (*PI).I_part = 0.0;

(*PI).output_value = P_part + (*PI).I_part;

(*PI).limit_on_low   = 0;
(*PI).limit_on_high   = 0;

if ((*PI).output_value > Out_max)
{
  (*PI).output_value   = Out_max;
  (*PI).limit_on_high   = 1;
}
else if ((*PI).output_value < Out_min)
{
  (*PI).output_value   = Out_min;
  (*PI).limit_on_low   = 1;
}
return (*PI).output_value;


//Regeldifferenz für nächsten Zyklus beschreiben
(*PI).delta_input_last_cycle = delta_input;


}

[\c]



daneben habe ich disen Struct global definiert

[c]
struct PI_Control
{
  float P_Part;
  float OutValueRamp;
  float output_value;
  bool limit_on_low;
  bool limit_on_high;
  float I_part;
  float delta_input_last_cycle;
}PI;
[\c]


Beim Aufruf der Funktion im Interrupt mittels


[c]
void TIM3_IRQHandler(void){    //10ms / 100Hz

  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
//  PI_Regler(struct PI_Control &PI, float P_Gain, float Out_min, float 
Out_max, float I_Time, bool I_Reset, float cycle_time, float 
control_value, float actaul_vaule)
  TIM1->CCR2 = (int) PI_Regler((&PI), 1.0, 10.0, 90.0, 5000.0, I_Reset, 
10.0, 50.0, 45.0 );
  I_Reset = false;
  //(float) actRpm
}
[\c]


meldet er mir jedoch flgende Fehlermeldungen, die ich absolut nicht 
verstehe, da ich die Pointer so verwendet habe wie im Tutorial gelesen.
Wo ist mein Knoten im Hirn, hat jemand auf die Schnelle ne Idee?

warning: 'struct PI_Control' declared inside parameter list
warning: its scope is only this definition or declaration, which is 
probably not what you want
warning: passing argument 1 of 'PI_Regler' from incompatible pointer 
type [-Wincompatible-pointer-types]
       [cc]   TIM1->CCR2 = (int) PI_Regler((&PI), 1.0, 10.0, 90.0, 
5000.0, I_Reset, 10.0, 50.0, 45.0 );
       [cc]                                ^
note: expected 'struct PI_Control *' but argument is of type 'struct 
PI_Control *'
       [cc]  float PI_Regler(struct PI_Control *PI, float P_Gain, float 
Out_min, float Out_max, float I_Time, bool I_Reset, float cycle_time, 
float control_value, float actaul_vaule);
       [cc]        ^

von Cyblord -. (cyblord)


Lesenswert?

STM Neuling schrieb:
> (*PI).

Der Pfeiloperator (->) ist dir kein Begriff?

von STM Neuling (Gast)


Lesenswert?

ehm...ja ehrlich gesagt nicht zu 100%, deshalb diese 
"OldschoolVariante", da ich diese aus dem Tutorial entnommen hab

von Daniel V. (danvet)


Lesenswert?

STM Neuling schrieb:
> Hallo liebe Forumgemeinde,
>
> ich versuche seit einiger Zeit meinen PID Regler ans Laufen zu bekommen.
> Da ich den Regler mehrfach aufrufen will und ich innerhalb des Reglers
> statische Variablen benötige habe ich diese per Pointer angebunden.
> (siehe nachfolgenden Code für PID Regler)
>
> [c]float PI_Regler(struct PI_Control *PI, float P_Gain, float Out_min,
> float Out_max, float I_Time, bool I_Reset, float cycle_time, float
> control_value, float actaul_vaule)
> {

Wo ist denn struct PI_Control definiert?
Der Compiler findet das anscheinend nicht.

von STM Neuling (Gast)


Lesenswert?

Das struct ist in einer global.c definiert, die ich aber VOR dem Regler 
inkludiere. Von daher verstehe ich das nicht...

#include <stdbool.h>
void SendeProtokoll(void);
float PI_Regler(struct PI_Control *PI, float P_Gain, float Out_min, 
float Out_max, float I_Time, bool I_Reset, float cycle_time, float 
control_value, float actaul_vaule);



#include <stm32f0xx.h>
#include <stm32f0xx_conf.h>
#include "stm32f0xx_dbgmcu.c"
#include "globals.h"
#include "setup.c"
#include "stm32f0xx_it.c"
#include "i2c_io.c"
#include "Anzeige.c"
#include "PI-Regler.c"
//#include "A3Setup.c"

von Daniel V. (danvet)


Lesenswert?

STM Neuling schrieb:
> Das struct ist in einer global.c definiert, die ich aber VOR dem Regler
> inkludiere. Von daher verstehe ich das nicht...
>
> #include <stdbool.h>
> void SendeProtokoll(void);
> float PI_Regler(struct PI_Control *PI, float P_Gain, float Out_min,
> float Out_max, float I_Time, bool I_Reset, float cycle_time, float
> control_value, float actaul_vaule);
>
>
>
> #include <stm32f0xx.h>
> #include <stm32f0xx_conf.h>
> #include "stm32f0xx_dbgmcu.c"
> #include "globals.h"
> #include "setup.c"
> #include "stm32f0xx_it.c"
> #include "i2c_io.c"
> #include "Anzeige.c"
> #include "PI-Regler.c"
> //#include "A3Setup.c"

Nein, das möchtest du nicht: Never ever #include *.c
Bitte keine C-Files includieren, das führt zu solchen Resultaten.
Deine struct gehört in die global.h (oder eine andere *.h).
Alle *.c #includes entfernen und deinen Compiler veranlassen, dass er 
jedes einzelne C-File compiliert. Der Linker soll dann alles 
zusammenbauen.

edit: und wenn jetzt die Frage kommt, wieso das so ist: Tutorial nochmal 
von Anfang lesen (oder ein gutes C-Buch kaufen)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

1. Schreibe [/c] statt [\c]
2. Schreibe "PI->" statt "(*PI)."
3. Poste kompletten Code, nicht Codefetzen

Zu 1. Das wird dann wesentlich lesbarer :-)

Zu 2. Einfach mit dem Editor global ersetzen, das passt schon.

Zu 3. Offenbar kennt das Modul, wo im IRQ-Handler TIM1->CCR2 zugewiesen
      wird, Deine globale Definition nicht.

Sonstiges:

Warum übergibst Du überhaupt PI als Argument an PI_Regler(), wenn PI 
global ist? Da kann PI_Regler() doch auch so drauf zugreifen.

Achtung: Wenn Du auf Elemente der Struct sowohl aus dem Hauptprogramm 
als auch aus der ISR zugreifst, müssen diese volatile definiert werden. 
Besser wäre wohl, in der ISR ein Flag zu setzen und dieses in der 
Hauptschleife auszuwerten.

Als letztes:
1
//Regeldifferenz für nächsten Zyklus beschreiben
2
(*PI).delta_input_last_cycle = delta_input;

hat Null Effekt hinter einem unbedingten return-Statement.

von STM Neuling (Gast)


Lesenswert?

Hallo Frank,
erst mal vielen dank...
Zu1: Uuups...sorry, klar mach ich
Zu2: Hab ich gemacht und sogar verstanden warum  :-)
Zu3: Hier bin ich auf der Suche, aber leider noch ohne Erfolg  :-(

Sonstiges: Warum ich das so mache? Die Erklärung ist m.E. nach einfach, 
ich möchte den Regler für insgesamt 3 Motoren aufrufen, somit kann ich 
unterschiedlche structs bei den mehrfachen Aufrufen verwenden, was bei 
globaler Verwednung nicht möglich wäre...


Als letztes: Klar, totaler Knoten im Hirn...geändert

von W.S. (Gast)


Lesenswert?

Cyblord -. schrieb:
> Der Pfeiloperator (->) ist dir kein Begriff?

Mach es doch bitte einem Neuling nicht zum Vorwurf, daß er die vielen 
Verschrobenheiten von C noch nicht auswendig kennt.

C als solches ist ein Problem, das wissen wir doch eigentlich.

W.S.

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.