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?
>Warum verrechnet sich der µC?
schau bitte mal in die Assemblerausgabe was da passiert.
Und zeige bitte das komplette Testprogramm.
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 | // WiFi & OTA Update
|
2 | #include <ESP8266WiFi.h> |
3 | #include <ESP8266mDNS.h> |
4 | #include <WiFiUdp.h> |
5 | #include <ArduinoOTA.h> |
6 | |
7 | // I2C & MPU6050
|
8 | #include "Wire.h" |
9 | #include "I2Cdev.h" |
10 | #include "MPU6050.h" |
11 | |
12 | // WiFi & OTA Update
|
13 | const char* ssid = "xxx"; |
14 | const char* password = "xxx"; |
15 | |
16 | // I2C & MPU6050
|
17 | MPU6050 mpu_1; |
18 | MPU6050 mpu_2(0x69); |
19 | int16_t gx, gy, gz, g_1, g_2, zaeler; |
20 | int16_t ax, ay, az; |
21 | unsigned long Zeit_alt = 0; |
22 | unsigned long Zeit_neu = 0; |
23 | const long Dauer = 1000; |
24 | |
25 | |
26 | void setup() { |
27 | Serial.begin(115200); |
28 | |
29 | // WiFi & OTA Update
|
30 | ArduinoOTA.setHostname("xxx"); |
31 | ArduinoOTA.onError([](ota_error_t error) { |
32 | ESP.restart(); |
33 | });
|
34 | ArduinoOTA.begin(); |
35 | |
36 | // I2C & MPU6050
|
37 | Wire.begin(); |
38 | mpu_1.initialize(); |
39 | mpu_2.initialize(); |
40 | }
|
41 | |
42 | void loop() { |
43 | // WiFi & OTA Update
|
44 | ArduinoOTA.handle(); |
45 | |
46 | |
47 | // I2C & MPU6050
|
48 | mpu_1.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); |
49 | int g1 = gx + gy + gz; |
50 | g_1 = abs(gx) + abs(gy) + abs(gz); |
51 | mpu_2.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); |
52 | g_2 = abs(gx) + abs(gy) + abs(gz); |
53 | |
54 | |
55 | Serial.print(g_1); |
56 | Serial.print(" "); |
57 | Serial.print(abs(gx)); |
58 | Serial.print(" "); |
59 | Serial.print(abs(gy)); |
60 | Serial.print(" "); |
61 | Serial.println(abs(gz)); |
62 | |
63 | delay(50); |
64 | |
65 | |
66 | |
67 | } // loop |
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.
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?
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 | #define ABS16(X) ((uint16_t)(abs(X)))
|
2 | uint16_t g_1 = ABS16(gx) + ABS16(gy) + ABS16(gz); |
3 | #undef ABS16
|
bzw in C++ (was ja die arduino sprache eigentlich ist)
1 | #define ABS16(X) static_cast<uint16_t>(abs(X))
|
2 | auto g_1 = ABS16(gx) + ABS16(gy) + ABS16(gz); |
3 | #undef ABS16
|
(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.
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.
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)
Frederic K. schrieb: > Lieber mehr Warnings als zu wenige Und genau deshalb keine casts. Alternativ z.b. typsichere Inline-funktionen mit expliziter Zuweisung.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.