Most ICOM transceivers have a voice / message memory on board, able to 'play' 1 ... 4 pre defined messages - very handy to run contests or pile-ups ! The playback of the messages can be initiated by depressing a multi function key on the front panel (however in this mode you are losing the scope view - this is a disadvantage) , or by the F1 ... F4 keys on a USB keyboard connected (some additional clutter on the desktop) , or by providing a small external homebrew keypad with 4 pushbuttons - connected to the MIC key.
Here is the schematic diagram of such keypad :
However, there is no possibility to provide automatic repetition of messages - and this is a pity indeed ...
The project hereby presented will ensure the interactive control of playback of the 4 messages, either in 'single-shot' mode or with a possibility to have them automatically repeated after an adjustable pause in between.
A small ARDUINO controller will handle all the logic, and can be integrated in the external key pad box; which - if fitted with a mating MIC plug, can simply be inserted in-line with the microphone!
The total project cost is estimated around 20, EUR, and probably the most expensive single component will be microphone plug !
Module is autonomous & powered by the +8v supply available on the MIC plug, no external power & messy leads required !
4 push buttons provided to trigger playback of each message
A short tap on a button will generate a 'single shot' message (just like on the transceiver panel)
A longer press will start the playback of corresponding message, and set the unit in repeat mode.
The interval between messages (= pause) can be adjusted by a potentiometer between 1 and 20 seconds (irrespective of message lenght)
Visual indication of mode : 2 possibilities, with no software change required :
One LED : flashing briefly in single shot mode, constantly lit in repeat mode , for any message played
Four LEDs : same as above, but the LED corresponding to the message / button is lit. Can be used with buttons where LED are integrated ;o)
At any time, in any mode, the message playback can be immediately ended by depressing any button.
If any button is depressed while in repeat mode, repeat mode is halted and keyer is reverting into stand-by mode
if the PTT (or footswitch, CW key...) is depressed during a pauze in repeat mode (e.g. reverting to a calling station), the auto mode is halted and the keyer is reverting into stand-by mode
The project was realized with an ARDUINO Nano board, offering the advantage of being flashable by USB port. But smaller versions can be used if desired ! Click on the image below to download the full sized digram. During realization, take care not short-circuiting the +8v supply or the voltage regulator in your transceiver will be SK !
Click to download full size PDF
Below is the sketch or download it here. It was compiled with IDE version 1.0.6 - IMPORTANT : Should you get errors when compiling, use the same version of IDE ! You still can download previous versions from ARDUINO website .
IMPORTANT: Please note that the software & device concept is presented 'as is' with no guarantees whatsoever and can be used free of license cost by individual HAMs, but not used for any commercial purpose, as the intellectual property remains entirely by the author.
/////////////////////////////////////////////////////// // // // ICOM AUTO KEYER // // by ON7EQ 03/2016 // // // /////////////////////////////////////////////////////// // compiled with IDE v 1.0.6 #define input1 (2) // pushbutton 1 input pin (pushbutton depressed = LOW) #define input2 (3) // pushbutton 2 input pin #define input3 (4) // pushbutton 3 input pin #define input4 (5) // pushbutton 4 input pin #define output1 (6) // output 1 pin - to open collector NPN - output active = HIGH #define output2 (7) // output 2 pin - to open collector NPN #define output3 (8) // output 3 pin - to open collector NPN #define output4 (9) // output 4 pin - to open collector NPN #define LED_output (13) // output pin - to LED - if only one LED #define LED_output1 (A2) // output pin - to LED corresponding with button 1 (optional) #define LED_output2 (A3) // output pin - to LED corresponding with button 2 (optional) #define LED_output3 (A4) // output pin - to LED corresponding with button 3 (optional) #define LED_output4 (A5) // output pin - to LED corresponding with button 4 (optional) #define PTT_read (A1) // input for reading PTT (to define RX/TX status) #define Delay_pot_pin (A0) // input for reading potentiometer for delay byte mode = 0; byte button = 0; byte longpress = 0; byte OneShot = 0; // one shot flag byte Repeat = 0; byte arm = 0; // arm for repress detect in repeat mode byte stop_by_PTT = 0; byte EOM_flag = 0; // end of message flag byte button_pressed = 0; int unsigned long RX_time = 0; int unsigned long RepeatInterval = 0; int unsigned long Button_time_pressed = 0; int unsigned long EOM_time = 0; //////////////////////////////////////////////////////////// //////////////////// S E T U P ////////////////////////// //////////////////////////////////////////////////////////// void setup() { pinMode (input1, INPUT); pinMode (input2, INPUT); pinMode (input3, INPUT); pinMode (input4, INPUT); //Activate pull-ups digitalWrite(input1, HIGH); digitalWrite(input2, HIGH); digitalWrite(input3, HIGH); digitalWrite(input4, HIGH); digitalWrite(PTT_read, HIGH); pinMode (output1, OUTPUT); pinMode (output2, OUTPUT); pinMode (output3, OUTPUT); pinMode (output4, OUTPUT); digitalWrite(output1, LOW); digitalWrite(output2, LOW); digitalWrite(output3, LOW); digitalWrite(output4, LOW); pinMode (LED_output, OUTPUT); pinMode (LED_output1, OUTPUT); pinMode (LED_output2, OUTPUT); pinMode (LED_output3, OUTPUT); pinMode (LED_output4, OUTPUT); digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); } /////////////////////////////////////////// //////////// L O O P /////////////// /////////////////////////////////////////// void loop() { if (Repeat == 0) { // single shot mode button actions // check if any button depressed, and define mode if (digitalRead(input1) == LOW) button = 1; // any of 4 buttons pressed else if (digitalRead(input2) == LOW) button = 1; else if (digitalRead(input3) == LOW) button = 1; else if (digitalRead(input4) == LOW) button = 1; else { // no button pressed button = 0; // no button pressed if (button_pressed == 1) button_pressed = 0; // button was released OneShot = 0; // be ready for new pulse longpress = 0; // long press released } if ((button == 1) and (mode < 20)) { // if ((button == 1)) { delay (30); //Crude debounce if (digitalRead(input1) == LOW) button = 11; // Button 1 effectively pressed else if (digitalRead(input2) == LOW) button = 12; // Button 1 effectively pressed else if (digitalRead(input3) == LOW) button = 13; // Button 1 effectively pressed else if (digitalRead(input4) == LOW) button = 14; // Button 1 effectively pressed else { button = 0; // it was bounce or button was released button_pressed = 0; longpress = 0; OneShot = 0; // be ready for new pulse } if ((button_pressed == 0) and (button > 10) and (button < 20)) { button_pressed = 1; // a button was depressed ! Button_time_pressed = millis(); // time stamp a button pressed } } if ((button_pressed == 1) and (millis() - Button_time_pressed > 300) ) { // check if long press on button > 0.5 sec if (longpress == 0) { // going into repeat mode longpress = 1; // button pressed for repeat mode ! if (digitalRead(input1) == LOW) mode = 21; // Button 1 else if (digitalRead(input2) == LOW) mode = 22; // Button 2 else if (digitalRead(input3) == LOW) mode = 23; // Button 3 else if (digitalRead(input4) == LOW) mode = 24; // Button 4 digitalWrite(LED_output, HIGH); // Repeat mode RX_time = millis () + 60000; // set repeat timer } } } // end single shot mode if (Repeat == 1) { // repeat mode button actions // Wait for button released = arm condition ! if ((digitalRead(input1) == LOW) // any of 4 buttons pressed ? or (digitalRead(input2) == LOW) or (digitalRead(input3) == LOW) or (digitalRead(input4) == LOW)) { delay (0) ; // do nothing } else (arm = 1); // button released, arm for repress => force stop // Wait for button pressed = exit mode ! if (((digitalRead(input1) == LOW) // any of 4 buttons pressed ? or (digitalRead(input2) == LOW) or (digitalRead(input3) == LOW) or (digitalRead(input4) == LOW)) and (arm == 1)) { arm =0; mode = 99; // Exit repeat mode } } // end repeat mode button actions //////////////////////////////////////////////////////////// /////////////// Take actions according to mode /////////// //////////////////////////////////////////////////////////// /////////////////// Single press //////////////// if ((button_pressed == 1) and (OneShot == 0) ) { digitalWrite(LED_output, HIGH); if (button == 11) { digitalWrite(output1, HIGH); digitalWrite(LED_output1, HIGH); } if (button == 12) { digitalWrite(output2, HIGH); digitalWrite(LED_output2, HIGH); } if (button == 13) { digitalWrite(output3, HIGH); digitalWrite(LED_output3, HIGH); } if (button == 14) { digitalWrite(output4, HIGH); digitalWrite(LED_output4, HIGH); } delay (100); // pulse keyer digitalWrite(output1, LOW); digitalWrite(output2, LOW); digitalWrite(output3, LOW); digitalWrite(output4, LOW); digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); OneShot = 1; } ///////////////// Long press ////////////// if ((mode > 20) and (mode < 30)) { Repeat = 1; RepeatInterval = map(analogRead(Delay_pot_pin), 0, 1023, 1000, 20000); // 1 to 20 sec interval // Generate repeat pulse after interval, only in in RX if ((millis() - RX_time > RepeatInterval) and (EOM_flag == 1) and (analogRead(PTT_read) > 500)) { RX_time = millis (); EOM_flag = 0; if (mode == 21) digitalWrite(output1, HIGH); if (mode == 22) digitalWrite(output2, HIGH); if (mode == 23) digitalWrite(output3, HIGH); if (mode == 24) digitalWrite(output4, HIGH); digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); delay (100); // Pulse output digitalWrite(LED_output, HIGH); if (mode == 21) digitalWrite(LED_output1, HIGH); if (mode == 22) digitalWrite(LED_output2, HIGH); if (mode == 23) digitalWrite(LED_output3, HIGH); if (mode == 24) digitalWrite(LED_output4, HIGH); digitalWrite(output1, LOW); digitalWrite(output2, LOW); digitalWrite(output3, LOW); digitalWrite(output4, LOW); } delay(50); // extra delay - allow TRX to go into TX mode and bring PTT line down if (analogRead(PTT_read) < 500) RX_time = millis () ; if ((analogRead(PTT_read) < 500) and (EOM_flag == 0)) { // Higher than 2,5 V on PTT line = RX // // RX_time = millis (); // timestamp going into RX mode. as long as in TX, RX_time is reset to millis() EOM_time = millis(); // timestamp end of message } if (analogRead(PTT_read) > 500) EOM_flag = 1; // PTT line becomes HIGH, message has been played. Required to detect subsequent stop by PTT /// STOP BY PTT during pause interval if (((millis( )- EOM_time > 50)) and (millis() < (EOM_time + RepeatInterval - 50)) and (analogRead(PTT_read) < 500) and (arm == 1)) { // PTT depressed during pause between messages --> stop keyer! stop_by_PTT = 1; arm = 0; mode = 99; EOM_flag = 0; } } // end of repeat mode // EXIT REPEAT MODE if (mode == 99) { Repeat = 0; digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); mode = 0; // check if message playing, issue a pulse to stop if ((analogRead(PTT_read) < 500) and (stop_by_PTT == 0)) { // Yes, PTT is low, and was not forced stop by keying digitalWrite(output1, HIGH); delay (100); // Pulse output digitalWrite(output1, LOW); } stop_by_PTT = 0; //wait till buttons released before looping again while ((digitalRead(input1) == LOW) // if any of 4 buttons pressed, wait till released ! or (digitalRead(input2) == LOW) or (digitalRead(input3) == LOW) or (digitalRead(input4) == LOW)) {} delay (100); } } // End of loop