Vordefinierten Code aus beliebiger Zahlenreihenfolge erkennen

Hallo zusammen!

Eine Frage: Nehmen wir an, ich erhalte per Serial eine wilde HEX Zahlenfolge. Ich müsste aber, sobald ich eine bestimmte Kombination erhalte - z.B. 73 74 61 74 75 73 - eine Aktion ausführen... z.B. eine grüne LED leuchten lassen.

Wenn ich aber jetzt einen anderen vordefinierten Code erhalte, muss z.B. eine rot LED leuchten. Das ganze müsste dann für 5 vordefinierte Codes funktionieren. und der Rest der HEX Zahlen die daherkommen, sollte ignoriert werden.

Könnt ihr mir kurz auf die Sprünge helfen?

Gruss!

Vielleicht mit verschachtelten if oder case Anweisungen???

Habe ich auch dran gedacht. Aber wie kann ich eine ganze Zahlenreihenfolge testen? Da müsste ich die doch in ein Array schreiben?! Das Problem wäre dann aber, dass ja irgendwelche Zahlen daher kommen. Das Array wird sich dann nicht mit genau der Zahlenkombination füllen, die ich brauche. Ich steh da irgendwie auf dem Schlauch..

Nehen wir mal an Du hast die Soll-Zahlenfolgen in mehreren Arrays. und die Länge von allen ist gleich.

Sobald das erste Byte aus der Seriellen Schnittstelle ankommt vergleichst Du es mit dem ersten Element der Soll-Zahlenfolgen. Falls es richtig ist erhöhst Du einen Zähler falls nicht lädst Du den zähler mit null. Dann kontrollierst das 2. empfangene Byte mit dem ersten oder nten. Element (je nach Zählerstand) Wenn der Zählerstand gleich lang wie die Soll-Zahlenfolge ist dann startest Du deine Aktion. Grüße Uwe

ProtonX:
sobald ich eine bestimmte Kombination erhalte - z.B. 73 74 61 74 75 73 - eine Aktion ausführen…
Das ganze müsste dann für 5 vordefinierte Codes funktionieren.

Vielleicht was in der Richtung:

char command0[] = "status";
char command1[] = "zwei";
char command2[] = "drei";
char command3[] = "vier";
char command4[] = "fuenf";
char *commands[] = {command0, command1, command2, command3, command4};
int whichOne = -1;
int posCount = 0;

void setup() {
  // ...
}

void loop() {
  if (Serial.available() > 0) {
    int input = Serial.read();
    if (posCount==0) {
      for (int t=0; t<5; t++) { // Zuerst bestimmen um welchen Befehl es sich handeln koennte
        if (commands[t][0] == input) {
          whichOne = t; // Achtung: Befehle MUESSEN mit unterschiedlichen Buchstaben beginnen!
          posCount++;
        }
      }
    } else if (commands[whichOne][posCount] == input) {
      posCount++;
    } else if (commands[whichOne][posCount] == '\0') { // Am Ende jedes Befehls steht automatisch eine 0
      befehlAusfuehren(whichOne); // Uebergibt eine int zwischen 0 und 4. "0" steht fuer "status"...
      whichOne = -1;
      posCount = 0;
    } else { // Reset bei unerwartetem Zeichen...
      whichOne = -1;
      posCount = 0;
    }
  }
}

void befehlAusfuehren(int befehl) {
  // ...
}

So oder so ähnlich, konnte es nicht testen…

Wow! Das hilft mir sehr viel weiter. Vielen Dank für deine Mühe!

Leider musste ich feststellen, dass manchmal der gleiche Anfangsbuchstabe kommt. Aber ich bin mir sicher dass du mit folgenden Infos etwas anfangen kannst:
Die eingehenden Signale kommen von einem TV, der bei einer änderung gleich per RS-232 die Änderung herausgibt.

So sieht es aus wenn ich den TV einschalte, Mute, unmute, die Lautstärke ändere, und wieder ausschalte:
status tv off pipoff recoff<\r><\n>>data mute 1<\r><\n>>data mute 0<\r><\n>>data volume 40<\r><\n>>status standby off pipoff recoff<\r>
Was hier als <\r><\n>> dargestellt wird ist nach jedem eingehenden Befehl jeweils ein CR-LF und dann noch ein > hintendran. Vielleicht kann man so die eingehenden Befehle besser abgrenzen…?!

