int16_t addieren

OP #5693271
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?
OP #5693307
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
OP #5693408
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?
#5693449
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)
#5693499
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.
#5693511
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)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.