Schräg-, Bindestriche und Punkte "lesen" in Seriellerkommunikation

Hallo
Ich versuche momentan ein Programm zuschreiben, dass Morsecode übersetzen, ausgeben, und verstehen kann. Das Übersetzen habe ich schon erledigt und will als nächstes den übersetzten Morsecode mit einer LED und/oder einem Summer ausgeben. Jetzt könnte ich natürlich mir eine Riesenarbeit machen und jeden Buchstaben zu programmieren wie die LED blinken soll, aber ich habe ja schon den jeden Buchstaben für das Übersetzen definiert, nur sind das halt eben Schräg-, Bindestriche und Punkte. Kann ich dem Programm sagen, dass es jedes Zeichen "lesen" soll und dann die Dauer des Summens oder Leuchtens so definieren?

int incomingByte;
byte outgoingByte;
int morseArrayAlphabetPos;
int morseArrayNumbersPos;
String morseArrayAlphabet[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
String morseArrayNumbers[] = {"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."};
void setup() {

  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (incomingByte>=97) {
      morseArrayAlphabetPos = (incomingByte - 97);
      Serial.print (morseArrayAlphabet[morseArrayAlphabetPos]);
      Serial.print ("/");
    }
    else if (incomingByte>=48) {
      morseArrayNumbersPos = (incomingByte - 48);
      Serial.print (morseArrayNumbers[morseArrayNumbersPos]);
      Serial.print ("/");
    }
    else if (incomingByte == 32){
      Serial.print ("  /");
    }
    else if (incomingByte == 10) {
      Serial.println ();
    }
  
  }

}

Kann ich dem Programm sagen, dass es jedes Zeichen "lesen" soll und dann die Dauer des Summens oder Leuchtens so definieren?

Ob du das kannst, kann ich dir nicht genau sagen.
Aber vom Prinzip her, sollte da kein (wirkliches) Problem bestehen.

Welche Sorgen plagen dich?

Ja, ich meine wie ich das mache.
Ich finde nicht heraus wie ich die Striche und Punkte, die ich zum PC schicke, lesen kann damit ich dann nur programmieren muss wenn es ein Punkt ist soll es kurz leuchten bei einem Stroch lang.

iteriere in einer schleife durch die Positionen deines

morseArrayAlphabet[morseArrayAlphabetPos]

und dann tüte kurz oder lang abhängig von - oder .

SleepingSumo:
Ja, ich meine wie ich das mache.
Ich finde nicht heraus wie ich die Striche und Punkte, die ich zum PC schicke, lesen kann damit ich dann nur programmieren muss wenn es ein Punkt ist soll es kurz leuchten bei einem Stroch lang.

Der PC soll also leuchten?
Bei einem Punkt, kurz, und bei einem Strich lang.

combie:
Der PC soll also leuchten?
Bei einem Punkt, kurz, und bei einem Strich lang.

Eine LED die an den Arduino Angeschlossen ist.

Vorweg: Stelle Dein Programm im ersten Posting in code-Tags. Dann wird der Code in einer Festbreitenschrift dargestellt und ist scrollbar. Du kannst das auch nachträglich tun.

SleepingSumo:
Ja, ich meine wie ich das mache.
Ich finde nicht heraus wie ich die Striche und Punkte, die ich zum PC schicke, lesen kann damit ich dann nur programmieren muss wenn es ein Punkt ist soll es kurz leuchten bei einem Stroch lang.

Du hast die Zeichen ja schon in Strings festgelegt. Du musst nur das, was da drin steht, auslesen und entsprechend eine LED schalten. Wie die Zeichen in den Strings stehen, weißt Du wohl. Also liest Du den Morsecode eines Zeichens aus und schaltest die LED bei einem Punkt nur kurz, bei einem Strich lang ein.

Da Du mehrdimensionale Arrays hast, sieht der Zugriff etwas anders aus als evtl. gewohnt.

zeichen=morseArrayAlphabet[5].charAt(1);

Damit wird die Variable zeichen zu dem, was in Zeichen 5 an Stelle 1 steht. Ich hoffe, dass das so stimmt. Mit derlei String-Arrays hatte ich noch nicht (oder kaum) zu tun. Wenn, dann müsste ich erst suchen.

Gruß

Gregor

SleepingSumo:
Eine LED die an den Arduino Angeschlossen ist.

Gut!

Und, was hindert dich daran, das so zu tun?

Ich behaupte, du möchtest, eine Ablaufsteuerung bauen.

Ablaufsteuerung
Meine Standardantwort zu Ablaufsteuerungen:

Eine Stichworte Sammlung für Google Suchen:
Endlicher Automat,
State Machine,
Multitasking,
Coroutinen,
Ablaufsteuerung,
Schrittkette,
BlinkWithoutDelay,

Blink Without Delay
Der Wachmann

Multitasking Macros
Intervall Macro

Welche Schrägstriche?

Vieleicht solltest Du ein 2-dimensionales Array verwenden statt eines Arrays von strings.

Dann einfach den innhalt des Arrays an der gesuchten Position mir "-" bzw "." vergleichen.

Grüße Uwe

Musst außerdem noch die Länge jedes MorseArray - Strings wissen und dir überlegen, ob dein Programm für die Dauer der Blink-Sequenz nichts anderes zu machen braucht.

Damit du eine Idee kriegst, dass Zeichenarrays in C / C++ einfacher sind als Arduino String Objekte:

const byte OUT=LED_BUILTIN;
const uint16_t KURZ=200;  // . 
const uint16_t LANG=600;  // -
const uint16_t PAUSE = 400; // Zeichen-Ende

void blinkMorse(const char* sequenz) {
 while (true) {
   char c = *sequenz++;
   switch (c) {
   case 0: delay(PAUSE); return;  // sequenz abgearbeitet
   case '.': blink(KURZ); break;
   case '-': blink(LANG); break;
   default: break; // falsche Zeichen ignorieren  
   }
  }
}
void blink(uint16_t dauer) {
  digitalWrite(OUT, HIGH); 
  delay(dauer);
  digitalWrite(OUT, LOW);
  delay(KURZ);
}

von agmue getestet

Dann erweiterst du dein

    Serial.print (morseArrayAlphabet[morseArrayAlphabetPos]);

zu

     const char* morseText = morseArrayAlphabet[morseArrayAlphabetPos].c_str();
      Serial.print(morseText);
      blinkMorse(morseText);

Auch wenn der Hinweis "Ablaufsteuerung" immer richtig ist, hilft er manchmal nicht viel :wink:
Morsen dauert nun mal seine Zeit, da sind auch delay() Aufrufe ok, finde ich.

michael_x:
Auch wenn der Hinweis "Ablaufsteuerung" immer richtig ist, hilft er manchmal nicht viel :wink:
Morsen dauert nun mal seine Zeit, da sind auch delay() Aufrufe ok, finde ich.

Da bin ich aber jetzt schwer geschockt!

Wie auch immer man die Bedeutungen der Worte umdefinieren will, ein wenig Übereinstimmung muss erhalten bleiben, damit eine erfolgreiche Kommunikation geführt werden kann.

An dieser Stelle möchte ich betonen, dass ein Morseautomat, eine Ablaufsteuerung ist, bzw, einer solchen bedarf.

Niemand hat gesagt, dass hier kein Delay verwendet werden darf.
Zumindest ich nicht.
Und schaut man sich die endlichen Automaten bei Wikipedia an, ist da weit und breit nichts von Zeit zu sehen.
Zeitabhandlung und endlicher Automat, kommen oft zusammen vor, sind aber nicht das gleiche.

Wobei ich mir aber sicher bin, ist, dass DIESER Morse Automat eine Zeitabhandlung brauchen wird.
Welche der drei verschiedenen/üblichen Zeit Verfahren man hier realisiert, ist mir egal.

Also, ich hab das von gregorss ausprobiert und das hat mir schon weitergeholfen, und ich bekomme jetzt die zugehörige Nummern ausgespuckt im Serial Monitor, aber komischer weise 2 mal. Hat jemand eine Idee an was das liegen könnte?

