Ich sitze gerade an einem Projekt, bei dem ich per Seriellen Monitor Daten zwischen dem Arduino und einen Python Programm hin und her schicken möchte. Dazu habe ich eine Frage.
Nur kurz zur Erklärung:
Wenn Python einen Befehl an den Arduino sendet, dann besteht der "Befehl" aus 9 aneinander gereihten Zeichen (Datentyp char), die ersten drei spiegeln einen Befehl wieder, die zweiten 3 den Pin oder möglicherweise etwas anderes, im Moment aber nur Pins und die letzten Drei die Parameter, beispielsweise 001013001 (001 ist der Befehl digitalWrite(), 013 ist der Pin 13 und 001 ist der Zustand HIGH) mal so zum Verständins dann noch für analoge Pins 0030A2--- (003 ist der Befehl analogRead() , 0A2 ist der Pin A2 also ein analoger Pin und --- bedeutet kein Parameter -> nur Pin gebraucht). Ich hoffe das ist jetzt etwas verständlich
gespeichert werden soll das in einen Array read_in von chars der 9 Zeichen groß sein soll, so wie der "Befehl". Nun meine Frage, wie kann man abfragen, ob der Wertebereich der ersten 3 Stellen des Arrays zusammen einen bestimmten Wert hat, hier jetzt mal als Beispiel 001 ist ja im Array read_in[0], read_in[1] und read_in[2].
Somit kann man dann nach den einzelnen Teilen des "Befehls" nach einander abfragen und muss nicht für jeden Wert einzeln nachfragen.
Ich hatte eigentlich noch eine zweite Frage dazu, aber da komme ich gerade beim besten Willen nicht drauf. Sollte sie mir noch einfallen werde ich die dann noch ergänzen, freue mich auf Hilfe
So jetzt ist mir die Zweite Frage doch noch eingefallen:
Wenn ich etwas vom Arduino zum Python-Programm zurücksenden möchte, dann möchte ich einen array haben, der gesendet wird, von dem ich allerdings nicht weiß, welcher Typ die Daten haben, die zurückgesendet werden, denn wenn ich beispielsweise eine Fehlermeldung zurücksende, dann ist das ja ein String, aber wenn ich bloß einen Zustand von einem Pin herausfinden möchte, dann ist das ja entweder ein int oder etwas anderes im Zahlenbereich.
Gibt es sowas wie ein unwissender Datentyp? Oder einen den man ersteinmal da zuweisen kann um den später noch zu ändern? So was wie in pseudocode unknowntype array send_out[] ?
Und wie kann ich in Python mit Datentypen umgehen, die es in C /C++ gibt, aber in Python nicht vorkommen wie uint16_t (Adafruit_7735R.h Library), sollten diese abgefragt bzw. aus irgendeinem Grund zurückgegeben werden Müssen? Umwandlung in einen Python Datentyp, der ja recht spärlich ist (int, unicode, etc.) könnte ja möglicherweise etwas verfälschen, was bei späteren Anwendungen vielleicht zu Problemen führen könnte :o
Wäre nett wenn auch dazu jemand was wüsste
LG Hubble
Nun meine Frage, wie kann man abfragen, ob der Wertebereich der ersten 3 Stellen des Arrays zusammen einen bestimmten Wert hat, hier jetzt mal als Beispiel 001 ist ja im Array read_in[0], read_in[1] und read_in[2].
Am besten du trennst deine Befehle in dem Array mit Kommas oder Strichpunkten ab. z.B. sowas:
char data[] = "001;569;456";
Dann kannst du die Gruppen mit atoi() einfach in einen Integer wandeln:
int data1 = atoi(data);
int data2 = atoi(data + 4);
int data3 = atoi(data + 8);
EDIT:
Für die analogen Pins verwendest du am besten nicht A2, etc. sondern auch Zahlen. Die analogen Pins haben Nummern eins höher als der höchsten Digital-Pin. Also auf dem UNO A0 = 14, A1 = 15, etc.
Gibt es sowas wie ein unwissender Datentyp?
Dafür gibt es void pointer.
Damit kann man sowas machen:
void printArray(void* data, int size)
{
byte* ptr = (byte*)data;
for(int i = 0; i < size; i++)
Serial.println(ptr[i]);
}
Für size musst du dann Größe in Byte angeben. Also wenn z.B. ein int Array hast:
int data[10] = { ... };
printArray(data, sizeof(data));
Du kannst aber den Datentyp des Arrays genauso in byte oder long ändern und musst an printArray() nichts ändern
Ich bin gerade auf den C++ Datentyp size_t gestoßen, der Eintrag bei cpluplus.com "It is a type able to represent the size of any object in bytes" hieße das nicht, dass man diesen Typs anstatt eines Pointers nutzen könnte um das Objekt bzw. die Objekte zu deklarieren, die versendet werden sollten? Weil ich weiß selbst noch nicht so viel über Pointer, habe sie fast nie gebraucht.
Ich würde es einfacher finden Datentypen anstatt von Pointern zu gebrauchen, denn die weisen ja auch nur auf etwas hin ein void Pointer ja so gesehen auf void (Leere) -> nix warum also nicht size_t. Ich weiß allerdings nicht, ob man die in dem Arduino C++ nutzen kann.
Wäre nett wenn jemand mir auch vereinfacht Pointer erklären kann und warum sie hier vielleicht besser sind :o
Nein. size_t lediglich ist ein typedef auf unsigned long . Das ist nur für die Größe von Arrays oder Objekten. Nicht für den Inhalt. So steht es ja auch da:
represent the size
In C sind Arrays nicht anderes als Zeiger auf das erste Element. Das ist kein komplexer Datentyp! Arrays sind also schon Zeiger. Und void Pointer dienen u.a. dazu dass eine Funktion beliebige Datentypen als Parameter übernehmen kann. Siehe z.B. memset().
Man deklariert dann das Array mit einem richtigen Datentyp. Die Funktion hat einen void* als Parameter und castet diesen auf byte*. Somit werden alle Daten die man übergibt, egal welchen Typ sie haben, als Byte betrachtet. Und die Übertragung - egal ob seriell, SPI, I2C oder sonstwas - geschieht ja auch Byte-weise.
Das funktioniert nicht nur mit Arrays, sondern auch mit Objekten oder structs wenn man deren Adresse an die Funktion übergibt
Templates sind reines C++, während void Pointer eher klassisches C sind
EDIT:
Einen wirklich allgemeinen Datentyp gibt es nicht. Void pointer sind dadurch eingeschränkt, dass man sie auf einen richtigen Datentyp casten muss bevor man darauf zugreift.
Am nächsten kommt vielleicht in gewissen Grenzen ein Byte Array. Das kann man auch als Array anderer Datentypen betrachten, da man einen byte* z.B. auf int* casten kann. Da muss man halt mit der Länge aufpassen. Ein Array aus 8 Bytes hat auf dem Arduino nur Platz für 4 ints. Oder 2 longs oder floats.
Die Funktion sollte natürlich formal universell als
void printArray(void* data, size_t size);
deklariert sein.
sizeof liefert übrigens ein Ergebnis vom Datentyp size_t.
(Beim kleinen Arduino sollte man evtl. byte size nehmen, wenn 255 sicher reicht,
und eigentlich sollte size_t sollte als unsigned int deklariert sein, weil es keine Objekte > 64kB geben kann. )
In 63,2% aller Stellen wo **</sub> <sub>** int**</sub> <sub>** steht, handelt es sich um Faulheit, Gedankenlosigkeit oder einen Fehler.
Wobei man da höchstens auf dem Due reinfallen kann, wenn man sehr große Arrays hat. In diesem Fall wäre es wohl gegangen, da die Arrays nur ein paar Bytes groß sind.
ging mir auch weniger ums Reinfallen ( Fehler ), sondern mehr um Faulheit/Gedankenlosigkeit ... und ein bisschen Rummeckern
int ist halt am schnellsten getippt, und da Arduino die Warnungen abschaltet, stört es auch keinen
Ein Byte auf dem Stack zu sparen, ist auch nicht der Rede wert.
{
byte* ptr = (byte*)data;
for(int i = 0; i < size; i++)
Serial.println(ptr[i]);
}
soll ich da jetzt int size oder size_t size nehmen?
Ich würde es dann bevorzugen, der Einfachheit halber, ein Array zu nehmen, das entweder den Datentyp int /char oder float hat (oder in Extremfällen noch einen anderen) mit der Größe 255, dass sollte reichen oder?
Übernehmen möchte ich auch die Idee mit der Unterteilung per: Simikolon -> char arr[/*11*/] = "123;456;789";
Sollte sich noch etwas ergeben oder Anmerkungen werde ich das noch dazuschreiben, muss das jetzt erst einmal austesten.
Wenn du es ganz schön machen willst nimm size_t. Auch in der for-Schleife. Wobei es in deinem Fall auch mit int geht, da dein Array kleiner als 32kB ist.
Übernehmen möchte ich auch die Idee mit der Unterteilung per:
Kommt darauf an wie viele Zahlen du hast. Aber damit muss man nicht für jede Zahl extra atoi() schreiben, sondern kann das in einer Schleife erledigen. Vor allem muss man damit nicht wissen wieviele Elemente gesendet werden und die Tokens können eine unbekannte Länge haben, statt immer konstant 3 Zeichen haben zu müssen.
Du kannst da natürlich auch Speichern sparen, wenn du die Zahlen nicht erst in einem int Array abspeicherst, sondern nach atoi() gleich verarbeitest, z.B. an der Stelle gleich den Pin schaltest, oder was du sonst damit machen willst. 255 ints belegen nämlich 510 Bytes. Wobei du das glaube ich gar nicht so groß brauchst.
Bei Integer Zahlen besteht auch die Möglichkeit die Daten erst gar nicht in ein char Array zu speichern sondern die Zeichen Schritt für Schritt von der seriellen Schnittstelle einzulesen und gleichzeitig zu konvertieren. Wenn man das macht:
123 = 1 * 100 + 2 * 10 + 3 * 1
Also immer das eingelesene ASCII Zeichen in Dezimal wandeln (- 48), dann mit der aktuellen Wertigkeit multiplizieren, auf das Ergebnis addieren und die Wertigkeit mit 10 Multiplizieren. Und wenn ein Strichpunkt kommt die Zahl verarbeiten.
Dann fällt auch strtok() + atoi() weg da man beides auf einmal macht.
Also immer das eingelesene ASCII Zeichen in Dezimal wandeln (- 48)
48 ist das gleiche wie das Zeichen '0', falls du dich wunderst. Und die Zeichen '0' , '1', '2' ... liegen glücklicherweise direkt aufeinanderfolgend richtigrum hintereinander. ( ('9' - '0') == 9 ) Fertig ist die Wandlung ASCII - Dezimal.
Ob du int, size_t, oder gar als Sparfuchs byte nimmst, war mehr ein theoretischer Einwand.
( [b]size_t[/b] ist am schönsten, [b]byte[/b] ist am sparsamsten wenns passt, und bei ** ** int** **
hast du weniger zu tippen )