Turn your Arduino into an AM radio transmitter!

This simple project shows how you can make your Arduino into an AM-band transmitter.

Wiring: Plug a wire into pin D9.

Sketch:

const byte ANTENNA = 9;

void setup() 
  {
  // set up Timer 1
  TCCR1A = _BV (COM1A0);  // toggle OC1A on Compare Match
  TCCR1B = _BV(WGM12) | _BV(CS10);   // CTC, no prescaler
  OCR1A =  9;       // compare A register value to 10 (zero relative)
  }  // end of setup

void loop() 
  {
  pinMode (ANTENNA, OUTPUT);
  delay (500);
  pinMode (ANTENNA, INPUT);
  delay (300);
  }  // end of loop

Theory: The 16 MHz clock is divided by 10 (that is, 1.6 MHz) and that is used to toggle pin 9 at that rate, giving a frequency of 800 KHz, since one toggle turns the output on, and second toggle turns it off.

If you hold the Arduino near an AM radio tuned to around 800 KHz you should hear a hissing toggling on and off (like Morse code) as the carrier is turned on and off for 0.5 / 0.3 second intervals.

FUN!
what stopped you from implementing a real morse lib into the code ? :wink:

Trying to keep it simple. :slight_smile:

But I'm sure adding Morse into it would be pretty trivial.

Nice work.

I am going to try it. Just one wire... SIMPLE hook-up... and load the code... you are done...

Thank Nick Gammon

Well the next logical step would be to add in the tone library and allow a audio frequency tone output pin to modulate the timer output pin 'AM carrier frequency', then you would be talking true Amplitude Modulation, AM. However with everything being square wave outputs, don't now how easy it would be to combine these two signal outputs into a single AM output. Needs a little cleaver passive filtering and combining function circuit.

Lefty

How do you change the frequency ?

The OCR1A variable is related to the frequency.
The OCR1A variable is one less than the actual divisor.
OCR1A - Frequency
15 - 500 khz
14 - ~530 khz
13 - ~570 khz
12 - ~610 khz
11 - ~670 khz
10 - ~730 khz
9 - 800 khz
8 - ~890 khz
7 - 1000 khz
6 - ~1140 khz
5 - ~1330 khz
4 - 1600 khz
3 - 2000 khz
2 - ~2670 khz
1 - 4000 khz
0 - 8000 khz *would not recommend this setting

The formula is (16÷(OCR1A+1)÷2)×1000 = frequency in khz

The way to add tone to this, is by changing the delay between the two states, to get a 500 or 1000 hz (I'm not to sure) tone, you simply put in

pinMode (ANTENNA, OUTPUT);
 delay (1);
 pinMode (ANTENNA, INPUT);
 delay (1);

And you can adjust the delay to meet your specifications.

This is really handy. I added some basic tone abilities and encoded twinkle twinkle.

const byte ANTENNA = 9;

unsigned long A = calcDelayTimeForFreq(440);
unsigned long B = calcDelayTimeForFreq(494);
unsigned long C = calcDelayTimeForFreq(523);
unsigned long D = calcDelayTimeForFreq(587);
unsigned long E = calcDelayTimeForFreq(659);
unsigned long F = calcDelayTimeForFreq(699);
unsigned long G = calcDelayTimeForFreq(784);
unsigned long _A2 = calcDelayTimeForFreq(880);
unsigned long rest = 1;

unsigned long q = 652;
unsigned long e = q/2;
unsigned long s = e/2;
unsigned long t = s/2;
unsigned long h = q*2;
unsigned long f = q*4;

void setup() {
  // set up Timer 1
  TCCR1A = _BV (COM1A0);  // toggle OC1A on Compare Match
  TCCR1B = _BV(WGM12) | _BV(CS10);   // CTC, no prescaler
  OCR1A =  9;       // compare A register value to 10 (zero relative)
}  // end of setup

void tone(unsigned long dTime, unsigned long playTime) {
  unsigned long end = millis() + playTime;
  
  while (end > millis()) {
    pinMode (ANTENNA, OUTPUT);
    delayMicroseconds(dTime);
    pinMode (ANTENNA, INPUT);
    delayMicroseconds(dTime);    
  }
}

void note(unsigned long dTime, unsigned long playTime) {
  tone(dTime,playTime-50);
  tone(rest,50);
}

unsigned long calcDelayTimeForFreq(unsigned long freq) {
  return 500000/freq;
}


void twinkleTwinkle() {
  note(C,q);
  note(C,q);
  note(G,q);
  note(G,q);
  note(_A2,q);
  note(_A2,q);
  note(G,h);
  
  note(F,q);
  note(F,q);
  note(E,q);
  note(E,q);
  note(D,q);
  note(D,q);
  note(C,h);
  
  note(G,q);
  note(G,q);
  note(F,q);
  note(F,q);
  note(E,q);
  note(E,q);
  note(D,h);
  
  note(G,q);
  note(G,q);
  note(F,q);
  note(F,q);
  note(E,q);
  note(E,q);
  note(D,h);
  
  note(C,q);
  note(C,q);
  note(G,q);
  note(G,q);
  note(_A2,q); 
  note(_A2,q);
  note(G,h);

  note(F,q);
  note(F,q);
  note(E,q);
  note(E,q);
  note(D,q);
  note(D,q);
  note(C,h);
} 

void locateTone() {
  note(A,t);
  note(B,t);
  note(C,t);
  note(D,t);
  note(E,f);
  note(D,t);
  note(C,t);
  note(B,t);
}

void loop() {
  twinkleTwinkle();
}

I actually attached this to a disconnected sprinkler valve control wire and followed it around my yard with an am radio to find where the old valves were located. Pretty handy.

Nice, going to try it

Where I connect the audio in

Hmmm. Compiles and runs OK on 1.0.6 and 1.6.4 buts lots of compile errors on 1.6.7

What don't I understand??

I got compiled all of two using 1.6.7 but in the second one by headpigeons I had to move the calcDelayTimeForFreq function before the others declarations, just after "const byte ANTENNA = 9;"

This is a very fun project for learning about radio frequencies. I am wondering if there is a way to increase the range of the transmission. I have figured out how to change the frequency by modifying the OCR1A variable. Adding a longer antenna wire doesn't seem to make much of a difference. I have about 1ft of antenna wire attached and I can notice the signal works up to about 1-2 feet.

Would tuning the antenna length to some fraction of a full wavelength (375m at 800KHz) increase the output?

Would an opamp drive the signal far enough to be of any use?

Hi Smoke & Nick,

Hmmm..
13 - ~570 khz

I gotta run this; I used to work for the Straus Broadcasting Group (WMCA Good Guys 50 KW on 570 KHz ).

And I am doing a little with Morse (AKA Real Simple Digital Communications) with kids. Some info here:
http://arduino-info.wikispaces.com/YourSmartArduino

Would tuning the antenna length to some fraction of a full wavelength (375m at 800KHz) increase the output?

5V signal should be able to put 10 Mv/M at over 100 feet I would think.. I'll do some testing...

I'd like to do something about Switches... to "How can you communicate with just one Switch?" to kids communicating across a classroom. In the Internet Era this is still relevant.

(I had to move this to the beginning to get it to compile on 1.8.2 )

unsigned long calcDelayTimeForFreq(unsigned long freq) {
  return 500000/freq;
}

Hi, OK got this working for very simple Morse Key mode. I'll use it this week with 4th grade. we are doing Electricity, serial-parallel, and SWITCHES.. Last week I manually sent "HI" with a piezo buzzer and two wires. They were intrigued with "Signals"...

I have a hand-cranked radio (shows conversion of mechanical energy to electrical energy)... I'll use that to show "wireless" communication. AKA "RADIO"...

Here's the simplified code:

/* YourDuinoStarter Example: Morse Radio Transmitter
 - WHAT IT DOES: User sends Morse code in the AM Broadcast Band - very low power
 - SEE the comments after "//" on each line below
 - CONNECTIONS:
   - Pin 2  - Morse key to ground
   - Pin 9  - Antenna (20+ feet long)
 - V1.00 05/01/2017
   Questions: terry@yourduino.com */

/*-----( Declare Constants and Pin Numbers )-----*/
#define MORSE_KEY 2
#define ANTENNA 9

/*
 The OCR1A variable is related to the frequency.
The OCR1A variable is one less than the actual divisor.
OCR1A - Frequency
15 - 500 khz
14 - ~530 khz
13 - ~570 khz   (WMCA New York )
12 - ~610 khz
11 - ~670 khz
10 - ~730 khz
9 - 800 khz
8 - ~890 khz
7 - 1000 khz   (Good for test)
6 - ~1140 khz
5 - ~1330 khz
4 - 1600 khz* 
 */
#define MORSE_KEY 2
#define ANTENNA 9

void setup()   /****** SETUP: RUNS ONCE ******/
{
  // set up Timer 1
  TCCR1A = _BV (COM1A0);           // toggle OC1A on Compare Match
  TCCR1B = _BV(WGM12) | _BV(CS10); // CTC, no prescaler
  OCR1A =  7; //(From frequency Table Above ( compare A register value to 10 (zero relative))
  pinMode(MORSE_KEY,INPUT_PULLUP);
}  // end of setup



void loop()   /****** LOOP: RUNS CONSTANTLY ******/ 
{
  if (digitalRead(MORSE_KEY) == LOW)
  {
    pinMode (ANTENNA, OUTPUT);  // Modulate the RF carrier on-off at audio rate
    delayMicroseconds(800);
    pinMode (ANTENNA, INPUT);
    delayMicroseconds(800);     
  }
  else  
  {
    pinMode (ANTENNA, OUTPUT);   // Unmodulated carrier: not so much background noice
  }

}//--(end main loop )---
1 Like

Hello, can anyone post receiver circuit? I need it just to turn led on/off on signal received. Thanks.

terryking228, did you ever listen to Waltzing Matilda on a portable radio set on top of an IBM 1401/1440?

Paul

ArduinoUser:
Hello, can anyone post receiver circuit? I need it just to turn led on/off on signal received. Thanks.

Search on crystal radio set for how to build a receiver. What can be heard on an earphone can be detected by Arduino.

Test the transmitter with an ordinary AM radio.