 the Leonardo, since it has native USB HID support, without having to use additional boards or shields. Other boards might work, based on the ATmega32u4, but they haven't been tested. The Arduino Uno will NOT work.
2 Female 1/8" mono input plugs. These will accept the switch inputs.
1 Male 1/8" stereo output plugs. This will be plugged into whatever device you want to relay the switch closures to. Of course, you can also use 2 mono plugs as well.
2 2N2222 transistors.
A normally open momentary push button. This will be used to switch states.
1 10K Ohm potentiometer. This is used to control the output rate of the dots and dashes to the gBoard.
2 330 Ohm resistors.
Various Jumper wires.
Step 1: Fritzing Diagram...
If you are familiar with electronics, and just want to dive in an start assembling the parts, here is the Fritzing diagram.
You can assemble your project, and skip right to step X, where we will start programming it.
Here, we are just splicing our input wires on to jumper wires, which will later be plugged into the breadboard. Both input share the same ground.
Step 3: Create Your Output Wires.
Just splice the male plug to the jumper wires.
I just split to jumper wires, and put a 330 Ohm resistor between two of them. Make sure that all current in the wires is flowing through the resistor, and the resistor is not shorted.
I just found this to be a more reliable method for adding the resistors than adding them to the breadboard.
Step 5: Splice Jumper Wires on to Your Push Button.
That's it. All the prep work is done, and it's now time to start adding the components to the Arduino and the Breadboard.
Step 6: Add a Transistor to the Breadboard...
Put your NPN 2n2222 transistor on the breadboard.
The emitter goes to ground.
The base is going to go to an IO pin on the Arduino through a 330 Ohm resistor. We are using the wire we created with the resistor in step 3.
The collector goes to one of the wires for output that we created in step 2.
This is a wonderfully useful little circuit that can be used in a variety of applications where you want to automate control of a manual switch closure.
Just a little bit of how it works, that isn't necessary to understand...
The I/O pin sends current to the base through a resistor. The resistor keeps the current low enough to turn the transistor on, without going into saturation.
Step 7: Add Another Transistor to the Breadboard...
We are hooking it up the same way...
The base is going to go to an IO pin on the Arduino through a 330 Ohm resistor, using the wire created in step 3.
The collector goes to the other wire for output that we created in step 2.
We are also putting the ground wire for the output wire to the ground track of the breadboard at this time.
Notice that, at this time, we are just leaving the ground wires dangling.
We will tie them together later on.
Remember when we talked about how the transistors worked. The Arduino sends voltage through a resistor so that it activates the transistor without saturating it.
We hook one of the output wires with the resistor to PIN 2. We hook the other one up to PIN 3.
Later, when we program the Arduino, we will send HIGH to the appropriate pin when we want to close the switch.
Step 9: Add the Input Switch Pins to the Arduino...
Next plug the pins for the switch input into the Arduino.
There will be 3 wires.
One of the channels goes to PIN 5. The other channel goes to PIN 6.
The ground goes to a ground on the Arduino.
We are just using this ground because it is convenient. We have other grounds that we will be tying together later.
When we program the Arduino, we will be using an internal PULLUP resistor. When we see this goes low. We are going to do stuff.
We will send dots or dashes to the USB port. Or, we will send other characters to the USB port. Or, we will relay the switch closures to the transistors. In other applications, we could send data to an RF module.
Step 10: Add the Potentiometer...
The left wire goes to Ground.
The middle wire goes to PIN A0 on the Arduino.
The right wire goes to 5V on the Arduino.
The potentiometer in this project is to control the rate of dits and dahs (periods and hyphens) that the device is sending out.
Early in the development, the GBoard Morse code keyboard did not have the ability to send continuous dits and dahs when the key was held. Therefore, the functionality of this device was to mimic that behavior. And the potentiometer is used to set the rate in which those dits and dahs are repeated.
Current releases of the GBoard Morse code keyboard do support the functionality of producing multiple dits and dahs when the key is held, so the potentiometer to control the rate is now optional. (You can control the rate of the repeat in the GBoard settings).
But, the functionality is being retained because it remains useful to be able to control the speed just by turning the dial.
Step 11: Add the Speaker...
Positive goes to PIN 9.
Negative goes to ground.
The Speaker provides feedback for the keying of the dits and the dahs. It also provides a tone to signal changing the state.
Step 12: Wire the Push Button Which Changes States...
This project uses a momentary, normally open push button to change states.
One lead of the switch goes to PIN 12.
The other lead goes to ground.
Step 13: Finally, Tie Together All of Your Ground Wires.
Make sure that all of your ground wires are tied together, and lead to a ground on an Arduino.
The full source code for this project is included in the next step.
There is a lot of functionality in that source code that is not being included, and mentioned in this project.
In the source code is the ability to send switch states wirelessly through RF.
It also has the ability to switch states by holding down a switch longer than 3 seconds. This did not work well with the menu scanning features, so I switched to a push button to switch states.
The unused functionality is disabled in the source; either by commenting it out, or if statements or compiler directives.
I'm leaving it in the final source in case it is of interest to anyone, but I won't be explaining it's functionality here.
Also in the source is a lot of code for debouncing. When a mechanical switch is closed, as it is making contact, it often makes very short opening and closings before it reaches it's final state. This can produce unintentional double or triple beeps. This can be horribly frustrating to a disabled person attempting to type with Morse code.
I was debugging the code with particularly noisy switches, which needed a lot of debouncing. So, the code handles it pretty aggressively, but you can set the amount of debouncing with a variable in the code.
I will not be calling out the debouncing code, because it can be distracting.
I've mentioned it before, but if you are using an Arduino other than the Leonardo, your project might fail on this statement.
Next, we are going to assign our PINS to variables to be used later in the program.
const int DitOut = 2;   //When in TM mode, this sends the dit switch states to the TM.
const int DahOut = 3;   //When in TM mode, this sends the dah switch states to the TM.
const int SpeakerOut = 9;  //The speaker pin.
const int DitPot = A0;  //Analog port for Dit Potent to adjust speed.
const int DahPot = A1;  //Analog port for Dah Potent to adjust speed.
The following are configuration variables used in the program.
//These are the codes that the receiver is expecting to receive for DIT's and DAH's.
//These set what character to send when in GB mode.
//These set what characters to send when in Scanning mode.
//These are the frequencies that will be played when sounding.
//The available states that are achieved by holding down a switch.
//TODO:  These should be put into an array.
//Various housekeeping variables.
//These variables keep track of how long a switch was held.
//as soon as a switch is hit.  But only once.  This keeps track of that for us.
Read the value of the state switching button.
If it's been closed (LOW), then increment the state (see later function), put a bit of a delay in there, and make sure that we are only executing it once per closure.
Check to see if the Dit switch has been closed.
Then, we see what State the device is in.
If it is in GBoard State OR the Scan State, then we are going to be doing keyboard events.
We want to get a character out there, right away. When a switch is hit, no delay routines should get in the way.
Play the dit tone, with a duration of 1/2