Here are the slides for the next Concept Session 2. This will cover the breadboarding of the VFO and RTC modules. Concept will conclude with the construction two shields for the Arduino UNO
For the whole system to work there has to be a standard interconnect between shields. This is
The important part is the new connector on the left, carrying the RF signals - VFO, RX and TX.
Receivers and Transmitters
A VFO needs three things, a VFO and BFO output and a quadrature I & Q output. Thus our Shield will look like this.
The VFO is based around the Si5351, which has 3 RF outputs, Outputs 1 & 2 are for VFO & BFO, output 3 is connected to a SN74AC74 as a Johnson counter to generate the IQ signals for an SDR.
The RTC is also a pre-built module using the DS3231 RTC chip and a backup battery.
Build a VFO
Code
This code runs the Si5351, with frequency display on the Arduion Monitor and new frequency input on the keyboard.
// My_VFO_KB is a keyboard input/screen display VFO
// Starter kit VFO using Si5351 module, freq in cHz
// Si5351 I2C bus
// SDA = A4
// SCL = A5
// I2C and Si5351 Libraries
#include "Wire.h"
#include "si5351.h"
// create dds object
Si5351 dds;
// start frequency (cHz)
uint32_t freq = 700000000; // 7MHz
uint32_t prevFreq = freq;
// setup runs once on upload
void setup(){
// start serial (monitor "NEWLINE" & 9600 baud)
Serial.begin(9600);
// init dds si5351 module, "0" = default 25MHz XTAL
dds.init(SI5351_CRYSTAL_LOAD_8PF, 0);
// set 8mA output drive
dds.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
// 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);
freqOut(freq); // output freq
dispFreq(freq); // display freq in Hz
}
void loop(){
freq = getIn(); // get input freq cHz
// new freq?
if(freq != prevFreq)
{
freqOut(freq); // output freq
dispFreq(freq); // display in Hz
prevFreq = freq; // remember as previous freq
}
}
// freq output in cHz on CLK0
void freqOut(uint32_t freq){
dds.set_freq(freq, 0, SI5351_CLK0); // cHz
}
// get input Hz, return cHz
uint32_t getIn(){
uint32_t in;
while(Serial.available() > 0) // flush buffer
Serial.read();
while(Serial.available() == 0) // wait for input
in = Serial.parseInt(); // read input in Hz and parse to integer
return in * 100UL; // return in cHz
}
// display frequency on monitor
void dispFreq(uint32_t f){
// display freq
Serial.print("My_VFO = ");
Serial.print((float)f / 100, 0); // convert to float & display in Hz
Serial.println(" Hz");
}Build an RTC
Code
These two sketches first set the RTC time, then display it on an I2C connected LCD display
// My_RTC set
// enter YYMMDDwHHMMSS on Monitor, w = week day
// note 1 = mon. 01 = Jan
// hit ENTER exactly on the time you want to set
#include "Wire.h"
#include "DS3231.h"
#include "LiquidCrystal_I2C.h"
// LCD address, cols, rows
#define LCDADDR 0x27
#define LCDCOLS 16
#define LCDROWS 2
// RTC address
#define RTCADDR 0x68
// LCD object
LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS);
// rtc object
DS3231 rtc;
// RTC time and date
byte Second, prevSecond, Minute, Hour, DoW, Date, prevDate, Month, Year;
bool gotString;
void setup() {
// Start the serial port
Serial.begin(9600);
// init LCD & backlight on
lcd.init();
lcd.backlight();
// Start the I2C interface
Wire.begin();
dispMsg(0, 0, "Enter time: ");
dispMsg(0, 1, "\"YYMMDDwHHMMSS\"");
gotString = false;
}
void loop() {
char inString[20] = "";
byte j = 0;
while (!gotString) {
if (Serial.available()) {
inString[j] = Serial.read();
if (inString[j] == '\n') {
gotString = true;
Serial.println(inString);
// convert ASCII codes to bytes
Year = ((byte)inString[0] - 48) * 10 + (byte)inString[1] - 48;
Month = ((byte)inString[2] - 48) * 10 + (byte)inString[3] - 48;
Date = ((byte)inString[4] - 48) * 10 + (byte)inString[5] - 48;
DoW = ((byte)inString[6] - 48);
Hour = ((byte)inString[7] - 48) * 10 + (byte)inString[8] - 48;
Minute = ((byte)inString[9] - 48) * 10 + (byte)inString[10] - 48;
Second = ((byte)inString[11] - 48) * 10 + (byte)inString[12] - 48;
rtc.setYear(Year);
rtc.setMonth(Month);
rtc.setDate(Date);
rtc.setDoW(DoW);
rtc.setHour(Hour);
rtc.setMinute(Minute);
rtc.setSecond(Second);
}
j += 1;
}
}
getRTC(); // get time
if(Second != prevSecond) {
dispTime(4, 1); // display it, if changed
prevSecond = Second;
}
if(Date != prevDate) {
dispDate(0, 0);
prevDate = Date;
}
}
// get time from RTC, convert bcd to decimal
void getRTC() {
// Reset the RTC register pointer
Wire.beginTransmission(RTCADDR);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
// request 7 bytes from the RTC address
Wire.requestFrom(RTCADDR, 7);
// get the time data
Second = bcdToDec(Wire.read()); // 0 - 59
Minute = bcdToDec(Wire.read()); // 0 - 59
Hour = bcdToDec(Wire.read() & 0b111111); //mask 12/24 bit
DoW = bcdToDec(Wire.read()); //0 - 6 = Sunday - Saturday
Date = bcdToDec(Wire.read()); // 1 - 31
Month = bcdToDec(Wire.read()); // 0 = jan
Year = bcdToDec(Wire.read()); // 20xx
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val) {
return ( (val / 16 * 10) + (val % 16) );
}
// 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 date and time
void dispDate(byte c, byte r) {
lcd.clear();
lcd.setCursor(c, r);
switch (DoW) {
case 1:
lcd.print("Mon");
break;
case 2:
lcd.print("Tue");
break;
case 3:
lcd.print("Wed");
break;
case 4:
lcd.print("Thu");
break;
case 5:
lcd.print("Fri");
break;
case 6:
lcd.print("Sat");
break;
case 7:
lcd.print("Sun");
break;
}
lcd.print(" ");
lcd.print(Date);
lcd.print(" ");
switch (Month)
{
case 1:
lcd.print("Jan");
break;
case 2:
lcd.print("Feb");
break;
case 3:
lcd.print("Mar");
break;
case 4:
lcd.print("Apr");
break;
case 5:
lcd.print("May");
break;
case 6:
lcd.print("Jun");
break;
case 7:
lcd.print("Jul");
break;
case 8:
lcd.print("Aug");
break;
case 9:
lcd.print("Sep");
break;
case 10:
lcd.print("Oct");
break;
case 11:
lcd.print("Nov");
break;
case 12:
lcd.print("Dec");
break;
}
lcd.print(" ");
lcd.print("20");
lcd.print(Year);
}
void dispTime(byte c, byte r) {
lcd.setCursor(c, r);
if (Hour < 10)
lcd.print("0");
lcd.print(Hour);
lcd.print(":");
if (Minute < 10)
lcd.print("0");
lcd.print(Minute);
lcd.print(":");
if (Second < 10)
lcd.print("0");
lcd.print(Second);
}
// My_RTC_LCD
// display time on LCD I2C
// CONNECTIONS
// RTC DS1307 or DS3231
// SCL = A5
// SDA = A4
// I2C address 0x57
// ------
// display LCD I2C
// o A5 SCL
// o A4 SDA
// o +5
// o GND
// I2C address 0x27
// libraries
#include "Wire.h"
#include "LiquidCrystal_I2C.h"
// RTC I2C address
#define RTCADDR 0x68
// LCD
#define LCDADDR 0x27
#define LCDCOLS 16
#define LCDROWS 2
// LCD object
LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS);
// RTC time and date
byte Second, prevSecond, Minute, Hour, DoW, Date, prevDate, Month, Year;
void setup() {
// initialise the wire library for I2C comms
Wire.begin();
// init LCD & backlight on
lcd.init();
lcd.backlight();
getRTC();
dispDate(0, 0); // display date & time
dispTime(4, 1);
prevSecond = Second; // save current second & date
prevDate = Date;
}
void loop() {
getRTC(); // get time
if (Second != prevSecond) {
dispTime(4, 1); // display it, if changed
prevSecond = Second;
}
if (Date != prevDate) {
dispDate(0, 0);
prevDate = Date;
}
}
// get time from RTC, convert bcd to decimal
void getRTC() {
// Reset the RTC register pointer
Wire.beginTransmission(RTCADDR);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
// request 7 bytes from the RTC address
Wire.requestFrom(RTCADDR, 7);
// get the time data
Second = bcdToDec(Wire.read()); // 0 - 59
Minute = bcdToDec(Wire.read()); // 0 - 59
Hour = bcdToDec(Wire.read() & 0b111111); // mask 12/24 bit
DoW = bcdToDec(Wire.read()); //0 - 6 = Sunday - Saturday
Date = bcdToDec(Wire.read()); // 1 - 31
Month = bcdToDec(Wire.read()); // 0 = jan
Year = bcdToDec(Wire.read()); // 20xx
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val) {
return ( (val / 16 * 10) + (val % 16) );
}
// display date and time
void dispDate(byte c, byte r) {
lcd.clear();
lcd.setCursor(c, r);
switch (DoW) {
case 1:
lcd.print("Mon");
break;
case 2:
lcd.print("Tue");
break;
case 3:
lcd.print("Wed");
break;
case 4:
lcd.print("Thu");
break;
case 5:
lcd.print("Fri");
break;
case 6:
lcd.print("Sat");
break;
case 7:
lcd.print("Sun");
break;
}
lcd.print(" ");
lcd.print(Date);
lcd.print(" ");
switch (Month)
{
case 1:
lcd.print("Jan");
break;
case 2:
lcd.print("Feb");
break;
case 3:
lcd.print("Mar");
break;
case 4:
lcd.print("Apr");
break;
case 5:
lcd.print("May");
break;
case 6:
lcd.print("Jun");
break;
case 7:
lcd.print("Jul");
break;
case 8:
lcd.print("Aug");
break;
case 9:
lcd.print("Sep");
break;
case 10:
lcd.print("Oct");
break;
case 11:
lcd.print("Nov");
break;
case 12:
lcd.print("Dec");
break;
}
lcd.print(" ");
lcd.print("20");
lcd.print(Year);
}
void dispTime(byte c, byte r) {
lcd.setCursor(c, r);
if (Hour < 10)
lcd.print("0");
lcd.print(Hour);
lcd.print(":");
if (Minute < 10)
lcd.print("0");
lcd.print(Minute);
lcd.print(":");
if (Second < 10)
lcd.print("0");
lcd.print(Second);
}
No comments:
Post a Comment