Thursday, January 25, 2024

DIY CW Keyer for Ham Radio



Telegraphic CW keyer for HamRadio

( Based on Cheap Micro controller - ATTiny13  and 8 Pin IC )


Wednesday, January 24, 2024

USB Keyboard telegraphic CW keyer

 USB Keyboard telegraphic CW keyer for Ham radios




Circuit and Program by VU3AVE 
Anish VR, North Paravur 
 Phone: +91 9995957776







Use USB / PS2 keyboard to send cw message :  Using Arduino nano


Thanks to VU3AJU Ajan PJ, Moothakunnam for code support

Find video details at:  www.youtube.com/watch?v=Y5XYUysJYd8

Sending CW in ameature radio


 Using a Computer Keyboard (PS/2 model or USB model)

for typing and sending cw telegraphic codes is the discussion here.

Code reference  from: https://www.codeproject.com/Articles/1250929/Sending-Morse-Code-with-your-Arduino

http://www.arduino.cc/playground/Main/PS2Keyboard

 http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html



This code modified for “String” variable for convenience of adding a keyboard

Support ( thanks to AJAN PJ, VU3AJU )

Features

  1. Use USB or PS2 keyboard  to send CW directly
  2. Speed up / down using arrow keys
  3. Preset messages sending

Hardware

  1. Arduino nano
  2. PS2 keyboard
  3. 8 ohm speaker
  4. Buzzer (optional)
  5. BC148 (1 nos), 10 K ohm ( 2 nos)

Wire Connections:

 PS2 Keyboard - to - Arduino nano

OR

USB keyboard - to - Arduino nano

 V  = connected to + 5V of Arduino

 G - Ground = connected to GND of Arduino

 D - Data = connected Pin = 8  DataPin of Arduino [ or D+ pin of USB keyboard ]

C - Clock = connected Pin = 3 , IRQpin of Arduino  [ or D- pin of USB keyboard ]

for more information you can read the original wiki in arduino.cc at

http://www.arduino.cc/playground/Main/PS2Keyboard

OR

 http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html

 Speaker connection

Pin 7 of .Arduino nano is connected through a 100 mico farad capacitor to 8 ohm speaker, and other end of the speaker is connected to ground, GND

This provide tone() while speeding Up and Down keyer speed (WPM)

CW Key connection

 Pin 13 of Arduino is connected through 10 K ohm resistance to Base of BC148 transistor. Its Emitter is connected to common ground, GND.

Collector if BC148 connected to CW KEY , centre lead of the Transceiver RIG

Arduino is given +5 volt via its own USB connector.

IMPORTANT 

1. Used shield wire for PTT / KEY outgoing wires

 2. Use RF choke, by looping wires through toroids, in 9V DC line

Hardware used


Arduino nano




Programming Software
Arduino IDE ( www.arduino.cc )




Connection Diagram




USB Keyboard Modification

Popular keyboard nowadays is the USB keyboard.

Use the connections change as the below figure and this programme

Work smoothly on the usb keyboard too!!

Arduino nano PIN

USB keyboard Pin

PS2 keyboard Pin

5V

5V

5V

GND

GND

GND

D3

  • - D

Clock (c)

D8

  • + D

Data (d)



Use " ps2keyboard "Library by  Christian Weichel, Paul Stoffregan



Source Code  DOWNLOAD FROM GITHUB

 


// code begin here

#include <PS2Keyboard.h>

// PS2 KEYBOARD

const int DataPin = 8; // DATA out of ps2 keyboard

const int IRQpin =  3; // for arduino nano //clock out of ps2 keyboard

PS2Keyboard keyboard;

// AUTOMATIC KEYER USING PADDLE AND USB/PS2 KEYBOARD

int Maximum_speed_WPM=30;

int Minimum_speed_WPM=3;

int P_DOT =   2;   // Connects to the dot lever of the paddle

int P_DASH =  4;   // Connects to the dash lever of the paddle 3 to 4

int P_AUDIO = 7;   // Audio output

// int P_AUDIO = 12;   // Audio output

int P_CW  =  13;   // Output of the keyer, connect to your radio

#define P_SPEED A0   // Attached to center pin of potmeter, allows you

int speed;

////////////////////////////// CW sender/////

