Si5351 VFO

By | October 5, 2023

Here is an older project of mine – another variant of a VFO. This time with the popular Si5351 clock generator, allowing to create a complete solution for a superhet, including both the VFO and BFO oscillators.

This project is an evolution of the older AD9850 based VFO (here and here). However, this time I wanted to build a superhet receiver and AD9850 has only a single output, so the BFO would need to be separate. Si5351 has up to 8 outputs (depending on version), covering all the common radio needs easily.

Features

The VFO has the following features:

  • Independent VFO and BFO oscillators
  • RIT/XIT offsets
  • Tx signal input – used to let the microcontroller know when to apply the XIT offset
  • Same display layout as the AD9850 VFO
  • Revised controls – gone are the complicated button combinations, there is now a menu for configuring things such as the IF and BFO frequencies, operating mode, IF mode, etc.
  • Output limited to 1MHz-30MHz (but easily changeable in the code)
  • Supports both 3.3V and 5V LCD modules
  • Easy to adapt to different IF filter frequencies and setups
  • Arduino compatible
  • 2019/11/9 – EEPROM persistence for the settings and frequencies
  • 2023/01/16 – Si5351 frequency calibration menu

Schematic

The VFO uses a standard ATMega328P-AU (in TQFP-32 package), running from the internal RC oscillator at 8MHz. The frequency generation is provided by Si5351a, running from a 25MHz crystal, with all 3 outputs routed to the edge of the board (should fit an SMA connector). In my case the loading capacitors C6, C7 weren’t necessary because my crystal needs only few pF of capacitance – the parasitic capacitance of the PCB is sufficient there.

The user interface is provided by 4 tactile switches (SW1, SW2 & SW3 + RESET) and a clickable rotary encoder (SW4). The output uses a standard 1602 LCD module1. Both 3.3V and 5V (most common) LCDs are supported – select the desired voltage by shorting the corresponding pads of the J4 jumper.

The device is powered from from two LD1117S50TR and LD1117S33TR linear regulators – everything except the LCD module is running directly from 3.3V rail, avoiding the need for voltage translation.

Firmware programming is possible either through the standard 6pin AVR ISP connector (J7) or using a serial bootloader on a 3 pin UART header (J8).

In case of use in a transciever it is possible to connect the external Rx/Tx switching circuitry to the J5 header – if the line /RIG_TX is pulled low, the microcontroller will switch to transmit mode.

si5351synth.png

Figure 1: VFO Schematic (click to enlarge)

PCB

The board was designed in KiCAD 5.0.2, the complete project is included below. The board is double sided, meant to accomodate everything including connectors, the LCD module and all controls.

Most of the passives are 0805 sized, except of C9, C10 which are 1206 sized. Everything should be relatively easy to hand-solder, the special larger “HandSoldering” footprints were used where applicable.

The most tricky component Si5351a comes in a tiny (3x3mm!) MSOP-10 package with 0.5mm pin pitch but it is still doable with a bit of care and careful inspection (use a magnifier!).

Don’t forget to short the correct side of the J4 voltage selection jumper for the LCD or the display will not work!

vfo-si5351-pcb-top.png

Figure 2: Top side (click to enlarge)

vfo-si5351-pcb-bottom.png

Figure 3: Bottom side (click to enlarge)

2019-01-03_15.29.59.jpg

Figure 4: Populated board driving a simple 40m receiver

2019-01-03_15.30.48.jpg

Figure 5: Populated board driving a simple 40m receiver

I still have a few spare unpopulated boards, if someone is interested in having one (or more), contact me.

Firmware

The firmware is written in C++ using the Arduino framework for simplicity.

The UI part contains a small template library using both the CRTP pattern to avoid the overhead of virtual functions (saves code memory and a bit of runtime overhead) and compile-time evaluation with variadic templates to permit strong compiler optimizitation. In fact, the version 2.0 of this code used regular inheritance, virtual functions and no templates – and was about 2kB larger. Quite a difference in a micro controller with 32kB of code memory. The drawback is that the code is not exactly easiest to follow and read without some experience in template metaprogramming.

If someone is interested in learning how this works, some good resources are here:

The code does not depend on the standard library because that is not commonly available for AVR. That is also why I had to include minimal implementations of an array and tuple containers. Those don’t claim to be complete or bug-free by any measure, they are meant to be only used for the purposes of this UI library.

Otherwise the code depends on the Etherkit Si5351a library (not the Adafruit one, that one didn’t work for me), Brian Low’s Rotary encoder library and Bounce2 button debouncing library. Install those either using the Arduino library manager or manually, as described on their Github pages.

EDIT: EEPROM functionality has been added in version 4.x

The functionality is very similar to the AD9850 VFOs, however I didn’t implement the automatic saving and restoring of the last state to/from the EEPROM. I have rarely used that feature and it only complicated the code and was wearing the microcontroller out (EEPROM has a limited number of writes). The code is prepared for it, if someone needs it, it shouldn’t be too difficult to add this back.

The serial port is also unused in the current version (apart from debugging). It could be used either for remote control or e.g. for band switching in the future if someone wants to implement it. The connector is there.

IMPORTANT

When uploading the firmware, do make sure to select a board variant that supports 8MHz internal oscillator (normal Arduino Uno uses 16MHz crystal/resonator).

The instructions how to add a custom board configured for the internal 8MHz RC oscillator are, for example, here.

Basic controls

Encoder left/right Tuning, menu navigation, changing values
Encoder button Change tuning step, confirm selection
Button A Hold down to enter “cursor” mode where you can rapidly dial in the desired frequency decade by decade
Button B Set RIT offset (XIT when /RIG_TX is active as well)
Button C Enter/exit the settings menu

The numeric settings (such as the IF and BFO frequencies in the settings) are changed by clicking the encoder, scrolling the cursor to the decade you want to adjust, clicking again to confirm and then rotating the encoder to change the value. Click to confirm again. The mode is exited by moving the cursor completely to the left of the display and clicking the encoder button again.

Settings

Operating mode – for the offsets see below

AM BFO off
LSB BFO freq = BFO center + BFO SSB offset
USB BFO freq = BFO center – BFO SSB offset
CW BFO freq = BFO center – BFO CW offset

IF mode

Off Frequency on display is the frequency output
F+IF VFO outputs the displayed frequency + the configured IF (additive IF)
F-IF VFO outputs the displayed frequency – the configured IF (subtractive IF)

IF & BFO frequency

IF and BFO center frequency, useful for peaking filters, etc. The default in the code is 8987.5kHz because that is the center frequency of a surplus Yaesu filter my receiver is using.

Invert sidebands

A small hack that reverses the meaning the LSB/USB modes when active. Rarely useful, mostly for debugging and testing.

Si5351 Cal

Si5351 calibration adjustment. Use a frequency counter to measure the frequency output (make sure to disable IF & RIT!) then subtract it from the value on the display and enter the value here. The frequency on the display should now match the frequency measured by the counter.

IMPORTANT note on the settings persistence (EEPROM)

In order to minimize the amount of writes into the EEPROM and to maximize its endurance, changed settings are stored only about 10 seconds after the last change. This is done to ensure that e.g. rotating the tuning knob/encoder doesn’t result in a “storm” of writes and wears the EEPROM out prematurely.

Thus it is important to wait after changing a setting before turning the device off/resetting it if you want it to be saved.

If the 10 seconds is too annoying/long, you can change it in the main sketch, look for the following code:

// save to eeprom
if(memory_dirty && last_memory_save + 10000 < millis())
{
   memory_dirty = false;
   storeState(VFOState);
}

Configuration

Everything that is configurable is collected in the file definitions.h. The following values are likely the ones that will need to be customized depending on your radio (filters, etc.):

