Probleme mit Morsecodegenerator

Hi

Ich bastel mir gerade einen einfachen Morsecodegenerater in Arduino.
Da das Morsealphabet keine Groß- oder Kleinschreibung kennt, wollte ich vorher alle eingegebenen Buchstaben mit der Funktion toLowerCase() in Kleinbuchstaben umwandeln lassen und anschließend jedem Buchstaben mit einer switch-case-Anweisung das passende Morsecodezeichen zuweisen.

Mit der toLowerCase()-Funktion komme ich aber überhaupt nicht zurecht. So wie ich das Beispiel verstanden habe, habe ich folgende Anweisung zusammengebastelt:

lowerCaseLetter = incomingByte.toLowerCase();

Diese scheint aber vollkommen falsch zu sein, da die Syntax meiner Anweisung von der Arduino IDE nicht mal hervorgehoben wird.

Wie gehts richtig?

Gruß
Atalanttore

Guckst Du da: http://arduino.cc/en/Tutorial/StringCaseChanges

So habe ich es auch versucht, aber irgendwie funktioniert das bei mir nicht.

Vieleicht zeigst Du uns auch noch den Rest Deines Codes? Was für einen Typ hat incomingByte und was machst Du noch so damit? Woher weisst Du, daß das nicht funktioniert?

Davon abgesehen würde ich die Morsezeichen nicht per Switch auseinandersteuern. Ich würde einfach ein Stringarray nehmen und das Zeichen (abzüglich Offset) als Index. Damit dabei der Speicher noch reicht wird man das wohl mit "progmem" Makros verzieren müssen. Cases wären mir für sowas aber zu nervig.

Als Alternative:
Die Großbuchstaben A-Z sind von 65 bis 90 dezimal und die Kleinbuchstaben a-z von 97 bis 122

Einfach Daten in eine byte-Variable einlesen und kontrollieren ob die eingehenden Zahlen zwischen 65 und 90 sind und dann 32 dezimal addieren.

Du kannst auch im switch schreiben:
...
case "a"
case "A"
morsekode umwandeln
break();
case...

Einfacher ist es Du definierst ein Array und indizierst es mit den Buchstaben

Beispiel dem Morsekode wurde eine führende 1 hinzugefügt um die Länge des Codes zu bestimmen. Eine 1 bedeutet langes Signal, eine 0 ein kurzes. Also 0000 0101 bedeutet kurz - lang
morse[0] = b 0000 0101 // A
morse[1] = b 0001 1000 // B
morse[3] = b 0001 1010 //C
...
dann einfach vom Buchstaben 65 bzw 97 subtrahieren und als index des Arrays verwenden.
Das ist die schnellste und platzsparenste Implementierung.

[Edit] jetzt war Udo schneller.

Grüße Uwe