String mappings[] = {

                         ".-",  // A

                         "-...",

                         "-.-.",  

                         "-..",

                         ".",  

                         "..-.",

                         "--.",  

                         "....",

                         "..",  

                         ".---",

                         "-.-",  

                         ".-..",

                         "--",  

                         "-.",

                         "---",  

                         ".--.",

                         "--.-",  

                         ".-.",

                         "...",  

                         "-",                          

                         "..-",  

                         "...-",

                         ".--",  

                         "-..-",

                         "-.--",  

                         "--..", // Z

                         ".----",  // 1

                         "..---",

                         "...--",  

                         "....-",

                         ".....",  

                         "-....",

                         "--...",  

                         "---..",

                         "----.",  

                         "-----",   // 0

                         "..--..",  // ?

                         ".-.-.-",  // .

                         "--..--",  // ,

                         "-..-.",   // /

                         "...-.-"  // @

                         };

String  morsecode;

String message;

const String  characters = "abcdefghijklmnopqrstuvwxyz1234567890?.,/";

int sm_time;

int time_step=100;  // initial timer

int TIME_UNIT;

String inputString = "";                 // a String to hold incoming data

bool stringComplete = false;  // whether the string is complete

////////////////////////////

int KEY_PIN=13; // relay drive to transimit cw in port

// tone frequency for speaker

int notes[] = {

  1047, 1319, 1175, 1568

};

void setup() {

  delay(1000);

  keyboard.begin(DataPin, IRQpin);

  Serial.begin(9600);

  Serial.println("Keyboard Test:");

            pinMode(13, OUTPUT);  // connect a buzzer at pin 13 to listen cw

            pinMode(9, OUTPUT);  // connect and LED in pin 9

   

  pinMode(6, OUTPUT);  // Local speaker or LED

   

            // reserve 200 bytes for the inputString:

            inputString.reserve(200);

  pinMode(P_DOT, INPUT);

  pinMode(P_DASH, INPUT);

  pinMode(P_AUDIO, OUTPUT);

  digitalWrite(P_CW, LOW);              // Start with key up

  // sound welcome tone

  speeddown();

  speedup();

  // speeddown_mute();

  speedup_mute();

 

 }

void loop() {

 

//// LAMBIC KEYER START

speed = 60000 / (map(analogRead(P_SPEED), 0, 1023, Maximum_speed_WPM, Minimum_speed_WPM) * 73);

  // speed = 100;

 if(!digitalRead(P_DOT))            // If the dot lever is presssed..

         {

        keyAndBeep(speed);               // ... send a dot at the given speed

        delay(speed);                    //         and wait before sending next

         }

 

if(!digitalRead(P_DASH))           // If the dash lever is pressed...

        {

   keyAndBeep(speed*3);             // ... send a dash at the given speed

   delay(speed);                    //         and wait before sending next

        }

//// LAMBIC KEYER CLOSE

 

  // print the string when a newline arrives:

  if (stringComplete)

  {

            Serial.println(inputString);

   

            message=inputString;

            digitalWrite(9,HIGH);

            delay(100);

            int result= messagetocw();

            digitalWrite(9,LOW);

   

            // clear the string:

            inputString = "";

            stringComplete = false;

  }

  // print the string when a newline arrives:

  if (keyboard.available()) {

   

            // read the next key

            char c = keyboard.read();

   

            // check for some of the special keys

            if (c == PS2_ENTER) {

              // Serial.println();

             

             

            } else if (c == PS2_TAB) {

              Serial.print("[Tab]");

              message="vu2acc";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

             

            } else if (c == PS2_ESC) {

              // Serial.print("[ESC]");

              message="hi";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

             

            } else if (c == PS2_PAGEDOWN) {

              //Serial.print("[PgDn]");

              message="qrz?";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

             

            } else if (c == PS2_PAGEUP) {

              //Serial.print("[PgUp]");

              message="cq cq cq de vu2acc vu2acc vu2acc pse k";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

             

            } else if (c == PS2_LEFTARROW) {

              Serial.print("[Left]");

            } else if (c == PS2_RIGHTARROW) {

              Serial.print("[Right]");

           

           

            } else if (c == PS2_DELETE) {

              // Serial.print("[Del/Backspace]");

              message="de vu2acc tks fer qso 73 tu i";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

             

            } else if (c == PS2_UPARROW) {

              //Serial.print("[Up]- Speed UP");

              speedup();

             

            } else if (c == PS2_DOWNARROW) {

              //Serial.print("[Down]- Speed DOWN");

              speeddown();

             

            } else if (c =='=') {

              //Serial.print("CQ Call");

              message="cq cq cq de vu2acc vu2acc vu2acc k";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

            } else if (c == '?') {

              // Serial.print("qrz call");

              message="qrz ? de vu2acc k";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

            } else if (c == '-') {

              message="de vu2acc tks fer qso 73 tu i";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

            } else if (c == '%') {

              message="hi";

              digitalWrite(9,HIGH);

              delay(100);

              int result= messagetocw();

              digitalWrite(9,LOW);

            } else {

             

              // otherwise, just print all normal characters

              Serial.print(c);

///test

            message=c;

            digitalWrite(9,HIGH);

            delay(100);

            int result= messagetocw();

            digitalWrite(9,LOW);

///test

             

            }

 

  }// 'if' is close

 

}// LOOP() close

