Seit knapp einer Woche befasse ich mich nun mit Arduino und bin etwas am rumexperimentieren. Meine Programierkentnisse sind eher schlecht als recht und lerne eher nach dem Try and Error Prinzip.
Ich versuche mittels Infrarot zwei Arduino Uno miteinander komunizieren zu lassen, was eigentlich auch ganz gut geht mit "normalen" Codes. Ich suche nun aber nach einer Lösung eigene Codes zu übermitteln.
Beispiel:
Arduino 1 soll an Arduino 2 folgenden Code übermitteln: 011991 Zusammengesetzt aus: [0][1][1][99][1]
Bis jetzt habe ich den Code Manuell gesendet dazu habe ich folgenden Befehl verwendet:
irsend.sendSony(0x011991, 32)
Soviel ich rausgefunden habe Formatiert das anfängliche 0x den Datensatz in eine Dezimalzahl um, denn ohne dies erhalte ich eine ganz andere Ausgabe.
Nun weis ich aber nicht wie ich die ganze Geschichte Variabel gestalten kann, dieses 0x schränkt mich mit den Möglichkeiten stark ein da ich so keine Möglichkeit habe mit den Datensatz als int, bzw long zu arbeiten.
Eine weitere Möglichkeit wäre vorgefertigte Codes als übertragung zu verwenden und dann per switch zu verarbeiten, allerdings kann der Code für jedes Feld 0-99 als Inhalt haben was einen unendlich langen Code resultieren würde.
Ich hoffe man verstehl was ich meine und was mein Ziel ist, würde mich freuen wenn sich jemand findet der mir weiterhelfen kann.
D4xX6:
Soviel ich rausgefunden habe Formatiert das anfängliche 0x den Datensatz in eine Dezimalzahl um, denn ohne dies erhalte ich eine ganz andere Ausgabe.
Nun weis ich aber nicht wie ich die ganze Geschichte Variabel gestalten kann, dieses 0x schränkt mich mit den Möglichkeiten stark ein da ich so keine Möglichkeit habe mit den Datensatz als int, bzw long zu arbeiten.
Quatsch, wo hast das "herausgefunden"?
0x am Anfang einer Ganzzahl-Konstanten bedeutet, dass die Konstante in hexadezimaler Notation angegeben ist.
Dass man Konstanten nicht verändern kann, liegt in der Natur von "konstant".
Tu dir einen Gefallen und arbeite mal eine Anfänger Einführung in C(++) durch.
Der Tip mit der Einführung in C++ ist sehr hilfreich. In der Arduino Referenz zu Integer Constants ist das übrigens auch beschrieben.
Ob du als zu übertragenden Code 0x011991 oder 72081 (oder zur Sicherheit 72081UL) schreibst, ist Geschmackssache und inhaltlich identisch. Da du der Meinung bist, es würde [1][1][99][1] übertragen (eine sehr individuelle Schreib- und Sichtweise, übrigens), empfiehlt sich wohl die hexadezimal-Schreibweise dieses Werts.
Deine Programmzeile
irsend.sendSony(0x011991, 32);
Kannst du auch so schreiben:
const long BEFEHL1 = 0x011991;
...
irsend.sendSony(BEFEHL1, 32);
oder auch per Variable:
const unsigned long BEFEHL1 = 0x011991;
...
unsigned long irBefehl;
...
irBefehl = BEFEHL1;
...
irsend.sendSony(irBefehl, 32);
Hoffe, das war jetzt nicht zu verwirrend und gibt dir Material für weitere Try&Error Versuche
Hallo,
ich weiß nicht ob das der richtige Weg ist den Du da verwenden möchtest.
Das was Du da vor hast ist serielle Kommunikation mit dem Arduino.
Mir ist keine IR-Lib bekannst, die außerhalb ihrer Protokolle auch fremde
Daten übertragen kann.
Was Deine "011991" so sind das für mich 6 Integer. Die kannst Du doch in
Hex wandeln. Dann in Hex senden- und auf der anderen Seite wieder in INT
wandeln.
Das setzt aber vorraus, das Deine Lib fremde Daten senden kann.
Wenn ich das anfangen würde, dann würde ich mir einen IR-Sender besorgen, der
über die serielle Schnittstelle angesprochen wird.
Gruß und Spaß
Andreas zur Info
Wenn man zwei Arduinos über IR kommunizieren lassen möchte (nur eine begrenzte Zahl von Befehlen in nur eine Richtung braucht und Sender und Empfänger aufeinander ausgerichtet sind), kann man schon die IRremote Library verwenden. Ist halt preiswerter als andere drahtlose Verbindungen.
Wenn man das ganze auch manuell testen möchte, empfiehlt es sich, Codes zu verwenden, die auch eine vorhandene Fernbedienung sendet, ansonsten sollte jeder beliebige (32 bit) - Wert möglich sein und von IRreceive so empfangen werden wie IRsend es aussendet.
Seriell via Bluetooth ist sicher vielseitiger, aber ob dies hier besser ist, muss D4xX6 entscheiden oder erzählen, wofür das ganze gut sein soll.
Ich habe das wohl wirklich etwas ungeschickt formuliert. Ich versuche es nochmals etwas genauer.
Ich probiere ein Laser-Tag System aufzubauen. Dazu sende ich über Infrarot (Waffe) ein Signal an den Empfänger einer anderen Waffe. Um nun das ganze zu filtern, also fremdsignale auszuschliessen und eine verarbeitung über einen Server (ist über 433MhZ mit den Waffen verbunden) zu ermöglichen bin ich darauf angewiesen dass der Infrarot-Code einer bestimmten Reihemfolge entspricht.
Aufbau des Signals:
Das IR-Signal besteht aus mehreren "Blöcken". Waffen-ID¦Schuss¦Treffer¦ZielWaffen-ID¦Bestätigung
So entsteht zum Beispiel das Signal 2¦1¦0¦5¦0
So nun zu meinem Problem:
Ich kann manuell den Code 21050 senden und auf dem anderen Arduino empfangen, allerdings nur wenn ich 0x21050 sende.
Nun dachte ich ich kann das ganze über einen Array realisieren z.B:
int my_signal[] = {0x,2,1,0,5,0};
Da nun ja aber ein x enthalten ist fällt int weg also mit char
char my_signal[] = {0x,2,1,0,5,0};
Nur da ist es mir ja leider auch nicht möglich in einen int umzuwandeln da ein x vorkommt was nicht verarbeitet werden kann.
Und genau da ist nun mein Problem, was für Lösungsansätze gibt es um my_signal Variabel gestalten zu können. Ich hoffe ich konnte es nun etwas genauer erklären.
D4xX6:
Eine weitere Möglichkeit wäre vorgefertigte Codes als übertragung zu verwenden und dann per switch zu verarbeiten, allerdings kann der Code für jedes Feld 0-99 als Inhalt haben was einen unendlich langen Code resultieren würde.
Du kannst den Befehl, den Du senden möchtest, auch zusammensetzen. Du gehst von einer leeren Maske aus und veroderst den um vier Bits nach links verschobenen Befehl (ungetestet als Anregung):
const unsigned long MASKE = 0x11001UL;
...
byte befehl = 0x99; // variabel 0 - 99
unsigned long irBefehl = MASKE | befehl << 4; // vier Bits nach links
irsend.sendSony(irBefehl, 32);
Ob das für Dich zielführend ist, kann ich nicht beurteilen, da mir das Ziel nicht wirklich klar ist.
D4xX6:
So entsteht zum Beispiel das Signal 2¦1¦0¦5¦0
Das ist irBefehl =
0x20000 | // Waffen-ID um 16 Bits nach links
0x01000 | // Schuss um 12 Bits nach links
0x00000 | // Treffer um 18 Bits nach links
0x00050 | // ZielWaffen-ID um 4 Bits nach links
0x00000 ; // Bestätigung
wobei ein Halbbyte auf 0 bis 15 (0x0 bis 0xF) beschränkt ist.
Schau dir erst mal das Hexa-Dezimalsystem an. Für eine Zahl zwischen 0 und 15 braucht man 4 Bit und nach 9 macht man einfach mit Buchstaben weiter:
0 = 0000
...
9 = 1001
A (10) = 1010
B (11) = 1011
C (12) = 1100
D (13) = 1101
E (14) = 1110
F (15) = 1111
Jede Hex-Ziffer ist also ein Block aus 4 Bit bzw. eine Dezimalzahl von 0-15. Das ist der Grund weshalb das in der Programmierung so häufig verwendet wird. Man sieht die Bit-Darstellung auf einen Blick und es entspricht der Größe von Worten als Vielfache von 4
Wenn du also sowas hast: 0xA9
Dann siehst du sofort dass das in Binär das ist: 1010 1001
Und in Dezimal das: 10 9
Für eine Wandlung der ganzen Zahl nach Dezimal würde dem höheren Block eine Wertigkeit von 16 geben und dem unteren 1. Aber du kannst das auch als zwei völlig voneinander getrennte Zahlen betrachten
Mit 16 Bit kannst du also 4 Hex Zifffern übertragen. Mit 32 Bit 8 Stück. Das ist perfekt für dich. Für Zahlen größer als 15 kann man zwei Ziffern spendieren (praktisch wäre da auch BCD-Code. Also 99 = 1001 1001)
Ob das für Dich zielführend ist, kann ich nicht beurteilen, da mir das Ziel nicht wirklich klar ist.
Das entspricht eigentlich genau dem was ich gesucht habe. Vielen herzlichen Dank.
Serenifly:
Schau dir erst mal das Hexa-Dezimalsystem an. Für eine Zahl zwischen 0 und 15 braucht man 4 Bit und nach 9 macht man einfach mit Buchstaben weiter:
Auch das hat mir enorm weitergeholfen vielen Dank.
Nun habe ich noch ein anderes Problem. Um eine Überprüfung zu machen sende ich das Signal einmal über Infrarot und einmal über 433MhZ Funk.
Mein Sende-Testcode sieht momentan folgendermasen aus:
void loop()
{
if (mySwitch.available())
{
Serial.print("433 Empfängt: ");
Serial.println(mySwitch.getReceivedValue());
delay(400);
mySwitch.resetAvailable();
};
if (irrecv.decode(&results))
{
Serial.print("Infrarot Empfängt: ");
Serial.println(results.value, DEC);
irrecv.resume(); // Receive the next value
};
}
Das Problem ist nun dass der Infrarot Empfänger eine falsche Ausgabe tätigt da im Sendecode das 0x fehlt. Gibt es eine Möglichkeit irsend.sendSony(hex, 32); so zu schreiben das immer zu beginn ein 0x vor hex gesendet wird?
Auch das hat mir enorm weitergeholfen vielen Dank.
Scheinbar nicht, da du die Zahl unnötigerweise als String übertragen willst.
printf() formatiert dir einen Integer in einen Null-terminierten String. Das geht auch - wenn man es richtig macht - ist aber etwas völlig anderes. Und man muss auf dem Empfänger den String wieder in einen Integer konvertieren.
@D4xX6
Das 0x wird NICHT versendet!!
Du kannst so nur einen Wert in Hexadezimal übergeben.
B101 - Binär (2er System, führendes B), der Wert beträgt 4+1, also 5
0101 - Octal (8er-System, führende Null), der Wert beträgt 64+1, also 65
0x101 - Hexadezimal (dieses Beispiel ist halt drei stellig, 16er System, führendes Null x), der Wert beträgt 256 + 1, also 257
Da Octal mit einer führenden Null gekennzeichnet wird, kann man sich schnell eine Falle bauen, wenn man eine Zahl <100 dreistellig im Sketch einträgt, so müsste eine 080 zu einem Fehler führen, da es im Octalen keine 8 gibt - vll. ist der Compiler aber auch so schlau, hier dann im Dezimalen (also unser Zahlensystem) zu rechnen und eine 80 draus zu machen - kA (bisher habe ich das Octale aber auch echt nicht gebraucht, wenn, dann für Sonderzeichen auf einem LCD)
Jetzt bitte keine Sprüche - wenn Wer weiß, was der Compiler zu 080 sagt, reicht eine einfache Antwort.
postmaster-ino:
vll. ist der Compiler aber auch so schlau, hier dann im Dezimalen (also unser Zahlensystem) zu rechnen und eine 80 draus zu machen - kA
Warum sollte er versuchen "schlau" zu sein - gerade das wäre doch dumm.
Es ist definiert, dass 080 oktal ist, also sollte der Compiler es auch so behandeln, genau wie 0x80 Hex ist.
Merke: Wenn Rechner anfangen mitdenken zu wollen, kommt Schrott raus.
Außerdem sitzt das Problem generell vorm Monitor.
Hä ?
Ich bin sicher, dass 080 nicht oktal ist. Genausuwenig wie 0xyz eine Hexadezimalzahl ist.
AFFE könnte eventuell eine Hex-Zahl sein.
Als C-Literal müsste man sie allerdings 0xAFFE schreiben, um mal was zu schreiben auf das wir uns einigen können
Ein Variablenname kann nicht mit einer Ziffer anfangen.
Aber das geht:
unsigned long irgendeineVariable = 0x12345;
irgendeineVariable = 74565; // dies ist unnötig, da sich der Wert nicht ändert.
irsend.sendSony(irgendeineVariable, 32);
Schonmal in Windows den Taschenrechner auf "Programmierer-Modus" gestellt und ein bisschen rumgespielt?
So einfach wäre es gewesen. Aus irgend einem Grund bin ich davon ausgegangen das 0x mitgesendet wird und auf der Empfängerseite sagt wie mit der Zahl umgegangen wird.
Ich möchte mich bei allen bedanken die mir hier geholfen haben und entschuldige mich für mein Unwissen.