July 22, 2018

VFO on Arduino Nano (Avinash Aeron)

I was looking for a VFO for my newly acquired Bitx40 http://www.hfsigs.com and got this while discussing with my friend Priyasloka Arya:

Required items:
– Arduino nano https://www.arduino.cc/en/Guide/ArduinoNano
– 1602 16×2 Character LCD Display Module HD44780
– SI5351 VFO circuit board http://radiojitter.com/
– Rotary encoder with a circuit board
– jumper wires (~20 numbers)

Preparing the Arduino nano:
Create the setup as follows:
1. Download Arduino SDE from https://www.arduino.cc/en/Main/Software
– install all USB drivers
– install the library for 5351
2. connect to Arduino nano and setup

Setup Arduino SDE

3. flash below code into nano.

CODE: SELECT ALL
#include <LiquidCrystal.h>
//for LCD board
//LiquidCrystal lcd(9, 8, 4, 5, 6, 7);
//LiquidCrystal lcd(RS,E, D4, D5, D6, D7);
LiquidCrystal lcd (9,8, 4, 5, 6, 7);int Contrast=15;
//CLK D2
//DT D3
//SW D12
//VO D11
//A  D12
int i=0;
//******************************************
/*
* si5351example.ino – Simple example of using Si5351Arduino library
*
* Copyright (C) 2015 Jason Milldrum <milldrum@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//*********************************************

/*******Interrupt-based Rotary Encoder Sketch*******
by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt, Steve Spence
*/

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
static int pinC = 12; //pin push
int buttonState = 0;

volatile byte aFlag = 0; // let’s us know when we’re expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let’s us know when we’re expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent
//***********************************************
#include “si5351.h”
#include “Wire.h”
#define MHZ_7_BAND 700000000ULL
#define INCREMENT_STEP 100000LL;
unsigned long long frequency_CLOK0=0;
Si5351 si5351;

void setup()
{
lcd.begin(16, 2);

pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
pinMode(pinC, INPUT_PULLUP);

attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the “PinA” Interrupt Service Routine (below)
attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the “PinB” Interrupt Service Routine (below)
Serial.begin(115200); // start the serial monitor link
Serial.println(“LCD test with PWM contrast adjustment”);
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);

// Set CLK0 to output 7 MHz with a fixed PLL frequency
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
frequency_CLOK0=MHZ_7_BAND;
si5351.set_freq(frequency_CLOK0, 0ULL, SI5351_CLK0);

// Set CLK1 to output 14 MHz
si5351.set_freq(1400000000ULL, 0ULL, SI5351_CLK1);
}
void PinA(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB’s values
if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin’s rising edge
encoderPos –; //decrement the encoder’s position count
frequency_CLOK0-=INCREMENT_STEP;
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
}
else if (reading == B00000100) bFlag = 1; //signal that we’re expecting pinB to signal the transition to detent from free rotation
sei(); //restart interrupts
}

void PinB(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB’s values
if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin’s rising edge
encoderPos ++; //increment the encoder’s position count
frequency_CLOK0+=INCREMENT_STEP;
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
}
else if (reading == B00001000) aFlag = 1; //signal that we’re expecting pinA to signal the transition to detent from free rotation
sei(); //restart interrupts
}
void loop()
{
buttonState = digitalRead(pinC);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == LOW)
{
Serial.println(“PRESSED”);
}

if(oldEncPos != encoderPos)
{
Serial.println(encoderPos);
oldEncPos = encoderPos;
}

//***************************************
pinMode(10,OUTPUT);
analogWrite(11,Contrast);
lcd.setCursor(0,0);

lcd.print(“freq:”);
//lcd.setCursor(0,6);
si5351.set_freq(frequency_CLOK0, 0ULL, SI5351_CLK0);
float frequency_LCD=frequency_CLOK0/100000000.0;
//DISPLAY 4 DECIMAL AFTER
lcd.print(frequency_LCD,4);

/*
si5351.update_status();
Serial.print(“SYS_INIT: “);
Serial.print(si5351.dev_status.SYS_INIT);
Serial.print(”  LOL_A: “);
Serial.print(si5351.dev_status.LOL_A);
Serial.print(”  LOL_B: “);
Serial.print(si5351.dev_status.LOL_B);
Serial.print(”  LOS: “);
Serial.print(si5351.dev_status.LOS);
Serial.print(”  REVID: “);
Serial.println(si5351.dev_status.REVID);

delay(10000);
*/
}

4. Assemble nano and Rotary encoder as per the diagram below:

Rotary encoder to nano

5. Assemble nano and LCD Display as per diagram below:

Nano, LCD Display, VFO and rotatory encoder connection

I used a breadboard per the picture below. Once power on you should get as displayed.

demo assembly

Leave a Reply

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