////LAMBIC FUNCTIONS START

// Key the transmitter and sound a beep

void keyAndBeep(int speed)

{

  digitalWrite(P_CW, HIGH);                // Key down

  for (int i=0; i < speed; i++)        // Beep loop

  {

   digitalWrite(P_AUDIO, HIGH);

   delay(1);

   digitalWrite(P_AUDIO, LOW);

   delay(1);

  }

 

  digitalWrite(P_CW, LOW);                 // Key up

 }

////LAMBIC FUNCTIONS CLOSE

void speedup()

{

  time_step=time_step-10;

            if(time_step<=10)

  {

                time_step=10;

  }

 

  for (int thisSensor = 0; thisSensor < 4; thisSensor++) {

             tone(7, notes[thisSensor]);

             delay(time_step);

             noTone(7);

  }

 

}

void speeddown()

{

  time_step=time_step+10;

 

   

  for (int thisSensor = 3; thisSensor >= 0; thisSensor--) {

             tone(7, notes[thisSensor]);

             delay(time_step);

             noTone(7);

  }

}

void  speedup_mute(){

time_step=time_step-10;

            if(time_step<=10)

  {

                time_step=10;

  }

 

 }

int messagetocw()

{  

  // FUNCTION messagetocw() START

 

  // int size = strlen(message);

  int size = message.length();

  int TIME_UNIT = 50; // default time for DIT

  ///

  if(TIME_UNIT==time_step)

  {

   

  }

  else

  {

            TIME_UNIT=time_step;

  }

  ///

  if(TIME_UNIT<=10)

  {

            TIME_UNIT=10;

            time_step=10;

  }

  ///

  const int DOT = TIME_UNIT;

  const int DASH = 3 * TIME_UNIT;

  const int SYMBOL_SPACE = TIME_UNIT;

  const int LETTER_SPACE = 3 * TIME_UNIT - SYMBOL_SPACE;

  const int WORD_SPACE = 7 * TIME_UNIT - LETTER_SPACE;

 

  message.toLowerCase();

  for (int i = 0; i < size; i++) {

   

            // const char* ch = strchr(characters, tolower(message[i]));

            char ch = characters.charAt(characters.indexOf(message.charAt(i)));//

            // if (ch != NULL){

   if (ch != '\0'){

             

              // int position = ch-characters;

              int position = characters.indexOf(message.charAt(i));

             

              morsecode = mappings[position];

             

              // int count = strlen(morsecode);

             int count = morsecode.length();

             

             

              //Serial.print("symbol ");

              //Serial.print(message[i]);

              //Serial.print(" is in position ");

              //Serial.print(position);

              //Serial.print("\n");

              //Serial.print(morsecode);

              //Serial.print("\n---------------\n");

             

             

              for( int j=0; j< count; j++)

              {

               

                char symbol = morsecode[j];

               

                if(symbol =='.')

                {

                  sm_time = DOT;

                }

               

                if(symbol =='-')

                {

                  sm_time = DASH;

                }

                digitalWrite(KEY_PIN, HIGH);

                delay(sm_time);

                digitalWrite(KEY_PIN, LOW);

                delay(SYMBOL_SPACE);

              }// for loop close2

             

              delay(LETTER_SPACE);

             

            }

            delay(WORD_SPACE);

   

  }// for loop close1

 

} // FUNCTION messagetocw() close

/*

  SerialEvent occurs whenever a new data comes in the hardware serial RX. This  routine is run between each time loop() runs, so using delay inside loop can  delay response. Multiple bytes of data may be available.

*/

void serialEvent()

{

  while (Serial.available()) {

            // get the new byte:

            char inChar = (char)Serial.read();

            // add it to the inputString:

            inputString += inChar;

            // if the incoming character is a newline, set a flag so the main loop can

            // do something about it:

            if (inChar == '\n') {

              stringComplete = true;

            }

  }

}

// thanks de vu3ave

// code complete


Thank you

Anish VR

VU3AVE

Mobile phone: 91 9995957776

vu3ave@gmail.com

Use this code as a reference, make changes as necessary