Happy new year!
I have hacked together on an Arduino breadboard the AD8703 Module and an output for an LCD display. Here it is:
It is showing the output from my DDS (Si5351) into its input impedance of 50R.
The planned Return Loss Bridge
The plan is to build an Return Loss bridge on the free side of the board, with an antenna connection. Then use new software I have written to scan 5-10MHz and display the Return Loss on a small 128x64 OLED display.
There will be an SMA link between the detector output of the bridge and the input of the detector module, and a separate antenna SMA input. Here's a diagram of a bridge:
Take no notice of the values given here. The resistors will be 50R (two 100R in parallel) and the transformer will be a FT37-43/2x10t. The RF source will come from the DDS output G0.
Code for RF Meter
// RFDBM-Module (AD8307 direct, no attenuator, 3.3V AREF // displays dBm, Watts, Volts. Autoscaling #include "Wire.h" #include "si5351.h" #include "LiquidCrystal_I2C.h" #include "Rotary.h" // chose address of 3F or 27 for LCD //#define LCDADDR 0x27 #define LCDADDR 0x3F #define LCDCOLS 16 #define LCDROWS 2 // rotary Encoder pins 2 & 3 (DT & CLK), step change pin 4 (SW) #define DT 2 #define CLK 3 #define SW 4 // Analog input pin #define DCIN A0 #define AREF 3.3 // intercept (dBm), slope (mw/dB), input impedance, attenuator (dB). #define INTERCEPT -84.0 #define SLOPE 25.0 #define IMP 50.0 #define ATTN 0.0 // create lcd object LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS); // rotary Encoder object Rotary rot = Rotary(DT, CLK); // use uint64_t to go above 40MHz uint64_t freq = 700000000; // start frequency cHz uint64_t step = 10000; // init 100Hz step uint64_t fminimum = 10000000; // 100kHz min uint64_t fmaximum = 20000000000; // 200MHz max // dds object Si5351 dds; void setup() { lcd.begin(); lcd.backlight(); // 3.3V connected to AREF analogReference(EXTERNAL); // init dds si5351 module, "0" = default 25MHz XTAL, no correction dds.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); // set 8mA output drive (max possible) dds.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // can insert Si5351 calibration here if required // enable VFO output CLK0, disable CLK1 & 2 dds.output_enable(SI5351_CLK0, 1); dds.output_enable(SI5351_CLK1, 0); dds.output_enable(SI5351_CLK2, 0); // encoder, button, RX, TX, band and KEY pins pinMode(DT, INPUT_PULLUP); pinMode(CLK, INPUT_PULLUP); pinMode(SW, INPUT_PULLUP); freqOut(freq); // cHz, output freq dispFreq(0, 0, freq, 1); // display FREQ xxxxxx.xx kHz col 0 row 0 dispStep(step, 10, 0); // display STEP xxxxHz|kHz col 8, row 0 dispDbm(); // display initial dBm, mW & mV } void loop() { // display dBm etc dispDbm(); // tune? if (tune()) { freqOut(freq); // output freq dispFreq(0, 0, freq, 1); // update freq display } // step? if (button()) { dispStep(step, 10, 0); // update step display } } // tune? bool tune() { unsigned char dir; // tuning direction CW/CCW dir = rot.process(); // read encoder if (dir != DIR_NONE) { // turned? if ((dir == DIR_CW) && (freq <= fmaximum)) freq += step; if ((dir == DIR_CCW) && (freq >= fminimum + 1)) freq -= step; return true; } else { return false; } } // change step? bool button() { if (digitalRead(SW) == LOW) { // button pressed? while (!digitalRead(SW)); // wait for release if (step == 10000000) step = 10000; // back to 10Hz else step = step * 10; // or increase by x10 return true; } else { return false; } } // Output Freq for VFO, on CLK0, f cHz void freqOut(uint64_t f) { dds.set_freq(f, SI5351_CLK0); } // display freq in kHz at col c, row r, f cHz, d decimal places void dispFreq(uint8_t c, uint8_t r, uint64_t f, uint8_t d) { lcd.setCursor(c, r); lcd.print((float)f / 100000, d); // convert to float & kHz lcd.print("kHz "); } void dispDbm() { float mV, dBm, mW, V; // calculations for mV input, dBm, mW and Volts mV = 1000.0 * (float)analogRead(DCIN) * (AREF / 1024); dBm = INTERCEPT + (mV / SLOPE); dBm += ATTN; // if external attenuation, add it back in mW = pow(10, (dBm / 10)); V = sqrt((mW / 1000) * IMP); // dBm lcd.setCursor(0, 1); lcd.print(dBm, 0); lcd.print("dBm "); // Watts if (mW < 1.0) { lcd.print(mW * 1000, 0); lcd.print("uW "); } else if (mW < 1000.0) { lcd.print(mW, 0); lcd.print("mW "); } else { lcd.print(mW / 1000, 1); lcd.print("W "); } // Volts if (V < 1.0) { lcd.print(V * 1000.0, 0); lcd.print("mV "); } else { lcd.print(V, 1); lcd.print("V "); } } // display step void dispStep(uint64_t s, byte c, byte r) { lcd.setCursor(c, r); switch (s) // display step { case 1000: lcd.print("10Hz "); break; case 10000: lcd.print("100Hz "); break; case 100000: lcd.print("1kHz "); break; case 1000000: lcd.print("10kHz "); break; case 10000000: lcd.print("100kHz "); break; } }
No comments:
Post a Comment