Die Aktionen die dann schliesslich ausgeführt werden, steuern ein Homecinema (Dieses hat aber eine andere RS-232 “Sprache”).
Das heisst, wenn ich den TV mute, muss das Homecinema auch muten. Wenn ich das Volume auf 40 stelle, muss das Homecinema auch auf Vol 40 gehen.

Vielen Dank für eure Hilfe! Ein tolles Forum hier!

Alles klar, damit sieht die Sache ganz anders aus. :wink:

Wenn Du das Gerät frisch einschaltest, fängt das dann wirklich mit “status” an oder ist dann das erste Zeichen ein “>”?

Mit fällt bei solchen Fragen immer erst mal das hier ein: http://www.arduino.cc/playground/Code/Messenger

Klingt doch genau nach dem was er braucht. :)

Hallo,

ProtonX: Die Aktionen die dann schliesslich ausgeführt werden, steuern ein Homecinema (Dieses hat aber eine andere RS-232 "Sprache"). Das heisst, wenn ich den TV mute, muss das Homecinema auch muten. Wenn ich das Volume auf 40 stelle, muss das Homecinema auch auf Vol 40 gehen.

Vielen Dank für eure Hilfe! Ein tolles Forum hier!

wenn ich Dich richtig verstehe, sollen mit einem Tastendruck der Fernbedienung 2 Geräte gesteuert werden. Du möchtest die Befehle mit dem Arduino interpretieren und geändert weiterleiten.

Hast Du mal über eine lernbare Fernbedienung nachgedacht ? Es gibt welche, die pro Taste soviel Speicherplatz haben, dass man 2 Tasten von unterschiedlichen Fernbedienungen anlernen kann. Ich habe so etwas im Einsatz und es funktioniert bestens.

Gruss Kurti

Leider, leider wird da kein > am Anfang gesendet. Immer nur am Schluss. Aber man kann davon ausgehen dass der erste Befehl (der ja nur bei der Inbetriebnahme vorkommt.)
immer “status tv off pipoff recoff<\r><\n>>” ist.
Hab deinen Link kurz überflogen. Habs aber noch nicht gecheckt. Muss mir das am Wochenende mal genauer anschauen.

@ kurti,
Es geht darum, dass ich meine sauteure LOEWE Fernbedienung verwenden möchte. Diese sendet per IR an den Loewe TV (Interne Lautsprecher sind deaktiviert).
Mittels den Statusinfos, die der Loewe ausspuckt soll dann ein Bose AV-35 gesteuert werden. (Die FB beim Bose ist per Bluetooth, was die Loewe FB nicht kann.)
Eigentlich ist die Loewe Fernbedienung ja für Drittgeräte programmierbar. Diese kann aber leider nicht alle Funktionen meiner Loewe FB aufnehmen.

Das Arduino soll dabei eine günstigere, abgespeckte Version eines AMX, Crestron oder RTI Controllers übernehmen :slight_smile:

Gruss!

OK. Hab die Messenger library mal probiert.

ich kann nun mit “on” die LED einschalten und mit “off” wieder ausschalten. Das lässt sich theoretisch wunderbar für meine Zwecke umschreiben.
ABER:
Wenn ich etwas anderes sende, wie z.B. “hallo” stürzt das ganze ab und ich muss das Arduino resetten.

Könnte man da bei der if-Schlaufe nicht irgendwie machen, dass alle nichtdefinierten Befehle ignoriert werden?
Mein Code sieht im Moment so aus:

#include <Messenger.h>

// Instantiate Messenger object with the message function and the default separator
// (the space character)
Messenger message = Messenger();

// Define messenger function
void messageCompleted()
{
// This loop will echo each element of the message separately
while ( message.available() )
{
if ( message.checkString(“on”) )
{
digitalWrite(13,HIGH);
}
else if ( message.checkString(“off”) )
{
digitalWrite(13,LOW);
}
else if ( message.checkString(“blink”) )
{
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
}
}
}

void setup() {
// Initiate Serial Communication
Serial.begin(115200);
message.attach(messageCompleted);

pinMode(13,OUTPUT);

}

