My friend Dan thought it would be good to control his Christmas lights with an Arduino, so perhaps I'd better the get the Arduino to convert text to morse so he can flash out Christmas greetings - to neighbouring radio hams at least.
Reading Mark VandeWettering's article on a morse decoder, I really liked his way of encoding the morse codes, with a terminal 1 . So I've borrowed his encodings and algorithm. However his table contains characters and their codes which is searched iteratively. I'm just interested in letters and numbers so I can store just the codes in a small array and index into it with the ASCII value of the character suitably offset.
Going from XQuery to C-style programming leads to the usual trip-ups with syntax. I forget to type variables. I also forget that underneath this is just C with unprotected array accesses so I'm puzzled by funny lights when I overrun the end of the message. My main difficulty though is testing an algorithm. I need to find out how to debug code or at least send a message back to the IDE.
[Oh I see - I have to initialise the Serial connector first - Serial.begin(9600); then I can send data like Serial.print(ch) to echo each character as its decoded. It comes on on the Serial monitor. Neat.]
Apart from a typo in copying the codes, I also made an off-by one error which caused an array overrun. I blamed the switch from 1-based arrays in XQuery to 0-based arrays in C but in fact the problem was the the terminal string character. Anyway, I much prefer 1-based arrays now, I'm sure they are less error-prone. I wonder how many mega-hours have been lost through 0-based arrays.
Here is the Arduino code. Uppercase characters and numbers only in the message. Uploaded it takes 1388 bytes out of the available 32K. I know it's a commonplace remark for an old timer like me, but that memory (and processor) bought for £25 quid has about the same main memory as the Eliott 503 I worked on in New Zealand - the size of a room and only 8K 39bit words.
const int d = 300;
const int led = 13;
int morseChars[] = {
63,62,60,56,48,32,33,35,
39,47, 1, 1, 1, 1, 1,76,
1, 6,17,21, 9, 2,20,11,
16, 4,30,13,18, 7, 5,15,
22,27,10, 8, 3,12,24,14,
25,29,19, 1, 1, 1, 1, 1
};
char message[]="BRISTOL";
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
send-message(message);
delay(3000);
}
void send_message(message) {
for (int i=0;i < sizeof(message) - 1; i = i + 1) {
char ch = message[i];
int ascii = int(ch);
if (ascii == 32) {
word_space();
} else {
int code = morseChars [ascii - 48 ];
send(code);
letter_space();
}
}
}
void send_char(int code) {
while (code != 1) {
if (code & 1)
dash() ;
else
dot() ;
code = code / 2 ;
}
}
void dot () {
digitalWrite(led, HIGH);
delay(d);
digitalWrite(led, LOW);
delay(d);
}
void dash () {
digitalWrite(led, HIGH);
delay(3*d);
digitalWrite(led, LOW);
delay(d);
}
void letter_space () {
delay(3*d);
}
void word_space () {
delay(7*d);
}
So now I have a replacement (sort of ) for the Cabot Tower light. Just need to make it switch a few hundred watts.