Arduino Fox
This project is largely based off VK5FSKS and WT4Y’s design, with a few modifications. I only intend for the Fox to be in use for a few hours at a time. Therefore, I pulled 7v DC power from the Baofeng UV-5R battery to power the Arduino Mega using a barrel connector. You could use a smaller Arudino for this project. I used the Mega as I had an extra laying around.
I also modified the Arudino code a bit. I was unable to identify the ‘Aussie Folk Song’. I changed the melody to A-Tisket A-Tasket, which is in the public domain. I didn’t care for the melody playing on every loop iteration. Therefore, I made a new switch case which can be called by DTMF tone.
Supply list includes:
- Baofeng UV-5R
- Beofeng Headset/Mic
- Arudino Mega 2560
- 5v Single Channel Autocoupler Relay (10amp)
- Toggle Switch (not necessary)
Fritzing Diagram :

Arduino Code
*NOTE* The DTMF Library and Pitches.H are required. Both are attached at the bottom of this post.
/*Be Sure to Edit variables for beaconstring[] and idstring[] in code replacing "CALLSIGN" with your actual callsign
char beaconstring[] = "CQ CALLSIGN/FOX";
char idstring[] = "DE CALLSIGN";
*/
//DTMF controlled Fox
//DTMF 1 = Start Fox
//DTMF 2 = A-Tisket A-Tasket
//DTMF 7 = Fox Tx '73' in Morse
//DTMF 5 = Fox Tx 'Have you found me yet' in Morse
//DTMF 0 = Fox DISABLED
// Arduino controlled Fox Hunting Xmtr and / or Beacon
// Code cobbled together from various sources
//Connections
//Baofeng Mic/Headset cable
//-------------------------
//3.5mm Sleve (orange) to Relay Common
//3.5mm Ring (Red) to Arduino Pin6 (PWM)
//2.5mm Sleve (Blue) to Relay N/C (Normally Closed)
//2.5mm Tip (Green) to Arduino A0
//Relay
//Normally open to Relay GND
//Signal Pin to Arduino Pin7
//VCC to Arduino 5V
//GND to Arduino GND
// Pin 6 is the square wave output for the Morse Code
// Pin 7 is Push to Talk pin (low = PTT)
// A0 is the Analog Input for DTMF detection
#include <DTMF.h>
#include "pitches.h"
int sensorPin = A0; //The following block used by DTMF
float n = 128.0;
float sampling_rate = 8926.0;
DTMF dtmf = DTMF(n, sampling_rate);
float d_mags[8];
char thischar;
int xmit = 1; // if xmit = 0, don't transmit
int pause = 220; // pause between transmissions, 22 = 1 second (approx)
// notes in the melody:
int melody[] = {
NOTE_G4, NOTE_G4, NOTE_E4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_G4, NOTE_E4, NOTE_A4, NOTE_G4
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 2, 4, 4, 2, 4, 4, 4, 4, 4, 4, 2
};
#define PTT 7
#define BUZZER_PIN 6 // send music and cw out this pin
#define BUZZER_FREQUENCY 700 // cw pitch
char beaconstring[] = "CQ CALLSIGN/FOX";
char idstring[] = "DE CALLSIGN";
int randNumber;
char chartemp[4] ;
char incomingByte = 0;
//int morseOutput = 4; //Pin for receiving Morse output - attach LED to this pin
int interval = 60; //length of time for one dot - basic unit of measurement; one interval occurs between each dot or dash; dash is equivalent to 3 dots; 7 dots between words
String alphabet = "abcdefghijklmnopqrstuvwxyz1234567890/ ";
String ALPHABET = alphabet;
String morseCode[] = {
".-", // A
"-...", // B
"-.-.", // C
"-..", // D
".", // E
"..-.", // F
"--.", // G
"....", // H
"..", // I
".---", // J
"-.-", // K
".-..", // L
"--", // M
"-.", // N
"---", // O
".--.", // P
"--.-", // Q
".-.", // R
"...", // S
"-", // T
"..-", // U
"...-", // V
".--", // W
"-..-", // X
"-.--", // Y
"--..", // Z
".----", // 1
"..---", // 2
"...--", // 3
"....-", // 4
".....", // 5
"-....", // 6
"--...", // 7
"---..", // 8
"----.", // 9
"-----", // 0
"-..-.", // forward slash
" " //space character
};
void setup() {
pinMode(PTT, OUTPUT);
digitalWrite(PTT, LOW);
Serial.begin(9600);
// pinMode(morseOutput, OUTPUT);
ALPHABET.toUpperCase();
randomSeed(analogRead(0)); // in case random delays between
// transmissions are used
}
void loop() {
// randNumber = random(110, 440); // remove comments to use random delays
// pause = randNumber; // example is 5 to 20 second pause
Serial.println("BeginPause");
for (int x = 0; x < pause; x ++) // while waiting between transmissions, look for DTMF
{
Serial.println(x);
dtmf.sample(sensorPin);
dtmf.detect(d_mags, 506);
thischar = dtmf.button(d_mags, 1800.);
if (thischar) { // decide what to do if DTMF tone is received
switch (thischar) {
case 49: // the number 1
xmit = 1; // set the flag to enable transmissions
break;
case 50: //number 2
digitalWrite(PTT, HIGH);
delay(2000);
// play a little melody
for (int thisNote = 0; thisNote < 12; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000 / noteDurations[thisNote];
tone(BUZZER_PIN, melody[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(BUZZER_PIN);
}
digitalWrite(PTT, LOW);
delay(2000);
break;
case 53: //number 5
digitalWrite(PTT, HIGH);
delay(2000);
sendLetter('h');
sendLetter('a');
sendLetter('v');
sendLetter('e');
sendLetter('y');
sendLetter('o');
sendLetter('u');
sendLetter('f');
sendLetter('o');
sendLetter('u');
sendLetter('n');
sendLetter('d');
sendLetter('m');
sendLetter('e');
digitalWrite(PTT, LOW);
delay(2000);
break;
case 54: //number 6
digitalWrite(PTT, HIGH);
delay(2000);
for (int i = 0; i < sizeof(idstring); i++){
sendLetter(idstring[i]);
}
digitalWrite(PTT, LOW);
delay(2000);
break;
case 55: //number 7
digitalWrite(PTT, HIGH);
delay(2000);
sendLetter('7');
sendLetter('3');
digitalWrite(PTT, LOW);
delay(2000);
break;
default: // any other number, turn off transmissions
xmit = 0; // set the flag to disable transmissions
break;
}
}
delay(1);
}
Serial.println("PauseEnd");
if (xmit == 1)
{
digitalWrite(PTT, HIGH);
delay(2000); // delay 2 seconds after PTT to account for race condition
for (int i = 0; i < sizeof(beaconstring); i++){
sendLetter(beaconstring[i]);
}
delay(500);
digitalWrite(PTT, LOW); // drop the PTT and wait a while
}
}
// End of Loop()
// Functions follow
void sendLetter (char c) {
int i;
for (i = 0; i < alphabet.length(); i = i + 1) {
if (alphabet[i] == c || ALPHABET[i] == c) {
//Serial.print(c);
sendMorseCode(morseCode[i]);
return;
}
}
if (c == '\n')
Serial.println();
}
void sendMorseCode (String tokens) {
int i;
for (i = 0; i < tokens.length(); i = i + 1) {
switch (tokens[i]) {
case '-':
sendDash();
break;
case '.':
sendDot();
break;
case ' ':
sendEndOfWord();
break;
}
}
morseOutputOff(2);
// Serial.print(" ");
}
void sendEndOfWord() {
morseOutputOff(4);
// Serial.print(" ");
}
//basic functions - Morse code concepts
void sendDot() {
tone(BUZZER_PIN, BUZZER_FREQUENCY);
morseOutputOn(1);
noTone(BUZZER_PIN);
morseOutputOff(1);
// Serial.print(".");
}
void sendDash() {
tone(BUZZER_PIN, BUZZER_FREQUENCY);
morseOutputOn(3);
noTone(BUZZER_PIN);
morseOutputOff(1);
// Serial.print("-");
}
//Low level functions - how the actions are accomplished
// n = number of intervals
// interval is a fixed length of time determined at start, for example 200 milliseconds
void morseOutputOn (int n) {
// example: morseOutputOn(1) means turn output on and keep it on for 1 interval
// morseOutputOn(3) means turn output on and keep it on for 3 intervals
//
// digitalWrite(morseOutput, HIGH);
delay(n * interval);
}
void morseOutputOff (int n) {
// digitalWrite(morseOutput, LOW);
delay(n * interval);
}