Getting started with Arduino: morse keyer
Using a paddle to operate in morse code is very convenient. But paddles don’t create dots and dashes on their own, so you need some electronics, called a “keyer”. You may use the build-in keyer of your radio, but most of them lack of functionality. You may buy a keyer at your local ham store, but these are rather expensive. So why not build your own keyer? It’s fun to do, and you learn new things. The Arduino prototyping board allows you to build the most advanced and personalized keyer that you have in mind! This article gives you a decent start for such a keyer, by implementing the basic functionality and learn a bit about the Arduino platform if you’re not familiar with this board yet.
About the Arduino
The Arduino is one of the easiest prototyping platforms available nowadays. You can easily attach buttons, sensors, lights, displays, relays and motors and control them all with a simple program. You write the program using the Arduino IDE software (available for Linux, Windows and Mac) and transfer it to your Arduino board using a USB-cable. Arduino boards are sold at most electronics shops and will cost about 20-25 euros / 25-30 USD. You may consider buying a starter kit, containing an Arduino board, a breadboard, and handful of parts (LED’s, switches, sensors, motor, servo, etc), wires, and a guide learning you the basics. Visit the Arduino website for more information.
About paddles
Paddles come in different shapes and sizes. The keyer discussed in this article is meant for “twin paddles” or “iambic paddles”. Such a paddle has 2 levers, one for sending dots and one for the dashes. The “iambic” means that, when squeezing both levers, the keyer will translate this to a repetitive series of dot-dash-dot-dash-dot-dash-etc…
Actually, if you look at your paddle, it’s just a double switch. Ok, it’s probably the most expensive and specialized switch in your home, but still it’s a switch. Each contact is shortened to a common contact, normally connected to “ground”. The other ends of the switches are connected to the “dot” and “dash” inputs of your keyer.
The keyer hardware
It’s time to build the circuit. I suggest that you first build your prototype on a breadboard, at least I did for this article.
The main component of the keyer is (of course) the Arduino board, and we will create the following inputs and outputs:
- 2 Digital inputs for the paddle (dot and dash contact).
- 1 Digital output to the key jack of your transmitter.
- 1 Digital output to sound a sidetone buzzer.
- 1 Analog input to read the speed from a potmeter.
Down here I’ll discuss these.
The paddle contacts have to be translated to a digital “1” or “0”. Most paddles pull connect the contacts to ground, so when a lever is pressed it is a digital “0”. So when not pressed, a “1” should appear at the Arduino’s input, so we add a 10k pull-up resistor to each contact, connecting it to +5V (operating voltage of the Arduino). The contacts can now be connected to the Arduino, using the digital I/O pins labelled “D2” and “D3”. The arduino also provides pins labelled “GND” (for the ground connection of the keyer) and “5V” (for the pull-up resistors).
The software processes the inputs from the keyer and produces the dots and dashes. Therefore it keys pin “D13”. When high (+5V), the key is pressed. We attach a transistor (almost any common NPN type transistor will do) to this pin. When ping D13 is high, the transistor pulls the key input of the connected transmitter to ground, as if a straight key was connected.
During key down, the software will generate a square wave on pin “D12”, allowing you to attach a small buzzer. You could also shape the signal a bit using an RC circuit and feed a LM386 based audio amplifier, allowing you to attach a small speaker or headphones, but I’ll leave that to you. For now, the buzzer will be fine.
You definitely want to be able to set the keying speed, so therefore we will attach a potmeter. The center pin will be connected to analog input “A0” of the Arduino, while the other 2 pins are connected to GND and 5V.
The hardware is finished now, so let’s go on to the software part.
The keyer software
Once installed the Arduino IDE software, you can simply start it and begin typing your code. You can download the keyer code from my GitHub repository to save you some time. If you have never programmed an Arduino before, you might first take a look at some examples, starting with this one: File → Examples → Basics → Blink. In the text down here I have added links to the online Arduino Language Reference.
Let’s start coding. The keyer software consists of 4 parts:
- Declarations.
- The “setup” function.
- The main routine, called “loop”.
- The custom “keyAndBeep” function.
We start with the declarations. We define constants for all pins used, and also introduce a variable (integer) to store the value of the potmeter, called “speed”:
#define P_DOT 2 // Connects to the dot lever of the paddle #define P_DASH 3 // Connects to the dash lever of the paddle #define P_AUDIO 12 // Audio output #define P_CW 13 // Output of the keyer, connect to your radio #define P_SPEED A0 // Attached to center pin of potmeter, allows you // to set the keying speed. int speed;
The next step is the setup routine. The Arduino runs this code only once, at start/boot time. We use this to define which pin is an input or an output, using the pinMode statement. We also ensure that there is no key output, by setting the output pin to LOW using the digitalWrite statement:
// Initializing the Arduino void setup() { pinMode(P_DOT, INPUT); pinMode(P_DASH, INPUT); pinMode(P_AUDIO, OUTPUT); pinMode(P_CW, OUTPUT); digitalWrite(P_CW, LOW); // Start with key up }
Notice that we used the contants we just declared, not the pin numbers itself.
Let’s go on to the main routine, called loop. This one repeats itself continuously, so when the last statement is executed, it returns to the start of this loop again. The first statement reads the value of the potmeter using the analogRead statement, and stores it in our “speed” variable. Next it reads the input pin connected to the “dot” contact of the paddle using digitalRead. If the input is low, it calls a custom function called “keyAndBeep”, which we will discuss in a moment. Then there’s a short delay, since we want a bit of time after sending a dot. If we would skip this delay, there would be no separation between succeeding dots and/or dashes. Finally, we do the same for the “dash” contact, but now the key has to be down 3x longer, hence the “speed*3” argument. Now the routine returns to the first statement, reading the value of the potmeter again, checking the dot lever, etc…
// Main routine void loop() { speed = analogRead(P_SPEED)/2; // Read the keying speed from potmeter 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 } }
The final part of the code does the actual keying and sounding. We call this function “keyAndBeep”. It starts with keying the output, setting the P_CW pin to “HIGH” (5V). This will drive the transistor to key the transmitter. Then a for loop runs for a while, all statements within this loop are repeated lots of times, depending on the value of the “speed” variable (so the setting of the potmeter). Each iteration the audio output is set to HIGH, then we wait 1 millisecond, and then set the output to LOW again and wait another millisecond. This results in a square wave of about 500 Hz (roughly). When the loop is ended, the key output is set to “LOW” again and the connected transmitter will stop.
// Key the transmitter and sound a beep void keyAndBeep(int speed) { digitalWrite(P_CW, HIGH); // Key down for (int i=0; i < (speed/2); i++) // Beep loop { digitalWrite(P_AUDIO, HIGH); delay(1); digitalWrite(P_AUDIO, LOW); delay(1); } digitalWrite(P_CW, LOW); // Key up }
In case you missed it… you can download the complete code here: pa3hcm_simple_iambic_keyer.txt
Now connect the Arduino to your PC and upload the code. Once uploaded the keyer will come to live immediately, since it’s powered by USB now. You can simply remove the USB cable now and power the Arduino by attaching a 9V battery or a 9-15 volts DC adapter.
Next steps
Congratulations, You’ve just finished the prototype of your keyer! But this is just a very basic keyer. Here are some ideas to extend/personalize your keyer:
- Add one ore more buttons (use pull-up resistors, like done with the paddle buttons) to transmit standard texts, like your callsign or a CQ message.
- Add an LCD display showing the current speed. It’s easier than you think! For an example just go to the menu of the Arduino IDE software and click: File → Examples → LiquidCrystal → HelloWorld.
- Create a memory keyer, the Arduino has an internal EEPROM where you can store your messages.
- Replace the buzzer by a lowpass filter (to shape the square wave) and a LM386 based audio amplifier, so you can use a small speaker (sounds nicer) and/or headphones.
- Place a small capacitor (10nF) between each input/output and ground to prevent RF interference.
- Take a look at other Arduino-based keyers on the web and get inspired.
- Add an Ethernet Shield to the Arduino and enable keying over your local network.
- Add a Bluetooth Shield to the Arduino, and create an app to control the keyer using your mobile phone.
- Build a very small keyer using the Arduino Mini, Micro or Nano.
- Build your final version in a fancy enclosure!
As always… for any questions or comments regarding this article just place a comment down here, or use the contact form on this website to send me a private email.
What others did
Chris ZS1CDG built a slightly different version, which is a touch paddle. He replaced both 10k resistors with 2M ones and uses his fingers as “switches”. He showed the result in this nice video.
Tommy NE5TH built it using a breadboard shield.
Maks UT3UEZ used it in a morse trainer/simulator, using an Arduino Mini. He uses a second Arduino Mini to decode the signal again and show the result on a display.
Yuri EW6BN put his version into a small plastic mints box.
Based on this article, Daniel VE7LCG built this very small keyer, including a tiny paddle!
Anthony DU1AU build this neat integrated keyer.
More builders:
This article was also published in:
Hoi Ernest
Zag je naam voorbij komen in een mailtje van Aeilko van der Wagen (de enige andere ham van Soesterberg, hi)
Hij schreef dat jij hem geholpen had met de Arduino software voor zijn DDS protect.
Natuurlijk even gegoogled op jouw call, en kwam op je website (gaaf!!!)
Ik zag dat je een keyer gemaakt had met een Arduino.
Ik dus ook, maar ik heb daar de bekende software van K3NG vor gebruikt, en in mijn Arduino Nano gezet (nanokeyer)
Echt waanzinnige functionaliteit, ik wil er alleen nog een display aanhangen, maar datn past de code niet meer in het geheugen van de nano en zal ik moeten ‘verkassen’ naar een Arduino Mega (2850, die inmiddels een opvolger heeft: de 2860..heeft geen FTDI chip meer)
Zoek even op nanokeyer, en je ziet vazelf de links naar de keyersoftware.
73 de Robbert / PA3BKL
Hello Robert,
I know there are more Arduino based keyers available, and yes, K3NG did a really nice job. However, my article is not meant to build your own fancy / sophisticated / feature-rich keyer, but to be part of learning to write your own code for Arduino. Therefore its functionality is very limited, but most people should understand the code. Still, it might add some links to such projects for inspiration.
Thanks for your comment, always appreciated!
73, Ernest PA3HCM
Ernest, Very impressive it seems to me. I have been using the Arduino for less than 1 week. I could never set aside the time to learn the basics. Then a week ago, I did … by watching a youtube video. Then I discovered your keyer. It appeared so simple and yet when I loaded in your sketch, it almost worked the first time. I had left off the pull up resistor as I was not sure they were needed. Yes, they are! I almost understand your sketch. Now I’m going to play around with it until I understand it. I was intrigued as I am a very active CW enthusiast! Thank you for posting this project. jim/w4qo
Thanks for the good job, I was looking for such a thing.
It has been working at the first time
73’s from F6FRI
Thanks so much for this “how to”. Very simple and easy to follow.
Chris ZS1CDG
The values one gets from analogRead are rather unusable as is even after scaling down by 2. To get a linear speed adjustment from 10 to 35 WPM, you can use e.g.
speed = 60000 / (map(analogRead(P_SPEED), 0, 1023, 35, 10) * 44);
to calculate the proper delay. I’ve posted the modified version on my GitHub account.
Yes Antti, the speed adjustment is far from perfect, however I tried to keep the code as simple as possible, to allow starters to understand the code. Thanks for your input!
More information on the map function can be found here: https://www.arduino.cc/en/Reference/Map
I’ve seen others solving this issue by adding series resistors on both sides of the potmeter, which is actually the “physical way” of implementing the map() function 😉
Antti’s version of the code can be downloaded here: https://github.com/andyn/iambic
Ernest, an excellent simple iambic keyer project and the code is easy to read. It worked first time. I modified the speed setting as per Antti above but modified it a little to read better by defining Maximum_speed_WPM, and Minimum_speed_WPM early on. I used this line;
speed = 60000 / (map(analogRead(P_SPEED), 0, 1023, Maximum_speed_WPM, Minimum_speed_WPM) * 44)
This now gives a reasonably linear speed adjustment.
Thank you for posting this.
John G3VRF
Hi John
I am an enthusiast Arduino and CW. I have little knowledge to program but I like to experiment. You tell me where you put the line in the code created by Ernest?
Thank you so much
Osvaldo – LU5XP
Osvaldo,
It replaces this line:
speed = analogRead(P_SPEED)/2;
73, Ernest PA3HCM
Thank you Ernest..!!
Hallo Ernest
,
ik ben al een tijd opzoek naar een Arduino morse keyer zou u mij mischien willen en
kunnen helpen hoe kom ik aan zo een keyer?
en wat eventueel de prijs er van?
ik zit op dit moment in het buitenland maar ik kom binnenkort naar nederland,
met vriendelijke groet.
Ben,
73’s
Ben,
You may consider buying this nanoKeyer kit, which includes a PCB and all parts, except an Arduino Nano and a case.
73, Ernest PA3HCM
[…] that change on pins 10 and 11 and send the dit and dah accordingly. Very much how PA3CHM did it here: in his simple […]
Hello, Ernest!
Thanks a lot, good job!
https://www.youtube.com/watch?v=J-2DsarAEOA
73! Yuri EW6X
Please provide the exact parts list.
Hi, nice project!
If you use pinMode(P_DOT, PULLUP_INPUT); you can remove the external pullup resistors and use the internal ones 🙂
73 de Adrian YO3HJV
pinMode(P_DOT, INPUT_PULLUP);
minor mistake 🙂
I applied external pullup resistors, so ‘INPUT’ is ok then. You can skip the external resistors and use the internal pullup resistors instead, but I found that less clear for educational purposes 😉
Nice job!
Just what I was looking for.
Made mods to code as suggested above, added a a switch and a couple of lines of code to give iambic or semi auto.
Simple sideswiper/cootie key gives same effect as vibroplex but without the $$$$ price.
73 de Dave GM4HPK
Nice job.
Couldn’t afford the $$$$ price wanted for a vibroplex.
Added a semi auto option and now able to use homebrew cootie to mimic.
Thanks
de Dave GM4HPK
Hi Ernest,
congratulation!!!
How to memorize dot after dash in your simple iambic keyer?
Rubens PY2PVB
Ilha Solteira SP Brazil
Hi Rubens,
If you want to implement that, things get a bit more complex. You will probably have to use interrupts to handle this, most Arduino boards do support this on pins 2 and 3. See https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/ for more information on how to use interrupts. For this simple morse keyer I don’t have any code available for this yet.
73, Ernest PA3HCM
I made a very compact version, all in one. You can see the video at:
https://www.youtube.com/watch?v=cFADTW8faSA
Daniel VE7LCG
Thanks for such a nice keyer, needed something for my HW9 was able to put a volume and switch control in a very small box. Makes a nice package. Thanks again worked right off.
Rick WB8ZRQ
Hi, you say you use the blue wire to key the radio. But the radio keyer input needs a complete circuit. So you must be connecting more than just the blue wire? Do you connect the key-input ground to the arduino ground also?
Yes, it’s the blue wire and ground for most radios. Some really old radios don’t key to ground, in that case check your manual.
Hello Ernest, best 73.
Tks a lot your easy arduino keyer project.
I’m not an expert on arduinos, só I’m trying to update the project to have a simple 1602 LCD. Try severals parts os LCD programs (like Hello World) but nothing works.
Can you update your project with LCD?
Many thanks.
Carlos, CT1GFQ
Hello Carlos,
The goal of this article is to get you started with an Arduino, not to provide a full featured CW keyer. That said, maybe I can tell you how to start:
In the Arduino software, go to the menu: File –> Examples –> LiquidCrystal. You will find a bunch of examples on how to control your LCD. If your LCD has 16 pins, it’s probably an HD44780 type, the HelloWorld example works for sure. If your LCD has only 4 pins or has a backpack, it’s probably an I2C type, in that case you could use the LiquidCrystal_PCF8574 library. You can install this library via the menu: Sketch –> Include Library –> Manage Libraries. Search for ‘LiquidCrystal_PCF8574’ and hit the ‘Install’ button. Now go back to your Examples, scroll all the way down and you’ll find a new menu ‘LiquidCrystal_PCF8574’, including an example called ‘LiquidCrystal_PCF8574_Test’. Good luck!
73, Ernest PA3HCM
Amazing! It worked first try for me. I’m using it with a 3D printed set of paddles. https://www.thingiverse.com/thing:2055829
Thank you for taking the time to share your work!
Hi,
it works great. Have just one problem, currently it works in Mode A
how to set it to mode B?
I mean just reverse, from mode A to mode B
The term ‘reverse’ is normally used to swap levers. Iambic mode B has nothing to do with that, it has anything to do with what to do when both levers are pressed simultaneously. I must say I have never practiced mode B, but I know mode B alternates once more compared to mode A. This will require a bit more code, since then you have to determine if both levers were pressed. I don’t have code readily available to demonstrate this, sorry!
Thanks for sharing this, I just built one. I appreciate how you made the code and circuitry very simple and easy to understand, for instance, you used external pull-up resistors to help visualize how the code and the circuit works!
73, Anthony DU1AU (Philippines)
Hi, you can delete this two resistors pull up, replace:
pinMode(P_DOT, INPUT);
pinMode(P_DASH, INPUT);
with:
pinMode(P_DOT, INPUT_PULLUP);
pinMode(P_DASH, INPUT_PULLUP);
73
For educational purposes however I decided to use real pull-up resistors. Both solutions will work, choose whatever you like 😉
Hi Ernest
built the keyer using a Teensy LC mounted on a piece of printed circuit perf board. Downloaded and installed Arduino ide and Teensyduino. Downloaded the sketch and to my dismay it would not verify or upload. kept getting a “no usb ports found” error. then I discovered that my USB cable was a charge only cable! replaced that and at last,the sketch compiled and uploaded. my issue now is..the dots and dashes are not stable and vary in duration and time. I have no or at the very best limited experience in the world of “duinos” or sketches and am looking for help. Hopefully you or someone who reads this post can help me.
-Thanks-
Sorry, I don’t have any experience with Teensy LC boards… code is tested on both official Arduino’s and clones from those popular chinese webshops. You might try an Arduino Nano, which has about the same form factor as the Teensy LC. Good luck!
the problem was me!
the wiper of the speed control should be connected to A0. …I had connected it to A6 because thats what these 79 year old eyes saw (or was sure they saw) when I looked at the schematic. once I fixed that error, the keyer works perfectly….the unstable characteristic of the keyer went away..
by the way. I am using a 3-1/3” 8 ohn loudspeaker with a 50k ohm pot in the hot side of the speaker…works perfectly as a volume for the sidetone.
another mod I will be doing is adding a spst switch from the collector of the keying transistor to ground to use as a Tune switch.
Dear Ernest,
Please help me to program an Arduino NANO with your software
“Simple Iambic Keyer v1.00.”
After the manual implementation of the program I did the Upload but it did not succeed, the error appearing below:
1. My work
// Simple Iambic Keyer v1.00
// by Ernest PA3HCM
#define P_DOT 2 // Connects to the dot lever of the paddle
#define P_DASH 3 // Connects to the dash lever of the paddle
#define P_AUDIO 12 // Audio output
#define P_CW 13 // Output of the keyer, connect to your radio
#define P_SPEED A0 // Attached to center pin of potmeter, allows you
// to set the keying speed.
int speed;
// Initializing the Arduino
void setup() {
// put your setup code here, to run once:
{
pinMode(P_DOT, INPUT);
pinMode(P_DASH, INPUT);
pinMode(P_AUDIO, OUTPUT);
pinMode(P_CW, OUTPUT);
digitalWrite(P_CW, LOW); // Start with key up
}
// Main routine
}
void loop() {
// put your main code here, to run repeatedly:
{
speed = analogRead(P_SPEED)/2; // Read the keying speed from potmeter
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 ay the given speed
delay(speed); // and wait before sending next
}
}
// Key the transmitter and sound a beep
void keyAndBeep(int speed)
{
digitalWrite(P_CW, HIGH); // Key down
for (int i=0; i < (speed/2); i++) // Beep loop
{
digitalWrite(P_AUDIO, HIGH);
delay(1);
digitalWrite(P_AUDIO, LOW);
delay(1);
}
digitalWrite(P_CW, LOW); // Key up
}
………………………………………………………………//……………………………………………………………………
// Simple Iambic Keyer v1.00
// by Ernest PA3HCM
#define P_DOT 2 // Connects to the dot lever of the paddle
#define P_DASH 3 // Connects to the dash lever of the paddle
#define P_AUDIO 12 // Audio output
#define P_CW 13 // Output of the keyer, connect to your radio
#define P_SPEED A0 // Attached to center pin of potmeter, allows you
// to set the keying speed.
int speed;
// Initializing the Arduino
void setup() {
// put your setup code here, to run once:
{
pinMode(P_DOT, INPUT);
pinMode(P_DASH, INPUT);
pinMode(P_AUDIO, OUTPUT);
pinMode(P_CW, OUTPUT);
digitalWrite(P_CW, LOW); // Start with key up
}
// Main routine
}
void loop() {
// put your main code here, to run repeatedly:
{
speed = analogRead(P_SPEED)/2; // Read the keying speed from potmeter
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 ay the given speed My note:the program has been blockt here telling : “keyAndBeep” was not declared in this scope !
delay(speed); // and wait before sending next
}
}
// Key the transmitter and sound a beep
void keyAndBeep(int speed)
{
digitalWrite(P_CW, HIGH); // Key down
for (int i=0; i < (speed/2); i++) // Beep loop
{
digitalWrite(P_AUDIO, HIGH);
delay(1);
digitalWrite(P_AUDIO, LOW);
delay(1);
}
digitalWrite(P_CW, LOW); // Key up
…………………………………………………………………………//………………………………………………………………
Error:
Arduino: 1.8.19 (Windows 8.1), Board: "Arduino Nano, ATmega328P"
(I'v tested also with ATmega328P – Old Bootloader , but I have the same result)
C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\daniel\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\daniel\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\daniel\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10819 -build-path C:\Users\daniel\AppData\Local\Temp\arduino_build_928746 -warnings=none -build-cache C:\Users\daniel\AppData\Local\Temp\arduino_cache_289800 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.arduinoOTA.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.avrdude.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -verbose C:\Users\daniel\Documents\Arduino\simple_iambic_keyer\simple_iambic_keyer.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\daniel\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\daniel\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\daniel\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10819 -build-path C:\Users\daniel\AppData\Local\Temp\arduino_build_928746 -warnings=none -build-cache C:\Users\daniel\AppData\Local\Temp\arduino_cache_289800 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.arduinoOTA.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.avrdude.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -verbose C:\Users\daniel\Documents\Arduino\simple_iambic_keyer\simple_iambic_keyer.ino
Using board 'nano' from platform in folder: C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.4
Using core 'arduino' from platform in folder: C:\Users\daniel\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.4
Detecting libraries used…
"C:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\cores\\arduino" "-IC:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\variants\\eightanaloginputs" "C:\\Users\\daniel\\AppData\\Local\\Temp\\arduino_build_928746\\sketch\\simple_iambic_keyer.ino.cpp" -o nul
Generating function prototypes…
"C:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\cores\\arduino" "-IC:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\variants\\eightanaloginputs" "C:\\Users\\daniel\\AppData\\Local\\Temp\\arduino_build_928746\\sketch\\simple_iambic_keyer.ino.cpp" -o "C:\\Users\\daniel\\AppData\\Local\\Temp\\arduino_build_928746\\preproc\\ctags_target_for_gcc_minus_e.cpp"
"C:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\ctags\\5.8-arduino11/ctags" -u –language-force=c++ -f – –c++-kinds=svpf –fields=KSTtzns –line-directives "C:\\Users\\daniel\\AppData\\Local\\Temp\\arduino_build_928746\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch…
"C:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\cores\\arduino" "-IC:\\Users\\daniel\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\variants\\eightanaloginputs" "C:\\Users\\daniel\\AppData\\Local\\Temp\\arduino_build_928746\\sketch\\simple_iambic_keyer.ino.cpp" -o "C:\\Users\\daniel\\AppData\\Local\\Temp\\arduino_build_928746\\sketch\\simple_iambic_keyer.ino.cpp.o"
C:\Users\daniel\Documents\Arduino\simple_iambic_keyer\simple_iambic_keyer.ino: In function 'void loop()':
simple_iambic_keyer:34:5: error: 'keyAndBeep' was not declared in this scope
keyAndBeep(speed); // … send a dot at the given speed
^~~~~~~~~~
simple_iambic_keyer:39:4: error: 'keyAndBeep' was not declared in this scope
keyAndBeep(speed*3); // … send a dash ay the given speed
^~~~~~~~~~
simple_iambic_keyer:47:1: error: a function-definition is not allowed here before '{' token
{
^
simple_iambic_keyer:57:1: error: expected '}' at end of input
}
^
exit status 1
'keyAndBeep' was not declared in this scope
Invalid version '2021.12.16.01' for library in: C:\Program Files (x86)\Arduino\libraries\K3NG_PS2Keyboard
Invalid library found in C:\Program Files (x86)\Arduino\libraries\simple_iambic_keyer: no headers files (.h) found in C:\Program Files (x86)\Arduino\libraries\simple_iambic_keyer
Invalid version '2021.12.16.01' for library in: C:\Users\daniel\Documents\Arduino\libraries\K3NG_PS2Keyboard
Invalid version '2021.12.16.01' for library in: C:\Program Files (x86)\Arduino\libraries\K3NG_PS2Keyboard
Invalid library found in C:\Program Files (x86)\Arduino\libraries\simple_iambic_keyer: no headers files (.h) found in C:\Program Files (x86)\Arduino\libraries\simple_iambic_keyer
Invalid version '2021.12.16.01' for library in: C:\Users\daniel\Documents\Arduino\libraries\K3NG_PS2Keyboard
Hi Dan,
I think you did some copy/paste work of the code from my website, since I see HTML-characters included. You better download the code from Github: https://raw.githubusercontent.com/pa3hcm/simple_iambic_keyer/master/simple_iambic_keyer.ino
Good luck!
Ernest
Hi Ernest,
Thanks, I solved the problem by following your advice.
In the future I intend to experiment with a keyer with ATMEGA 2560.
See You,
Dan b
OBS: I think it would be good to delete the pages with the “big problem” of uploading software from Feb 9, 2022 / 12:30
Hi all, Here’s a better version. Using a 10K pot the WPM span is precisely 10WPM to 30 WPM.
This uses the PARIS method of 50 time units per word. 44 is wrong, by the way.
The buzzer output gives a plain DC output, designed to connect to a regular self oscillating 5v buzzer.
// Simple Iambic Keyer v1.2
//
// Authors:
// Ernest PA3HCM
// Antti OH3HMU
// James Kearns
// Pin configuration
#define P_DOT 2 // Connects to the dot lever of the paddle
#define P_DASH 3 // Connects to the dash lever of the paddle
#define P_AUDIO 12 // Buzzer output
#define P_CW 13 // Output of the keyer, connect to your radio
#define P_SPEED A0 // Middle analog pin of potentiometer for adjusting keyer speed.
// Initializing the Arduino
void setup()
{
pinMode(P_DOT, INPUT_PULLUP);
pinMode(P_DASH, INPUT_PULLUP);
pinMode(P_AUDIO, OUTPUT);
pinMode(P_CW, OUTPUT);
digitalWrite(P_CW, LOW); // Start with keyer output low
digitalWrite(P_AUDIO, LOW); // Start with buzzer low
}
// Main routine
void loop()
{
// Read the keying speed from potentiometer and convert it to 10 to 30 WPM
int raw_wpm = (analogRead(P_SPEED)* 0.02)+10;
// Examples:
// 0 * 0.02 = 0 Add 10 = 10 WPM
// 512 * 0.02 = 10.xx Add 10 = 20 WPM
// 1023 * 0.02 = 20.xx Add 10 = 30 WPM
// Convert WPM result to unit time in milliseconds.
int delay_for_wpm = 60000 / (raw_wpm *50); // PARIS method of 50 time units per word.
// Examples continued:
// 60000 / (10wpm * 50) = 120ms
// 60000 / (20wpm * 50) = 60ms
// 60000 / (30wpm * 50) = 40ms
// If available, send new keyer data plus delay intervals
if(!digitalRead(P_DOT))
{
keyAndBeep(delay_for_wpm);
delay(delay_for_wpm);
}
if(!digitalRead(P_DASH))
{
keyAndBeep(3 * delay_for_wpm);
delay(delay_for_wpm);
}
}
// Key the transmitter and buzzer
void keyAndBeep(int speed)
{
// Output lines on
digitalWrite(P_CW, HIGH);
digitalWrite(P_AUDIO, HIGH);
delay(speed); // 40ms to 120ms x 3. ie 360ms
// Output lines off
digitalWrite(P_CW, LOW);
digitalWrite(P_AUDIO, LOW);
}
Ten years later, I built it! On an Arduino Nano, but did it, hihihi.
73
OA4CKN
Congratulations! 😀