Arduino Keyer with Adjustable speed and LCD

The Basic Arduino Keyer is a great project but was purposely designed to have no frills. This week we will be adding an adjustment for speed and a LCD. For speed adjustment, there is 2 buttons. One is for words per minute up and the other is words per minute down. As you change the speed it is displayed on the LCD. Since buttons were being added an extra was installed for a memory. The memory is very basic and just sounds KM4NMP in morse code. This can be commented out or changed to your call sign.

Advertisements
Advertisements
//Basic Arduino Keyer 6/9/19
//https://MacarrLabs.com/
//https://KM4NMP.com/
//LCD and speed adjust added 6/15/19
//Memory Button added 6/16/19
//Author Matthew Carr KM4NMP
//common plug pin outs are:
//  Tip – left lever, or left side of single lever, normally Dot
//  Ring – right lever, or right side of single lever, normally Dash
//  Shaft – common
//Libraries 
#include <Wire.h>  
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
int UpButton = 4;
int DownButton = 5;
int LeftPin = 2;  //left paddle push pin
int RightPin = 3; //right paddle push pin
int memoryButton = 6; //memory button pin
int memoryButtonState = 0;
int DownButtonPinState = 0;
int UpButtonPinState = 0;
int LeftPinState = 0;
int RightPinState = 0;
int audio = 12;   //audio out pin
int note = 600;   //note pitch change for a difrent tone
float dotTime;
float dotTimeSec;
float dashTime;
int WordPerMin = 10; //sets words per minute at 10 to start
float CharPerMin;
Advertisements
void setup() {
  Serial.begin(9600);        //for debugging
  pinMode(UpButton, INPUT);  //set pin as input
  pinMode(DownButton, INPUT);  //set pin as input
  pinMode(LeftPin, INPUT);   //set pin as input
  pinMode(RightPin, INPUT);  //set pin as input
  pinMode(memoryButton, INPUT);  //set pin as input
  lcd.begin(16,2);   
  lcd.backlight();   // Turn on the backligt  lcd.noBaklight() to turn it off
  lcd.setCursor(0,0); 
  lcd.print("KM4NMP.COM Keyer");
  lcd.setCursor(2,1);
  lcd.print("*KM4NMP.COM*");
  WordPerMin = 10;
  CharPerMin = WordPerMin * 50;
  dotTimeSec = 60 / CharPerMin;    //dot time in seconds
  dotTime = dotTimeSec * 1000;
  dashTime = dotTime * 3;
  delay(1500);
  lcd.clear();
  lcd.print("KM4NMP.COM Keyer");
  lcd.setCursor(0,1);
  lcd.print("MacarrLabs.com");
  delay(1500);
  lcd.clear();
}

