ٱلْحَمْدُ لِلّٰهِ رَبِّ ٱلْعَالَمِينَ، وَٱلصَّلَاةُ وَٱلسَّلَامُ عَلىٰ خَاتَمُ ٱلْأَنْبِيَاءِ وَٱلْمُرْسَلِينَ
When repairing or experimenting with AM radios, one of the most useful tools is a small AM signal generator. Professional RF signal generators are expensive, but for basic alignment, testing, and educational purposes, a microcontroller can generate a surprisingly useful AM-modulated signal.
The ESP32-C3 has a fast RISC-V processor, flexible GPIO hardware, and peripherals capable of generating accurate digital waveforms. By generating a carrier frequency in the AM broadcast band and switching its amplitude ON and OFF according to an audio signal, the ESP32-C3 can act as a simple AM transmitter.
This project creates a low-power AM transmitter that can be received on any ordinary AM radio.
/*
Arduino Uno
D9 (OC1A) -> 1 MHz AM output
1 MHz carrier is turned ON and OFF to create
100% amplitude modulation.
*/
const byte RF_PIN = 9;
const int notes[] = {
262,262,392,392,440,440,392,
349,349,330,330,294,294,262
};
const int beats[] = {
4,4,4,4,4,4,8,
4,4,4,4,4,4,8
};
const int NUM_NOTES = sizeof(notes)/sizeof(notes[0]);
void carrierOn()
{
TCCR1A = _BV(COM1A0); // Toggle OC1A
}
void carrierOff()
{
TCCR1A = 0;
digitalWrite(RF_PIN, LOW);
}
void playTone(int freq, int duration)
{
unsigned long period = 1000000UL / freq;
unsigned long endTime = millis() + duration;
while (millis() < endTime)
{
carrierOn();
delayMicroseconds(period / 2);
carrierOff();
delayMicroseconds(period / 2);
}
carrierOn();
}
void setup()
{
pinMode(RF_PIN, OUTPUT);
TCCR1A = 0;
TCCR1B = _BV(WGM12) | _BV(CS10); // prescalar = 1, CTC or
OCR1A =7; //1600 khz
//| OCR1A | Frequency |
//| ----: | ------------------------: |
//| 4 | 1.600 MHz |
//| 5 | 1.333 MHz |
//| 6 | 1.143 MHz |
//| 7 | 1.000 MHz |
//| 8 | 888.889 kHz |
//| 9 | 800.000 kHz |
//| 10 | 727.273 kHz |
//| 11 | 666.667 kHz |
//N=1 for TCCR1B = _BV(WGM12) | _BV(CS10); // CTC mode, prescaler = 1
// f= fcpu / 2×N×(OCR1A+1
carrierOn();
}
void loop()
{
for (int i = 0; i < NUM_NOTES; i++)
{
playTone(notes[i], beats[i] * 125);
delay(30);
}
carrierOn();
delay(1000);
}