PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega rechnet falsch...



Hemi
19.05.2022, 11:38
Hallo zusammen,

ich ein sehr dubioses Problem und zwar rechnet eine Funktion falsch..

Hier ist erstmal die Funktion:




#define SENSOR_SHUNT 61.9

int16_t calculate_pump_current (uint16_t Ua, uint16_t Ua_cal)
{
float diff;
diff = Ua - Ua_cal;


return (int16_t)(diff / (SENSOR_SHUNT * 8.0) * 1000);
}


Ua und Ua_cal sind Spannungen, in Millivolt zwischen 0 und 5000 (also 0V und 5V)

Nun zum Problem:

Wenn diff negativ ist, rechnet er einen Blödsinn zusammen.

Beispiel für falsche Berechnung:
Ua = 750
Ua_cal = 1500
Berechneter Wert ist: -222
Erwarteter Wert: -1515

Beispiel für korrekte Berechnung:
Ua = 3000
Ua_cal = 1500
Berechneter Wert ist: 3029
Erwarteter Wert: 3029

Ich habe es mit Excel gegengerechnet.

Hat jemand eine Idee, was da schief läuft?

Danke Euch!

EDIT:
MCU: Atmega2560
IDE: Mcrochip Studio 7.0.2542

Gnom67
19.05.2022, 12:45
Bist du sicher, dass du beim Return einen Datentyp angeben kannst oder musst? Der ist doch schon oben in der Funktionsdefinition angegeben.

int16_t calculate_pump_current (uint16_t Ua, uint16_t Ua_cal)

Was passiert, wenn du den bei der Return-Anweisung weglässt?

Holomino
19.05.2022, 12:51
Da...

diff = (int16_t)Ua - (int16_t)Ua_cal;

...musst Du casten.
Ansonsten subtrahierst Du zwei UINTs, was genauso schief geht, wie ein Addieren mit Überlauf.

BTW: Hast Du noch den Simulator im Microchip Studio? Damit lässt sich sowas debuggen.

Hemi
19.05.2022, 12:53
@Gnom67:

Habe den cast gerade rausgenommen, beeindruckt hat es ihn aber nicht.

Sieht jetzt so aus:


int16_t calculate_pump_current (uint16_t Ua, uint16_t Ua_cal)
{
float diff;
diff = Ua - Ua_cal;

return ((Ua - Ua_cal) / (SENSOR_SHUNT * 8.0) * 1000);
}



Da...

diff = (int16_t)Ua - (int16_t)Ua_cal;

...musst Du casten.
Ansonsten subtrahierst Du zwei UINTs, was genauso schief geht, wie ein Addieren mit Überlauf.

BTW: Hast Du noch den Simulator im Microchip Studio? Damit lässt sich sowas debuggen.

Nein, da muss ich nichts casten und es geht auch nichts schief, der diff wird immer richtig gerechnet, ob positiv oder negativ. Die Variable diff ist ein float...

Holomino
19.05.2022, 13:02
Probier es bitte erst aus, bevor Du meckerst.
750U-1500U= 64xxxU
Danach erst wird implizit in float gewandelt.

Hemi
19.05.2022, 13:17
WTF.... Du hast Recht.

Er tut jetzt so wie es sein soll.

Ich verstehe es trotzdem nicht, warum die Variable diff, ohne cast, richtig ausgegeben wird.

Hier der vollständige code:



int16_t calculate_pump_current (uint16_t Ua, uint16_t Ua_cal)
{
float diff;
diff = (int16_t)Ua - (int16_t)Ua_cal;

liveData[26] = low(diff);
liveData[27] = high(diff);

return ((diff) / (SENSOR_SHUNT * 8.0) * 1000);
}


Die Variable liveData[...] ist als uint8_t liveData[30] definiert, die dann per usart rausgeschoben wird. Der Empfänger sieht den diff-Wert aber korrekt...

Hab jetzt den ganzen Mist rausgeworfen und nun sieht es so aus:


int16_t calculate_pump_current (uint16_t Ua, uint16_t Ua_cal)
{
return (((int16_t)Ua - (int16_t)Ua_cal) / (SENSOR_SHUNT * 8.0) * 1000);
}

und rechnet auch richtig.

Danke schön!

Holomino
19.05.2022, 13:23
Ich denke mal, dass der Unterschied in den VIER Bytes des floats nicht in deinen beiden ausgegebenen Testbytes liegt.