Probleme bei auswertung eines Seriellen Befehls

Hallo Zusammen,
leider steh ich gerade absolut auf dem schlauch und brauche eure hilfe.
Ich bekomme von einem externen System über die Serielle Schnitstelle einen Befehl, die wie folgt aufgebaut ist: S124T oder S124F
Hierbei ist “S” ein Startbyte, die folgende Nummer sagt welches bistabile Ralais gesteuert werden soll und T/F steht für an oder aus. Nun habe ich das problem, dass ich den Int wert nicht direkt auf die dazugehörigen Ausgangsports mit:

      int iVal;  // 0-124
      digitalWrite(led0Pin, (iVal &        B1)); // -------X Decimal value 1
      digitalWrite(led1Pin, (iVal &       B10)); // ------X- Decimal value 2
      digitalWrite(led2Pin, (iVal &      B100)); // -----X-- Decimal value 4
      digitalWrite(led3Pin, (iVal &     B1000)); // ----X--- Decimal value 8
      digitalWrite(led4Pin, (iVal &    B10000)); // ---X---- Decimal value 16
      digitalWrite(led5Pin, (iVal &   B100000)); // --X----- Decimal value 32
      digitalWrite(led6Pin, (iVal &  B1000000)); // -X------ Decimal value 64
      digitalWrite(led7Pin, (iVal & B10000000)); // X------- Decimal value 128

schreiben kann, sondern aus dem int wert einen Zustand für an oder aus definieren muss.

Bespiel:
Wenn ich “S1T” bekomme, soll dass binär 00000000 darstellen und wenn “S1F” dann 00000001.
Wenn ich “S2T” bekomme, soll dass binär 00000010 darstellen und wenn “S2F” dann 00000011.

Ich hoffe ihr könnt mir weiterhelfen.

P.S. Hintergrundinfo, es werden ein Komperator und ein MUX damit angesteuert.

Hallo,

da mußte uns schon mehr vom Code zeigen. Wie sieht denn Deine serielle Einlesefunktions aus? Oder gleich den gesamten Code in Codetags oder die .ino Datei anhängen.

Hallo Doc_arduino,
das ist der vollständige Programm.

int led0Pin = 10;
int led1Pin = 11;
int led2Pin = 12;
int led3Pin = 13;
int led4Pin = 6;
int led5Pin = 7;
int led6Pin = 8;
int led7Pin = 9;

int relais;
 
void setup()
{
   //Set up each of the pins for output only.
   pinMode(led0Pin, OUTPUT);
   pinMode(led1Pin, OUTPUT);
   pinMode(led2Pin, OUTPUT);
   pinMode(led3Pin, OUTPUT);
   pinMode(led4Pin, OUTPUT);
   pinMode(led5Pin, OUTPUT);
   pinMode(led6Pin, OUTPUT);
   pinMode(led7Pin, OUTPUT);
}
 
  
void loop() {
  readSerial(); // Aufruf der Auswertung
}
    
void readSerial() {
      if(Serial.available() > 0) {
        while (Serial.peek() == 'S') { // Start-Tag
          Serial.read();               // S (Start) vom Serial-Buffer löschen
          relais = Serial.parseInt();    // ElektrodenNummer-Information lesen
          mode = Serial.read();        // D bzw. A vom Serial-Buffer löschen
          if(mode == 'T')
          {
            an();   // Bisatbiles Relais einschalten
          }
          if(mode == 'F')
          {
            aus();   // Bisatbiles Relais ausschalten
          }
        }
        while (Serial.available() > 0){ // Buffer löschen
          Serial.read();
        }
      } 
    }
}

void an(int relais)
{
  byte iVal=relais;
  int reset=255;
      digitalWrite(led0Pin, (iVal &        B1)); // -------X Decimal value 1
      digitalWrite(led1Pin, (iVal &       B10)); // ------X- Decimal value 2
      digitalWrite(led2Pin, (iVal &      B100)); // -----X-- Decimal value 4
      digitalWrite(led3Pin, (iVal &     B1000)); // ----X--- Decimal value 8
      digitalWrite(led4Pin, (iVal &    B10000)); // ---X---- Decimal value 16
      digitalWrite(led5Pin, (iVal &   B100000)); // --X----- Decimal value 32
      digitalWrite(led6Pin, (iVal &  B1000000)); // -X------ Decimal value 64
      digitalWrite(led7Pin, (iVal & B10000000)); // X------- Decimal value 128
      delay(6);
      digitalWrite(led0Pin, (reset &        B1)); // -------X Decimal value 1
      digitalWrite(led1Pin, (reset &       B10)); // ------X- Decimal value 2
      digitalWrite(led2Pin, (reset &      B100)); // -----X-- Decimal value 4
      digitalWrite(led3Pin, (reset &     B1000)); // ----X--- Decimal value 8
      digitalWrite(led4Pin, (reset &    B10000)); // ---X---- Decimal value 16
      digitalWrite(led5Pin, (reset &   B100000)); // --X----- Decimal value 32
      digitalWrite(led6Pin, (reset &  B1000000)); // -X------ Decimal value 64
      digitalWrite(led7Pin, (reset & B10000000)); // X------- Decimal value 128
}

