I rushed an order out for the new Elektor SDR as soon as I discovered it on the Web. It arrived this morning.
Note: If you read this blog before, revised VFO code V3 is listed below, now covers 2-30MHz and includes frequency corrections
I have already designed and built an SDR for use with the Arduino (see github.com/M6KWH). This SDR had a custom sketch written for Ham use on 40m.
The system uses a rotary encoder KY-40 and an LCD 1602 to tune and display the frequency.
I am using HDSDR software running under Wine on a Macbook and this works fine.
Comments on the design:
The antenna connection would be better if it was laid out for an SMA connector. And a actual 50R input matching would be better. Connections could be added on the right side for a rotary encoder (5pins) and an LCD display (4 pins). Instead of the usual peak in the centre of the SDR display, usually caused by 50Hz mains hum, there is a dip! Clever design or a mistake, I don't know.
Now how about a complementary Transmitter board Elektor?
According to me the frequency is not correct, it is about 1.4kHz wrong, maybe the xtal is not exactly on 25MHz? Looking at the xtal spec it says 18pF load, the max of the Si5351 is 8pF... So a software error correction, a large one, has to be used. This is in the code below I have calibrated against one of the Si5351 modules from Adafruit or Kanga which I have found to be very accurate.
Code
// SDR_ELEKTOR // V3 3-3-17 // Output 4 x 2-30MHz on CLK1, in 10kHz-1MHz steps // Si5351 I2C bus // SDA = A4 // SCL = A5 // LCD I2C bus (16x2) // SDA = A4 // SCL = A5 // rotary encoder pins // DT = 2 // CLK = 3 // SW = 4 // Si5351 V2, LCD and Rotary Encoder libraries #include "si5351.h" #include "LiquidCrystal_I2C.h" #include "Rotary.h" // chose address of 0x27 or 0x3F for LCD #define LCDADDR 0x27 //#define LCDADDR 0x3F #define LCDCOLS 16 #define LCDROWS 2 // chose pin 2,3 or 3,2 for encoder #define DT 2 //#define DT 3 #define CLK 3 //#define CLK 2 #define SW 4 // xtal correction for Elektor DDS #define CORRE 180000 // min freq 7.0MHz, max 7.2MHz (cHz) #define FREQMIN 700000000 #define FREQMAX 720000000 // freq steps 100kHz max, 10kHz step (cHz) #define FREQSTEPMAX 10000000 #define FREQSTEP 1000000 // dds object Si5351 dds; // lcd object LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS); // Encoder object Rotary enc = Rotary(DT, CLK); // start freq & freqStep (cHz) volatile uint64_t freq = 710000000; // 7.1MHz volatile uint64_t freqStep = 1000000; // 10kHz // freq change flag volatile bool freqChange; void setup() { // encoder, button pins pinMode(DT, INPUT_PULLUP); pinMode(CLK, INPUT_PULLUP); pinMode(SW, INPUT_PULLUP); // setup interrupts from DT or CLK for tuning attachInterrupt(digitalPinToInterrupt(DT), freqTune, CHANGE); attachInterrupt(digitalPinToInterrupt(CLK), freqTune, CHANGE); // enable interrupts interrupts(); // init LCD lcd.begin(); // init dds si5351 module, "0" = default 25MHz XTAL, correction dds.init(SI5351_CRYSTAL_LOAD_8PF, 0, CORRE); // set 8mA output drive dds.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA); // enable VFO output CLK1, disable CLK0 & 2 dds.output_enable(SI5351_CLK0, 0); dds.output_enable(SI5351_CLK1, 1); dds.output_enable(SI5351_CLK2, 0); freqOut(freq); // cHz, output freq freqChange = false; dispMsg(2, 0, "SDR ELEKTOR"); dispFreq(0, 1, freq, 0); // display freq dispfreqStep(10, 1, freqStep); // display freqStep xxxxHz|kHz col 10, row 1 } void loop() { // freqStep? if (button()) { dispfreqStep(10, 1, freqStep); // display freq step } if (freqChange) { freqOut(freq); freqChange = false; dispFreq(0, 1, freq, 1); // display freq } } // ISR - encoder interrupt service routine void freqTune() { unsigned char result; result = enc.process(); if (result == DIR_CW && freq < FREQMAX) { freq += freqStep; freqChange = true; } else if (result == DIR_CCW && freq > FREQMIN) { freq -= freqStep; freqChange = true; } } // change freqStep, 10kHz to 1MHz bool button() { if (digitalRead(SW) == LOW) { // button pressed? while (!digitalRead(SW)); // wait for release if (freqStep == FREQSTEPMAX) freqStep = FREQSTEP; // back to 10kHz else freqStep = freqStep * 10; // or increase by x10 return true; } else { return false; } } // Output Freq for Elektor SDR, f (cHz) x 4 on CLK1 void freqOut(uint64_t f) { dds.set_freq(f * 4ULL, SI5351_CLK1); } // display freq at c)ol, r)ow, f (cHz), to d decimal places (kHz) 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 "); } // display at c)ol, r)ow freq step s (cHz) void dispfreqStep(byte c, byte r, uint64_t s) { lcd.setCursor(c, r); switch (s) // display freqStep { 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; case 100000000: lcd.print("1MHz "); break; } } // display msg *m at c)ol, r)ow void dispMsg(uint8_t c, uint8_t r, char *m) { lcd.setCursor(c, r); lcd.print(m); }
1 comment:
The new board has a transmit output. Have you done a sketch that supports transmit? My Arduino coding is crap! Will try your sketch. 73
Post a Comment