
Originally Posted by
MarkT
Sounds like a job for a DDS module, not a microcontroller. Cheap AD9833 module perhaps?
That was my first thought as well. Since I had such a $2.50 module laying around, I decided to give it a try.
The nice thing about the AD9833 is that it has 2 frequency registers that you can pre-program and than dynamically switch between those 2 registers and thus send out these 2 frequencies alternatingly.
Here is the code:
Code:
// AD9833 bd Teensy 3.x
// VCC Vin 5V
// DGND GND
// SDATA 11 MOSI
// SCLK 13 SCK
// FSYNC 10 SS
#include <SPI.h>
#define FSYNC 10
#define SPI_CLOCK_SPEED 12000000 // 12MHz SPI clock
uint32_t spaceFreqWord = 0x1888f8; // 150kHz - 250Hz, FreqWord = (frequency * pow(2, 28))/MCLK
uint32_t markFreqWord = 0x189df1; // 150kHz + 250Hz
uint16_t MSB;
uint16_t LSB;
void setup() {
pinMode (FSYNC, OUTPUT);
digitalWrite(FSYNC, HIGH);
SPI.begin();
AD9833setFrequencies();
}
void loop() {
// switch between freq 0 and freq 1
WriteRegister(0x2000); // output freq 0 "SPACE"
delay(50);
WriteRegister(0x2800); // output freq 1 "MARK"
delay(50);
}
void AD9833setFrequencies() {
WriteRegister(0x2100); // put AD9833 into reset and tell it to accept 14bit words (DB13=1, DB8=1)
MSB = (uint16_t)((spaceFreqWord & 0xFFFC000) >> 14); // only lower 14 bits are used for data
LSB = (uint16_t)(spaceFreqWord & 0x3FFF);
LSB |= 0x4000; // DB 15=0, DB14=1 FreqReg0
MSB |= 0x4000; // DB 15=0, DB14=1
WriteRegister(LSB); // write lower 16 bits to AD9833 registers
WriteRegister(MSB); // write upper 16 bits to AD9833 registers
MSB = (uint16_t)((markFreqWord & 0xFFFC000) >> 14); // only lower 14 bits are used for data
LSB = (uint16_t)(markFreqWord & 0x3FFF);
LSB |= 0x8000; // DB 15=1, DB14=0 FreqReg1
MSB |= 0x8000; // DB 15=1, DB14=0
WriteRegister(LSB); // write lower 16 bits to AD9833 registers
WriteRegister(MSB); // write upper 16 bits to AD9833 registers
WriteRegister(0xC000); // write phase register 0
WriteRegister(0xE000); // write phase register 1
WriteRegister(0x2000); // take AD9833 out of reset, output freq 0
}
void WriteRegister(uint16_t data) {
SPI.beginTransaction(SPISettings(SPI_CLOCK_SPEED, MSBFIRST, SPI_MODE2));
digitalWrite(FSYNC, LOW); // set FSYNC low before writing to AD9833 registers
SPI.transfer16(data);
digitalWrite(FSYNC, HIGH); // write done, set FSYNC high
SPI.endTransaction();
}
...and the spectrum on pin "OUT":

Seems to work.
Paul