The Shield has four outputs, VFO, BFO, I & Q from the Si5351 DDS CLk0, CLK1 & CLK2.
It covers 40, 30 & 20m with tuning in 100Hz steps.
It connects to an LCD and ROtary Encoder with Button.
Transmit is enabled by a LOW signal on D9 (KEY) input, this controls D31 & D12 (Tx & Rx) outputs.
Code
// Universal_VFO outputs for 40-30-20m // V1.0 M6KWH ganymedeham.blogspot.com // "Universal SDR|VFO" shield uses CLK0 for VFO output // Frequency changes in STEPS by rotary encoder. Button changes band for 40-30-20m // Start frequency on each band is selected on startup or band change // LCD displays frequency in kHz, band and RX/TX // note: freq variable is in cHz // ----- CONNECTIONS // DDS I2C SI5351 // SCL = A5 // SDA = A4 // I2C address 0x60 // ------ // display I2C LCD 16 * 2 // o A5 SCL (y) // o A4 SDA (or) // o +5 (r) // o GND (bwn) // I2C address 0x27 // ----- // encoder KY-040 // o D2 DT (y) // o D3 CLK (g) // o D4 SW (or) // o +5 (r) // o GND (bwn) // ----- // Control bus definition // D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 // RX TX Band * Key NMEA 1PPS Btn EncB EncA PC PC // out out out in in in in in in // * for future Band switch control, e.g. transverter // RX | TX out enable LOW // Band 40 LOW, 30 & 20 HIGH // Key in LOW TX, HIGH or O/C RX // I2C, Si5351, LCD and rotary Encoder libraries #include "Wire.h" #include "si5351.h" #include "LiquidCrystal_I2C.h" #include "Rotary.h" // LCD #define LCDADDR 0x27 #define LCDCOLS 16 #define LCDROWS 2 // rotary Encoder pins 2 & 3 (DT & CLK), band change pin 4 (SW) #define DT 2 #define CLK 3 #define SW 4 // RX & TX (enable = LOW), band relay and XMIT (LOW = TX) #define RX 13 #define TX 12 #define BAND 11 #define XMIT 9 // tuning freq STEPS (cHz), 100Hz #define STEPS 10000 // dds object Si5351 dds; // LCD object LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS); // rotary Encoder object Rotary rot = Rotary(DT, CLK); // start frequencies (cHz), band names uint32_t freqStart[3] = { 710000000, 1014000000, 1410000000}; char bandName[][4] = { "40m", "30m", "20m"}; // band, freq, RXTX flag init byte band = 0; uint32_t freq = freqStart[band]; void setup() { // init LCD & backlight on lcd.init(); lcd.backlight(); // init dds si5351 module, "0" = default 25MHz XTAL dds.init(SI5351_CRYSTAL_LOAD_8PF, 0); // 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 XMIT pins pinMode(DT, INPUT_PULLUP); pinMode(CLK, INPUT_PULLUP); pinMode(SW, INPUT_PULLUP); pinMode(RX, OUTPUT); // SDR RX enable pinMode(TX, OUTPUT); // SDR TX enable pinMode(BAND, OUTPUT); // PA band relay 40/30&20m pinMode(XMIT, INPUT_PULLUP); // key default HIGH // init RX digitalWrite(RX, LOW); // RX enable digitalWrite(TX, HIGH); // TX disable bandRly(band); // switch PA band relays freqOut(freq); // output freq dispMsg(0, 0, "VFO "); // display VFO col 0 row 0 dispFreq(5, 0, freq, 1); // display freq col 5 row 0 dispMsg(0, 1, "Band "); // display Band col 0 row 1 dispMsg(5, 1, bandName[band]); // display band col 5 row 1 RxTx(digitalRead(XMIT)); // set RX } void loop() { tune(); // rotary encoder tuing bandChg(); // button pushed for band change RxTx(digitalRead(XMIT)); // PTT/KEY for transmit, 1 = RX, 0 = TX } void tune() { unsigned char dir; // tuning direction CW/CCW // tune? dir = rot.process(); // read encoder if(dir != DIR_NONE) // turned? { if(dir == DIR_CW) freq += STEPS; // increment freq +/- STEPS if(dir == DIR_CCW) freq -= STEPS; freqOut(freq); // output freq dispFreq(5, 0, freq, 1); // update freq display } } void bandChg() { // change band? if(digitalRead(SW) == LOW) // button pressed? { while(!digitalRead(SW)); // wait for release if(band == 2) band = 0; // loop else band++; freq = freqStart[band]; // set centre freq of new band bandRly(band); // switch PA band relays freqOut(freq); // output freq dispFreq(5, 0, freq, 1); // update freq & band display dispMsg(5, 1, bandName[band]); } } // frequency (in cHz) for VFO, on CLK0 void freqOut(uint32_t f) { dds.set_freq(f, 0ULL, SI5351_CLK0); // converted to cHz } // switch band relay void bandRly(byte b) { switch(b) { case 0: // 40m digitalWrite(BAND, LOW); break; case 1: // 30 & 20m case 2: digitalWrite(BAND, HIGH); break; } } // change RX TX, x = HIGH RX, x = LOW TX void RxTx(bool x) { if(x == LOW) // TX { dispMsg(13, 1, "TX"); digitalWrite(RX, HIGH); // RX off digitalWrite(TX, LOW); // TX on } else { dispMsg(13, 1, "RX"); digitalWrite(RX, LOW); // RX on digitalWrite(TX, HIGH); // TX off } } // display char msg at col c, row r void dispMsg(uint8_t c, uint8_t r, char *m) { lcd.setCursor(c, r); lcd.print(m); } // display freq in kHz,col c, row r, d decimal places void dispFreq(uint8_t c, uint8_t r, uint32_t f, uint8_t d) { lcd.setCursor(c, r); // clear last freq display lcd.print(" "); lcd.setCursor(c, r); // clear last freq display lcd.print((float)f / 100000, d); // convert to float for print function lcd.print("kHz"); }
No comments:
Post a Comment