Components and supplies
Gikfun Round Micro Speaker Diameter 30mm 8Ohm 8R 2W for Arduino Mini Box Speakers DIY
Stemedu 2 Sets LoRa32u4ii Lora Development Board Module
Lithium Ion Polymer Battery
Telegraph Key
Resistor 221 ohm
Tools and machines
Soldering iron (generic)
3D Printer (generic)
Project description
Code
Morse code
arduino
-Beeps when button is pressed. -Records timing of button presses. -Sends timing info over LoRa. -Receives and plays message. You'll need the radiohead RF95 library : https://github.com/kenbiba/RH-RF95
1#include"pitches.h" 2#include <RH_RF95.h> 3#define RFM95_CS 8 4#define RFM95_RST 4 5#define RFM95_INT 7 6#define RF95_FREQ 915.0 7RH_RF95 rf95(RFM95_CS, RFM95_INT); 8 9 10const int buttonPin = 11; // the pin that the pushbutton is attached to 11const int tonepin = 12; //the pin that the speaker is attached to 12 13int buttonState = 0; // current state of the button 14int lastButtonState = 0; // previous state of the button 15int startPressed = 0; // the moment the button was pressed 16int endPressed = 0; // the moment the button was released 17int holdTime = 0; // how long the button was hold 18int idleTime = 0; // how long the button was idle 19int idleArray[100]; // array to record button idle times 20int holdArray[100]; // array to record button hold times 21int i; 22int j; 23int k; 24int sendArray[200]; // array to store idle/hold times to be sent 25uint8_t buf[251]; //Lora message buffer 26int recvArray[124]; 27int pressed = 0; 28 29 30void setup() { 31 pinMode(RFM95_RST, OUTPUT); 32 digitalWrite(RFM95_RST, HIGH); 33 34 //Serial.begin(9600); 35 36 // while (!Serial) { 37 // delay(1); 38 // } 39 40 delay(100); 41 digitalWrite(RFM95_RST, LOW); 42 delay(10); 43 digitalWrite(RFM95_RST, HIGH); 44 delay(10); 45 while (!rf95.init()) { 46 //Serial.println("LoRa radio init failed"); 47 SoS(); // beeps SoS if radio fails to start 48 while (1); 49 } 50 if (!rf95.setFrequency(RF95_FREQ)) { 51 //Serial.println("setFrequency failed"); 52 SoS(); 53 while (1); 54 } 55 //Serial.print("Set Freq to: "); Serial.println(RF95_FREQ); 56 57 pinMode(buttonPin, INPUT); // initialize the button pin as a input 58 rf95.setTxPower(23, false); 59 60} 61 62void loop() { 63 buttonState = digitalRead(buttonPin); // read the button input 64 updateState(); 65 /******************************Transmit******************************/ 66 if(idleTime > 5000 && pressed == 1){ //Only transmit if it's been 5 seconds since last button press 67 pressed = 0; //reset button press 68 k = 0; 69 idleArray[0] = 0; //set first delay to zero so the message doesn't start with delay 70 for(i=0;i<124;){ 71 sendArray[i]=idleArray[k]; //Put idle times in even index of sendArray 72 i = i + 1; //indexing sendArray 73 sendArray[i]=holdArray[k]; //Put hold times in odd index of sendArray 74 i = i + 1; 75 k = k + 1; //indexing idle and hold arrays 76 } 77 memcpy(buf,sendArray,sizeof(sendArray)); //copy send array into uint8_t buffer 78 //for(i=0;i<200;i++){ //For debug 79 // Serial.println((int)x[i]); 80 //} 81 rf95.send(buf, sizeof(buf)); // Send buffer 82 rf95.waitPacketSent(); 83 startPressed = millis(); //reset counter 84 memset(idleArray,0,sizeof(idleArray)); //clear arrays 85 memset(holdArray,0,sizeof(holdArray)); 86 i = 0; 87 j = 0; 88 tone(tonepin,NOTE_C6); //play tone to indicate message sent 89 delay(100); 90 noTone(tonepin); 91 } 92 delay(2); 93 if(lastButtonState != buttonState && buttonState == 1){ 94 idleArray[i] = idleTime; //Record button idletime into array 95 //Serial.print(idleArray[i]); 96 //Serial.print(" "); 97 i++; 98 } 99 100 if(lastButtonState != buttonState && buttonState == 0){ 101 holdArray[j] = holdTime; 102 //Serial.println(holdArray[j]); 103 j++; 104 } 105 lastButtonState = buttonState; 106 /******************************Recieve******************************/ 107 if (rf95.available()) 108 { 109 uint8_t len = sizeof(buf); 110 if (rf95.recv(buf, &len)) 111 { 112 /* 113 RH_RF95::printBuffer("Received: ",buf, len); 114 Serial.println(*(int*)buf); 115 Serial.print("RSSI: "); 116 Serial.println(rf95.lastRssi(), DEC); 117 */ 118 memcpy(recvArray,buf,sizeof(buf)); //copy recieved buffer into our reciving array 119 /* 120 for(i = 0; i < 100; i++){ 121 Serial.println(x[i]); 122 Serial.print(idleIn[i]); 123 Serial.print(" "); 124 Serial.println(holdIn[i]); 125 }*/ 126 for(i = 0; i < 124; i++){ //play the message 127 noTone(tonepin); 128 delay(recvArray[i]); 129 tone(tonepin,NOTE_C5); 130 i = i + 1; 131 delay(recvArray[i]); 132 noTone(tonepin); 133 } 134 i = 0; 135 } 136 } 137 138} 139 140void updateState() { 141 if (buttonState == HIGH) { 142 startPressed = millis(); 143 holdTime = startPressed - endPressed; //time button was held down 144 tone(tonepin,NOTE_C5); 145 if(idleTime > 5000){ 146 idleTime = 0; //if button was pressed after more than 5 seconds idle, restart 5 second timer 147 } 148 pressed = 1; //button was pressed 149 } 150 if(buttonState == LOW){ 151 noTone(tonepin); 152 endPressed = millis(); 153 idleTime = endPressed - startPressed; //time button was idle 154 } 155} 156 157void SoS() { //SoS message 158tone(tonepin,NOTE_C5); 159delay(300); 160noTone(tonepin); 161delay(100); 162tone(tonepin,NOTE_C5); 163delay(300); 164noTone(tonepin); 165delay(100); 166tone(tonepin,NOTE_C5); 167delay(300); 168noTone(tonepin); 169delay(300); 170 171tone(tonepin,NOTE_C5); 172delay(100); 173noTone(tonepin); 174delay(100); 175tone(tonepin,NOTE_C5); 176delay(100); 177noTone(tonepin); 178delay(100); 179tone(tonepin,NOTE_C5); 180delay(100); 181noTone(tonepin); 182delay(300); 183 184tone(tonepin,NOTE_C5); 185delay(300); 186noTone(tonepin); 187delay(100); 188tone(tonepin,NOTE_C5); 189delay(300); 190noTone(tonepin); 191delay(100); 192tone(tonepin,NOTE_C5); 193delay(300); 194noTone(tonepin); 195}
Morse code
arduino
-Beeps when button is pressed. -Records timing of button presses. -Sends timing info over LoRa. -Receives and plays message. You'll need the radiohead RF95 library : https://github.com/kenbiba/RH-RF95
1#include"pitches.h" 2#include <RH_RF95.h> 3#define RFM95_CS 8 4#define 5 RFM95_RST 4 6#define RFM95_INT 7 7#define RF95_FREQ 915.0 8RH_RF95 rf95(RFM95_CS, 9 RFM95_INT); 10 11 12const int buttonPin = 11; // the pin that the pushbutton 13 is attached to 14const int tonepin = 12; //the pin that the speaker is attached 15 to 16 17int buttonState = 0; // current state of the button 18int lastButtonState 19 = 0; // previous state of the button 20int startPressed = 0; // the moment the 21 button was pressed 22int endPressed = 0; // the moment the button was released 23int 24 holdTime = 0; // how long the button was hold 25int idleTime = 0; // 26 how long the button was idle 27int idleArray[100]; // array to record button 28 idle times 29int holdArray[100]; // array to record button hold times 30int 31 i; 32int j; 33int k; 34int sendArray[200]; // array to store idle/hold times 35 to be sent 36uint8_t buf[251]; //Lora message buffer 37int recvArray[124]; 38int 39 pressed = 0; 40 41 42void setup() { 43 pinMode(RFM95_RST, OUTPUT); 44 digitalWrite(RFM95_RST, 45 HIGH); 46 47 //Serial.begin(9600); 48 49 // while (!Serial) { 50 // delay(1); 51 52 // } 53 54 delay(100); 55 digitalWrite(RFM95_RST, LOW); 56 delay(10); 57 58 digitalWrite(RFM95_RST, HIGH); 59 delay(10); 60 while (!rf95.init()) { 61 62 //Serial.println("LoRa radio init failed"); 63 SoS(); // beeps SoS if 64 radio fails to start 65 while (1); 66 } 67 if (!rf95.setFrequency(RF95_FREQ)) 68 { 69 //Serial.println("setFrequency failed"); 70 SoS(); 71 while (1); 72 73 } 74 //Serial.print("Set Freq to: "); Serial.println(RF95_FREQ); 75 76 77 pinMode(buttonPin, INPUT); // initialize the button pin as a input 78 rf95.setTxPower(23, 79 false); 80 81} 82 83void loop() { 84 buttonState = digitalRead(buttonPin); 85 // read the button input 86 updateState(); 87 /******************************Transmit******************************/ 88 89 if(idleTime > 5000 && pressed == 1){ //Only transmit if it's been 5 seconds since 90 last button press 91 pressed = 0; //reset button press 92 k = 0; 93 idleArray[0] 94 = 0; //set first delay to zero so the message doesn't start with delay 95 for(i=0;i<124;){ 96 97 sendArray[i]=idleArray[k]; //Put idle times in even index of sendArray 98 99 i = i + 1; //indexing sendArray 100 sendArray[i]=holdArray[k]; //Put 101 hold times in odd index of sendArray 102 i = i + 1; 103 k = k + 1; //indexing 104 idle and hold arrays 105 } 106 memcpy(buf,sendArray,sizeof(sendArray)); 107 //copy send array into uint8_t buffer 108 //for(i=0;i<200;i++){ //For debug 109 110 // Serial.println((int)x[i]); 111 //} 112 rf95.send(buf, sizeof(buf)); 113 // Send buffer 114 rf95.waitPacketSent(); 115 startPressed = millis(); //reset 116 counter 117 memset(idleArray,0,sizeof(idleArray)); //clear arrays 118 memset(holdArray,0,sizeof(holdArray)); 119 120 i = 0; 121 j = 0; 122 tone(tonepin,NOTE_C6); //play tone to indicate 123 message sent 124 delay(100); 125 noTone(tonepin); 126 } 127 delay(2); 128 129 if(lastButtonState != buttonState && buttonState == 1){ 130 idleArray[i] = 131 idleTime; //Record button idletime into array 132 //Serial.print(idleArray[i]); 133 134 //Serial.print(" "); 135 i++; 136 } 137 138 if(lastButtonState != buttonState 139 && buttonState == 0){ 140 holdArray[j] = holdTime; 141 //Serial.println(holdArray[j]); 142 143 j++; 144 } 145 lastButtonState = buttonState; 146 /******************************Recieve******************************/ 147 148 if (rf95.available()) 149 { 150 uint8_t len = sizeof(buf); 151 if (rf95.recv(buf, 152 &len)) 153 { 154 /* 155 RH_RF95::printBuffer("Received: ",buf, len); 156 157 Serial.println(*(int*)buf); 158 Serial.print("RSSI: "); 159 Serial.println(rf95.lastRssi(), 160 DEC); 161 */ 162 memcpy(recvArray,buf,sizeof(buf)); //copy recieved buffer 163 into our reciving array 164 /* 165 for(i = 0; i < 100; i++){ 166 Serial.println(x[i]); 167 168 Serial.print(idleIn[i]); 169 Serial.print(" "); 170 Serial.println(holdIn[i]); 171 172 }*/ 173 for(i = 0; i < 124; i++){ //play the message 174 noTone(tonepin); 175 176 delay(recvArray[i]); 177 tone(tonepin,NOTE_C5); 178 i = i 179 + 1; 180 delay(recvArray[i]); 181 noTone(tonepin); 182 } 183 184 i = 0; 185 } 186 } 187 188} 189 190void updateState() { 191 if (buttonState 192 == HIGH) { 193 startPressed = millis(); 194 holdTime = startPressed - 195 endPressed; //time button was held down 196 tone(tonepin,NOTE_C5); 197 if(idleTime 198 > 5000){ 199 idleTime = 0; //if button was pressed after more than 5 seconds 200 idle, restart 5 second timer 201 } 202 pressed = 1; //button was pressed 203 204 } 205 if(buttonState == LOW){ 206 noTone(tonepin); 207 endPressed = 208 millis(); 209 idleTime = endPressed - startPressed; //time button was idle 210 211 } 212} 213 214void SoS() { //SoS message 215tone(tonepin,NOTE_C5); 216delay(300); 217noTone(tonepin); 218delay(100); 219tone(tonepin,NOTE_C5); 220delay(300); 221noTone(tonepin); 222delay(100); 223tone(tonepin,NOTE_C5); 224delay(300); 225noTone(tonepin); 226delay(300); 227 228tone(tonepin,NOTE_C5); 229delay(100); 230noTone(tonepin); 231delay(100); 232tone(tonepin,NOTE_C5); 233delay(100); 234noTone(tonepin); 235delay(100); 236tone(tonepin,NOTE_C5); 237delay(100); 238noTone(tonepin); 239delay(300); 240 241tone(tonepin,NOTE_C5); 242delay(300); 243noTone(tonepin); 244delay(100); 245tone(tonepin,NOTE_C5); 246delay(300); 247noTone(tonepin); 248delay(100); 249tone(tonepin,NOTE_C5); 250delay(300); 251noTone(tonepin); 252}
Downloadable files
Hookup schematic
Wire up your arduino according to this diagram. The button represents the telegraph key!
Hookup schematic
Hookup schematic
Wire up your arduino according to this diagram. The button represents the telegraph key!
Hookup schematic
Documentation
Antenna holder
This 3d printed part helps attach the antenna to the telegraph key.
Antenna holder
Comments
Only logged in users can leave comments
Anonymous user
4 years ago
FYI there is a vibrant morse keyer project https://github.com/k3ng/k3ng_cw_keyer and I have used it to do wireless keying over ESP-NOW https://www.youtube.com/watch?v=OppEUv7Lreg I found there are many advantages of esp-now, as it comes with any esp32 or esp8266 board, easy to use, and very fast with good range.