Alex Chang
Published © GPL3+

Walkie Tappie (Wireless Morse Code)

Ditch your phones for a wireless Morse code transmitter!

IntermediateFull instructions provided4 hours2,634
Walkie Tappie (Wireless Morse Code)

Things used in this project

Hardware components

Stemedu 2 Sets LoRa32u4ii Lora Development Board Module
×1
Telegraph Key
×1
Gikfun Round Micro Speaker Diameter 30mm 8Ohm 8R 2W for Arduino Mini Box Speakers DIY
×1
Resistor 221 ohm
Resistor 221 ohm
×1
Adafruit Lithium Ion Polymer Battery
Optional
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
3D Printer (generic)
3D Printer (generic)
(Optional)

Story

Read more

Custom parts and enclosures

Antenna holder

This 3d printed part helps attach the antenna to the telegraph key.

Schematics

Hookup schematic

Wire up your arduino according to this diagram. The button represents the telegraph key!

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
#include"pitches.h"
#include <RH_RF95.h>
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7
#define RF95_FREQ 915.0
RH_RF95 rf95(RFM95_CS, RFM95_INT);


const int  buttonPin = 11;    // the pin that the pushbutton is attached to
const int tonepin = 12; //the pin that the speaker is attached to

int buttonState = 0;     // current state of the button
int lastButtonState = 0; // previous state of the button
int startPressed = 0;    // the moment the button was pressed
int endPressed = 0;      // the moment the button was released
int holdTime = 0;        // how long the button was hold
int idleTime = 0;        // how long the button was idle
int idleArray[100];     // array to record button idle times
int holdArray[100];   // array to record button hold times
int i; 
int j;
int k;
int sendArray[200];   // array to store idle/hold times to be sent
uint8_t buf[251];   //Lora message buffer
int recvArray[124];   
int pressed = 0;


void setup() {
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);

 //Serial.begin(9600);
  
 // while (!Serial) {
 //   delay(1);
 // }

  delay(100);
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);
  while (!rf95.init()) {
    //Serial.println("LoRa radio init failed");
    SoS(); // beeps SoS if radio fails to start
    while (1);
  }
  if (!rf95.setFrequency(RF95_FREQ)) {
    //Serial.println("setFrequency failed");
    SoS();
    while (1);
  }
  //Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
  
  pinMode(buttonPin, INPUT); // initialize the button pin as a input
  rf95.setTxPower(23, false);

}

void loop() {
  buttonState = digitalRead(buttonPin); // read the button input
  updateState();
  /******************************Transmit******************************/
  if(idleTime > 5000 && pressed == 1){ //Only transmit if it's been 5 seconds since last button press
  pressed = 0; //reset button press
  k = 0;
  idleArray[0] = 0; //set first delay to zero so the message doesn't start with delay
  for(i=0;i<124;){
      sendArray[i]=idleArray[k]; //Put idle times in even index of sendArray
      i = i + 1; //indexing sendArray
      sendArray[i]=holdArray[k]; //Put hold times in odd index of sendArray
      i = i + 1;
      k = k + 1; //indexing idle and hold arrays     
  }
    memcpy(buf,sendArray,sizeof(sendArray)); //copy send array into uint8_t buffer
    //for(i=0;i<200;i++){ //For debug
    //  Serial.println((int)x[i]);
    //}
    rf95.send(buf, sizeof(buf)); // Send buffer
    rf95.waitPacketSent(); 
    startPressed = millis(); //reset counter
    memset(idleArray,0,sizeof(idleArray)); //clear arrays
    memset(holdArray,0,sizeof(holdArray));
    i = 0; 
    j = 0;
    tone(tonepin,NOTE_C6); //play tone to indicate message sent
    delay(100);
    noTone(tonepin);
  }
  delay(2);
  if(lastButtonState != buttonState && buttonState == 1){
    idleArray[i] = idleTime; //Record button idletime into array
    //Serial.print(idleArray[i]);
    //Serial.print(" ");
    i++;
  }
 
  if(lastButtonState != buttonState && buttonState == 0){
    holdArray[j] = holdTime;
    //Serial.println(holdArray[j]);
    j++;
  }
  lastButtonState = buttonState;
  /******************************Recieve******************************/
   if (rf95.available())
  {
    uint8_t len = sizeof(buf);
    if (rf95.recv(buf, &len))
    {
      /*
      RH_RF95::printBuffer("Received: ",buf, len);
      Serial.println(*(int*)buf);
      Serial.print("RSSI: ");
      Serial.println(rf95.lastRssi(), DEC);
      */
      memcpy(recvArray,buf,sizeof(buf)); //copy recieved buffer into our reciving array
      /*
      for(i = 0; i < 100; i++){
        Serial.println(x[i]);
        Serial.print(idleIn[i]);
        Serial.print(" ");
        Serial.println(holdIn[i]);
      }*/
     for(i = 0; i < 124; i++){ //play the message
        noTone(tonepin);
        delay(recvArray[i]);
        tone(tonepin,NOTE_C5);
        i = i + 1;
        delay(recvArray[i]);
        noTone(tonepin);
      }
      i = 0;
    }
  }
  
}

void updateState() {
  if (buttonState == HIGH) {
      startPressed = millis();
      holdTime = startPressed - endPressed; //time button was held down
      tone(tonepin,NOTE_C5);
      if(idleTime > 5000){
        idleTime = 0; //if button was pressed after more than 5 seconds idle, restart 5 second timer
      }
      pressed = 1; //button was pressed
  } 
  if(buttonState == LOW){
    noTone(tonepin);
      endPressed = millis();
      idleTime = endPressed - startPressed; //time button was idle
    }
}

void SoS() { //SoS message
tone(tonepin,NOTE_C5);
delay(300);
noTone(tonepin);
delay(100);
tone(tonepin,NOTE_C5);
delay(300);
noTone(tonepin);
delay(100);
tone(tonepin,NOTE_C5);
delay(300);
noTone(tonepin);
delay(300);

tone(tonepin,NOTE_C5);
delay(100);
noTone(tonepin);
delay(100);
tone(tonepin,NOTE_C5);
delay(100);
noTone(tonepin);
delay(100);
tone(tonepin,NOTE_C5);
delay(100);
noTone(tonepin);
delay(300);

tone(tonepin,NOTE_C5);
delay(300);
noTone(tonepin);
delay(100);
tone(tonepin,NOTE_C5);
delay(300);
noTone(tonepin);
delay(100);
tone(tonepin,NOTE_C5);
delay(300);
noTone(tonepin);
}

Credits

Alex Chang

Alex Chang

2 projects • 19 followers

Comments