Archiv verlassen und diese Seite im Standarddesign anzeigen : Grundsatzfragen
Hallo,
mich quält mal wieder C++.
Ich habe ein Array:
uint16_t meineWerte[3];
Jetzt will ich das speichern:
x.write(meineWerte[0],6);
Das ist wohl in Ordnung so.
Bloß, wie lese ich das zurück?
Idee:
xyzSet[0]=f.read();
error: incompatible types in assignment of 'int' to 'uint8_t [3] {aka unsigned char [3]}'
xyzSet[0]=f.read();
MfG
https://www.arduino.cc/en/Reference/FileRead
file.read(buf, len)
Danke!
Funktioniert nur mit
uint8_t meineWerte[6];
oh mist sorry hab das mit uint16 nicht gesehen :(
Behalte nur immer im Hinterkopf dass es da draußen verschiedene Byte Orders gibt, also MSB und LSB auch mal vertauscht sein könnten :) .... klar unwichtig für den speziellen Fall will nur darauf hinweisen!
oh mist sorry hab das mit uint16 nicht gesehen :(
Behalte nur immer im Hinterkopf dass es da draußen verschiedene Byte Orders gibt, also MSB und LSB auch mal vertauscht sein könnten :) .... klar unwichtig für den speziellen Fall will nur darauf hinweisen!
LSB oder MSB sind für Arduino eigentlich kein Thema,
aber mit char muss man aufpassen
char bei AVR : immer signed !
char bei ARM und ESP: immer unsigned!
daneben, aber ebenfalls hier offtopic:
int bei AVR = 16-bit
int bei ARM und ESP = 32-bit
(liegt an gcc, nicht an Arduino!)
deswegen nutzt er ja vorbildlich die expliziten typen
deswegen nutzt er ja vorbildlich die expliziten typen
ja, das geht aber auch nicht immer, manchmal muss man zwingend char benutzen.
@moppi:
ich vermute, du musst oben per file.read 2 bytes einzeln nacheinander lesen, und eines davon <<8 shiften, dann beide addieren.
Ja, HaWe.
Das war das schöne an x86 Assembler. Daten lesen in den Speicher und zugreifen mit 8Bit, 16Bit oder 32Bit - egal, weil Speicher ist Speicher.
So nun dachte ich, Daten einlesen in einem Rutsch, und zugreifen mit:
8Bit-Werten, liest mir ein Byte aus dem Puffer in meine uint8_t -Variable
16Bit-Werten, liest mir zwei Byte aus dem Puffer in meine uint16_t-Variable
geht nur nicht.
Ich habe es umgestellt auf Byte und muss dann shiften und den zweiten Wert nochmal verknüpfen.
- - - Aktualisiert - - -
Ich schlage mich mit den X-Y-Z-Werten des Lagessensors rum.
mit ACX = obj.getX(); bekomme ich einen 16Bit-Wert (anscheinend vorzeichenbehaftet)
obj.getCalculatedX(); liefert normalerweise positive und negative Werte als Float, wenn man das als Serial.print(..) ausgibt.
bei ACX = (uint16_t)obj.getCalculatedX(); bekomme ich aber nur "0"-Werte
bei ACX = obj.getCalculatedX(); ebenfalls
ACX ist dabei uint16_t
Diese Sensorwerte wollte ich einfach einlesen und speichern. Na ja ...
Wobei die Methode getCalculatedX() mit float als Rückgabewert deklariert ist.
Verstehe noch nicht, warum da nur Nullen bei rum kommen.
Jetzt hab ich es: ich bekomme nur Nullen als Nicht-float, weil die Werte so klein sind. 0 bis +1.
Daten lesen in den Speicher und zugreifen mit 8Bit, 16Bit oder 32Bit - egal, weil Speicher ist Speicher.
So nun dachte ich, Daten einlesen in einem Rutsch, und zugreifen mit:
Zwar gibt es das Credo bei C:
"alles ist ein file!",
das ist bei MCUs aber nicht so einfach, weil du bei Arduino aus einer "Stream class"-enherited "File class" liest (oder schreibst),
jedoch gibt es per Arduino gcc oder avrgcc ja überhaupt kein file System, weder für SD cards noch für sonst irgendwas!
:shock:
C bietet für FILE* aber auch nur Dinge wie fread() für byte-Blöcke oder (f)scanf() für formatierte Daten,
Arduino Stream allerdings kennt auch Stream.parseInt()
https://www.arduino.cc/reference/en/language/functions/communication/stream/streamparseint/
- das wäre vlt auch eine Möglichkeit, allerdings wird das auch nicht viel anderes tun als 2 Bytes lesen, das 1. dann shiften und das 2. dann dazuaddieren (kann man auch in eine eigene Funktion packen)
Zwar gibt es das Credo bei C:
"alles ist ein file!"
Das ist so nicht richtig. Das gilt für Unix, oder vergleichbare Systeme. Und die Sprache ist dabei nebensächlich. Richtig heißt es "Für Unix ist alles ein File (https://de.wikipedia.org/wiki/Everything_is_a_file)"
das ist bei MCUs aber nicht so einfach, weil du bei Arduino aus einer "Stream class"-enherited "File class" liest (oder schreibst), jedoch gibt es per Arduino gcc oder avrgcc ja überhaupt kein file System, weder für SD cards noch für sonst irgendwas!
Und auch das hat mit C oder dem benutzten Compiler nichts zu tun. Es fehlt dem Arduino-System ein Betriebssystem, ein Kernel, der ein Filesystem zur Verfügung stellt. Die libc stellt nur ein C-kompatibles Interface für die Systemcalls in den Kernel zur Verfügung.
C bietet für FILE* aber auch nur Dinge wie fread() für byte-Blöcke oder (f)scanf() für formatierte Daten,
C bietet genau das an, für was jemand eine Funktion geschrieben hat. C selbst kann nichts, außer vorhandene Funktionen aufrufen. Wenn die Arduino-Erfinder Files hätten haben wollen, hätten sie nur die passenden Funktionen schreiben müssen. Am besten (aber nicht notwendigerweise) kompatibel zur Standardlibrary von C.
MfG Klebwax
Das ist so nicht richtig. Das gilt für Unix, oder vergleichbare Systeme. Und die Sprache ist dabei nebensächlich. Richtig heißt es "Für Unix ist alles ein File (https://de.wikipedia.org/wiki/Everything_is_a_file)"
Und auch das hat mit C oder dem benutzten Compiler nichts zu tun. Es fehlt dem Arduino-System ein Betriebssystem, ein Kernel, der ein Filesystem zur Verfügung stellt. Die libc stellt nur ein C-kompatibles Interface für die Systemcalls in den Kernel zur Verfügung.
C bietet genau das an, für was jemand eine Funktion geschrieben hat. C selbst kann nichts, außer vorhandene Funktionen aufrufen. Wenn die Arduino-Erfinder Files hätten haben wollen, hätten sie nur die passenden Funktionen schreiben müssen. Am besten (aber nicht notwendigerweise) kompatibel zur Standardlibrary von C.
MfG Klebwax
Mit Unix vs. "nacktem" C hast du Recht, stimmt (und C wurde ja zum programmieren von Unix überhaupt erst entwickelt), aber für C gibt es die stdio.h, die genau die file- (FILE*) Funktionen zur Verfügung stellt (egal ob Unix oder x86), die es bei Arduino nicht gibt, obwohl sie auch "File" heißen.
Moppi bemängelte ja, dass es bei x86 asm so viel "logischer" wäre, aber auch hier bezog er sich auf x86, im Gegensatz zu C(++).
mich quält mal wieder C++
...
das war das schöne an x86 Assembler
In C aber gibt es ja gewisse Funktionen, die logisch wären, wie z.B. die printf/scanf-Familie, für stdin/out und files, und hier ist tatsächlich quasi "alles" ein File
Worauf ich hinaus wollte:
obwohl es das grundsätzlich für C gibt und dort auch logisch und im gewissen Rahmen verfügbar ist:
das gibt es eben nicht für Arduino, aber das ist keine Schuld von C++, womit moppi haderte, sondern es liegt am fehlenden File system mit den entsprechenden Libs.
Und hier sind wir uns ja auch einig.
Ich habe eine sehr interessante Lösungsstrategie gefunden.
https://www.arduinoforum.de/arduino-Thread-Die-Bytemühle-einfacher-Zugriff-auf-einzelne-Bytes-einer-Mehrbyte-Variablen
Mit dieser UNION-Geschichte sollte es möglich sein, eine Kette an Bytes zu laden, um dann mit verschiedenen Datentypen, an verschiedenen Stellen in dieser Byte-Kette, zugreifen zu können.
Da tun sich viele Möglichkeiten auf, was man mit UNION und Datentypen anstellen kann.
MfG
ja, mit union mache ich es teilw. auch, wenn ich einen array of bytes habe, der verschiedene Datentypen enthält, allerdings mit eigenen Funktionen, die weniger kompliziert aussehen 8)
Muss man mal wissen, dass es so etwas gibt.
Damit kann man char-Arrays an Methoden als string übergeben usw.
Mehrere Datentypen für einen Speicherbereich.
Damit kann man char-Arrays an Methoden als string übergeben usw.
ja, aber gerade bei cstring musst du beachten, dass sie immer aus
char
und nicht aus uint8_t bestehen:
char str1[20];
char* str2;
und dass char in cstrings bei AVR kein byte und auch kein uint8_t (0..255) sondern ein signed char ist (-128..+127).
Bei ARM/ESP hingegen ist die cstring-char unsigned, also quasi "wie ein byte".
Aber auch wenn char hier unsigned sind, kann man dennoch nicht byte oder uint8_t arrays dafür einsetzen bzw. verwenden.
Genau darauf wollte ich oben in meinen Posts #5 und #7 hinaus.
Muss man drauf achten, was man tut.
Habs jetzt mal so gemacht:
union xyzS{
uint8_t byt[6]; //XYZ-Array: 3 Werte mit 16 Bit
uint16_t val[3];
};
xyzS xyzSet;
Zugriff:
f.read(xyzSet.byt,6);
uint16_t ACX = xyzSet.val[0];
uint16_t ACY = xyzSet.val[1];
uint16_t ACZ = xyzSet.val[2];
Ich hatte das Problem, mit unterschiedlichen Aufrufparametern / Datentypen einer Funktion.
Jetzt kann man eine neue Funktion erstellen, normalerweise mit neuem Namen.
Jetzt hatte ich aber, aus weit zurückliegender Vergangenheit C++ Kurs, eine Eingebung, dass da was mit den Parametern war, insbesondere im Zusammenhang mit Methoden.
In C geht das nicht, dass man eine Funktion gleich benennt. Aber C++ erlaubt das - habe kurz gesucht und nachgelesen.
bool udp_send(char* string)
{
}
bool udp_send(String string)
{
}
C++ wählt, je nach Datentyp in den Übergabeparametern, die passende Funktion aus.
Der eigentliche Grund dafür:
mit ist noch unklar, wie ich in C++ einen String, Typs "String" in ein String, Typs "char" umwandle.
Und ob das überhaupt geht.
Müsste aber, habe was dazu gefunden: https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/tochararray/
Allerdings wird da der gesamte String als Kopie im Speicher abgelegt. Vermutlich passiert das Kopieren zur Laufzeit.
Das ist weniger gefällig.
MfG
Der eigentliche Grund dafür:
mit ist noch unklar, wie ich in C++ einen String, Typs "String" in ein String, Typs "char" umwandle.
Und ob das überhaupt geht.
Müsste aber, habe was dazu gefunden: https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/tochararray/
Allerdings wird da der gesamte String als Kopie im Speicher abgelegt. Vermutlich passiert das Kopieren zur Laufzeit.
Das ist weniger gefällig.
MfG
ja, du brauchst hier immer 2 verschiedene Variablen, da beide unabhängige Datentypen sind und nichts miteinander zu tun haben:
einen cstring von passender Größe
char cbuf[100];
und einen
String mString;
du kannst jetzt den Inhalt von String mString auf char cbuf[] kopieren:
mString.toCharArray(cbuf, 100);
Ist die Länge von mString kürzer als die vom cstring, wird in cstring hinter das letzte mString-Zeichen eine Null '\0' gesetzt (ich weiß allerdings jetzt grade nicht, ob der Rest ebenfalls mit '\0' aufgefüllt wird oder undefiniert bleibt).
- - - Aktualisiert - - -
PS,
es gbt noch eine 2. String-Methode, die einen Pointer auf den "reinen cstring-Inhalt" von String zurückliefert:
mString.c_str()
Ich habe das noch nicht benutzt, aber ich verstehe das so, dass du dann (z.B. für temporäre Zwecke) keinen extra cstring Buffer brauchst, z.B. direkt zur Verwendung in anderen C Funktionen, so als wäre es bereits selber ein cstring array. Vermutlich arbeitet die Methode genau wie beim großen Bruder, der C++ std::string class:
http://www.cplusplus.com/reference/string/string/c_str/
Ja, c_str() funktioniert in Verbindung mit write().
Gut!
Gibt aber einen "const char*" Datentyp zurück?
gibt dann so Meldungen dass von const char* nach char* ein Konvertierungsfehler auftritt.
- - - Aktualisiert - - -
c_str() gibt const char*
Ja ist wohl so, habe es woanders gelesen.
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.