My second Arduino project is about reading morse code. I have a board with a tactile switch which turns a LED on when pressed. An LDR connected to the same board reads the amount of light it receives. When LED is off pin 0 receives analogRead value < 100, when it's on (tactile switch pressed) it's well above it (300-400).
When the LDR is above the 100 treshold (switch is pressed and LED is on) it starts counting the number of milliseconds until the treshold gets below that (switch is released, LED is off). When the number milliseconds is lower than 700 ms, it's a short signal (dit), when it's between 700 and 1200 ms it's a long signal (dah), when it's above 1200 ms it's a space (signaling the start of the next letter).
This is all working fine, and I see that it gets correctly printed to the Serial, but when I want to compare the char array to convert morse (like "LLL") back to a alphabetic letter ("O" in this example) it doesn't work. The evaluation never returns true.
This is my code:
/* Receiving morse code - v0.1 */
int photocellPin = 0; // LDR connected to pin 0
int photocellReading; // the analog reading from LDR
long onmillis = 0; // reset onmillis
long timeon = 0; // reset timeon
void setup(void) {
Serial.begin(9600);
}
char morse[4];
void loop(void) {
photocellReading = analogRead(photocellPin);
if (photocellReading < 100) {
// off (no signal coming in)
if (onmillis > 0) {
// signal was coming in, we just lost it (count time spent and determine whether it's a S, L or space (end of letter))
timeon = millis() - onmillis;
if (timeon <= 700) {
Serial.print("S");
strcat(morse,"S");
} else if (timeon > 700 && timeon <= 1200) {
Serial.print("L");
strcat(morse,"L");
} else { // larger than 1200: space detected, which means the end of this letter
Serial.print(" ");
Serial.print("Full morse code of this letter: _"); Serial.print(morse); Serial.println("_");
Serial.print("Translated from morse to letter: ");
if (morse == "SSS") {
Serial.println("S");
} else if (morse == "LLL") {
Serial.println("O");
} else {
Serial.print("unknown, but morse was: "); Serial.println(morse);
}
}
onmillis = 0;
}
} else {
// on (receiving signal)
if (onmillis == 0) {
// we just started receiving signal
onmillis = millis();
}
}
delay(10); // read every 10 ms.
}
You can't compare two character arrays with '=='. That will compare the address of the first characters of the two strings and since the strainga are at different addresses they will never be 'equal'.
Try using the String object. It understands '==' so you compare character strings. You can also use '+=' for concatenate.
String morse;
void loop(void) {
photocellReading = analogRead(photocellPin);
if (photocellReading < 100) {
// off (no signal coming in)
if (onmillis > 0) {
// signal was coming in, we just lost it (count time spent and determine whether it's a S, L or space (end of letter))
timeon = millis() - onmillis;
if (timeon <= 700) {
Serial.print("S");
morse += "S";
} else if (timeon > 700 && timeon <= 1200) {
Serial.print("L");
morse += "L";
} else { // larger than 1200: space detected, which means the end of this letter
Serial.print(" ");
Serial.print("Full morse code of this letter: _"); Serial.print(morse); Serial.println("_");
Serial.print("Translated from morse to letter: ");
if (morse == "SSS") {
Serial.println("S");
} else if (morse == "LLL") {
Serial.println("O");
} else {
Serial.print("unknown, but morse was: "); Serial.println(morse);
morse = ""; // Important to clear the string so the signals don't just continue to accumulate!
}
}
onmillis = 0;
}
} else {
// on (receiving signal)
if (onmillis == 0) {
// we just started receiving signal
onmillis = millis();
}
}
delay(10); // read every 10 ms.
}
Is there any way to have this functionality when using a char* instead of string? Or should I always use a string when comparing?
How can I put this in an array where the morsecode ("LLL") is the key and the alphabetic letter ('O') is the value? That would be cleaner than having 26 if-else statements I think.
I showed you how in the thread you started for the encoder.
Yes, but that was the other way around. From a letter to morse. Now I want to do the opposite: from morse to letter. Is there a function to get the key for a value? Sorry for the n00b questions, I'm really new to C++.
Morse code can be thought of as Short, Long, and Space to mark End Of Character, a 3-state code.
You could use 2 binary bits to record that, one bit high to mark a tap and the next to mark short/low or long/high.
Last I remember there are no Morse code letters that use more than 4 taps. However with digits and punctuation there can be six, woo-hoo, which would require unsigned int.
Letters only, 'O' would be binary 00111111 where 'S' would be binary 00101010
Translation to ASCII would only require a switch-case statement and be very fast.
My second Arduino project is about reading morse code.
This was my second project with embedded processors as well, but that was back in 1975.
The way I encoded morse was to use a 0 for dot and 1 for dash. Of course that meant you didn't know how long a morse character was so the end of the character was marked with a 1. So an S for example ( three dots ) would show as 00001000, Then all you need to do to convert it into ASCII is to use a lookup table in an array. All morse characters can be encoded in a single byte.
I did automatic speed tracking as well. If I timed a signal and it was greater than the threshold then it was treated as a dash. Then the threshold was set at half what I timed the dash to be. If it was less than the threshold and so a dot I adjusted the threshold to be twice what I timed. In that way the receiver always locked onto any speed signal.