void loop() {

// The following line is the most effective way of
// feeding the serial data to Messenger
while ( Serial.available() ) message.process( Serial.read() );

}

UP

Kann mir da niemand helfen? Sooo ein kleiner Schritt noch zum funktionierenden Projekt... :)

Ich habe ja selber keine Ahnung aber ich habe trotzdem eine Lösung. Allerdings musst du etwas in der Librari verändern!

in der Messenger.h gibts folgende Zeile: void reset(); Diese steht unter private Verschiebe diese Zeile in public: Sollte dann so aussehen:

public:
 Messenger();
  Messenger(char separator);
  int readInt();
  long readLong(); // Added based on a suggestion by G. Paolo Sani
  char readChar();
  double readDouble(); // Added based on a suggestion by Lorenzo C.
  void copyString(char *string, uint8_t size);
  uint8_t checkString(char *string);
  uint8_t process(int serialByte);
  uint8_t available();
  void attach(messengerCallbackFunction newFunction);
  void reset();
  
private:
  void init(char separator);
  uint8_t next();

Abspeichern.

Dann in deinen Code ein weiteres else machen mit dem reset. Sieht dann so aus:

if ( message.checkString("on") ) 
        {
        digitalWrite(13,HIGH);
        } 
    else if ( message.checkString("off") ) 
        {
        digitalWrite(13,LOW);         
        }
    else if ( message.checkString("blink") ) 
        {
        digitalWrite(13,HIGH);
        delay(500);
        digitalWrite(13,LOW);
        delay(500);        
        digitalWrite(13,HIGH); 
        delay(500); 
        digitalWrite(13,LOW);        
        }
     else 
        {
         message.reset();  
        }

Bei mir scheint es zu funktionieren!

Keine Garantie blablabla :)

Danke für deinen Tipp! Das funktionierte auch bei mir im Test hervorragend.

Die Daten die ich erhalte sehen so aus:
data mute 1 /und danach immer/ CR LF >

oder dann z.B.

cmd Power tv CR LF >

Da wäre es wohl das sinnvollste, wenn ich den “separator” vom Messenger auf das letzte Zeichen “>” ändern würde. Oder?
Kann ich das dann so machen oder geht das nicht weil CR LF nicht verarbeitet wird?:

#include <Messenger.h>

// Instantiate Messenger object with the message function and the default separator
// (the space character)
Messenger message = Messenger(’>’); // Separator wurde zu > geändert ?!

// Define messenger function
void messageCompleted()
{
// This loop will echo each element of the message separately
while ( message.available() )

if ( message.checkString(“data mute 1”) )
{
digitalWrite(13,HIGH);
}
else if ( message.checkString(“data mute 0”) )
{
digitalWrite(13,LOW);
}
else if ( message.checkString(“blink”) )
{
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
}
else
{
message.reset();
}
}

void setup() {
// Initiate Serial Communication
Serial.begin(9600);
message.attach(messageCompleted);

pinMode(13,OUTPUT);

}

void loop() {

// The following line is the most effective way of
// feeding the serial data to Messenger
while ( Serial.available() ) message.process( Serial.read() );

}

Gruss Proton

Das kann ich Dir leider nicht sagen! Ich bin eher ein try and error Typ. Da ich keine Quelle da habe kann ich nicht genau testen was kommt. Probier es einfach aus :)

Funktioniert leider noch nicht.

Wie schreib ich denn den CR und den LF in ASCII hin?
In DEC wäre dass ja 13 und 10… Aber ich darf ja beim Messenger als eingehende Daten nur ASCII verwenden.

Wenn ich mit meinem Terminal “HTerm” nachschaue was anstelle vom CR und vom LF ankommt, sind es in ASCII zwei ganz komische Zeichen. :~

Gruss Proton!

'\r' und '\n'

Thx!

Ich hatte kontakt zum programmierer der messenger library. Dieser sagte mir, dass das > am Schluss das Problem ist. Die library erwartet zum Schluss ein CR-LF.

Hat jemand eine andere Idee? Wäre wirklich super wenn ichs langsam hibekommen würde :S

Dann verklicker der Library eben dass ein ggf. vorhandenes ">" an einem Befehl vorne stehen kann.

Wenn CR/LF für die Library das Ende des Befehls ist ist die folgende ">" eben der Anfang des nächsten Kommandos. ;)