Thursday, September 05, 2024

High quality AM exciter using a diode ring mixer with DC offset

There is a very active AM net here on 7.125Mhz and quite a few of the stations come up with home brew transmitters. (There's also a few using IC-7300s which do sound good on AM).

Dave, VK3ASE, mentioned recently that a good way to generate high quality AM is by using a diode ring mixer (which would normally produce double sideband with suppressed carrier) but with a DC offset added to the audio input.

My build is being prototyped on a literal bread board:


In place of a 7.125 crystal I'm using an Arduino Nano that simply boots up and puts an Si5351 on 7.125. That signal is buffered with a 2N2222 before being fed into a TUF-1 mixer. (I did build my own diode ring mixer but it doesn't work as well as the pre-built ones). I buffer the output and then amplify it through a few DB139s.


Only a few watts out so far and I'm keenly aware that AM transmitters like to provide RF feedback.

The Arduino sketch is quite simple and has bits of code primarily from Paul VK3HN.

/*
Single frequency oscillator

Si5351

Based on code from Paul, VK3HN
https://github.com/prt459/Arduino_si5351_VFO_Controller_Keyer

Don't forget:
* Arduino Nano 328p
* Old bootloader
* 115200 baud

*/

const unsigned long int FREQ_DEFAULT = 7125000ULL;
const unsigned long int FREQ_CALIBRATION = 370ULL;

#include <si5351.h> // Etherkit Si3531 library Jason Mildrum, V2.1.4
// https://github.com/etherkit/Si5351Arduino
#include <Wire.h> // built in

// Global objects

Si5351 si5351; // I2C address defaults to x60 in the NT7S lib

unsigned long int gFrequency = FREQ_DEFAULT + FREQ_CALIBRATION;


void setup() {
Serial.begin(115200);
Wire.begin();
Serial.println("Starting");
setupOscillator();
delay(500);
si5351.set_freq(gFrequency * SI5351_FREQ_MULT, SI5351_CLK0);
si5351.output_enable(SI5351_CLK0, 1);
Serial.println("Output enabled");
}

void loop() {
}

void setupOscillator() {
bool i2c_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
Serial.print("si5351: ");
Serial.println(i2c_found ? "Found" : "Missing");
si5351.set_correction(135000, SI5351_PLL_INPUT_XO); // Library update 26/4/2020: requires destination register address ... si5351.set_correction(19100, SI5351_PLL_INPUT_XO);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.set_freq(500000000ULL, SI5351_CLK0);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_4MA);
si5351.output_enable(SI5351_CLK0, 1); // turn VFO on
printSi5351Status();
}

/*
The nominal status for each of those flags is a 0. When the program indicates 1,
there may be a reference clock problem, tuning problem, or some kind of other issue.
(Note that it may take the Si5351 a bit of time to return the proper status flags,
so in program initialization issue update_status() and then give the Si5351 a
few hundred milliseconds to initialize before querying the status flags again.)
*/
void printSi5351Status(){
si5351.update_status();
delay(500);
Serial.print("SYS_INIT: ");
Serial.print(si5351.dev_status.SYS_INIT);
Serial.print(" LOL_A: ");
Serial.print(si5351.dev_status.LOL_A);
Serial.print(" LOL_B: ");
Serial.print(si5351.dev_status.LOL_B);
Serial.print(" LOS: ");
Serial.print(si5351.dev_status.LOS);
Serial.print(" REVID: ");
Serial.println(si5351.dev_status.REVID);
}

No comments: