Forum: Mikrocontroller und Digitale Elektronik Variablenüberlauf bei Parameterübergabe


von Johannes S. (Firma: Privat) (bitschieber123)


Lesenswert?

Hallo liebe µC.net Gemeinde!

Zur Lageregelung eines Antriebes übergebe ich die Stellgröße des 
P-Reglers an eine Funktion zur PWM-steuerung des Motors. Der Wert P wird 
je nach Regelanforderung zwischen 15 und 50 variiert.

Funktionsdefinition:
1
 void MOTOR_set_rpm(int speed);
Der Wert speed wird innerhalb der Funktion auf +1499 und -1499 begrenzt.
Für jede Drehrichtung ergibt das 100% PWM Duty-Cycle am jeweiligen 
Ausgang

Funktionsaufruf:
1
 MOTOR_set_rpm( P*(soll-ist) );
Soll und Istwert sind jeweils unsigned 16-bit Digitalwerte.

Übersteigt der Wert P*(soll-ist) den Wertebereich vom 16-bit int, ergibt 
sich ein Überlauf und die Regelung funktioniert nicht mehr.

Meine Frage:
1) Wie lässt sich das Problem am besten lösen?
2) Mit welchem Wertebereich/Kommazahlen wird die Berechnung 
P*(soll-ist)an sich ausgeführt?

Ich verwende den µC SAMD21G18 und Atmel Studio 7.

Ich hoffe, dass ich alles verständlich formuliert habe - ansonsten bitte 
einfach nachfragen.

Vielen herzlichen Dank,
Johannes

von Sly_marbo (Gast)


Lesenswert?

void MOTOR_set_rpm(long speed);

wäre eine Möglichkeit.

von Einer K. (Gast)


Lesenswert?

Johannes S. schrieb:
> Übersteigt der Wert P*(soll-ist) den Wertebereich vom 16-bit int, ergibt
> sich ein Überlauf und die Regelung funktioniert nicht mehr.

Naja...
Soweit mir bekannt, ist int auf den SAM Dingern 32Bit groß.
sizeof() würde dir das beweisen.

von Vincent H. (vinci)


Lesenswert?

Johannes S. schrieb:
> Meine Frage:
> 1) Wie lässt sich das Problem am besten lösen?

Zum Beispiel in dem man den Algorithmus für x86 compiliert, mit Werten 
befeuert und mit einem sogenannten Sanitizer auf Overflows prüft.

https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

> 2) Mit welchem Wertebereich/Kommazahlen wird die Berechnung
> P*(soll-ist)an sich ausgeführt?

Es erfolgt eine sogenannte "integer promotion". Das heißt wenn man alle 
impliziten casts miteinbezieht steht hier eigentlich:
1
P*((int)(soll)-(int)(ist))

von GEKU (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Johannes S. schrieb:
> Übersteigt der Wert P*(soll-ist) den Wertebereich vom 16-bit int, ergibt
> sich ein Überlauf und die Regelung funktioniert nicht mehr.
>
> Naja...
> Soweit mir bekannt, ist int auf den SAM Dingern 32Bit groß.
> sizeof() würde dir das beweisen.

 Sollte sizeof (int) 2 ergeben, dann hilft es long anstelle von int zu 
verwenden

von Johannes S. (Firma: Privat) (bitschieber123)


Lesenswert?

Sly_marbo schrieb:
> void MOTOR_set_rpm(long speed);
>
> wäre eine Möglichkeit.

Danke für deine Antwort! Ist eine sehr simple&einfache Möglichkeit, 
braucht halt etwas Programmspeicher, aber der SAM hat ja genug! Für den 
Anfang relisiere ich das über die long-Variable, später werde ich auf 
die Möglichkeit von Vincent H. zurückgreifen. - Ich liebe es neue Dinge 
zu testen.

Arduino Fanboy D. schrieb:
> Johannes S. schrieb:
>> Übersteigt der Wert P*(soll-ist) den Wertebereich vom 16-bit int, ergibt
>> sich ein Überlauf und die Regelung funktioniert nicht mehr.
>
> Naja...
> Soweit mir bekannt, ist int auf den SAM Dingern 32Bit groß.
> sizeof() würde dir das beweisen.

Danke für den Hinweis! Werd ich auf jeden Fall testen und bescheid geben 
- hat mich selbst gewundert ob das mit den 16-bit bei einem 32-bit µC so 
richtig ist :)

Vincent H. schrieb:
> Johannes S. schrieb:
>> Meine Frage:
>> 1) Wie lässt sich das Problem am besten lösen?
>
> Zum Beispiel in dem man den Algorithmus für x86 compiliert, mit Werten
> befeuert und mit einem sogenannten Sanitizer auf Overflows prüft.
>
> https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
> https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
>
>> 2) Mit welchem Wertebereich/Kommazahlen wird die Berechnung
>> P*(soll-ist)an sich ausgeführt?
>
> Es erfolgt eine sogenannte "integer promotion". Das heißt wenn man alle
> impliziten casts miteinbezieht steht hier eigentlich:
>
>
1
> P*((int)(soll)-(int)(ist))
2
>

Danke für deinen Hinweis, klingt interessant! So tief habe ich mich in 
die c-Programmierung noch nicht vorgewagt, man lernt immer wieder dazu. 
Sieht für mich auf jeden Fall nach einer sehr eleganten Lösung aus.

von Vincent H. (vinci)


Lesenswert?

Johannes S. schrieb:
> Danke für deinen Hinweis, klingt interessant! So tief habe ich mich in
> die c-Programmierung noch nicht vorgewagt, man lernt immer wieder dazu.
> Sieht für mich auf jeden Fall nach einer sehr eleganten Lösung aus.

Soweit mir bekannt ist funktionieren Sanitizer (Memory, 
UndefinedBehavior, usw.) nur mit C++. Aber in den meisten Fällen lässt 
sich der C-Code natürlich direkt als C++ übersetzen und die Sanitizer 
damit genutzt werden.

Lustigerweise hab ich erst selbst vor etwa einem halben Jahr damit einen 
int32 Überlauf in einem PID-Regler Code für DC-Motoren gefunden.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Johannes S. schrieb:
> 2) Mit welchem Wertebereich/Kommazahlen wird die Berechnung
> P*(soll-ist)an sich ausgeführt?

Welche Typen haben "P", "soll" und "ist"?

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.