Variablenüberlauf bei Parameterübergabe

OP (Firma: Privat) #5881816
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
#5881854
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))
Gast #5881885
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
OP (Firma: Privat) #5881900
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.
#5881909
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren