Hameg HM5014 1GHz Spectrum Analyzer with Tracking Generator
Not shown are my RigExpert VNAs, the NanoVNA, the Koolertron 60MHz function generator, the Tacklife 30V 5A variable DC power supply, and handheld digital multi- and LCR meters. On the bench is the Weller WE1010NA soldering station. Oh yeah, and my Elegoo 3D printer.
I think its turning into a proper little radio lab! State of the art, circa 1982!
This one to be used on a future project, a transverter for QO-100 satellite where a TX and RX frequency will be needed, depending if RX or TX enabled. The original design of the RX for around 50Mhz is that it can be divided by two so that signal will drive the 25Mhz oscillator of the LNB. I'll probably do that way for the LNB but also as full down conversion from 790Mhz.
Main code is from F1CJN at: https://github.com/F1CJN/ARDUINO-ADF4351-QO-100/blob/master/ADF4351_Dual_251119.ino with small changes for my particular board and needs.
The end result:
The diagram:
might need a pull down resistor on pin D5 to ground since on open air even a finger touch will make it select the TX frequency. On "0" then default to enable the RX frequency. Added an LED to be on during TX frequency select and blinking 3 times during boot. The MUX out is not needed but could be implemented on the future to check if the lock is on.
The code (will change the TX and RX frequency for my needs in the future):
Original at: https://github.com/F1CJN/ARDUINO-ADF4351-QO-100/blob/master/ADF4351_Dual_251119.ino
Bellow with changes: ///// code adf4351_dual_v1.ino /// look for " PFDRFout=25; // Frequence de reference" if using a 10Mhz reference /// on the board
// ADF4351 with fixed frequency // By Alain Fort F1CJN november 29,2019 // alain.fort.f1cjn@orange.fr // // // // ****************************************************** FRANCAIS ******************************************************* // Ce programme permet de programmer un ADF 4351 avec deux fréquences fixes et en utilisant une fréquence de reférence de 10 MHz. // La premiére frequence frequence est utilisée avec un convertisseur émission (RX=0 et la seconde avec RX=1.Selection par PIN 5 // Les fréquence de sortie peuvent être modifiées aux lignes 79 et 80 en conservant le format. // La frequence de reference peut être modidiée à la ligne ligne 70 (10MHz par défaut) // ********************************************* HARDWARE IMPORTANT ******************************************************* // Avec un Arduino UN0 : utilise un pont de résistances pour réduire la tension, MOSI (pin 11) vers // ADF DATA, SCK (pin13) vers CLK ADF, Select (PIN 3) vers LE // Resistances de 560 Ohm avec 1000 Ohm à la masse sur les pins 11, 13 et 3 de l'Arduino UNO pour // que les signaux envoyés DATA, CLK et LE vers l'ADF4351 ne depassent pas 3,3 Volt. // Pin 2 de l'Arduino (pour la detection de lock) connectee directement à la sortie MUXOUT de la carte ADF4351 // La carte ADF est alimentée en 5V par la carte Arduino (les pins +5V et GND sont proches de la LED Arduino). // *********************************************************************************************************************** // // // *************************************************** ENGLISH *********************************************************** // This software is used to programm an ADF4351 with Two fixed frequency, using a 10 MHz reference frequency. // The frequency can be changed at lines 79 and 80, using the same format.Frequency selection is done with Arduino PIN 5. // The reference frequency can be changed at line 70, using the same format (Default 10 MHz) // ******************************************** HARDWARE IMPORTANT******************************************************** // With an Arduino UN0 : uses a resistive divider to reduce the voltage, MOSI (pin 11) to // ADF DATA, SCK (pin13) to ADF CLK, Select (PIN 3) to ADF LE // Resistive divider 560 Ohm with 1000 Ohm to ground on Arduino pins 11, 13 et 3 to adapt from 5V // to 3.3V the digital signals DATA, CLK and LE send by the Arduino. // Arduino pin 2 (for lock detection) directly connected to ADF4351 card MUXOUT. // The ADF card is 5V powered by the ARDUINO (PINs +5V and GND are closed to the Arduino LED).
#include <SPI.h> #define ADF4351_LE 3
uint32_t registers[6] = {0x4580A8, 0x80080C9, 0x4E42, 0x4B3, 0xBC803C, 0x580005} ; // 437 MHz avec ref à 25 MHz //uint32_t registers[6] = {0x3D88FA8, 0x8009F41, 0x14E42, 0x4B3, 0x91003C, 0x580005} ; // 1969,501 MHz avec ref à 10 MHz //uint32_t registers[6] = {0, 0, 0, 0, 0xBC803C, 0x580005} ; // 437 MHz avec ref à 25 MHz int address,modif=0; unsigned int i = 0; double FreqTX, FreqRX, RFout, REFin, INT, PFDRFout, OutputChannelSpacing, FRACF; double RFoutMin = 35, RFoutMax = 4400, REFinMax = 250, PDFMax = 32; unsigned int long RFint,RFintold,INTA,RFcalc,PDRFout, MOD, FRAC; byte OutputDivider;byte lock=2; byte RX=1; unsigned int long reg0, reg1;
void WriteRegister32(const uint32_t value) //Programme un registre 32bits { digitalWrite(ADF4351_LE, LOW); for (int i = 3; i >= 0; i--) // boucle sur 4 x 8bits SPI.transfer((value >> 8 * i) & 0xFF); // décalage, masquage de l'octet et envoi via SPI digitalWrite(ADF4351_LE, HIGH); digitalWrite(ADF4351_LE, LOW); }
void SetADF4351() // Programme tous les registres de l'ADF4351 { for (int i = 5; i >= 0; i--) // programmation ADF4351 en commencant par R5 WriteRegister32(registers[i]); }
//************************************ Setup **************************************** void setup() { Serial.begin (9600); // Serial to the PC via Arduino "Serial Monitor" at 9600
pinMode(2, INPUT); // PIN 2 en entree pour lock pinMode(5, INPUT); // Pin 5 for TX/RX pinMode(ADF4351_LE, OUTPUT); // Setup pins digitalWrite(ADF4351_LE, HIGH); SPI.begin(); // Init SPI bus SPI.setDataMode(SPI_MODE0); // CPHA = 0 et Clock positive SPI.setBitOrder(MSBFIRST); // poids forts en tête
PFDRFout=25; // Frequence de reference RFintold=1234;//pour que RFintold soit different de RFout lors de l'init RFout = RFint/100 ; // fréquence de sortie OutputChannelSpacing = 0.005; // Pas de fréquence min //****************************************************** FreqTX=1969.501; FreqRX=51.8462; //****************************************************** RX=1; //
// ct2gqv pinMode(6, OUTPUT); // PIN 6 for display if on tx and blink 3 times during boot. digitalWrite(6, HIGH); delay(500); digitalWrite(6, LOW); delay(500); digitalWrite(6, HIGH); delay(500); digitalWrite(6, LOW); delay(500); digitalWrite(6, HIGH); delay(500); digitalWrite(6, LOW); } // Fin setup
void loop() { //********************************************** RX = digitalRead(5); // reading RX/TX if (RX==0){RFout=FreqTX; digitalWrite(6, HIGH);} // output frequency selection // ct2gqv put out 6 high to display we are in tx if (RX==1){RFout=FreqRX; digitalWrite(6, LOW);} // output frequency selection // ct2gqv put out 6 high to low since we are in rx RFint=RFout; //******************************************** if (RFint != RFintold) { if (RFout >= 2200) { OutputDivider = 1; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 0); } if (RFout < 2200) { OutputDivider = 2; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 1); } if (RFout < 1100) { OutputDivider = 4; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 1); bitWrite (registers[4], 20, 0); } if (RFout < 550) { OutputDivider = 8; bitWrite (registers[4], 22, 0); bitWrite (registers[4], 21, 1); bitWrite (registers[4], 20, 1); } if (RFout < 275) { OutputDivider = 16; bitWrite (registers[4], 22, 1); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 0); } if (RFout < 137.5) { OutputDivider = 32; bitWrite (registers[4], 22, 1); bitWrite (registers[4], 21, 0); bitWrite (registers[4], 20, 1); } if (RFout < 68.75) { OutputDivider = 64; bitWrite (registers[4], 22, 1); bitWrite (registers[4], 21, 1); bitWrite (registers[4], 20, 0); }
Nothing major here, needed a small signal generator to test in the 10Ghz range (using harmonics from 3.3Ghz), decided to go with the ADF4351 module available everywhere. This is an improvement over the previous iteration here.
After the initial testing on 3.3Ghz made some changes on the software in order to set some common frequencies for future testing with QO-100 satellite equipment and also added provision to sweep around the frequency currently set in order to test some filters.
Output on 3.4Ghz:
And testing the third harmonic:
The Rigol is not a 10Ghz version, I'm using a down converter before the input, that will be another post...
The diagram, at this stage I still didn't added the two extra buttons (look on code for mode and band), to change band and to change mode between set frequency and sweep.
Inside on the almost final interaction (waiting SMA's to connect to front pannel):
And the front panel view working:
The code on the current version, keep in mind might still have some bugs, reach me for latest version if there is one:
If blogger breaks formatting ask me a copy by email.
/*! ADF4351 signal generator
CT2GQV 2020 v1.4
Based on code from: ADF4351 example program https://github.com/dfannin/adf4351
VFO with 100Khz steps starting from a predifined frquency (UL frequencia) using 2 buttons for up and down. Display on 16x2 I2C LCD of the frequency set and the third harmonic value Also serial output of the main frequency set. Possibility to sweep for filter testing. */
vfo.ChanStep = steps[4] ; ///< change to 100 kHz }
void loop() { int buttonState0 = analogRead(button0); // mode int buttonState3 = analogRead(button3); // band
int buttonState1 = analogRead(button1); // up int buttonState2 = analogRead(button2); // down // serial debug for the button for +/- frequency // Serial.print("B1,B2:"); Serial.print(buttonState1); Serial.print(","); Serial.println(buttonState2);
// band / start/stop sweep // button pin is puled down to ground...or close to it (100) as long as lower than 2049 if (buttonState3 <= 100) { {
if (opmode == 1 ){ /////// start stop start procedure if(tempopmode == 1) // started { lcd.clear(); lcd.setCursor(0, 0); lcd.print("SWEEPING starded "); lcd.setCursor(0, 1); lcd.print("Stop----------> "); tempopmode = 255; maxfrequencia=frequencia+10000000; //compute the max frequency so we start from the one now and 100Mhz down and up minfrequencia=frequencia-10000000; //compute the min frequency so we start from the one now and 100Mhz down and up delay(150); } else // is stoped { lcd.clear(); lcd.setCursor(0, 0); lcd.print("SWEEPING stoped "); lcd.setCursor(0, 1); lcd.print("Start---------->"); tempopmode = 1; delay(150); } };
// we are in band mode if (opmode == 0 ){ Serial.print ("BAND: "); band++; if (band > 4){band=0;}; if(band == 0){ frequencia=3496500000UL; vfo.setf(frequencia); lcd.clear(); lcd.setCursor(0, 0); lcd.print("F :"); lcd.print(frequencia/1000); lcd.setCursor(0, 1); lcd.print("F(3):"); lcd.print((frequencia/1000)*3); };
// if we are sweeping if (opmode==1 && tempopmode == 255){lcd.print(" .");}; if (opmode==1 && tempopmode == 255){lcd.print(" o");}; if (opmode==1 && tempopmode == 255){lcd.print(" O");};
if (opmode==1 && tempopmode == 255){ frequencia += vfo.ChanStep; // increase frquency by step if (frequencia >= maxfrequencia){frequencia=minfrequencia;}; // if we are on the limit then go to lower value vfo.setf(frequencia); Serial.print ("F:"); Serial.println(frequencia) ; };
// up frequency // button pin is puled down to ground...or close to it (100) as long as lower than 2049 if (buttonState1 <= 100) { frequencia += vfo.ChanStep; if ( vfo.setf(frequencia) == 0 ) { Serial.print ("VFO.SET: "); Serial.println(vfo.cfreq) ; lcd.clear(); lcd.setCursor(0, 0); lcd.print("F :"); lcd.print(frequencia/1000); if (band == 0 ){lcd.setCursor(0, 1); lcd.print("F(3):"); lcd.print((frequencia/1000)*3);}; } } // end up frequency
// down frequency if (buttonState2 <= 100) { frequencia -= vfo.ChanStep; if ( vfo.setf(frequencia) == 0 ) { Serial.print ("VFO.SET: "); Serial.println(vfo.cfreq) ; lcd.clear(); lcd.setCursor(0, 0); lcd.print("F :"); lcd.print(frequencia/1000); if (band == 0 ){lcd.setCursor(0, 1); lcd.print("F(3):"); lcd.print((frequencia/1000)*3);}; } } // end down frequency
// button software debounce if we are not sweeping if (opmode == 0) { delay(150); };
Needed a small microphone signal amplifier to connected to the external modulation input of the Wavetek 3001 signal generator so I can test an AM de-modulator.
Nothing fancy here, just basic electret microphone amplifier. Microphone is of the basic type sold for computers voice calls.
The diagram/schematic:
The result:
Works OK for basic testing, maybe in the future will join a noise and dual tone generator.
Not much here, just a simple signal generator based on ADF4351 module from "fleebay". PS: there is an improvement over this code at this new post.
I just needed to generate one single frequency that can go up or down in 100Khz steps via two push buttons. Added an optional LCD to display the main frequency and the third harmonic since I'm using it to verify some equipment on 10Ghz.
Test board:
On the frequency counter:
Schematic based on an Arduino Nano controler:
Spectrum output on lower frequencies (414Mhz) and output level at "0" (add 20db attenuation at the spectrum input):
and the third harmonic:
Power at "3" (second harmonic now visible)
3rd harmonic as seen on a 10Ghz adapter for a 1.5Ghz spectrum analyzer: (not calibrated):
Code:
/// code start /*! ADF4351 signal generator
CT2GQV 2020 v1.3
Based on code from: ADF4351 example program https://github.com/dfannin/adf4351
VFO with 100Khz steps starting from a predifined frquency (UL frequencia) using 2 buttons for up and down. Display on 16x2 I2C LCD of the frequency set and the third harmonic value Also serial output of the main frequency set. */
// buttons for up/down in frequency, puleed up from 5v with a 10K resistor, analog pin will be short to ground for button press int button1 = 1; int button2 = 2;
vfo.ChanStep = steps[4] ; ///< change to 100 kHz }
void loop() { int buttonState1 = analogRead(button1); int buttonState2 = analogRead(button2); // serial debug for the button for +/- frequency // Serial.print("B1,B2:"); Serial.print(buttonState1); Serial.print(","); Serial.println(buttonState2);
// up frequency // button pin is puled down to ground...or close to it (100) as long as lower than 2049 if (buttonState1 <= 100) { frequencia += vfo.ChanStep; if ( vfo.setf(frequencia) == 0 ) { Serial.print ("VFO.SET: "); Serial.println(vfo.cfreq) ; lcd.setCursor(0, 0); lcd.print("F :"); lcd.print(frequencia/1000); lcd.setCursor(0, 1); lcd.print("F(3):"); lcd.print((frequencia/1000)*3); } } // end up frequency
// down frequency if (buttonState2 <= 100) { frequencia -= vfo.ChanStep; if ( vfo.setf(frequencia) == 0 ) { Serial.print ("VFO.SET: "); Serial.println(vfo.cfreq) ; lcd.setCursor(0, 0); lcd.print("F :"); lcd.print(frequencia/1000); lcd.setCursor(0, 1); lcd.print("F(3):"); lcd.print((frequencia/1000)*3); } } // end down frequency
// button software debounce delay(150); } /// code end
Some other signal generators based on similar modules and also the ADF4355: http://f6kbf.free.fr/html/ADF4351%20and%20Arduino_Fr_Gb.htm https://pa0rwe.nl/?page_id=1345 (for the ADF4355)