Hessing_Pictures: Bespiel: Wenn ich "S1T" bekomme, soll dass binär 00000000 darstellen und wenn "S1F" dann 00000001. Wenn ich "S2T" bekomme, soll dass binär 00000010 darstellen und wenn "S2F" dann 00000011.

Bist du sicher, dass diese beiden Beispiele richtig sind?

Macht der Code schon irgendwas sinnvolles?

Serial.begin?

Hallo ELEspanol, ach upps in der version fhlt logischerweise der Setup teil mit

void setup() {
  Serial.begin(115200);
  pinMode(led0Pin, OUTPUT);
   pinMode(led1Pin, OUTPUT);
   pinMode(led2Pin, OUTPUT);
   pinMode(led3Pin, OUTPUT);
   pinMode(led4Pin, OUTPUT);
   pinMode(led5Pin, OUTPUT);
   pinMode(led6Pin, OUTPUT);
   pinMode(led7Pin, OUTPUT);
}

ja an sich funktioniert der code. Das einzigste Probleme liegt darin, wie ich meinen int wert so überprüfe, dass ich die folgende Tabelle benutzen kann.

Befehl Ralais Zustand an Zustand aus 1 00000000 00000000 00000001 2 00000001 00000010 00000011 3 00000010 00000100 00000101 4 00000011 00000110 00000111 5 00000100 00001000 00001001 6 00000101 00001010 00001011 7 00000111 00001100 00001101 8 00001000 00001010 00001111 9 00000001 00001100 00010001 ...

da ich insgesamt 8 ausgangspins habe, kann ich 128 bistabile Ralais steuern, da ich mit 4 bit einen den enable Eingang eines bestimmten Multiplexers über einen 4Bit-Komperator ansteuere. der MUX kann dann seinerseits 8 bilstabile Ralais steuern (16 Signale)

ich muss gestehen, dass ich die Logik der Geschichte noch nicht verstanden habe.

Kannst du etwas mehr den Aufbau beschreiben? Was verstehst du unter bistabile Relais? Stromstossrelais? Oder eben normale, die 2 (bi) Zustände kennen, sprich Spule schließt die Kontakte solange Strom anliegt.

Was genau soll vom Sketch getan konkret werden, wenn z. B "S14T" reinkommt danach S5T und dann S14F?

ich frag nur so dumm, weil für dich vielleicht vieles klar ist, für Assenstehende aber nicht so.

Hallo ElEspanol, ich nutze ein bistabiles Relai um einen Stromkreis zu schließen. Der vorteil eines bistabilen Relais im gegensatz zum normalen, besteht darin, dass es den aktuellen Zustand speichern kann und nicht durchgängig mit strom versorgt werden muss.

Zum schließen des Stromkreises muss ein HIGH-Impuls von 6ms gesendet werden. Durch einen Multiplexer kann ich die anzahl der digitalen Ausgänge vergrößern, da ich pro Relais zwei Ausgänge benötige.

die verwendeten Bauteile sind: Komperator: SN5485 Multiplexer: CD74HCT4067 Relais:Panasonic TQ2-L2-5V

Ansich ist aber die Schaltung die letztendlich angesteuert werden soll unerheblich, daes primär nu um die Konvertierung des Zahlenformates geht.

Das Serielle Signal ist wie folgt aufgebaut. S15T S //Mit dem Char soll ein eindeutiges Startsignal geliefert werden. 1 // Nummer des gewollten Relais T/F // Zustand des Relais T=an F=aus

Mein problem besteht darin, das ein Relais zwei Signalleitungen hat, weshalb ich nicht einfach die binärdarstellung benutzen kann um die Ausgänge 6-13 zu schlten.

Das ist schon sehr kompliziert irgendwie. Wenn du anstatt den bistabilen Relais Stromstoßschalter/relais hättest bräuchtest du nur die Hälfte deiner Ausgänge und deine Ansteuerung wäre auch einfacher. Ich weiß nur nicht ob es die auch auf 5V Basis gibt.

Wenn ich das richtig verstehe hast du den Ausgang zum einschalten des Relais direkt neben dem Ausgang zum ausschalten. Wenn du den Einschaltvorgang und den Ausschaltvorgang komplett von einander trennst wird es dann nicht einfacher? Z.b. Ausgang 0-5 schalten Relais 1-6 ein und Ausgang 6-12 schaltet die Relais wieder aus. So kannst du mit 2 getrennten Ausgangsworten arbeiten und müsstest nur dein Einschaltwort invertieren.

Gruß

Heho. Einfacher kommst du wenn du statt der integer zählen und dem F/T direckt die Bytes sendest. Also folgender maßen. "S[Byte für Relais Nummer][ Byte für zustand] Irgendwie glauben alle das man mit seriellen Verbindungen nur lesbare ASCII Zeichen senden kann, aber das ist ein Irrtum. Die Zeichen sind ja auch nur Bytes. Also kannst du sie auch direkt versenden. Dann Muster du nichts konvertieren, vergleichen oder Mappen sondern nimmst einfach das Byte und Reichst es durch.

