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