/**
- "Inspector Morse" Puzzle
- In this puzzle, messages can be sent through the serial connection to an Arduino.
- When received, letters and numbers in the message are encoded into dashes and dots of
- the Morse code alphabet, and transmitted by turning an output pin HIGH or LOW.
- The output pin can be used to flash a light, sound a buzzer, or activate a relay to
- control and other device which can signal the message.
- Demonstrates:
-
- Reading incoming data on Arduino serial connection
*/
- Reading incoming data on Arduino serial connection
// CONSTANTS
// This pin will be driven HIGH or LOW according to the Morse pattern transmitted.
const byte outPin = 13;
const byte piezoPin = 8;
// Defines the duration of one "dot" (in ms)
// Duration of 1 dash = 3 intervals
// Gap between dots/dashes in a single character = 1 interval
// Gap between characters in a single word = 3 intervals
// Gap between words = 7 intervals
const int interval = 200;
// Array of the dot/dash pattern for every letter in the alphabet
const char* morseLetters[] = {
//A B C D E F G H I J K L M
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
//N O P Q R S T U V W X Y Z
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."
};
// Array of dot/dash pattern for digits 0-9
const char* morseDigits[] = {
// 0 1 2 3 4 5 6 7 8 9
"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."
};
// One-time setup when the program first starts, or when Arduino is reset
void setup() {
// Initialise the serial connection
Serial.begin(9600);
// Define the pinmode of the pin used to transmit the Morse signal
pinMode(outPin, OUTPUT);
pinMode(piezoPin, OUTPUT);
digitalWrite(outPin, LOW);
}
void loop() {
// If there's data to process that has arrived via the serial connection
if (Serial.available() > 0) {
// Read the integer value of the first byte of data.
// Text is encoded as integer values according to ASCII codes as documented at
// https://www.arduino.cc/en/Reference/ASCIIchart
int c = (int)Serial.read();
// Print the character currently being sent
Serial.print((char)c);
// Variable to hold the pattern of dots/dashes for this letter
char* patternForLetter;
// lowercase characters a-z are stored as integer values 97-122
if(c>96 && c<123){
patternForLetter = morseLetters[c-97];
Serial.print(patternForLetter);
sendMorseCode(patternForLetter);
}
// UPPERCASE LETTER A-Z are stored as integer values 65-90
else if(c>64 && c<91){
patternForLetter = morseLetters[c-65];
Serial.print(patternForLetter);
sendMorseCode(patternForLetter);
}
// Digits 0-9 are stored as integer values 48-57
else if(c>47 && c<58){
patternForLetter = morseDigits[c-48];
Serial.print(patternForLetter);
sendMorseCode(patternForLetter);
}
// Space is integer value 32
else if(c == 32) {
Serial.print(" ");
// The gap between words in a morse code message lasts a total of seven units.
// One unit gap is added at the end of each dot/dash token automatically.
// Another two unit gap is added at the end of each letter/number.
// So, to get to total of 7 we need to add 4 more units' delay
morseOff(4);
}
}
}
/**
- Transmit a sequence of Morse code tokens that form a single character
*/
void sendMorseCode (char tokens[]) {
for (int i=0; i<strlen(tokens); i++) {
switch (tokens[i]) {
case '.':
morseOn(1);
morseOff(1);
break;
case '-':
morseOn(3);
morseOff(1);
break;
}
}
// After each character sent we need a total of 3 beats off, so add another 2.
morseOff(2);
}
/**
- Toggle the output ON for a given number of "beats"
*/
void morseOn (int duration) {
digitalWrite(outPin, HIGH);
tone(piezoPin, 1000, duration * interval);
delay(duration * interval);
}
/**
- Toggle the output OFF for a given number of "beats"
*/
void morseOff (int duration) {
digitalWrite(outPin, LOW);
noTone(piezoPin);
delay(duration * interval);
}