int16_t addieren

#5693271
Lesenswert?

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?
#5693307
Lesenswert?

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
#5693408
Lesenswert?

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
Lesenswert?

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)
#5693511
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren