Hilfe für berechnung

Hallo , bin neu auf dem Arduino gebiet habe aber schon einige kleinere projekte ohne probleme programmiert,
aber jetzt bin ich an meine grenzen gestossen , ich habe ein projekt , wo ich mit einem ultraschall sensor den inhalt von einem behälter in kilogramm ausgeben möchte. Das einzige was nicht funktioniert ist die berechnung . wenn der ultraschall sensor als beispiel 6cm angibt , und ich das in die formel einsetze , müsste ich einen wert von ca.250 erhalten . Arduino schreibt aber 15370. Was ist hier falsch?
habe den sketch mal angehängt

#define trigPin 12
#define echoPin 13
unsigned long kg_tilbage;

void setup() /----( SETUP: RUNS ONCE )----/
{
pinMode(trigPin, OUTPUT); //ultrasonic sensor trigger
pinMode(echoPin, INPUT); // ultrasonic sensor echo
Serial.begin(9600); // Used to type in characters
}

void loop() /----( LOOP: RUNS CONSTANTLY )----/
{
int duration , distance ; // run ultrasonic sensor
digitalWrite(trigPin, HIGH);
delayMicroseconds(1000);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration/2 / 29.1; // Ultrasonic sensor distance in cm

kg_tilbage = (((60*72 *(135-80-distance))*0.066)+13860)/ 100; // Calculation how many kilos left

Serial.println(kg_tilbage);

delay(500);

}

nyland:
Was ist hier falsch?

In Deiner Formel
kg_tilbage = (((60*72 *(135-80-distance))0.066)+13860)/ 100; // Calculation how many kilos left
ist mit
(60
72 *(135-80-6))
schon ein dicker fetter Integer-Überlauf in der Rechnung drin, bevor Du mit *.066 eine Gleitkommarechnung draus machst.

Versuch's mal, von Anfang an in der Rechnung mit Gleitkomma-Werten zu rechnen:
kg_tilbage = (((60.0*72.0 *(135.0-80.0-distance))*0.066)+13860.0)/ 100.0; // Calculation how many kilos left

Vielen Dank , funktioniert . Aber da war noch warum ?
Ich habe es mit unsigned long , long und int probiert , jedes mal das selbe richtige ergebnis, und das ,weil man alle zahlen als flieskomma zahlen dargestellt hat .
wie gesagt bin ich noch nicht der grosse arduino freak , aber vielleicht kann man das kurz erklären ,

Dankeschön aus dem hohen Norden :slight_smile:

Nur dein Endergebnis ist long. Die Zwischenergebnisse sind int wenn nichts spezifiziert ist und gehen daher bis maximal 32,767. Float hat dagegen einen Maximal-Wert von 3.4028235E+38