Variable Initial value Meaning
VFOFreq 7100000 Initial frequency of the VFO in Hz
IFFreq 8987500 Initial IF frequency in Hz
BFOFreq 8987500 Initial BFO frequency in Hz. BFO center frequency in Hz. Frequency from which the offsets are subtracted/added.
BFOSSBOffset 1250 How far to offset the BFO from the center when receiving SSB. Normally it should be 1/2 of the bandwidth of your IF filter.
BFOCWOffset 600 How far to offset the BFO from the center when receiving CW.
TuningIncrements 100000, 10, 50, 100, 500, 1000, 2500, 5000, 10000 Available tuning steps in Hz
RitIncrements 10, 100, 1000, 1 Available RIT/XIT tuning steps in Hz
TuningIncrementIdx 4 Initial tuning step (500 Hz in this case)
RitIncrementIdx 0 Initial RIT tuning step (10 Hz in this case)
Rit 0 Initial RIT in Hz
SidebandsSwap false Initial value of whether to swap the meaning of LSB/USB mode setting
FreqLimitUp 30e6 Upper frequency limit for the VFO (30 MHz)
FreqLimitDown 1e6 Lower frequency limit for the VFO (1 MHz)
SI5351Addr 0x62 I2C address of the Si5351a – according to the datasheet it should be 0x60 but chips with 0x62, 0x6f are common too. Try to change if the VFO is not tuning.
SI5351Correction 2004 Frequency correction for the Si5351 crystal – if you have accurate counter you could try to tweak this to calibrate the frequency of the VFO

Downloads

Schematic + PCB:

  • KiCAD 5.0.2 project, including the Gerber files (in the “gerbers” subdirectory), so no need to install KiCAD if you only want to have the PCBs manufactured. Just extract the gerbers and upload them to the board fabricator of your choice.
  • Bill of material

Firmware (GPL v3 licensed):

Footnotes:

1

Some other designs use the cheap 0.96″ OLED displays – I didn’t want to use one of these because they are both very electrically noisy (not something desirable around a sensitive receiver) and I find them too tiny to be comfortably readable, despite the excellent contrast. Also the squarish aspect ratio looks odd on a front panel.

