Hallo Ich habe drei Variablen, die alle zusammen addiert und in der vierten gespeichert werden sollen: int16_t gx, gy, gz, g_1; mpu_2.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); g_2 = abs(gx) + abs(gy) + abs(gz); Da ich nur positive Werte haben möchte, die abs() Funktion. Hier aber mal ein Stück aus der Ausgabe: (Die erste Spalte ist die Summe) 227 22 29 6 244 2 75 0 223 10 48 6 226 11 42 21 218 7 30 1 242 3 59 8 225 4 55 3 247 24 60 3 246 3 36 5 261 35 68 13 226 1 34 15 Warum verrechnet sich der µC?
Gast
#5693279
Wie ist denn abs() definiert? D.h. für welche Datentypen?
Gast
#5693286
>Warum verrechnet sich der µC?
schau bitte mal in die Assemblerausgabe was da passiert.
Und zeige bitte das komplette Testprogramm.
Wie wärs mit echtem Code?
Karl M. schrieb: > D.h. für welche Datentypen? Da steht nix: https://www.arduino.cc/reference/en/language/functions/math/abs/ Und heir der ganze Code:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
Die Werte für gx, gy, gz werden durch den Aufruf von mpu_2 überschrieben.
Kolja L. schrieb: > Und heir der ganze Code: Die ausgegebenen Werte gehören doch gar nicht zusammen. Die Summe kommt von mpu_1 und die Einzelwerte von mpu_2.
Danke :-) Vielleicht sollte ich doch lieber nen Töpferkurs machen :-(
Kolja L. schrieb: > Danke :-) > Vielleicht sollte ich doch lieber nen Töpferkurs machen :-( Da lernt man aber nicht logisch zu denken.
Noch was komisches.
Eigentlich sollten aus einer Addition von den drei Beträgen (abs)) ja
keine negativen Zahlen hervorgehen können:
for (int i = 0; i<200; i++){
// I2C & MPU6050
mpu_1.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
g_1 = abs(gx) + abs(gy) + abs(gz);
mpu_2.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
g_2 = abs(gx) + abs(gy) + abs(gz);
sum_g_1 = sum_g_1 + g_1;
sum_g_2 = sum_g_2 + g_2;
}
g_1 = sum_g_1/200;
g_2 = sum_g_2/200;
Serial.print(g_1);
Serial.print(" ");
Serial.println(abs(g_2));
delay(50);
Ausgabe:
-46 153
-133 69
101 13
6 99
-87 142
144 61
52 18
-41 101
-135 144
100 62
5 21
-87 103
Warum nur?
Überlauf?
Dann müsste die Summe größer als 32767 sein?
Kolja L. schrieb: > Dann müsste die Summe größer als 32767 sein? 200 Durchläufe à 3 Werte = Summe von 600 positiven Zahlen. Ich kenne deine Werte nicht, aber meinst du nicht, das könnte reichen?
A. K. schrieb: > 200 Durchläufe à 3 Werte. Meinst du nicht, das könnte reichen? Sicherlich. Die positiven Werte liegen zum Teil ja auch nah dran: 153 * 200 = 30600
Ganz dumme Frage, wenn die Fragen rein Positiv sein sollen, warum benutzt du dann nicht einfach einen unsigned integer? Damit hast du doppelt so viele Zahlen zur verfügung bevor es überläuft
1 | |
2 | |
3 | |
bzw in C++ (was ja die arduino sprache eigentlich ist)
1 | |
2 | |
3 | |
(C style casts in C++ sorgen dafür das der Compiler alle Casts ausprobiert, wenn es also Klassen Pointer sind wird der Compiler einen Dynamic cast draus machen, welcher zur runtime evaluiert wird, daher programm memory und runtime benötigt. Daher willst du eigentlich fast immer static_casts machen)
Frederic K. schrieb: > Ganz dumme Frage, wenn die Fragen rein Positiv sein sollen, warum > benutzt du dann nicht einfach einen unsigned integer? Damit hast du > doppelt so viele Zahlen zur verfügung bevor es überläuft Die Idee hatte ich auch schon, aber die MCU Librarie will nur int16_t.
Nicht mal bei den Summen ist mehr als int16_t erlaubt?
Kolja L. schrieb: > Die Idee hatte ich auch schon, aber die MCU Librarie will nur int16_t. Daher mein define, die Zahlen selbst sind zwar int16_t, aber das Makro ruft nicht nur abs auf, sondern sagt dem compiler gleichzeitig noch das das ergebnis als unsigned integer verwendet werden soll, also die Addition unsigned ist
Lib oder nicht: Deine Summen benötigen einen ausreichend grossen Datentyp. Das dividierte Ergebnis darf dann wieder int16_t sein.
Gast
#5693496
Frederic K. schrieb: > #define ABS16(X) static_cast<uint16_t>(abs(X)) > auto g_1 = ABS16(gx) + ABS16(gy) + ABS16(gz); > #undef ABS16 ist ein bißchen mit Kanonen auf Spatzen und so, es reicht auch int32_t sum_g_1;
Frederic K. schrieb: > #define ABS16(X) ((uint16_t)(abs(X))) Ich bin kein grosser Freund von Typecasts und ziehe es vor, sie nur da zu verwenden, wo sie wirklich zwingend sind. Die haben nämlich die Neigung, kommentarlos praktisch alles zu fressen, was man ihnen vorsetzt. Pointer inklusive. Dem Compiler nimmt man damit Möglichkeiten, auf Fehler hinzuweisen.
A. K. schrieb: > Ich bin kein grosser Freund von Typecasts und ziehe es vor, sie nur da > zu verwenden, wo sie wirklich zwingend sind. Die haben nämlich die > Neigung, kommentarlos praktisch alles zu fressen, was man ihnen > vorsetzt. Pointer inklusive. Dem Compiler nimmt man damit Möglichkeiten, > auf Fehler hinzuweisen. Ich caste lieber zu viel als zuwenig. Beispiel, wenn er jetzt das ergebnis statt in einer Variable zwischen zu speichern irgendwann direkt in eine Funktion speisen will, welche sowohl für signed als auch unsigned überladen ist, kracht es. So kann man sich sicher sein, jede Formel die ABS16 enthält wird auf unsigned "aufgewertet". Somit ist die Addition selbst unsigned, unabhängig vom Kontext. Außerdem ermöglicht der cast die verwendung von auto, damit spart man sich ein paar zeichen im gegensatz zu uint16_t (wobei ich mir für gewöhnlich eh die typen i8, i16, i32, i64 und u8, u16, ... definiere) Das mit den Warnings kann ich aber verstehen, daher arbeite ich fast immer mit den Flags -Wpedantic -Werror -Wall. Lieber mehr Warnings als zu wenige (außer ich verwende fremden code wie Header only Libraries, da kann Werror ganz schnell in die Hose gehen)
Gast
#5693527
Frederic K. schrieb: > Lieber mehr Warnings als zu wenige Und genau deshalb keine casts. Alternativ z.b. typsichere Inline-funktionen mit expliziter Zuweisung.
Walter schrieb: > int32_t sum_g_1; Danke :-)
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.