Seriellen Befehl (HEX) ohne Stop-Bit / LED´s schalten

Hallo Zusammen,

ich hatet mal dank eurer Hilfe vor Jahren eine Programm, welches engehende seriele Commands in eine Schaltung von LED´s umwandelte. Das war für mich auch völlig okay. Doch jetzt habe ich ein anderes Problem. Ich möchte nun etwas auswerten, was keinen Stop-Bit besitzt. Leider komme ich hier bei meiner aktuellen Vorlage nicht mehr weiter. Die Daten sind immer in gleicher Länge. Es geht rein um seriell zu Digital Out. Kann mir hier jemand nochmal freundlicher Weise helfen?

01 0F 00 00 00 04 01 01 FF 56 -> Ausgang 3
01 0F 00 00 00 04 01 02 BF 57 -> Ausgang 4

Ich würde mich freuen, wenn mir hier jemand helfen könnte.

Hier noch ein kleiner Auszug meines alten Programms für den Mega:

int out1 = 22;
int out2 = 24;
int out3 = 26;

const byte messages[][13] PROGMEM =
{
  { 0x30, 0x0A, 0x20, 0x0A, 0x25, 0x0A, 0x2E, 0x0A, 0x20, 0x37, 0x0A, 0x21, 0x37 },
  { 0x30, 0x0A, 0x20, 0x0A, 0x25, 0x0A, 0x2E, 0x0A, 0x20, 0x37, 0x0A, 0x20, 0x24 },
  { 0x30, 0x0A, 0x20, 0x0A, 0x25, 0x0A, 0x2E, 0x0A, 0x20, 0x38, 0x0A, 0x23, 0x91 },

};

const int MESSAGE_LENGTH = sizeof(messages[0]) / sizeof(messages[0][0]);
const int MESSAGE_COUNT = sizeof(messages) / MESSAGE_LENGTH;

const byte START_BYTE = 0x02 ;
const byte END_BYTE =  0x03;

byte inputData[MESSAGE_LENGTH];  


void setup() {
  Serial.begin(19200);

  pinMode(out1,OUTPUT);
  pinMode(out2,OUTPUT);
  pinMode(out3,OUTPUT);

}


void loop() {

  if (readSerial(Serial) == true)
  {
    Serial.print(F("read: "));
    for (unsigned int i = 0; i < MESSAGE_LENGTH; i++)
    {
      Serial.print(inputData[i], HEX); Serial.print(',');
    }
    Serial.print(F(" --- "));

    bool match = false;

    for (unsigned int i = 0; i < MESSAGE_COUNT; i++)
    {
      if (memcmp_P(inputData, messages[i], MESSAGE_LENGTH) == 0)
      {
        Serial.print(F("match found: ")); Serial.println(i);
        
        if ((i) == 0)
        {digitalWrite(out1, HIGH);}
        
        if ((i) == 1)
        {digitalWrite(out1, LOW);}

        if ((i) == 2)
        {digitalWrite(out2, HIGH);}


      
        match = true;

        break;
      }

      
    }


    
    if (!match)
      Serial.println(F("no match"));
  }


}




bool readSerial(Stream& stream)
{
  static byte index;
  static bool start;

  while (stream.available())
  {
    byte data = stream.read();

    if (!start && data == START_BYTE)
    {
      start = true;
      memset(inputData, 0, sizeof(inputData));
    }
    else if (start && data == END_BYTE)
    {
      index = 0;
      start = false;
      return true;
    }
    else if (start && index < MESSAGE_LENGTH)
    {
      inputData[index++] = data;
    }
  }

  return false;
}

, was keinen Stop-Bit besitzt.

Nee, oder?
Wer macht denn sowas?

Dann bisste auf jeden Fall, mit "Serial" auf einem faschen Dampfer.

Das hab ich schon zweimal bei verschiedenen Geräten gehabt. Ich hoffe jetzt allerdings nur, dass der Serial Port Monitor auch wirklich alles anzeigt. (Oder kennt jemand zufällig ein Programm, welches wirklich ungefiltert den HEX anzeigt?

Du sprichst in Rätseln!

Schaffe dir einen LogikAnalyser an, dann siehste was auf den Kabeln los ist.

Es geht um ein Programm, welches an eine HW Schaltbefehle sendet. diese HW ist Kabelgebunden und ich möchte nun diese Befehle auswerten um dann via LoRa anderweitige Befehle zu senden. Im Grunde ist das drum herum ja nicht wichtig. Ich habe nur keine Ahnung, wie ich die oben erwähnten Zeilen sicher ausweren kann, da ich hier kein Stop Bit habe (sofern mir das Com Analyseprogramm mir nicht genau Start und Stop Bit verheimlicht)

inhalt entfernt, schien mir zu grob zu sein

frannek:
Das hab ich schon zweimal bei verschiedenen Geräten gehabt. Ich hoffe jetzt allerdings nur, dass der Serial Port Monitor auch wirklich alles anzeigt. (Oder kennt jemand zufällig ein Programm, welches wirklich ungefiltert den HEX anzeigt?

(Deswegen steht hier auch die Frage, ob jemand ein Prog kennt, was wirklich alles anzeigt)
Dann könnte ich dies zumindest mal rausfinden. Wenn Start und Stopbit da sind, dann wäre es ja kein Problem. Und von welcher Hardware soll ich denn sprechen bzw was geheim halten? Es ist eine Software die Befehle an ein DCon 7060D Modul sendet, um dort drei Relais anziehen zu lassen. Diese "Funtion" soll nun der Arduino übernehmen. Die Software sendet:

01 0F 00 00 00 04 01 01 FF 56 -> Relais 1 schalten
01 0F 00 00 00 04 01 02 BF 57 -> Relais 2 schalten
[...]

Wenn ich diese ausgelesenen Bytes in das Programm "Serial Port Monitor" eingebe und eben als HEX sende, schaltet das Dcon Modul auch wunderbar.

Die Software sendet:

01 0F 00 00 00 04 01 01 FF 56 -> Relais 1 schalten
01 0F 00 00 00 04 01 02 BF 57 -> Relais 2 schalten
[...]

Wenn ich diese ausgelesenen Bytes in das Programm "Serial Port Monitor" eingebe und eben als HEX sende, schaltet das Dcon Modul auch wunderbar.

Und was genau ist jetzt das Problem? Das mit dem fehlenden "Stopbit" war sicher nur um uns zu verwirren. :wink:

Was ist die Hardware-Schnittstelle zwischen diesem "Serial Port Monitor" und deinem "Dcon Modul" ?
Ein 9 poliger Stecker ( COM1: an einem alten PC ?)

Die Software gibt den Befehl über Com1 aus - Nullmodemkabel - Laptop mit Com und "Serial Port Monitor".
Und am Com 1 des sendenden PC ist eben normal das "Dcon" Modul angeschlossen.

Mit Start- und Stop-Bits hast du im Code gar nichts zu tun. Das erledigt die Hardware automatisch, je nachdem was du bei begin() angibst:

"Kein Stop-Bit" gibt es aber nicht

DCon 7060D Modul

Ein RS485 Industrie Standard Protokoll.
Laut Spezifikation 8,N,1

Also bist du mit deinen Start- und Stoppbits völlig auf dem falschen Dampfer!
Du buddelst auf der falschen Baustelle, siehe: "Der Blaumilchkanal"

NATÜRLICH werden Start- und Stoppbits gesendet und müssen auch empfangen werden.
Und ebenso natürlich musst du dich, bis auf eine einmalige Initialisierung, nicht drum kümmern.

Ich glaube unser TO hat etwas Probleme mit der Terminologie und weis nicht wirklich, was Start- und Stop Bit ist ( als Anwender muss man sich da ja auch nicht drum kümmern ).

Ich denke, es geht eher darum, dass seine Befehlsfolgen keine eindeutiges Endezeichen ( so wie z.B. CR/LF ) haben.

Hi

Hauptsache, Er bekommt Antwort, wenn Er Das als HEX sendet ...
Kleiner Hinweis: Schaue Dir die Signale auf der Leitung wirklich Mal an.
Dann sendest Du
0b10101010 (binär oder auch dual genannt, führendes Null Beh)
0x99 (Hexadeziamal, führendes Null Iks)
153 (Dezimal)
0252 (Octal, führende Null)

Du wirst feststellen, daß auf der Leitung überall das Gleiche passiert (sofern ich mich nicht verrechnet habe).
Da der Computer nur Null und Eins kennt, was soll Da auch sonst kommen, außer dual/binär?
Einzig, ob HIGH eine Eins, oder eine Null ist ... aber darum kümmert sich das Protokoll.

MfG

Schönen guten Morgen und danke für die Rückmeldungen.

Ich hab nochmal etwas geschaut und dachte, ich hätte die Lösung für mich. Es handelt sich um Modbus RTU wobei im Coil ein single Coil (Function 0x05 / Write single coil) geschrieben wird. Alles soweit schön und gut. Mit einem Testprogramm für Modbus funktioniert es soweit auch halbwegs (single coil wird in der aktuellen Bibliothek nicht unterstützt, aber das werd ich schon irgendwo finden). Jetzt kommt aber scheinbar mein größeres Problem. Ich hatte eigentlich vor, den Arduino via USB an den "Server" anzuschließen. Ansich keine größere Sache - nur das sendende Programm nutzt die parität Even. Und das scheint wohl bei nem Arduino Uno doch ein etwas größeres Problem zu sein, oder?
Ich bin jetzt etwas leicht verwirrt, was die Informationsflut in den letzten beiden Tagen angeht (Foren, google etc.).
Natürlich ist so eine Modbus Library jetzt eine angenehme Sache aber das wäre ja mit Kanonen nach Spatzen schießen. Ich möchte ja wirklich nur drei bzw vier verschiedene Befehle auf der seriellen Leitung (also gesendet via USB) auswerten. Und ja.. .Bits Und bytes bringen mich schon ein wenig durcheinander :slight_smile:

Wie , denkst du, könntest du mit einem Arduino RS485 über eine COM Schnittstelle behandeln?

Da ist wohl ein -+ 15V Pegel im Spiel, ein Arduino kaan aber nur TTL-Pegel (0/5V), oder einen virtuellen COM Port über USB, was aber wohl nicht zu deinem "DCon" Modul passt.

Hast du den erforderlichen MAXIM transceiver-chip richtig angeschlossen ?

maxim:
Maxim offers over 160 RS-485/RS-422 transceivers

frannek:
Oder kennt jemand zufällig ein Programm, welches wirklich ungefiltert den HEX anzeigt?

Dafür gibt es doch einen Arduino, hier einen Mega2560. Die auszuwertenden Daten fließen nach Rx1:

uint16_t j = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("Empfangene Werte in Hex:");
  Serial1.begin(9600);
}

void loop() {
  if (Serial1.available() > 0)
  {
    byte wert = Serial1.read();
    if (wert < 16)
    {
      Serial.print('0');
    }
    Serial.print(wert, HEX);
    if (j++ % 10)
    {
      Serial.print(' ');
    } else {
      Serial.println();
    }
  }
}

Wenn der sendende UNO Werte zwischen 0 und 255 überträgt, so sieht ein Ausschnitt der Ausgabe so aus:

F8 F9 FA FB FC FD FE FF 00 01
02 03 04 05 06 07 08 09 0A 0B
0C 0D 0E 0F 10 11 12 13 14 15
16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29
2A 2B 2C 2D 2E 2F 30 31 32 33

Der Zeilenumbruch nach zehn Zeichen dient nur der besseren Lesbarkeit.

Nun kannst Du eine vollständige Liste der gesendeten Codes erstellen. Bitte Baudrate anpassen.

Wenn Du die Codes hast, machst Du Mustererkennung:

int out1 = 13;

const byte messages[][10] PROGMEM =
{
  { 0x01, 0x0F, 0x00, 0x00, 0x00, 0x04, 0x01, 0x01, 0xFF, 0x56 },
  { 0x01, 0x0F, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0xBF, 0x57 }
};

const int MESSAGE_LENGTH = sizeof(messages[0]) / sizeof(messages[0][0]);
const int MESSAGE_COUNT = sizeof(messages) / MESSAGE_LENGTH;
byte inputData[MESSAGE_LENGTH];

void setup() {
  Serial.begin(9600);
  Serial.println(F("\nEmpfangene Werte in Hex:"));
  Serial1.begin(9600);
  pinMode(out1, OUTPUT);
}

void loop()
{
  if (Serial1.available() > 0)
  {
    byte wert = Serial1.read();
    if (wert < 16)
    {
      Serial.print('0');
    }
    Serial.print(wert, HEX);
    Serial.print(' ');
    for (byte j = 0; j < MESSAGE_LENGTH - 1; j++)
    {
      inputData[j] = inputData[j + 1];
    }
    inputData[MESSAGE_LENGTH - 1] = wert;
    for (byte i = 0; i < MESSAGE_COUNT; i++)
    {
      if (memcmp_P(inputData, messages[i], MESSAGE_LENGTH) == 0)
      {
        Serial.print(F("\nTreffer: ")); Serial.println(i);
        switch (i)
        {
          case 0:
            digitalWrite(out1, HIGH);
            break;
          case 1:
            digitalWrite(out1, LOW);
            break;
        }
      }
    }
  }
}

nur das sendende Programm nutzt die parität Even. Und das scheint wohl bei nem Arduino Uno doch ein etwas größeres Problem zu sein, oder?

Lese die Doku!!!

Parameters

speed: in bits per second (baud) - long
config: sets data, parity, and stop bits. Valid values are :

SERIAL_5N1
SERIAL_6N1
SERIAL_7N1
SERIAL_8N1 (the default)
SERIAL_5N2
SERIAL_6N2
SERIAL_7N2
SERIAL_8N2
SERIAL_5E1
SERIAL_6E1
SERIAL_7E1
SERIAL_8E1
SERIAL_5E2
SERIAL_6E2
SERIAL_7E2
SERIAL_8E2
SERIAL_5O1
SERIAL_6O1
SERIAL_7O1
SERIAL_8O1
SERIAL_5O2
SERIAL_6O2
SERIAL_7O2
SERIAL_8O2

Aus: Serial.begin() - Arduino Reference

Und jetzt, sage mir nochmal, welches Problem du mit gerader Parität gerne hättest...?

Danke für die Antworten.

Nun, die Doku hatte ich ja gelesen und genau auch diese Config zur Parität eingestellt. Hat nicht funktioniert (Hatte ein Modbus Slave prog drauf gemacht und diese Einstellung angepasst) Ich hatte It SERIAL_8E1 geflast aber dennoch nahm er nur 8N1. Dann ein wenig rumgelesen, wieso dem so ist und dann tauchten so Dinge auf, dass der Uno keine andere Parität via USB kann.
Ich möchte der Einfachkeit halber das habze über USB anschließen - also kein externer MAX485.

Zur Auswertung @agmue. Das mache ich doch dann besser mit dem Arduino Mega, oder? Wen nich mich recht erinnere, hat dieser zwei HW Serials, oder? Also lese ich mit dem einen Serial die gesendeten Daten aus und gebe diese über USB ans terminal weiter, richtig?

aus Zeitgründen hatte ich jetzt vorübergehend über das Dikon ausgegebene Schaltkontakte auf die Arduino Inputs gelegt. Ist eine hässliche Strickerei aber jetzt hab ich neue Ansatzpunkte. Vielen lieben Dank für die Geduld mit mir :slight_smile:

dann tauchten so Dinge auf, dass der Uno keine andere Parität via USB kann

falsch

frannek:
Zur Auswertung @agmue. Das mache ich doch dann besser mit dem Arduino Mega, oder? Wen nich mich recht erinnere, hat dieser zwei HW Serials, oder? Also lese ich mit dem einen Serial die gesendeten Daten aus und gebe diese über USB ans terminal weiter, richtig?

Er hat gleich vier dieser Schnittstellen, weshalb ich ihn für dieses Testprogramm ausgewählt habe.

Den gibt es als Mega 2560 PRO MINI als kleinere Alternative zum Löten.