void loop() {
  //Read the state of the inputs
  LeftPinState = digitalRead(LeftPin);
  RightPinState = digitalRead(RightPin);
  UpButtonPinState = digitalRead(UpButton);
  DownButtonPinState = digitalRead(DownButton);
  memoryButtonState = digitalRead(memoryButton);
    
  
  if (UpButtonPinState == 1) {
    WordPerMin = WordPerMin + 1;
    lcd.clear();
    lcd.setCursor(0,0); 
    lcd.print("KM4NMP.COM Keyer");
    lcd.setCursor(0,1);
    lcd.print( WordPerMin );
    lcd.print(" WPM");
  }
  if (DownButtonPinState == 1) {   
    WordPerMin = WordPerMin - 1;
    lcd.clear();
    lcd.setCursor(0,0); 
    lcd.print("KM4NMP.COM Keyer");
    lcd.setCursor(0,1);
    lcd.print( WordPerMin );
    lcd.print(" WPM");
  }
  if (WordPerMin < 5){
    WordPerMin = 5;
    lcd.clear();
    lcd.setCursor(0,0); 
    lcd.print("KM4NMP.COM Keyer");
    lcd.setCursor(0,1);
    lcd.print( WordPerMin );
    lcd.print(" WPM");
  }
   if (WordPerMin > 35){
    WordPerMin = 35;
    lcd.clear();
    lcd.setCursor(0,0); 
    lcd.print("KM4NMP Keyer.COM");
    lcd.setCursor(0,1);
    lcd.print( WordPerMin );
    lcd.print(" WPM");
  }
Advertisements
 //calculate dot time
  CharPerMin = WordPerMin * 50;
  dotTimeSec = 60 / CharPerMin;    //dot time in seconds
  dotTime = dotTimeSec * 1000;     //dot time in milliseconds
  dashTime = dotTime * 3;          //dash time
  
  lcd.setCursor(0,0); 
  lcd.print("KM4NMP.COM Keyer");
  lcd.setCursor(0,1);
  lcd.print( WordPerMin );
  lcd.print(" WPM");
 
  if (LeftPinState == 1) {
    Serial.print("left ");         //for debugging
    Serial.println(LeftPinState);  //for debugging
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
  }

  if (RightPinState == 1) {
    Serial.print("Right ");         //for debugging    
    Serial.println(RightPinState);  //for debugging
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
  } 
  delay(dotTime);                   //time between tones
  
  if (memoryButtonState == 1) {    //memory button
    //k
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    
    delay(dashTime);
    //m
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    
    delay(dashTime);
    //4
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);

    delay(dashTime);
    //n
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    
    delay(dashTime);
   //m
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    delay(dashTime);
    
   //p
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);              //start tone
    delay(dashTime);                //tone length
    noTone(audio);
    delay(dotTime);
    tone(audio, note);             //start tone
    delay(dotTime);                //tone length
    noTone(audio);
    delay(dashTime);
 }     
}
Advertisements

Links

https://km4nmp.com/2019/06/09/basic-arduino-keyer/

https://km4nmp.com/2019/03/31/arduino-morse-code-practice-oscillator-project/

https://km4nmp.com/2019/04/06/arduino-oscillator-with-morse-code-decoder/

https://www.ardumotive.com/i2clcden.html

https://www.arduino.cc/

https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

Latest Posts

Advertisements

4 thoughts on “Arduino Keyer with Adjustable speed and LCD

  1. I notice you are not debouncing the buttons. This WILL cause problems. Here is how I do it:
    /********************************************************
    function to read analog pins as debounced digital inputs
    works with 10k pull up and 0.01 or 0.1 ufd cap across switch
    has 33 percent hysteresis.
    Beware this will spin forever on an unterminated analog input
    ********************************************************/
    boolean Button(int Bpin) {
    // Force an initial analogRead
    int level = 600; // middle of dead zone
    while (level > 400 && level = 800) {
    return HIGH; // in upper third
    }
    else {
    return LOW; // in lower third
    }
    }
    The way it works is, I connect a button to an Analog input. There is a 10-20k pull up resistor on the input and a .01 or .1 ufd capacitor across the switch. That capacitor will charge or discharge relatively slowly and smooth over any contact bounce. The Button function watches the voltage on the pin and waits for it to be in the upper third or the lower third of the analog range to declare a high or low. I’ve had very little trouble with switch bounce since using this function.. Only the worst of switches will glitch, they vary a lot.

    Like

    1. For this project to keep it simple, the delays built into the sketch are kinda acting as the debounce. If the unit is set at 35wpm there is at least 34 ms before the next read. In this case, there is enough time between reads for the switch to settle down. There is no interrupt so once pressed any activation is ignored until the loop goes around. This project will be modified over time and later versions will have a debounce similar to what you use. There a lot of ways to do the debounce and In the future, there will be a post of several different methods of debouncing. This may be sooner than later, My project that controls the RCS-10 antenna switch will require an interrupt for some functions that I am adding.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this:
search previous next tag category expand menu location phone mail time cart zoom edit close