129 thoughts on “Si5351 VFO

  1. Ben

    Just wanted to say thank you for this. I just built this and it is working wonderfully. (I build your AD9850 version a few years ago.)

    Reply
    1. Klaus

      Hello,

      I translate my English with google da …..

      Thanks for publishing it here on the net.
      For me the whole thing runs with an Arduino Nano and an external 1602 display.
      I will take it as a quartz replacement.

      73 de Klaus, DL2HAD

      Reply
      1. Jan Post author

        Hello,

        Thank you and I am glad that it is useful for you!

        73 de Jan, OM2ATC

        Reply
    2. Tito Mendoza

      Saludos Jan, gracias por sus aportes, uso este VFO en varios de mis proyectos y ahora con el ajuste de la si5351 resulta mucho más fácil y fiable su uso.
      Gracias
      73 CO2KMK.

      Reply
      1. Jan Post author

        Hello,

        I am happy it is working so well for you.

        Enjoy and 73!

        Jan

        Reply
  2. Tony

    Hi Jan,
    I am rebuilding a hf man-pack (tr28) with a range of 1-8Mhz.
    I have tried many si5351 vfo’s which were just not right.
    Then I found your vfo and after lots of attempts I got it right…… learning Arduino etc.
    It is everything in one practical package .. brilliant!!
    As the man-pack has side-band filters I changed the mode to AM SSB CW. 1976 vintage
    Would it be possible to change the tuning-steps to a cursor under the relevant number ( same line)?
    Now I am pushing my luck———What about resetting the previous numbers to zero when changing the
    tuning-step eg 7,069,400 to 7,070,000 ?
    Once again great design!
    Regards,
    Tony ZR6ALG

    Reply
    1. Jan Post author

      Hello,

      I am glad that the thing works for you.

      Re display of the tuning steps – you mean to display it as a list of numbers with the selected step underlined? I am afraid that wouldn’t fit on the display (there is only 16 characters per line!). But feel free to hack, the display is defined in vfo-screen.h, in the render_impl() function. It is commented and should be fairly obvious what needs to be modified if you prefer a different style of display.

      If you want to reset the frequency to the default one when changing the step (not sure why you would want to do that, though), you can easily change that yourself. In vfo-screen.h, search for the function handle_input_impl() (line 195) and you will see two if statements that change the step up or down depending on the sign of the ev.ay variable (the encoder rotation). If you want to reset the frequency, just add there:


      m_state.vfo_freq = Defs::VFOFreq;
      m_state.vfo_dirty = true;

      And recompile. That should do the job. You can replace Defs::VFOFreq with your own frequency if you don’t want to use the default starting frequency from definitions.h.

      Reply
      1. Tony

        Hi Jan,
        Thanks for the prompt reply.
        I am sorry I did not explain my self properly re tuning-steps
        Instead of the freq being displayed on the bottom line in Hz is it possible
        to place the cursor under the appropriate digit on the main freq, eg if the
        tuning-step is 100Hz place the cursor under the 3rd digit, so you will see
        the step position at a glance, and not have the freq displayed below.
        The other query is if you are on 7.022500 Mhz and want to go to 7.070000 Mhz
        and select the 10000Khz step you will have (after tuning) 7.722500 Mhz.
        If the last 5 digits are reset to zero when the 10000 Khz step is selected you would have 7.070000 Mhz.
        This would save you from having to step back for each digit.
        My programming skills are still in the baby steps mode!! hi
        Thanks again
        Tony ZR6ALG

        Reply
        1. Jan Post author

          Ah I see.

          Re cursor – feel free to add that yourself for your radio but I am certainly not going to add this. I am afraid it would just confuse people because they would think the cursor tuning mode is enabled. Furthermore, the tuning steps are not only powers of 10 (whole decades). How will you indicate e.g. a very common 500Hz or 2500Hz tuning step then?

          The question about resetting the frequency – I think what you want is to actually round the frequency to the nearest multiple of the tuning step (again, zeroing the digits is not enough – the tuning steps are not only whole decades!). Feel free to add this in the place I have indicated above but I am not going to add this into my code. Again, I think that would be confusing and annoying if the receiver jumps around/changes frequency merely because you have changed the tuning step.

          >My programming skills are still in the baby steps mode!!

          Well, good opportunity to learn something new! These modifications you are asking for are a good starting project, because they are relatively simple and you don’t need to go deep into the C++ “plumbing” of the code (especially the CRTP templates are tricky).

          Reply
          1. Tony

            Hi Jan,
            Points taken, I will soldier on and keep you posted.
            An odd thing occurred when I powered up the the vfo, there was no freq displayed,and if I turned the encoder a freq of 1Mhz appeared and it would not save.
            I reloaded a clean copy same problem. I then reloaded a fresh bootloader and loaded the vfo s/w … problem solved. It appeared that the bootloader had got corrupted.
            Thanks for your help and patience!
            Cheers
            Tony ZR6ALG

    2. Paulo

      Gostária de saber como ligar no arduino nano a si5351 pois tentei muito mais não sai RF em nemuma porta da si5351 obrigado aguardo resposta

      Reply
      1. Jan Post author

        Hello Paulo,

        Sorry, I don’t speak any Portuguese. What I could figure out is that you want to know how to connect a Si5351 to an Arduino Nano.

        That’s not possible to answer like that, I don’t know what you have done, don’t know what kind of software are you using, did you build your own Si5351 PCB or not … Anything could be wrong there.

        There are plenty of tutorials how to use this IC, literally the first link in Google:

        https://create.arduino.cc/projecthub/CesarSound/10khz-to-120mhz-vfo-rf-generator-with-si5351-and-arduino-3a7cad

        Reply
        1. Paulo

          Ok é o mesmo que voçê montou e não consegui sair radio frequencia use as portas A4 e A5 paraligar si5351 ok mais se tiver alguma configuração no seu esborço para ligar a radio frequencia , e qual menu que liga fico grato pois quero ligar no yaesu ft7b , obrigado.

          Reply
          1. Jan Post author

            Hello Paulo,

            There isn’t anything in the code to “turn on” the radio output, that should work as-is.

            However, that assumes that you have connected things correctly and there are no other issues. E.g. do you have pull-up resistors on I2C lines? The built-in pull-ups of the Nano **are not sufficient!**. This is a very common rookie mistake and a lot of Arduino-related sites show circuits without them – and then people wonder why things aren’t working right. That is something I can’t help you with because I don’t see what you have there.

            One thing that comes to my mind if it isn’t working and everything else is OK (display works, encoder, buttons, work, etc.), would be to try to check the I2C communication with a cheap logic analyzer or an oscilloscope if you have one with I2C decoding. If the communication is not working (the Nano is getting only NACK after every packet) then I would try to change the I2C address in the definitions.h file.

            It is documented in the text above – there are Si5351 chips on the market that have different addresses. Datasheet says 0x60, mine had 0x62 (that’s what the code uses!), there are possibly others. If it doesn’t work even with 0x60 then you need to install the I2C scanner sketch on the Arduino and have it detect the address.

            See: https://create.arduino.cc/projecthub/abdularbi17/how-to-scan-i2c-address-in-arduino-eaadda

  3. Jan Post author

    Feel free to get in touch if you have any questions.
    Re the weird problem you had – that could be also EEPROM corruption. If the data in the EEPROM are not what the program expects, all bets are off. If the EEPROM is erased/empty, it will detect that and initialize it properly but if there are some old data in there, anything could happen.

    Reply
  4. misael

    me interesa su sketch como lo puedo correr en arduino nano, si5351a, lcd 16×2

    Reply
    1. Jan Post author

      Hello,

      Sorry, my Spanish is non-existent but I assume you want to run this on an Arduino Nano. In that case the code should work as-is, but you will need to check that the pins I have used exist on a Nano and if not (or if conflict) change the code to use different ones.

      Otherwise it should work.

      Reply
  5. misael

    hello jan my English excuses
    friend already made the project everything it was successful alone I should change the pines asinacion for the nano and the address of si5351 0x60 that it is the one that I use; thank you and alone a comment because double VFO doesn’t add him with a fifth ideal botton to be the project of radios made at home. 73s cordial

    Reply
    1. Jan Post author

      Cool, congrats! The thing with the si5351 address is documented in the article, I have encountered chips with different addresses. It is strange, frankly – maybe there are fake chips around?

      If you want to add another button for dual VFO, well – if you have a free pin, adding a button is easy. What is less easy is extending the code to handle the state of two VFOs, especially if you want to keep track of more than just 2 frequencies (RIT/XIT, sideband, etc.) I am not planning on doing it because I don’t have need for it but if you do this, feel free to send me the patch or link to your version. I will add it to the post for others to find.

      Reply
  6. John Greusel

    Hi Jan,

    I haven’t built the board yet but trying to test compile I’m getting these errors. The only one that seems problematic is the Rotary one. Also based on other comments it sounds like I’ll need to install the bootloader. I just did an AVR project that didn’t use that but rather just had me upload a hex file.

    Thanks,
    John Greusel
    KC9OJV

    Warning: Board breadboard:avr:atmega328bb doesn’t define a ‘build.board’ preference. Auto-set to: AVR_ATMEGA328BB
    C:\vfo-si5351.2\vfo-si5351.2.ino: In function ‘void setup()’:
    vfo-si5351.2:54:11: error: ‘class Rotary’ has no member named ‘begin’
    encoder.begin(true); // enable encoder pull-ups
    ^~~~~
    Multiple libraries were found for “si5351.h”
    Used: C:\Users\John\Documents\Arduino\libraries\Si5351Arduino-master
    Not used: C:\Users\John\Documents\Arduino\libraries\Etherkit_Si5351
    Multiple libraries were found for “LiquidCrystal.h”
    Used: C:\Users\John\Documents\Arduino\libraries\LiquidCrystal
    Not used: C:\Users\John\Documents\Arduino\libraries\OLD_LiquidCrystal
    Not used: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\LiquidCrystal
    exit status 1
    ‘class Rotary’ has no member named ‘begin’

    Reply
    1. Jan Post author

      You have most likely an incorrect version of the Rotary library.
      Do make sure you use this one, linked from the article:

      https://github.com/brianlow/Rotary

      You have also multiple version of the si5351 library installed, that’s not good because it will likely cause problems. Same as for the LiquidCrystal lib.

      Reply
      1. John Greusel

        Thanks Jan,

        I did succeed in compiling and I generated a binary file.
        Interestingly it created two- one with bootloader and one without. I believe I may be able to use AVRDUDESS (or something similar and upload the binary file I’ve created? Alternatively I can us my USBtiny with the Arduino software and load it that way.

        John

        Reply
        1. Jan Post author

          That’s a bit weird that you have two binaries and one with a bootloader? Are you sure about that? I wonder how did you compile that because that’s not how the Arduino IDE works. Bootloader is flashed separately, it makes little sense for it to be bundled with the binary.

          If you have an Arduino with a bootloader (i.e. normal Arduino board), then you can upload it over USB, as a normal “sketch” using the built-in bootloader.

          If you don’t have an Arduino with a bootloader (i.e. a blank chip and not an Arduino board), then you can use USBTiny (programmer) and the ISP connection to flash it using the avrdude command line utility (AVRDUDESS is a graphic frontend for avrdude). But that is the same thing as clicking “Upload using Programmer” in the Arduino IDE.

          Reply
  7. John Greusel

    I was surprised too. Making the binaries was more of “let”s see what happens.” Here are the file names that were created:

    vfo-si5351.2.ino.arduino_standard.hex
    vfo-si5351.2.ino.with_bootloader.arduino_standard.hex

    I didn’t tel it to do that it just defaulted to making these two hex files.

    John

    Reply
  8. John Greusel

    Hello Jan,

    Works great. My SI5351 address was 0x60 so had to edit that. My encoder runs backwards for up/down frequency. Is there a setting for that in the sketch or should I reverse the pins?

    Thanks for another great project!

    John
    KC9OJV

    Reply
    1. Jan Post author

      Hello John,

      I am glad that it works for you.

      Re encoder – at the top of the main.cpp/main.ino file you will find the line:


      Rotary encoder = Rotary(2, 3); // Sets the pins the rotary encoder uses. Must be interrupt pins.

      Just change this to:

      Rotary encoder = Rotary(3, 2); // Sets the pins the rotary encoder uses. Must be interrupt pins.

      That should reverse the direction of the encoder. Of course, swapping the physical pins works too.

      Reply
  9. Charudatt

    I am a bit surprised by the fact that you are referring to the same thing twice by different names having the same value. IF and BFO.
    I guess for computational purposes , both are the same.

    de VU2UPX

    Reply
    1. Jan Post author

      Well IF and BFO are not the same thing! That they have the same value in the code is just initialization coincidence. IF is the intermediate frequency after mixing and BFO is the beat oscillator frequency. BFO is normally on the same frequency as your IF. However, you may want to offset the BFO, e.g. to select the upper or lower sideband or you may want to offset the center to deal with some peculiarity of your filters. That’s why there are separate values for each.

      Reply
  10. John Greusel

    Jan,
    Is there a way to change the code so it defaults to VFO plus IF instead if VFO minus IF?

    Thanks,
    John
    KC9OJV

    Reply
    1. Jan Post author

      Hello,

      Yes, for sure. Open the vfo-screen.h file and change the initialization of the ifmode field of the TVFOState struct from:


      struct TVFOState
      {
      Defs::OperatingMode opmode = Defs::OperatingMode::LSB;
      Defs::IFMode ifmode = Defs::IFMode::F_MINUS_IF;

      int_fast32_t vfo_freq = Defs::VFOFreq;
      ...

      to:

      struct TVFOState
      {
      Defs::OperatingMode opmode = Defs::OperatingMode::LSB;
      Defs::IFMode ifmode = Defs::IFMode::F_PLUS_IF;

      int_fast32_t vfo_freq = Defs::VFOFreq;
      ...

      And recompile.

      Reply
      1. John Greusel

        Thanks so much Jan!
        That worked perfectly. I tried to find that configuration setting but didn’t look there.

        John
        KC9OJV

        Reply
  11. YOEL MICHEL RODRIGUEZ.

    Hello. Cuando trato de compilar cualquiera de las dos versiones, me da error compilando para tarjeta. Q pudiera ser esto? No estoy muy ducho en temas de programación. Favor de escribirme a mi correo. No tengo muchas oportunidades de conectarme y estoy ansioso por ver trabajando este DDS. Gracias. God bless you.

    Reply
    1. Jan Post author

      Hello Michel,

      I am sorry, but I don’t speak any Spanish 🙁 I understood that you have some compilation problem? It would help to see all error messages you are getting, otherwise it is impossible to help you.

      If the code isn’t compiling, you are probably missing some of the dependencies – the Etherkit Si5351 library, Bounce2 debouncing library or the Brian Low’s Rotary encoder library. The links to them are in the article.

      Jan

      Reply
      1. YOEL MICHEL RODRIGUEZ.

        I will go to send you the mistakes messengers

        Reply
      2. YOEL MICHEL RODRIGUEZ.

        Hello friend. Finally, i could charge the firmware to the Atmega 328p. But, i have this question. I can used this firmware with a 16mhz external cristal without change nothing in the firmware? I hope you understand this, because i do not write in english very well. I wait your answer. God bless you.

        Reply
        1. Jan Post author

          That’s great news, congratulations.

          And yes, you can run it with a 16MHz crystal – just make sure to select an Arduino Nano or Uno in the menu as the boards you are building for. That will take care of any differences in the Arduino clock frequency.

          The VFO output is unaffected by this because the Si5351 has its own 25MHz crystal.

          Jan

          Reply
  12. Apud

    Great project… works perfectly on arduino nano.
    although I don’t know C++ language, but it’s quite easy to customize because the explanation of the program is very detailed.

    This is what I tweaked:
    – IF/BFO lower limit (I changed it to 0)
    – lower limit freq. (I changed it to 100kHz)
    – customize menu display (blink cursor, menu title, checkbox, menu highlight, etc)

    My question is, is there any effect if I change the minimum value of IF and BFO frequencies to 0 ?

    Thanks

    Reply
    1. Jan Post author

      Hello,

      Careful, you can’t have IF/BFO from 0Hz, that doesn’t work unless you are building direct conversion receiver (there your “IF” is effectively the audio).

      Also, the limits are there because in some combinations you could get invalid frequencies – Si5351 is not able to output completely arbitrary frequencies and there are upper and lower limits you must fit into or all bets are off.

      So do verify that you don’t get some negative numbers somewhere and that whatever is the resulting frequency that you are attempting to program into the Si5351 it is within the supported range.

      Jan

      Reply
      1. Apud

        ok thanks for the explanation, so far I don’t get negative numbers, because I separated the if/bfo frequency limit from the main frequency limit, by adding a new constexpr code, for the main frequency it is not affected, but it seems I still have to check again to make sure the frequency of si5351 is accurate.

        Reply
        1. Apud

          solved, I’ve checked again, the lower limit of IF/BFO runs fine at 100kHz, (1e5).

          thank you sir

          Reply
  13. Tito CO2KMK

    Hi Jan,
    I use this VFO with si5351 in some of my QRP,
    but in the vfo that I built with Atmega328P DIP, when I move the encoder
    the LCD 16×2 blink, others fact with arduino doesn’t have this problem,
    I am using the correct libraries,
    the vfo works very well, I am using it now, but when I move the encoder to syntonize
    the LCD 16×2 blink.
    I would thank their help with this, any suggestion or comment would help.
    73 co2kmk

    Reply
    1. Jan Post author

      Hello Tito,

      Sorry but that is something wrong with your build, given that it works with an Arduino and not with a standalone chip. I can’t really help you without seeing what you have done, how is the device built/wired and what exactly did you program into the chip.

      Also, I am not sure what exactly do you mean by “the LCD 16×2 blink”. Is the backlight flashing/flickering? That sounds like a bad connection/cold joint somewhere. Is the content of the display flashing? That sounds like some display connection problem or maybe interference. Or maybe the encoder is bad/connected wrong?

      You need to debug this – start by elimination. Check wiring, check all connections, solder joints. Try another LCD module (it could be defective!). Try another encoder (it could be bad). Etc.

      Jan

      Reply
      1. Tito CO2KMK

        hello Jan
        thank you for their answer, really everything is new,
        what I am thinking the VCC is 5v and not 3V, the can the voltage
        to influence in VFO ? .In other projects the Atmega328P works with 5V
        the display is in white not ligh the display, is the characters disappear and they appear when moving the encoder.
        I send picture of the design of the PCB so that I understand me
        excuse me and thank for you time my friend.
        73 co2kmk

        Reply
        1. Jan Post author

          Hello Tito,

          Unfortunately no picture of your board.

          Voltage doesn’t matter – the board has provision for running the LCD from both 5 and 3.3V (there is a jumper J4 for selecting the right one), so it can support both a 3V and 5V LCD module. The ATMega doesn’t care, so it is powered in my circuit from 3.3V. In that way no level conversion is required for the Si5351 (which is a 3.3V only part).

          What you are describing sounds like a bad contact somewhere that changes when you apply pressure on the board while moving the encoder. Or maybe your contrast pot needs adjusting/moves when you move the encoder. Even RF getting in through come capacitive coupling when you touch the encoder and causing interference/LCD blanking out is a possibility.

          Jan

          Reply
          1. Tito co2kmk

            Hi Jan
            I send you the pictute of my designer, or one video .
            Thank again.
            73 co2kmk.

          2. Jan Post author

            Hello Tito,

            Yes but where did you send it? You can upload the picture somewhere and post a link here or send it to my e-mail – it is on the contact page.

            Jan

          3. Jan Post author

            Hello,

            I believe I have received your e-mail & video now. I have replied to it but in case you don’t see it – that flicker you see on the LCD is normal, that is just updating of the display.

            However, it is supposed to be a bit faster than that (and thus less flickery).

            Since this is happening only with a fresh chip and not on your Arduino board, do make sure you have cleared the CLKDIV8 fuse – that one is programmed from the factory by default and causes the clock to be divided by 8, thus making everything run 8x slower. The chips on the Arduino boards have this fuse cleared from the manufacturer already, that’s why you don’t see the issue there.

            Jan

  14. Sunil A R

    // encoder
    encoder.begin(true); // enable encoder pull-ups …………………………

    in compiling time one error message is in this line ,
    exit status 1
    ‘class Rotary’ has no member named ‘please help how can correct it

    Reply
    1. Jan Post author

      Sorry but without seeing the entire error message and knowing what exactly you did I am literally unable to help you.

      That error happens because the code is calling some functionality that does not exist. That could be either because you have a different, incompatible, version of the Rotary library installed or because you have some typo in the code. However, can’t say more without seeing the entire error report – if this is not the first, top-most error you are getting, it could be well a complete red herring caused by errors before it!

      Make sure you have no typo in the code and that you have the correct dependencies linked from the post installed.

      Reply
  15. Fuds

    Perfect… a very complicated program but fun to learn. finally I was able to add automatic Band selection + BPF relays, IF values ??separate from VFO, display modifications, and some other modifications I needed. Right now I’m thinking of changing the LCD to OLED or graphic LCD, but it seems like a big change is needed while my knowledge is least. Hopefully later I can do that, I still have a lot to learn to understand the program. I think this program is the best because it is fully featured and shared for free. Thank you sir

    Reply
    1. Jan Post author

      Nice, congratulations!

      However, concerning the OLED displays or graphic LCDs – beware, some of those are extremely noisy because of the internal switching voltage converters and if you are building a radio, that’s probably the last thing you want. Also for driving a graphic LCD/OLED you may need more memory than a poor ATMega328 has available. In such case I would advise porting the code to a beefier microcontroller.

      Good luck!

      73 Jan

      Reply
    2. Gilles F1BFU

      Hello

      I am really interested in your modifications because I have the same wishes. Can you share your code?
      Big thanks

      Gilles

      Reply
  16. Jack Margolis

    Jan,
    What is the issue if compiling your si5351 script with a regular Nano?

    “When uploading the firmware, do make sure to select a board variant that supports 8MHz internal oscillator (normal Arduino Uno uses 16MHz crystal/resonator).”

    Where would there be a problem?

    73, Jack USA

    Reply
    1. Jan Post author

      Hello,

      The comment is meant that if you are building my circuit (i.e. it doesn’t have an external crystal/resonator), then you must select a board supporting the internal 8MHz RC oscillator in the Arduino IDE or you won’t have a clock and the microcontroller won’t work.

      If you build this and use an actual Arduino Nano instead (i.e. there is an resonator/crystal for the MCU clock), then it won’t be a problem.

      73, Jan

      Reply
  17. Apud (again)

    I’m using an STM32 board with LCD I2C and 24Cxx EEPROM, after going through a lot of trials, finally my attempt was successful and this DDS worked fine.
    Thank you sir.

    Reply
    1. Jan Post author

      Hello,

      Congrats! You are probably the first one I know about who runs this code on an STM32 board. Nice job!

      I am glad it is working for you.

      All the best,

      Jan

      Reply
  18. Juan Carlos Berberena Glez

    Hello Ian, I hope all is doing good with you and you family.
    A lot of friends from Cuba and Me are used your sythesizer as an a good optiosn for our homebrew Qrp.
    For us would be great to have a meter bar in the second line of the 1602A
    S meter for Rx and PWR/MOD/SWR for Tx.
    I think for you it will be “time” problem, but for us at this time is imposible.
    To show other features as voltage, time or a second VFo is no too important as a meter.
    Sorry if I am bother you in your off Sunday
    I will appreciate any answer
    Qrv’s
    73
    Juan Carlos

    ——————-
    Ahoj Ian, dúfam, že s tebou a tvojou rodinou je všetko v poriadku.
    Ve?a priate?ov z Kuby a ja používa váš syntetizátor ako dobrú vo?bu pre náš domáci nápoj Qrp.
    Pre nás by bolo skvelé ma? meter v druhom rade 1602A
    S meter pre Rx a PWR/MOD/SWR pre Tx.
    Myslím, že pre vás to bude “?asový” problém, ale pre nás je to v tejto chvíli nemožné.
    Zobrazovanie ?alších funkcií, ako je napätie, ?as alebo sekunda VFo, nie je príliš dôležité ako mera?.
    Prepá?te, ak vás ob?ažujem po?as vašej nedele
    Ocením každú odpove?
    Qrv
    73
    Juan Carlos

    Reply
    1. Jan Post author

      Hello Juan,

      I am glad that the device is useful to you and your friends.

      Given the size of the LCD I don’t see where would you want to fit an S-meter bar there while keeping the functionality (e.g. display of the LSB/USB and tuning steps). Moreover, that would also require an analog input and extra circuitry for that. That’s a fairly major redesign.

      I am sorry but I don’t do custom development like that. The project is published so that people can take it and modify it to their needs, so feel free to adapt it or ask someone around you who is able to do so. I am sure someone around can handle a bit of C++ programming to adapt the display code to do what you want.

      All the best,

      73! Jan

      Reply
  19. Gilles F1BFU

    Hello Jan

    Do you still have a PCB for me?
    Your VFO is very interesting especially for the use of the CRTP model.

    Many thanks

    Gilles F1BFU

    Reply
    1. Jan Post author

      Hello Gilles,

      Yes, I have some of the Si5351 PCBs still. If you want one, contact me by e-mail with your address. The boards are about 7€, postage to France included.

      73, Jan

      Reply
  20. jack

    Do you know if anyone has added an external QSK circuit to your very comprehensive VFO? I haven’t operated CW for over 70 years but I’m going to use your VFO for this. I don’t recall having a QSK function in 1946. Also, I used a separate receiver and transmitter, so RIT wasn’t an issue. I am pleased that you have an adjustable RIT function in your design. Comments on this from anyone would be appreciated.

    Jack W6VMJ

    Reply
    1. Jan Post author

      Oof, no idea. Sorry.

      I have certainly not heard from anyone using it like that.

      Good luck!

      Jan

      Reply
    1. Jan Post author

      Cool! Nice job! Personally I find those OLEDs too tiny for something like this and they are also notorious for EMI from their power supplies but glad to see it works for you!

      Reply
  21. Gand

    I failed to compile the sketch, the arduino IDE need
    lcdUI/utilities.h
    anyone can help me to send the link or the file also?
    thank you.

    Reply
    1. Jan Post author

      Hello,

      I have corrected the zip file, please re-download the code.

      Sorry about that.

      Jan

      Reply
  22. Ismael Daniel Moreno Rodríguez

    Primeramente Gracias por esto , está muy bueno !
    Tengo una pregunta
    Yo lo subí a mi Arduino NANO , hantes encendía en la frecuencia 7.110.000 , si mal no recuerdo . Pero ahora está iniciando en 7.358.000 , pensé que al subirle el skech nuevo y ponerle en la sentencia que encendiera en 7.125.000 se resolvería el detalle, pero no fue así ,aún enciende en 7.358.000
    Que puedo hacer ????????????

    Reply
  23. Ismael Daniel Moreno Rodríguez

    Buenos Días , primero que todo gracias por esto , es la solución que más me ha gustado
    Tengo un detalle , cuando subí a mi Arduino NANO la versión más antigua todo bien , encendidas y arrancaba en 7.110.000 o una frente cercana , de un tiempo a otro empezó arrancando en 7.358.000 , entonces pensé que subiendo el skech nuevo y declarando que la frecuencia de arranque fuera 7.125.000
    (constexpr auto VFOFreq = 7125000; // VFO starting frequency)
    resolvería el detalle , pero no fue así , sigue arrancando en 7.358.000
    puedo hacer ??????????????????

    Reply
    1. Jan Post author

      Hello,

      Sorry I don’t speak any Spanish. However, I suspect that the problem is only that you have uploaded the old version of the code, the frequency got stored into EEPROM – and now when you have uploaded the changed version, it still takes the saved frequency from there. Simply turn it on, change the frequency to the one you want using the encoder and then wait about 10 seconds. It will be stored in the EEPROM and next time your VFO will start from there.

      If you don’t want this functionality (that the VFO will remember the last used frequency and modes), you can disable it – look for the the code around line 190 in the vfo-si5351.2.ino file. If you disable it, it will always start the VFO in its default configuration.

      Good luck,

      J.

      Reply
      1. Ismael Daniel Moreno Rodríguez

        Thank you very much for answering But I have left my radius at 7,125,000 And other frequencies for long times Up to an hour or more, but does not save the frequency Come back and turn on 7,358,000

        Reply
        1. Jan Post author

          Sorry, then no idea. You will need to debug it. Try to disable the loadState() function and check that it starts at the default frequency you have set in the code.

          Also make sure you have the latest version of the code.

          J.

          Reply
  24. Ismael Daniel Moreno Rodríguez

    Thanks and excuse the annoyances that can occasion me you it have given count that if comment // the line 191 if ( memory_dirty && last_memory_save + 10000 ()) millises with it outside of service my synthesizer functions well and the frequency in which is working is in which is accustomed when lighting
    Then, one time return to leave active the line 191 already it stays in the frequency that stopped and there is will be for always, although move you of frequency and hope the time that it is

    Then I believe that my Arduino understand the line 192

    Reply
    1. Jan Post author

      Hello,

      If you comment that line, it will stop saving the settings *when they are changed* (current frequency, IF modes, etc.).
      However, if there is a remembered set of settings already, it will always use those, it will not use the defaults – this only disables the saving of the changes, not the loading!

      If you comment out the line saying loadState(VFOState) (line 81), it will always start with the default settings hardwired in the code.

      You may want to customize the storeState()/loadState() functions (they have to match!) if you do not want to save the last used frequency but e.g. want to keep the other user settings.

      Reply
  25. Ismael Daniel Moreno Rodríguez

    Thanks for the help mate
    I tell you what I did
    comment line 191, engrave the Arduino Nano
    So with the dial I placed myself at 7,123,000, I left it there, then I recorded the Arduino Nano again with line 191 enabled and now it starts at 7,123,000 whenever I turn on my equipment.
    The configurations of (IF,BFO,INVERT SIDEBANDS,SI5351 CALL) if they are saved 10 seconds after modifying them
    I would like to achieve that the frequency with which I turn it off is the same as where I turn it on

    Reply
    1. Jan Post author

      >I would like to achieve that the frequency with which I turn it off is the same as where I turn it on

      That’s exactly what my original code does. If that didn’t work for you for whatever reason it is likely your EEPROM was filled with some bad data from your previous attempts. Unfortunately unless you have an external programmer it is not possible to wipe/rewrite the EEPROM using only the Arduino bootloader. With an external programmer it should be enough to erase the EEPROM in such case.

      Reply
  26. Ismael Daniel Moreno Rodríguez

    Thank you
    I will try to it finds solution for which need
    Thanks

    Reply
  27. Juan Paz

    Good morning, greetings to you and your family.
    I am using your code in an arduino nanoi and it works very well for me. Congratulations.

    I have a question, I am at 7.175 mhz LSB tuning in to a station, if I change to USB I have to set myself to 7.178 mhz to tune in to the same station.
    Is it normal like this or do I have something wrong configured?
    thank you.

    Reply
    1. Jan Post author

      Hello,

      The fact that you need to change frequency when changing LSB to USB (and vice versa) is normal – the BFO moves to the other side of the carrier so that you can receive the other sideband. Since the transmitter isn’t transmitting on that frequency, you need to move your VFO too or you wouldn’t hear anything.

      J.

      Reply
  28. Juan Paz

    Greetings friend to you and the whole family
    I have professional HF equipment that, when changing sides, continues to tune to the same frequency. I will give an example:
    Mode
    USB F + 10.7 MHz + 1.5 kHz
    LSB F + 10.7 MHz – 1.5 kHz
    in USB 1.5 khz is added to the VFO frequency and in LSB subtracts 1.5 khz
    I don’t know about programming and I would like to be able to subtract the VFO – BFOSSBOffset, how could i do that in sketch
    I would appreciate your help.

    Reply
    1. Jan Post author

      Hello,

      Well, if you want it to do that you can change the code in the setFrequencies() function in the main file (vfo-si5351.2.ino – line 262 onwards).

      That function has all the logic that deals with the frequency calculation for both the VFO and BFO depending on the modes that are active.

      Jan

      Reply
  29. Juan Paz

    I don’t know about programming and I would like to be able to subtract the VFO – BFOSSBOffset, how could i do that in sketch

    Reply
    1. Juan Paz

      it could be this way. I don’t know about programming.

      // VFO
      switch (VFOState.ifmode)
      {
      case Defs::IFMode::F_PLUS_IF: frequency += VFOState.if_freq; break;

      case Defs::IFMode::F_MINUS_IF: frequency = abs(frequency – VFOState.if_freq); break;

      default: break;
      }

      {
      //for USB
      switch (VFOState.opmode)
      case Defs::OperatingMode::USB:

      VFOState.vfo_freq = VFOState.if_freq – Defs::BFOSSBOffset;
      }

      Reply
      1. Jan Post author

        Well, try it out. I can’t really program this for you here.

        All the best,

        Jan

        Reply
  30. Osmani

    Regards Jan
    I have already updated with version 5.0, everything is wonderful in terms of the calibration of the si 5351, only one detail that was not corrected, the starting frequency, that is, when I start the equipment, the VFO appears at the maximum frequency that I have programmed for it, for example 58 mhz, and I would like, for example, that every time I turn on the equipment, it would go out at 7,110,000, to give an example. Greetings

    Reply
    1. Jan Post author

      Hello,

      Normally the VFO is supposed to start at the last frequency you have left it on. Each time you tune it it will save the current frequency into the EEPROM after 10 seconds (the delay is there to minimize the wear on the EEPROM). Then when you power it up next time it will start on that frequency again.

      If you want to change this behavior it is documented in the post above.

      All the best,

      Jan

      Reply
      1. Osmani

        Thank you very much friend, could you help me correct that since I have no experience in programming. In the squech where I can find that exactly thank you very much in advance

        Reply
        1. Jan Post author

          Hello,

          If you want to have a fixed configuration that doesn’t remember the frequency or other changes and uses the hardwired defaults each time you turn it on, then in the main sketch find lines that say “loadState(VFOState);” and “storeState(VFOState);” and comment them out (put // in front of them).

          Then in the file “definitions.h” set up the defaults as you need (probably the VFOFreq, IFFreq, BFOFreq, LSB/USB mode, etc.)

          Save everything, upload to your board and it should work.

          Regards,

          Jan

          Reply
    2. iw2fvo

      good day !
      I have to control the si5351 VFO by the HDSDR or GSDR pc application. The PC will control the Arduino via the USB in order to set the frequency and the PTT. Frequency shall be 4 times the operating frequency on two clock outpus in quadrature.
      How could I do that please ? Could you suggest anything please ?
      Regards,
      iw2fo

      Reply
      1. Jan Post author

        Hello,

        Please don’t post multiple times in unrelated threads.

        Unfortunately I can’t help you with your project. That has nothing to do whatsoever with my VFO apart from using the same IC and that it is a VFO.

        You can achieve what you want in many ways – e.g. serial port over USB, use some USB IC on top of it, PTT can be wired and controlled in various ways … I have no idea how/whether HDSDR or GSDR can control external VFO’s/frontends or what protocols they use or how to write a driver for them. You will need to research that yourself.

        Generating quadrature signals with SI5351 has been done by some people but my VFO doesn’t do that. So you will need to read the datasheet and figure out how to program the chip to get you what you want.

        Sorry, can’t really help you here.

        73, Jan

        Reply
  31. Philip Hammon

    You know about programming but you have to better study the internal functioning of the equipment to do a correct job.

    Reply
    1. Jan Post author

      Thanks for your comment. Care to elaborate?

      I certainly don’t claim the code or design are error-free but I dare to say that the job has been correct enough given how many people are successfully using the project.

      ¯\_ (?)_/¯

      Reply
  32. Osmany

    Help your friends who have asked you for help in the sketch. If they have asked you for help, it is because they don’t know how to do it.

    Reply
    1. Jan Post author

      Hello,

      Sorry but I don’t read minds. Would you mind elaborating what exactly do you need?

      If you happen to be the same person as “Osmani” above, I have posted instructions what needs to be done there.

      I am sorry but I can’t make a custom modifications of the code for everyone. The code is free, both as in beer and freedom but the user is expected to put some own elbow grease in if changes are required.

      I am trying to support people as much as I can but I have only so much free time. So if the instructions I gave already are not sufficient to achieve what you need I am pretty sure there is someone around you who could help you with implementing them.

      All the best,

      Jan

      Reply
  33. Eduard Radi

    If you published it is because you like to help but there are many who are at zero in knowledge without your help they will not be able to achieve it. I actually had to migrate to another sketch, however I like that one but I can’t get it to work well for me. greetings

    Reply
    1. Jan Post author

      Hello Eduard,

      I fully recognize that not everyone can program and has the knowledge required to make this stuff work. Even though we aren’t talking rocket science here but basic microcontroller/Arduino programming for which there is a ton of tutorials around and even school children do it these days already.

      I do help where I can – as evidenced by all the comments above.

      However, people also need to realize that:

      a) I am doing all of this in my free time, as my hobby.

      b) I am not being paid a dime for doing what amounts to free consulting and bespoke software development. I have done some such modifications where it made sense and those changes were generally useful for everyone (e.g. the settings persistence) but I can’t be customizing the code to fit everyone’s individual needs. I don’t have neither the time nor the resources to do that.

      c) That I have released some free (as in freedom) software doesn’t mean that you or anyone else are automatically entitled to free support as well. I suggest anyone requesting various modifications and changes to check what are the going hourly prices for such work …

      That’s a bit like getting a free bicycle – and then taking it back to ask for it to be repainted in a different color for free as well because you like that one better, with the argument that you don’t know how to paint it yourself.

      That’s not how things work, I am afraid. I didn’t have to release anything – and people complaining about the code wouldn’t have had anything to complain about and to build their projects with.

      To be clear – I am not asking anyone to pay me here. However, I do expect that whoever takes this project and code knows what they are doing and has sufficient knowledge to use it. Or is at least willing to acquire it. I am willing to help with information where needed and even fixes where required but I can’t be reasonably expected to build projects for others because they don’t know how to do it themselves.

      Otherwise there are plenty of alternatives one can simply buy off-the-shelf.

      All the best & 73!,

      Jan

      Reply
  34. JONATHAN REA

    Hello Jan!

    Thanks for sharing your VFO

    I built it and it works as expected at first; but later on it always defaults at 7.163 mhz at power on instead of remembering the last frequency.

    I tried re-uploading the sketch, used V4 and V5 with no difference and even installed and uninstalled the IDE but still it does not remember the last frequency. Also the settings (IF, BFO, MODE) does not change even if I re-upload the sketch (It always remember my settings for the IF and BFO even with the sketch re-uploaded) it always defaults to 7.163.

    I have done nothing on the sketch as I don’t know how to code except to upload the sketch on arduino. Do you have any idea what to do next?

    Thanks and 73!

    Jo

    Reply
    1. Jan Post author

      Hi again,

      Could you try the version 5.1 that I have just published, please? It fixes one silly bug that could cause this problem to happen once the EEPROM gets filled up with saved values.

      73! Jan

      Reply
  35. Jan Post author

    Hello Jonathan,

    That’s odd. Let me recheck the code on my side, I think someone else has complained about something similar before. V4/V5 shouldn’t make any difference and you certainly shouldn’t reinstall the Arduino IDE, that will not do/change anything.

    For how long did it work before it stopped? I.e. did it work at all, remembering the frequency and then stopped remembering it? Or it has never worked correctly at all?

    Concerning the BFO/IF settings – do those get remembered? It is not clear for me from your message whether they still work or they don’t get saved either.

    Jan

    Reply
    1. JO

      HI Jan!
      Thanks for the reply!
      As I was rebuilding my BItx20 it worked at least for a week remembering the memory and then it defaulted to 7.163 after each power on.

      Another odd thing also is that the BFO/IF settings does not change ie the settings I set when it was still remembering (working fine) does not change (do not go to default settings) even after I upload a fresh sketch,
      I hope I explained my problem and hoping further for your solution

      Thanks and 73!
      Jo

      Reply
    2. JO

      Hello Jan!

      Thanks for the reply!
      I tried the V5.1 but sadly it still defaults to 7,163 every after power on
      What is weird is that the BFO/IF settings I earlier set using the previous versions remains the same even after I update the sketch
      I am confused as ever, is it time to replace the arduino nano?

      Thanks and 73!
      jo

      Reply
      1. Jan Post author

        Hello,

        You may want to wipe the EEPROM in the Nano, as described here:
        https://support.arduino.cc/hc/en-us/articles/5779192727068-Reset-your-board (scroll down). That will hopefully fix the issue with that wrong starting frequency.

        Re BFO/IF settings – that’s normal that they are preserved. Reflashing the sketch/firmware doesn’t touch those (nor the VFO frequency) because they are stored in a completely different memory – EEPROM, not flash used for the program. You would need to do the above to reset the EEPROM to the default state, then reflash the VFO sketch.

        Regards,

        Jan

        Reply
      2. JO

        BTW, It worked for at least a week before correctly saving values after 10 secs. The IF and BFO setting are also saved correctly. What is weird is that IF/BFO settings remains the same (the values I initially set ) even after I upload a fresh sketch whether its V4, V5 an V5.1.
        Jo

        Reply
        1. Jan Post author

          >BTW, It worked for at least a week before correctly saving values after 10 secs.
          Yeah, that just means the code reached the end of the EEPROM and since I had a bug there, it didn’t wrap around correctly 🙁

          >What is weird is that IF/BFO settings remains the same (the values I initially set ) even after I upload a fresh sketch whether its V4, V5 an V5.1.

          See above, there is nothing weird on that. It is saved in **EEPROM** which has nothing to do whatsoever with the flash memory where the sketch/program is stored. So reflashing/reuploading the sketch has zero impact on that.

          The IF/BFO are stored slightly differently than the VFO frequency – the assumption is that the BFO/IF aren’ t changed frequently because they are tied to how your radio is built. So there is no wear leveling to preserve the life of the EEPROM (it has finite amount of writes). However, the VFO is saved each time you retune it, so the writes are spread out over the rest of the EEPROM to maximize its life. And that code had a bug.

          Clear out the EEPROM, as described in the link above, then flash your VFO code – and it will hopefully work.

          Reply
  36. JONATHAN REA

    Jan,
    That was a fast reply! Thanks!
    I did clear the EEPROM as you advised, uploaded sketch V5.1
    But the frequency line (line 0) of the lcd does not have digits to display (just the 0Hz) while line 1 is ok
    The digits only appears after turning the encoder while the IF/BFO settings can not go below 1000000

    thanks a lot!

    jo

    Reply
    1. Jan Post author

      That is normal – the EEPROM has been reset, so it doesn’t remember the last settings. However, I have realized that the EEPROM reset sketch from the Arduino forum is buggy – please, change the line saying EEPROM.write(i, 0); to EEPROM.write(i, 255); and then re-run it. ATMega328 chip comes with the value 255 in the EEPROM when empty, not zero. And the VFO code assumes that.

      Afterwards it will be fine once you reload the VFO sketch and set the frequency for the first time.

      IF/BFO cannot go below 1MHz and above 30MHz by design – it is documented in the post. If you need different range then you need to modify the limits in the code.

      Reply
      1. JO

        Hello Jan,

        You’re the man!

        I am happy to tell you that after making the changes you advised everything works fine now (updated to V5.1 and reset the EEPROM). I will be doing a burn test for a while and update you if anything for any changes.

        Thanks a lot my friend, God bless you and your family! 73!

        Jo

        Reply
        1. Jan Post author

          Hello,

          Glad to hear it worked. That EEPROM saving code was written in a hurry after someone else has requested it above in the comments and not all that well tested – I am using the VFO only occasionally myself.

          So it is possible that some more bugs could be lurking in there. If it stops saving the settings/frequency again, let me know, please.

          73 and good luck,

          Jan

          Reply
  37. Tito Mendoza

    Hello Jan
    Friend needs of his help, I use his VFO a lot with the si5351 v 5.1 in these moments,
    in a project DEG (QSD and QSE) that I am making, I need the frequency x 4,
    for example;
    that if I work in 7 Mhz the VFO it generates 28Mhz, the frequency x 4.
    already modify without the problems using IFmode in OFF and using the way AM as SDR
    turning off CLK2 and this generating the frequency well for CLK0 28Mhz, but when moving
    the encoder to change frequencies makes POP strong that before not toward,
    it could be when enabling and to disable the CLK of the si5351
    I wait I understand each other and would thank him some suggestion.
    thank you.
    73 CO2KMK

    Reply
    1. Jan Post author

      Hello Tito,

      No idea what the problem could be, it is difficult to understand what the “POP” means for you and how exactly you have modified the code. Also no idea how your radio is built, so the source of the problem could be literally anywhere and you need to debug it on your desk.

      Still, there are two possible problems that come to my mind:

      – Make sure you adjust/disable the code in the clampFreq() function – that one limits the frequency being set (not the one on display!) to 30MHz by default. So make sure you are not exceeding that or you need to modify this.

      – Turning the output off while tuning/changing frequency could easily produce your “POP!”. No idea why are you doing this. The original code doesn’t turn the output off while tuning.

      Reply
  38. Nick / LZ3GN

    Hi dear friend !
    What are the RXD and TXD signals of the circuit ?
    73!

    Reply
    1. Jan Post author

      Hello Nick,

      Those are for the UART of the ATMega. I have used them for debugging the firmware but right now they aren’t really doing anything apart from printing out a welcome message when the MCU boots.

      The other use is if you have a bootloader (e.g. the Arduino one or Optiboot) flashed in the ATMega then you can upload the firmware using the serial port instead of the ISP connector.

      73 and regards

      Jan

      Reply
  39. Juhar

    Dear Jan,

    Nice software, I’ve downloaded the 5.1 zip file. Just curious , the portion of code still show version 4 ? Is it a typo ? The code is beautiful. I’ll made minor modifications to suit my need. I’ll let you know when it finished and tested. Thank you.

    Reply
    1. Jan Post author

      Hello and thank you. I am glad it works for you.

      Oh you mean that copyright banner on the serial port that literally nobody ever sees? I have completely forgotten about that string and didn’t update it.

      Thanks for letting me know, I will probably just remove that code, the serial port has only been used for debugging.

      Jan

      Reply
  40. Pingback: MEMBANGUN RADIO POCKET SEDERHANA – ELEKTRONIKA504

  41. Maciej L.

    Hello, buddy Jan!
    I’m trying to replicate your VFO project, which I found very interesting!
    Unfortunately I get errors when compiling:

    Arduino:1.8.19 (Windows 10), P?ytka:”Arduino Nano, ATmega328P (Old Bootloader)”

    C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void loadState(TVFOState&)’:eeprom.cpp:44:5: error: ‘EEPROM’ was not declared in this scope EEPROM.get(addr, freq); addr += sizeof(int_fast32_t); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:44:5: note: suggested alternative: ‘EECR’ EEPROM.get(addr, freq); addr += sizeof(int_fast32_t); ^~~~~~ EECRC:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void storeState(const TVFOState&)’:eeprom.cpp:99:5: error: ‘EEPROM’ was not declared in this scope EEPROM.put(addr, state.bfo_center); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:99:5: note: suggested alternative: ‘EECR’ EEPROM.put(addr, state.bfo_center); ^~~~~~ EECRC:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void storeVFO(int_fast32_t)’:eeprom.cpp:133:5: error: ‘EEPROM’ was not declared in this scope EEPROM.put(current_vfo_offset, sentinel_val); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:133:5: note: suggested alternative: ‘EECR’ EEPROM.put(current_vfo_offset, sentinel_val); ^~~~~~ EECRC:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void findLatestVFO(int_fast32_t&, uint16_t&)’:eeprom.cpp:149:5: error: ‘EEPROM’ was not declared in this scope EEPROM.get(addr, freq); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:149:5: note: suggested alternative: ‘EECR’ EEPROM.get(addr, freq); ^~~~~~ EECRexit status 1’EEPROM’ was not declared in this scope

    Reply
  42. Maciej L.

    Hello, buddy Jan!
    I’m trying to replicate your VFO project, which I found very interesting!
    Unfortunately I get errors when compiling:
    I tried version 5.0 and 5.1 same result.
    Jan, can you help me somehow?
    Where am I going wrong?

    Arduino:1.8.19 (Windows 10), P?ytka:”Arduino Nano, ATmega328P (Old Bootloader)”

    C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void loadState(TVFOState&)’:eeprom.cpp:44:5: error: ‘EEPROM’ was not declared in this scope EEPROM.get(addr, freq); addr += sizeof(int_fast32_t); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:44:5: note: suggested alternative: ‘EECR’ EEPROM.get(addr, freq); addr += sizeof(int_fast32_t); ^~~~~~ EECRC:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void storeState(const TVFOState&)’:eeprom.cpp:99:5: error: ‘EEPROM’ was not declared in this scope EEPROM.put(addr, state.bfo_center); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:99:5: note: suggested alternative: ‘EECR’ EEPROM.put(addr, state.bfo_center); ^~~~~~ EECRC:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void storeVFO(int_fast32_t)’:eeprom.cpp:133:5: error: ‘EEPROM’ was not declared in this scope EEPROM.put(current_vfo_offset, sentinel_val); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:133:5: note: suggested alternative: ‘EECR’ EEPROM.put(current_vfo_offset, sentinel_val); ^~~~~~ EECRC:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp: In function ‘void findLatestVFO(int_fast32_t&, uint16_t&)’:eeprom.cpp:149:5: error: ‘EEPROM’ was not declared in this scope EEPROM.get(addr, freq); ^~~~~~C:\Users\Maciek\Documents\Arduino\libraries\vfo-si5351.2\eeprom.cpp:149:5: note: suggested alternative: ‘EECR’ EEPROM.get(addr, freq); ^~~~~~ EECRexit status 1’EEPROM’ was not declared in this scope

    Jan, can you help me somehow?
    Where am I going wrong?

    Reply
    1. Jan Post author

      Hello Maciej,

      Sorry about this, this is most likely my bug. I am working in Linux and in Linux (also on Mac) “eeprom.h” and “EEPROM.h” are two different files. Whereas Windows considers them one and the same because it is not case sensitive, leading to a wrong file being included (name clash).

      Please try version 5.2 which I have just published, that will hopefully fix the problem for you.

      73,

      Jan

      Reply
      1. Maciej L.

        Hello JAN!
        Thank you very much. I was able to compile v5.2 without any problems.
        You are great! Kind regards. Maciej

        Reply
        1. Jan Post author

          Hello,

          I am glad that it works for you. Sorry about that bug again.

          All the best,

          Jan

          Reply
  43. Steve

    Hello Jan,

    Thanks for this great VFO sketch. i’m having trouble getting this to work with an I2C LCD display, I’ve included Liquidcrystal-i2c library, and changed what i think needs to be altered in the sketch, but unable to get it to compile.

    Will this VFO work with the i2c display?

    Any help would be greatly appreciated.

    Regards,
    Steve

    Reply
    1. Jan Post author

      Hello Steve,

      There is nothing intrinsic in the code that would make it not work but the code is designed to use the standard LiquidCrystal library. If you want to use something else then you need to modify the code yourself. Specifically implement the functionality that in the ArduinoLCDApi.h/ArduinoLCDApi.cpp files for whatever display type you are using.

      Regards,

      Jan

      Reply
  44. Riswan

    first of all I would like to say thank you very much for the knowledge you have shared with all of us.

    for your sketch I have applied it to several types of arduino, and all of them were successful, according to what was desired, especially in the eeprom section, all frequency configurations can be stored properly, when restarted.

    but there is a problem when I apply it to the LGT8F wavgat device. when the sketch has finished uploading, all configurations are at 0, frequency display, IF, BFO and calibration.
    and when we set the frequency, everything can run as it is, but when restarted, all frequency configurations will return to 0, it seems that the eeprom has not worked, so all settings return to 0, so we have to reset everything.

    is there anything that needs to be edited in your sketch script in the eeprom section.

    for your help, thank you very much.

    Reply
    1. Jan Post author

      Hello Riswan,

      I am sorry, I can’t help you here. I have no idea what the “Wavgat device” is. I have only found some references that it is some sort of Arduino clone using the LGT8F238P Chinese copy of ATMega328. I have never used the LGT8F238P MCU and don’t have any on hand. The chips are similar but are not 100% compatible.

      Among other things, it seems the Chinese chip doesn’t have an EEPROM at all but uses the internal flash instead, so no wonder it doesn’t work. Flash programming works completely differently than an EEPROM write. You will need to get the datasheet of that chip and eventually modify/replace the EEPROM code based on that.

      Even if it did work, it would probably kill the chip in no time, because flash memory has much more limited lifetime (amount of write cycles) than EEPROM does – orders of magnitude. E.g. the genuine ATMega328’s flash is rated for only 10 000 writes, EEPROM for at least 100 000! Unless the Chinese MCU has some sort of advanced high-endurance flash and/or wear leveling built-in a safer option would be adding an external EEPROM and modifying the code to use that instead, either over I2C or SPI.

      Good luck,

      Jan

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *