Background
Using simply a wire, an AM radio will be created.
It uses timer 0 to create a high-frequency carrier (1MHz) and timer 1 to create a low-frequency (125Hz) audio signal. Thus, timer peripheral can be used to create square waves of different frequencies.
Theory
AM Radio consists of a signal superimposed on a carrier signal. The frequency of the signal is less than the frequency of the carrier.
We’ll be configuring the Atmega328p as a AM radio transmitter. This entails sending a 1MHz square wave. This is the carrier frequency. We’ll modulate it by superimposing on the carrier frequency a rapidly changing squarewave set to the audio frequency. We’ll output this to an I/O pin and blast it across the room.
To listen to this project, set an AM radio to 1000kHz.
To output a 1MHz square wave, we need to increase the CPU clock frequency. Straight from the box, the 8MHz advertised frequency is actually divided by 8 to 1MHz. This is to save power. There are 2 ways to change this. Through hardware by configuring the fuse bits (this is permanent) or software via avr/power.h. The later is more flexible as you can adjust the clock speed on the fly. The program will use the later method.
The signal will consist of a beep tone. This is comprised of a pitch and duration. Just like this, we can create sound.
Hardware Connections
A dangling wire connected to an I/O, PD5/OCO5. The longer the better!
The Software
Program consists of a single main.c with a helper file, scale16.h. Full source code available at my GitHub repository.
We combine timers with interrupts.
To set the CPU speed to 8MHz, we simply add 2 lines in code. This undoes the CLDIV fuse bit which prescales the F_CPU by 8.
#include <avr/power.h>
clock_prescale_set(clock_div_1);
Timer 0 is configured to run in CTC Mode, thereby generating a 1MHz square wave. It triggers an ISR every time the counter overflows.
Showcase
One period lasts for 4ms. The 1MHz signal has a period of 1us. A high pulse is 2ms. This means that there are 2ms / 1us = 2000 oscillations in that single HIGH pulse. If my scope had greater resolution for the timebase, say 500ns/div, you’d be able to see the 1us waves toggling very fast. Also, this DIY scope doesn’t display the frequency, which is annoying.
