Forum: Mikrocontroller und Digitale Elektronik Überlauf bei int32_t trotz Satuierungsversuch?


von J. W. (jw-lighting)


Lesenswert?

Hallo,

ich habe hier Probleme mit einem Codeschnipsel (für einen ATmega644P @ 
16MHz).
Damit ihr euch einen Überblick verschaffen könnt, was der Schnipsel 
bewirken soll, erstmal eine kurze Erläuterung.


Ich möchte mehrere 8-Bit Werte (effektiv) innerhalb einer beliebigen, 
durch den Wert von fadeFaktor bestimmten Zeit ansteigen oder absinken 
lassen, bis ein Zielwert erreicht ist.
Da der Codeschnippsel ~ mit 100Hz aufgerufen wird und auch Zeiten > 2,55 
Sekunden möglich sein sollen, führe ich die Berechnung mit 16-Bit Werten 
durch, von denen im weiteren Programmverlauf (siehe unten im Code) dann 
jeweils nur die oberen 8-bit verwendet werden (daher effektiv 8-bit) - 
die unteren dienen dazu, den Ablauf zeitlich strecken zu können.

Die 8-bit Zielwerte sind in PresetTargetValues[] gespeichert, die 16-bit 
Berechnungswerte in PresetValues.

Da der Zielwert nicht überschritten werden soll berechne ich zunächst in 
einem int32_t und entscheide dann a posterori, ob der Zielwert erreicht 
ist (und setze diesen) oder benutze den berechneten Wert. Ein Überlauf 
sollte daher ja eigentlich nicht auftreten.

Trotzdem kommt es dann (und nur dann) wenn der Zielwert 255 ist und eine 
nicht natürliche Anzahl von Berechnungen notwendig ist um den Zielwert 
zu erreichen zu einem Überlauf - zumindest springt der Wert in 
PresetValues auf 0 zurück und bleibt nicht beim oberen Zielwert 255, 
sodass sich der Vorgang (mehrfach) wiederholt.


Ich habe jetzt mehrfach drübergeschaut und versucht einen Fehler zu 
finden, bin aber bisher ratlos geblieben. Liegts am großen int32_t oder 
habe ich ein Brett vorm Kopf?


Würde mich freuen, wenn ihr Rat wüsstet.

LG :)

(Dass dies nicht unbedingt der effizienteste Weg ist ist mir bewusst, 
soll aber nicht weiter Thema sein)
1
uint16_t fadeFaktor;
2
3
  // ...
4
5
uint8_t i;
6
int32_t tmp; // signed 32bit !!
7
for(i=0; i<CHANNEL_TO_TX; i++){
8
  
9
  if(PresetTargetValues[i] > ((uint8_t)(PresetValues[i] >> 8))){
10
    
11
    tmp = PresetValues[i] + fadeFaktor;
12
    
13
    if(tmp > ((uint16_t)(PresetTargetValues[i] << 8))){
14
      
15
      PresetValues[i] = (uint16_t) PresetTargetValues[i] << 8);
16
      
17
    }
18
    else{
19
      
20
      PresetValues[i] = (uint16_t) (tmp & 0xFFFF);
21
      
22
    }
23
    
24
  }
25
  else if(PresetTargetValues[i] < ((uint8_t)(PresetValues[i] >> 8))){
26
      
27
    tmp = PresetValues[i] - fadeFaktor;
28
      
29
    if(tmp < ((uint16_t)(PresetTargetValues[i] << 8))){
30
        
31
      PresetValues[i] = (uint16_t) (PresetTargetValues[i] << 8);
32
        
33
    }
34
    else{
35
        
36
      PresetValues[i] = (uint16_t) (tmp & 0xFFFF);
37
        
38
    }
39
      
40
  }
41
    
42
  DmxTx.values[i] = (uint8_t) (( ( (uint8_t)(PresetValues[i] >> 8) ) * masterChannel ) / 255);
43
    
44
}

von (prx) A. K. (prx)


Lesenswert?

> tmp = PresetValues[i] + fadeFaktor;

Wird in 16 Bits gerechnet und erst anschliessend nach 32 Bits 
konvertiert. Lies es als
  tmp = (PresetValues[i] + fadeFaktor);

von J. W. (jw-lighting)


Lesenswert?

A. K. schrieb:
> Wird in 16 Bits gerechnet und erst anschliessend nach 32 Bits
> konvertiert.

Hilft mir dann ein
1
 tmp = ((int32_t) PresetValues[i] + fadeFaktor);

weiter?

LG und dickes Dankeschön! :)

von (prx) A. K. (prx)


Lesenswert?

Ja.

von J. W. (jw-lighting)


Lesenswert?

Super, danke!

Wenn jetzt noch jemand Ideen hat, die Sache effizienter zu erledigen, 
immer her damit ;)

LG :)

von Peter D. (peda)


Lesenswert?

Hier mal meine Begrenzerroutine:
1
uint16_t min_max( uint16_t val, int8_t delta )  // unsigned limitaion
2
{
3
  val += delta;
4
  if( val >= delta ){
5
    if( delta < 0 )
6
      val = 0;
7
  }else{
8
    if( delta > 0 )
9
      val = 65535;
10
  }
11
  return val;
12
}


Peter

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.