Das geht so nicht, da ja die Daten von einem externen System kommen.

Das mit den Relais ist jetzt etwas klarer. Stromstossrelais gehen nicht, weil wenn 2 mal hintereinander "aus" kommt, würde dieses ja wieder einschalten.

Ich muss mir das nochmal durch den Kopf gehen lassen.

Aber meine Tendenz: Nimm ein mehrdimensionales Array, aus dem du dein jeweiliges Bitmuster holst, das du auf die Ausgänge legst. Also Spaltet für F und T, und für jedes mögliche Relais eine Zeile mit dem Bitmuster.

Hallo,

lass Dir mal am Ende der Einlesefunktion den Inhalt der Variable relais ausgeben und mode. Da steht bestimmt Müll drin.

Vermutung. Die Variable mode ist nirgends definiert. Bekommst Du keinen Compilerfehler? Vermutlich wird sie als int defaultmäßig angelegt, deshalb funktioniert der Stringvergleich nicht. Definiere mode als char und teste.

Nochwas. relais ist bei Dir eine globale Variable, die Du später aber an eine Funktion übergibts. Kannste Dir sparen.

void readSerial() {
      if(Serial.available() > 0) {
        while (Serial.peek() == 'S') { // Start-Tag
          Serial.read();               // S (Start) vom Serial-Buffer löschen
          relais = Serial.parseInt();    // ElektrodenNummer-Information lesen
          mode = Serial.read();        // D bzw. A vom Serial-Buffer löschen
          if(mode == 'T')
          {
            an();   // Bisatbiles Relais einschalten
          }
          if(mode == 'F')
          {
            aus();   // Bisatbiles Relais ausschalten
          }
        }
        while (Serial.available() > 0){ // Buffer löschen
          Serial.read();
        }
      } 
    }
}

Hallo,

hab's mir nochmal genauer angeschaut. Fakt ist, Du hast den geposteten Code nie im Leben auch nur einmal getestet. Sonst hättest Du schon über Compilerfehler stolpern müssen. Das ist nicht die feine Art.

Hab es mal dahingehend geändert das es überhaupt erstmal funktioniert. Eine gewisse Auswertung der Startkennung erfolgt am Anfang. Damit hat man etwas Übertragungssicherheit. Die Endeerkennung müßte noch rein. Dazu müßte man aber wissen ob und welche Endeerkennung wirklich geschickt wird und ob überhaupt eine existiert.

Warum die serielle Kontrollausgabe 2x ausgegeben wird, weis ich allerdings selbst noch nicht. Vielleicht liegts an der fehlenden Null Termination.

Jedenfalls ohne 'S' Erkennung passiert nichts, erst mit 'S' gehts überhaupt los.

int relais;
char mode;

void setup() {
  Serial.begin(9600);  
}


void loop() {
  readSerial(); // Aufruf der Auswertung
  
}

void readSerial() {
  boolean startRead = false;
  char Kennung = 'Z';        // irgendwas anderes defaultmäßiges
  
      while (Serial.available() > 0) {
        Kennung = Serial.read();
        if ( Kennung == 'S')  {         // Start-Tag Abfrage
          startRead = true;
        }  
        
        if (startRead == true) {  
          relais = Serial.parseInt();    // ElektrodenNummer-Information lesen
          mode = Serial.read();          // Schaltbefehlkennung lesen
          if(mode == 'T')
          {
            Serial.println("Relais ein");   // Bistabiles Relais einschalten
          }
          if(mode == 'F')
          {
            Serial.println("Relais aus");   // Bistabiles Relais ausschalten
          }
          
          // zum testen 
          Serial.print("Serial Inhalt 1: "); Serial.print(relais); Serial.print("  "); Serial.println(mode); 
        }
        
       // zum testen 
       Serial.print("Serial Inhalt 2: "); Serial.print(relais); Serial.print("  "); Serial.println(mode);
         
      } // end while Serial.available 
}  // end function

Hallo Doc_Arduino,
danke für deine Hilfe, hatte leider nicht alles reinkopiert sorry.
Ich habe heute aber endlich eine funktionierende Lösung gefunden.

void konvertierung(int nummer, char zustand)
{
  int komperatort=floor(nummer/8);
  mux=fmod(nummer,8)-1;
  
  if(mux<0)
  {
    mux=7;
    komperatort=komperatort-1;
  }
  komperator=komperatort;
  mux=mux*2;
  if(zustand=='F')
  {
    mux=mux+1;
  }
  Pin=((0xF & komperator) << 4) | (0xF & mux );
}

Schöne Grüße
Björn

Hallo,

naja, aber was soll das jetzt sein? Das hat doch nichts mit dem seriellen einlesen zu tun. Wenn Du nur Bruchstücke postest versteht dich niemand. Die gesamte Anfrage ist für niemanden hilfreich. Der Thread ist im Kern nichts sagend. Wenn Du wieder eine Frage haben solltest, dann mußte das große ganze zur Verfügung stellen, sonst wird das wieder nur so ein Kauderwelsch. Alle anderen außer Du sehen und lesen nur das was da steht und sollen/wollen/möchten irgendwie helfen. Nur so als Hinweis.