Was auch gehen könnte ist sowas:
kg_tilbage = ((( (unsigned long)60*72 *(135-80-distance)) ......

Durch den Cast sollte er dann die ganze Rechnung in long ausführen.

Das ist übrigens kein Arduino-spezifisches Problem, sondern auf dem PC genauso.

nyland:
Vielen Dank , funktioniert . Aber da war noch warum ?
Ich habe es mit unsigned long , long und int probiert , jedes mal das selbe richtige ergebnis, und das ,weil man alle zahlen als flieskomma zahlen dargestellt hat .
wie gesagt bin ich noch nicht der grosse arduino freak , aber vielleicht kann man das kurz erklären ,

Du mußt nicht links vom Gleichheitszeichen gucken, sondern rechts vom Gleichheitszeichen wird gerechnet!
Und wenn Du rechts vom Gleichheitszeichen mit Integer rechnest, dann wird diese Zwischenrechnung tatsächlich mit Integer gerechnet:
(60*72 *(135-80-6))
Da käme eigentlich heraus: 211680
Integer geht aber nur bis 32767. Und weil alle Zahlen in dieser Zwischenrechnung int sind, ist auch das Zwischenergebnis int.
Das reicht nicht aus für die Zwischenrechnung, daher geht die Rechnung mit Datenmüll als Zwischenergebnis weiter.

Mit long Integer würde es ausreichen, dann mußt Du rechts angeben, dass die Zahlen "long" sein sollen:
kg_tilbage = (((60L*72L *(135L-80L-distance))*0.066)+13860L)/ 100L; // Calculation how many kilos left

Standardvorgabe bei Zahlen auf den 8-Bit AVR-Controllern ist: Wenn die Zahl Nachkommastellen hat, ist es "float" und wenn sie keine Nachkommastellen hat ist es "int". Und wenn die Zahl mit der Du rechnest was anderes sein soll, mußt Du das angeben:
16L ==> mit einem nachgestellten "L" ist es eine "long" Zahl
(long)16 ==> ist auch eine "long" Zahl

Wenn Du intint rechnest, ist das Ergebnis int.
Wenn Du int
long rechnest, ist das Ergebnis long.
Wenn Du int*float rechnest, ist das Ergebnis float.
Das Ergebnis einer Rechnung entspricht vom Datentyp her immer dem mit der Zahl mit dem größten Wertebereich, die in der Rechnung verwendet wird.

Und die Zuweisung an eine Variable links vom Gleichheitszeichen ist noch eine ganz andere Sache.

Wenn das Ergebnis einer Rechnung richtig werden soll, brauchst Du nur darauf achten, dass weder bei Zwischenrechnungen noch beim Ergebnis der Wertebereich des bei der Rechnung verwendeten Datentyps überschritten wird. Und wenn Nachkommastellen nicht wegfallen sollen, rechnest Du am besten in "float".

Siehe ggf. auch: C++-Programmierung/ Einführung in C++/ Rechnen mit unterschiedlichen Datentypen – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher

Es ist sinnlos wenn man Konstanten nicht ausmultipliziert oder aussummiert.

(60*72 *(135-80-distance)

kann besser als

4320 * (55-distance)

geschrieben werden.

Grüße Uwe

@ Uwe:
Es ist sinnlos wenn man Konstanten ausmultipliziert oder aussummiert.

4320L * (55-distance)

kann besser als

(60L*72 *(135-80-distance)

geschrieben werden, wenn man dann die Berechnung versteht. ( Nu gut, ich weiss es nicht, warum nyland 60 * 72 rechnet )
Der Compiler übernimmt das Ausmultiplizieren für dich und erzeugt den gleichen Code daraus.

Noch besser sind selbsterklärende Konstanten-Namen wie z.B.

#define X_FACTOR 0.066
const float X_OFFSET 13860.0;    // man kann so sehr schön den gewünschten Datentyp festlegen,
                                 // es ist trotzdem eine Konstante, die wenn möglich keinen RAM braucht.

Hallo ,
Vielen dank für die interessanten antworten .
Der angehängte sketch war nur eine kurze version von dem original sketch.
Die berechnung enthält mehr variablen , diese formel war nur für einen bestimmten behälter gedacht , und ist auch schneller überschaubar, da es mir nur um die berechnung ging .

Wie gesagt es ist eine berechnung , wo ein Ultraschallsensor auf einem behälter montiert ist , und den abstand zum inhalt misst. Da es verschiedene behälter sein können , muss das volumen des behälters errechnet werden ,
kg_tilbage = (((60*72 *(135-80-distance))*0.066)+13860)/ 100; // Calculation how many kilos left ,

60*72 //in cm , grundfläche behälter
135 // höhe behälter
80 // weil sich bei 55 cm von oben nach unten gemessen sich die form von dem behälter ändert
distance // abstand gemessen vom Ultraschall sensor
0.066 // materialdichte für holzpellets hier 660kg/m3
13860 // volumen im unteren Teil des behälters in cm3 // der untere Teil hat eine andere form als der obere
100 // umrechnung in kilogramm
Die einzigen konstanten in der berechnung sind die 0.066 und die 100 .

Nochmals vielen dank für die schellen antworten.

Die einzigen konstanten in der berechnung sind die 0.066 und die 100 .

Alles was zum Ändern einen geänderten Sketch erfordert ( also nie irgendwie während der Laufzeit verändert wird ) , sind Konstanten.

const unsigend long GRUNDFLAECHE = 60*72;  // legt den Typ so fest, dass die Berechnung keine Überlauf-Probleme bekommt.