[quote author=Udo Klein link=topic=64946.msg474120#msg474120 date=1309004968]
Vieleicht zeigst Du uns auch noch den Rest Deines Codes?[/quote]
Gerne, aber mein Programm befindet sich noch in einem recht bescheidenen Zustand. Manche Sachen funktionieren noch nicht so wie geplant.
Hier einmal die aktuelle Fassung:

int ledPin = 13;
int Short = 200; // dit
int Long = 3 * Short; // dah
int wordsPerMinute = 1000;
char incomingByte = 0;


void setup()
{
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("Wie viele Woerter pro Sekunde sollen gemorst werden?");
  wordsPerMinute = Serial.read();
      
}

void blink(int L){
  digitalWrite(ledPin, LOW);
  delay(100);

  digitalWrite(ledPin, HIGH);
  delay(L);
  digitalWrite(ledPin, LOW);
}


void charBlink(char c){

  switch (c) {
  case 'a':
    blink(Short);
    blink(Long);
    return;

  case 'b':
    blink(Long);
    blink(Short);
    blink(Short);
    blink(Short);
    return;

  case 'c':
    blink(Long);
    blink(Short);
    blink(Long);
    blink(Short);
    return;

  case 'd':
    blink(Long);
    blink(Short);
    blink(Short);
    return;

  case 'e':
    blink(Short);

  case 'f':
    blink(Short);
    blink(Short);
    blink(Long);
    blink(Short);
    return;

  case 'g':
    blink(Long);
    blink(Long);
    blink(Short);
    return;

  case 'h':
    blink(Short);
    blink(Short);
    blink(Short);
    blink(Short);
    return;

  case 'i':
    blink(Short);
    blink(Short);
    return;

  case 'j':
    blink(Short);
    blink(Long);
    blink(Long);
    blink(Long);
    return;

  case 'k':
    blink(Long);
    blink(Short);
    blink(Long);
    return;

  case 'l':
    blink(Short);
    blink(Long);
    blink(Short);
    blink(Short);
    return;

  case 'm':
    blink(Long);
    blink(Long);
    return;

  case 'n':
    blink(Long);
    blink(Short);
    return;

  case 'o':
    blink(Long);
    blink(Long);
    blink(Long);
    return;

  case 'p':
    blink(Short);
    blink(Long);
    blink(Long);
    blink(Short);
    return;

  case 'q':
    blink(Long);
    blink(Long);
    blink(Short);
    blink(Long);
    return;

  case 'r':
    blink(Short);
    blink(Long);
    blink(Short);
    return;

  case 's':
    blink(Short);
    blink(Short);
    blink(Short);
    return;

  case 't':
    blink(Long);
    return;

  case 'u':
    blink(Short);
    blink(Short);
    blink(Long);
    return;

  case 'v':
    blink(Short);
    blink(Short);
    blink(Short);
    blink(Long);
    return;

  case 'w':
    blink(Short);
    blink(Long);
    blink(Long);
    return;

  case 'x':
    blink(Long);
    blink(Short);
    blink(Short);
    blink(Long);
    return;

  case 'y':
    blink(Long);
    blink(Short);
    blink(Long);
    blink(Long);
    return;

  case 'z':
    blink(Long);
    blink(Long);
    blink(Short);
    blink(Short);
    return;

  default:
    Serial.print("Sorry, Buchstabe ");
    Serial.print(c);
    Serial.print(" konnte leider nicht ausgegeben werden.");
  }

}


void loop()
{
  // Serielle Daten sind vorhanden
  if (Serial.available() > 1){
  
    // Daten einlesen
    Serial.println("Welcher Buchstabe soll ausgegeben werden?");
    incomingByte = Serial.read();
  
    Serial.print("Empfangen: ");
    Serial.println(incomingByte);

    charBlink(incomingByte);
    Serial.println("Buchstabe ausgegeben");
    delay(500);
  }

}

[quote author=Udo Klein link=topic=64946.msg474120#msg474120 date=1309004968]
Was für einen Typ hat incomingByte und was machst Du noch so damit?[/quote]
incomingByte ist vom Typ char.

Sorry, aber ich verstehe nur Bahnhof.

  1. Ist mit Stringarray ein Array mit Textstrings gemeint?
  2. Was ist eigentlich ein Offset? Die Wikipedia-Beschreibung dazu verstehe ich nicht.
  3. Warum muss ich das Offset vom Zeichen abziehen?
  4. Was meinst du mit Index?
  5. Was macht das Programm "progmem" und warum braucht man dazu Makros?

uwefed:
Als Alternative:
Die Großbuchstaben A-Z sind von 65 bis 90 dezimal und die Kleinbuchstaben a-z von 97 bis 122

Einfach Daten in eine byte-Variable einlesen und kontrollieren ob die eingehenden Zahlen zwischen 65 und 90 sind und dann 32 dezimal addieren.

OK. Meinst du mit "dezimal" das normale Dezimalsystem?

uwefed:
Du kannst auch im switch schreiben:
...
case "a"
case "A"
morsekode umwandeln
break();
case...

Einfacher ist es Du definierst ein Array und indizierst es mit den Buchstaben

Beispiel dem Morsekode wurde eine führende 1 hinzugefügt um die Länge des Codes zu bestimmen. Eine 1 bedeutet langes Signal, eine 0 ein kurzes. Also 0000 0101 bedeutet kurz - lang
morse[0] = b 0000 0101 // A
morse[1] = b 0001 1000 // B
morse[3] = b 0001 1010 //C
...
dann einfach vom Buchstaben 65 bzw 97 subtrahieren und als index des Arrays verwenden.
Das ist die schnellste und platzsparenste Implementierung.

  1. Für was steht das "b" am Anfang des Codes?
  2. Ist mit Index die Zahl in den eckigen Klammern hinter "morse" gemeint?

Gruß
Atalanttore

Hallo Atalanttore
Dir fehlen Grundlagen.

  1. Ist mit Stringarray ein Array mit Textstrings gemeint?
  2. Was ist eigentlich ein Offset? Die Wikipedia-Beschreibung dazu verstehe ich nicht.
  3. Warum muss ich das Offset vom Zeichen abziehen?
  4. Was meinst du mit Index?
  5. Was macht das Programm "progmem" und warum braucht man dazu Makros?
  1. in C im engeren Sinn gibt es keine Strings sondern arrays mit char die zusammen dann einen String ergeben.
  2. Offset ist der Wert nachdem etwas beginnt, der Versatz.
  3. Weil die Zeichen nicht bei null beginnen sondern bei 97 dez.
  4. Index ist bei einem Array die Zahl oder Variable in den eckigen Klammern.
  5. progmem ist kein Programm sondern eine Bibliothek. Mit progmem kann man Variablen, die sich nicht ändern, im Flash Speicher ablegen und so kein RAM dafür verbrauchen. In Deinem Fall die definitionen der Morsecode.

OK. Meinst du mit "dezimal" das normale Dezimalsystem?

Ja.

  1. Für was steht das "b" am Anfang des Codes?
  2. Ist mit Index die Zahl in den eckigen Klammern hinter "morse" gemeint?
  1. b steht für binär, also einer Zahl im Binärformat.
  2. ja

Grüße Uwe

Wenn man länger drüber nachdenkt fällt auf, das wohl kein Morsecode länger als 12 bit ist. Damit könnte man jeden locker in 2 Bytes (uint16_t) verpacken. 4bit um die Länge zu codieren und den Rest für den eigentlichen Code. Damit würde ein uint16_t array reichen. Da es nur sehr wenige Codes gibt kommt man dann vermutlich sogar ohne Progmem aus. Je nachdem wieviel Ram der Rest des Programms braucht.

uwefed:
Einfacher ist es Du definierst ein Array und indizierst es mit den Buchstaben

Beispiel dem Morsekode wurde eine führende 1 hinzugefügt um die Länge des Codes zu bestimmen. Eine 1 bedeutet langes Signal, eine 0 ein kurzes. Also 0000 0101 bedeutet kurz - lang
morse[0] = b 0000 0101 // A
morse[1] = b 0001 1000 // B
morse[3] = b 0001 1010 //C
...

Wie programmiert man, dass der eigentliche Morsecode nach der ersten 1 beginnt und bis zum Ende reicht?

uwefed:
Hallo Atalanttore
Dir fehlen Grundlagen.
(...)
5. progmem ist kein Programm sondern eine Bibliothek. Mit progmem kann man Variablen, die sich nicht ändern, im Flash Speicher ablegen und so kein RAM dafür verbrauchen. In Deinem Fall die definitionen der Morsecode.

Ja, das habe ich soweit verstanden.
Nun zu progmem: Muss ich vor dem Array mit den Morsecodes nur progmem so davorschreiben wie im Beispiel hier oder muss man sonst noch was beachten?

uwefed:

  1. b steht für binär, also einer Zahl im Binärformat.

Was hat es mit dem b auf sich? In den Beispielen zu Arrays finde ich kein vorstehendes Zeichen, dass den Datentyp angibt.

  1. Warum 12 Bit?
    Das ß besteht aus 7 Morsezeichen und länger ist sonst keines.

  2. Ist uint16_t vom Datentyp Integer mit der Länge 16 Bit (2 Byte)?

Gruß
Atalanttore

12bit weil ich keine Ahnung von Morsezeichen habe :wink: Also wenn keins länger als 7 ist, dann würde ich die wie folgt codieren:

Alle führenden Nullen werden ignoriert. Die erste 1 wird nicht ausgegeben sondern zeigt an, daß die folgenden Bits Morsezeichen sein sollen. Danach bedeutet 1 lang und 0 kurz. Also:

0b1 --> Fehler
0b0 --> Fehler
0b101 --> kurz lang
0b11101 --> lang lang kurz lang

Damit reicht dann ein Array von uint8_t

Die Bits holt man bequem per Shift aus dem Byte raus.

Gruß, Udo

Man müsste nur wissen wie das mit dem Shift geht. Ich weiß es nicht ...

Was hat das b in dem Array zu bedeuten?

Gruß
Atalanttore

Das "b" bedeutet daß die nachfolgende Zahl eine Zahl im Binärformat ist; das ist eine Konvention. Gleich wie für eine Hexadezimalzahl 0x.. geschrieben wird.
Grüße Uwe

http://www.google.com/search?client=ubuntu&channel=fs&q=c+shift&ie=utf-8&oe=utf-8