int incomingByte;
byte outgoingByte;
int zeichen;
int zeichenAnzahl;
int zeichenPos = 0;
int morseArrayAlphabetPos;
int morseArrayNumbersPos;
String morseArrayAlphabet[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
String morseArrayNumbers[] = {"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."};
void setup() {

  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (incomingByte >= 97) {
      morseArrayAlphabetPos = (incomingByte - 97);
      Serial.print (morseArrayAlphabet[morseArrayAlphabetPos]);
      Serial.print ("/");
    }
    else if (incomingByte >= 48) {
      morseArrayNumbersPos = (incomingByte - 48);
      Serial.print (morseArrayNumbers[morseArrayNumbersPos]);
      Serial.print ("/");
    }
    else if (incomingByte == 32) {
      Serial.print ("  /");
    }
    else if (incomingByte == 10) {
      Serial.println ();
    }
    zeichenAnzahl = morseArrayAlphabet[morseArrayAlphabetPos].length();
    for (zeichenPos = 0; zeichenPos <= zeichenAnzahl - 1; zeichenPos ++) {
      zeichen = morseArrayAlphabet[morseArrayAlphabetPos].charAt(zeichenPos);
      delay (100);
      
      Serial.println (zeichen);
    }
    if (zeichenPos = zeichenAnzahl - 1) {
      zeichenPos = 0;
    }


  }
}

Da bin ich aber jetzt schwer geschockt!

Oh, das wollte ich nicht.

Lies die zwei Sätze, die du zitiert hast, getrennt voneinander.
Beim Thema "delay" waren wir sowieso einer Meinung.

Beim Thema "Ablaufsteuerung" war meine Meinung, dass man sicher die Sequenz

  • LED an
  • eine Zeit warten
  • LED aus
  • eine andere Zeit warten
    als FiniteStateMachine sehen kann. Wie alles andere auch.

Aber wenn man dieses Denkmodell nicht immer im Kopf hat, kriegt man die Aufgabenstellung auch prima gelöst.

Smileys lass ich diesmal weg, helfen eh nicht.


@SleepingSumo:
morseArrayAlphabetPos wird manchmal verwendet, wenn es nicht mehr aktuell ist.
Weil es nur bei Buchstaben >= 'a' gesetzt wird.

@michael_x
Was würdest du vorschlagen?

michael_x:
ungetestet

Da fehlt ein Semikolon bei default und eine Schleife für mehrere Morsezeichen eines Buchstabens in blinkMorse.

Wahrscheinlich möchtest Du, der TO findest das :wink:

Wahrscheinlich möchtest Du, der TO findest das

Das wäre optimal, aber auch schön, dass du es wenigstens aufmerksam angeschaut und offensichtlich verstanden hast.
Danke


@SleepingSumo:
Ich würde dafür eine Funktion schreiben, die einen String als Parameter kriegt ( "..-." ) und in einer Schleife die enthaltenen Zeichen

  • als Testausgabe ausgibt (wie in deinem Beispiel)
  • die LED entsprechend kurz oder lang leuchten lässt. (was du eigentlich willst)

Alles über globale Variable zu machen, finde ich nicht so optimal.

michael_x:
... und offensichtlich verstanden hast.

Klappt leider nicht immer, aber ich gebe mir Mühe :slight_smile:

Mein PC sendet nachdem letzten Blinken vom LED, also am ende dieses Prozesses aus irgendeinem Grund nochmal etwas an den Arduino, und dadurch wird dann " if (Serial.available() > 0) {" wahr gemacht weil etwas im buffer ist, aber ich kann mir nicht erklären warum oder was der Pc schickt

Dann lass es Dir doch einfach mal ausgeben. Danach kannst Du besser nach der Quelle suchen.

Gruß Tommy

Der PC schickt nicht grundlos irgendwann irgendwas an den Arduino.

Auch passiert das vermutlich nicht erst nach dem letzten Blinken der LED, sondern bereits vorher.
Die serielle Schnittstelle hat einen Puffer, den Du Zeichen für Zeichen ausliest.

Dass ein Zeilenumbruch aus zwei Zeichen (CarriageReturn [13] & Linefeed [10]) besteht, ist Dir bekannt? :slight_smile: