Skip to content

Instantly share code, notes, and snippets.

@flybd5
Last active July 1, 2024 21:14
Show Gist options
  • Save flybd5/27fd8bfbf66f409ad3150b6a8d1a6765 to your computer and use it in GitHub Desktop.
Save flybd5/27fd8bfbf66f409ad3150b6a8d1a6765 to your computer and use it in GitHub Desktop.
#include "BluetoothSerial.h"
// This code will implement a International Morse Code keyer using bluetooth.
// The code implements all international morse code characters except the digraph 'ch'
// which was deprecated some time ago from the Spanish language.
// It requires an Arduino device and a 5v relay (can be mechanical or solid state).
// I used an ESP32 DevBoard and a simple 5v relay.
// The relay is powered from the Arduino, and the trigger comes from one of the pio pins
// (26 is the default). On the relay you connect the NO and center contacts to a 1/4" or 1/8" male plug
// (depending which one your radio uses) and connect that to the CW key jack on your radio. That's it.
// Written by Juan Jimenez, K1CPR/AE, June 2023
// Released to the public domain. Use as you wish but please give credit.
const int relay_pin = 26; // Change to the PIO pin you use to trigger the relay
const int dotTime = 50; // Time for a dot, dashes are always 3x this value
// const int pin = "0000" // Uncomment if using a pin for pairing. See below.
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
Serial.setTimeout(1000);
pinMode(relay_pin, OUTPUT);
SerialBT.begin("JJCWKeyBT"); //Bluetooth device name
Serial.printf("\"JJCWKeyBT\" is started, pair it with Bluetooth!");
// If you want to use a pin code for pairing, uncomment and set the pin code.
// #ifdef USE_PIN
// SerialBT.setPin(pin);
// Serial.println("Using PIN");
// #endif
}
// For dot and dash the relay is activated to close, triggering the key on your radio
// Spacing between letters same as a dash.
void space(){
delay(dotTime*3);
}
// Spacing between words is 7x the dot time
void wordSpace(){
delay(dotTime*7);
}
void dot(){
digitalWrite(relay_pin, HIGH);
delay(dotTime);
digitalWrite(relay_pin, LOW);
delay(dotTime);
}
void dash(){
digitalWrite(relay_pin, HIGH);
delay(dotTime*3);
digitalWrite(relay_pin, LOW);
delay(dotTime);
}
void symbol(char theSymbol){
if (isAlpha(theSymbol)){
switch(toupper(theSymbol)){
case 'A':
dot(); dash();
break;
case 'B':
dash(); dot(); dot(); dot();
break;
case 'C':
dash(); dot(); dash(); dot();
break;
case 'D':
dash(); dot(); dot();
break;
case 'E':
dot();
break;
case 'F':
dot(); dot(); dash(); dot;
break;
case 'G':
dash(); dash(); dot();
break;
case 'H':
dot(); dot(); dot(); dot();
break;
case 'I':
dot(); dot();
break;
case 'J':
dot(); dash(); dash(); dash();
break;
case 'K':
dash(); dot(); dash();
break;
case 'L':
dot(); dash(); dot(); dot();
break;
case 'M':
dash(); dash();
break;
case 'N':
dash(); dot();
break;
case 'O':
dash(); dash(); dash();
break;
case 'P':
dot(); dash(); dash(); dot();
break;
case 'Q':
dash(); dash(); dot(); dash();
break;
case 'R':
dot(); dash(); dot();
break;
case 'S':
dot(); dot(); dot();
break;
case 'T':
dash();
break;
case 'U':
dot(); dot(); dash();
break;
case 'V':
dot(); dot(); dot(); dash();
break;
case 'W':
dot(); dash(); dash();
break;
case 'X':
dash(); dot(); dot(); dash();
break;
case 'Y':
dash(); dot(); dash(); dash();
break;
case 'Z':
dash(); dash(); dot(); dot();
default:
// Do nothing
break;
}
} else if(isdigit(theSymbol)){
switch(theSymbol){
case '1':
dot(); dash(); dash(); dash(); dash();
break;
case '2':
dot(); dot(); dash(); dash(); dash();
break;
case '3':
dot(); dot(); dot(); dash(); dash();
break;
case '4':
dot(); dot(); dot(); dot(); dash();
break;
case '5':
dot(); dot(); dot(); dot(); dot();
break;
case '6':
dash(); dot(); dot(); dot(); dot();
break;
case '7':
dash(); dash(); dot(); dot(); dot();
break;
case '8':
dash(); dash(); dash(); dot(); dot();
break;
case '9':
dash(); dash(); dash(); dash(); dot();
break;
case '0':
dash(); dash(); dash(); dash(); dash();
break;
default:
// Do nothing
break;
}
} else switch(theSymbol){
case '.':
dot(); dash(); dot(); dash(); dot(); dash();
break;
case ',':
dash(); dash(); dot(); dot(); dash(); dash();
break;
case '?':
dot(); dot(); dash(); dash(); dot(); dot();
break;
case '\'':
dot(); dash(); dash(); dash(); dash(); dot();
break;
case '!':
dash(); dot(); dash(); dot(); dash(); dash();
break;
case '/':
dash(); dot(); dot(); dash(); dot();
break;
case '(':
dash(); dot(); dash(); dash(); dot();
break;
case ')':
dash(); dot(); dash(); dash(); dot(); dash();
break;
case '&':
dot(); dash(); dot(); dot(); dot();
break;
case ':':
dash(); dash(); dash(); dot(); dot(); dot();
break;
case ';':
dash(); dot(); dash(); dot(); dash(); dot();
break;
case '=':
dash(); dot(); dot(); dot(); dash();
break;
case '+':
dot(); dash(); dot(); dash(); dot();
break;
case '-':
dash(); dot(); dot(); dot(); dot(); dash();
break;
case '_':
dot(); dot(); dash(); dash(); dot(); dash();
break;
case '"':
dot(); dash(); dot(); dot(); dash(); dot();
break;
case '$':
dot(); dot(); dot(); dash(); dot(); dot(); dash();
break;
case '@':
dot(); dash(); dash(); dot(); dash(); dot();
break;
// Don't forget the non-latin symbols
case 'Ä':
case 'ä':
dot(); dash(); dot(); dash();
break;
case 'À':
case 'à':
dot(); dash(); dash(); dot(); dash();
break;
case 'Ç':
case 'ç':
dash(); dot(); dash(); dot(); dot();
break;
// Special case, digraph ch, not implemented due to no input code possible
case 'Ð':
dot(); dot(); dash(); dash(); dot();
break;
case 'È':
case 'è':
dot(); dash(); dot(); dot(); dash();
break;
case 'É':
case 'é':
dot(); dot(); dash(); dot(); dot();
break;
case 'Ĝ':
case 'ĝ':
dash(); dash(); dot(); dash(); dot();
break;
case 'Ĵ':
case 'ĵ':
dot(); dash(); dash(); dash(); dot();
break;
case 'Ñ':
case 'ñ':
dash(); dash(); dot(); dash(); dash();
break;
case 'Ö':
case 'ö':
dash(); dash(); dash(); dot();
break;
case 'Š':
case 'š':
dot(); dot(); dot(); dash(); dot();
break;
case 'þ':
dot(); dash(); dash(); dot(); dot();
break;
case 'Ü':
case 'ü':
dot(); dot(); dash(); dash();
break;
default:
// Do nothing
break;
}
space();
}
void loop() {
Serial.println("Enter data:");
while (Serial.available() == 0) {} // Wait for data available
String aString = Serial.readString(); // Read until timeout
aString.trim(); // remove any \r \n or whitespace at the end of the string
if (aString.length()>0) {
Serial.println("Sending: "+aString);
for (int i = 0; i < aString.length(); i++) {
symbol(aString.charAt(i));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment