Here's the code for 30m WSPR transmissions, it has my new call sign embedded. Reminder: the code runs on my Arduino shield using a Si5351 modules and a DS3231 RTC module for timing. The time has to be set to the nearest 1sec using special sketch.
Code
// WSPR_30M-Basic // Uses WsprMessage library of John Newcombe // reads time from RTC, must be set accurately by spearate program // Si5351 I2C bus // SDA = A4 // SCL = A5 // LCD I2C bus (16x2) // SDA = A4 // SCL = A5 // rotary encoder pins // DT = 2 // CLK = 3 // SW = 4 #include "WsprMessage.h" #include "si5351.h" #include "LiquidCrystal_I2C.h" // LCD 0x27 or 0x3F #define LCDADDR 0x27 //#define LCDADDR 0x3F #define LCDCOLS 16 #define LCDROWS 2 // RTC address #define RTCADDR 0x68 // RTC time byte sec, mns, hrs; // repeat TX interval (sec) uint8_t repeat; // WSPR data char callsign[] = " M0IFA"; // your callsign char loc_short[] = "IO92"; // your short locator int power = 20; // transmit power in dBm char msgtxt[] = {" M0IFA IO92 20 "}; // msg displayed on lcd // WSPR Frequency uint64_t WSPRFreq = 1014020000; // WSPR frequency (cHz) // WSPR Delta Freq for symbols 0, 1, 2, 3. = 145.48 x 0, 1, 2 and 3 to nearest cHz uint64_t delta[] = {0, 145, 291, 436}; // Data from WsprMessage unsigned char *sym; // ptr to symbol vector from WsprMessage // blank MSG_ZISE (= 162) char array for WSPR message, will be populated (0, 1, 2 or 3) in setup() by WsprMessage char WSPR_Message[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // create SI5351 object Si5351 dds; // create LCD object LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS); //=======SETUP======== void setup() { // init I2C Wire.begin(); // init lcd lcd.begin(); lcd.backlight(); // init dds dds.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); // set 8mA output drive (max possible) dds.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // init transmit frequency, set freq 1st as turns outputs on dds.set_freq(WSPRFreq, SI5351_CLK0); // disable outputs (CLK0 enabled on TX) dds.output_enable(SI5351_CLK0, 0); dds.output_enable(SI5351_CLK1, 0); dds.output_enable(SI5351_CLK2, 0); // build WSPR message, get size and pointer to symbols WsprMessage WsprMessage(callsign, loc_short, power); sym = WsprMessage.symbols; // get address ptr to symbols for(int i = 0; i < 162; i++) { // copy sym array to WSPR_Message array WSPR_Message[i] = sym[i]; // both are char arrays, same as bytes } repeat = 2; // defalt repeat WSPR TX every 2 minutes // initial display dispMsg(0, 0, "WSPR "); dispFreq(5, 0, WSPRFreq, 2); // display freq b dispNum(0, 1, repeat); dispMsg(1, 1, " min "); } // ========MAIN LOOP========= void loop() { // get time & display getRTC(); dispTime(8, 1); // send WSPR? if (mns % repeat == 0 && sec == 0) { // display message dispMsg(0, 0, msgtxt); dispMsg(8, 1, " TX "); // show transmit sendWspr(682); // transmit on freq. 682ms per suymbol 162 * 682 = 110.48 sec total frame // restore display dispMsg(0, 0, "WSPR "); dispFreq(5, 0, WSPRFreq, 2); // display freq dispMsg(1, 1, " min "); dispNum(0, 1, repeat); } } //========WSPR send routine void sendWspr(int SymbolLength) { // Send WSPR Message dds.output_enable(SI5351_CLK0, 1); // enable CLK0 output for (int s = 0; s < MSG_SIZE; s++) { // For all symbols, MSG_SIZE in WsprMessage.h dds.set_freq(WSPRFreq + delta[WSPR_Message[s]], SI5351_CLK0); // transmit frequency delay(SymbolLength); // symbol timing } dds.output_enable(SI5351_CLK0, 0); // disable CLK0 output } // get time from RTC, convert bcd to decimal void getRTC() { // Reset the register pointer Wire.beginTransmission(RTCADDR); byte zero = 0x00; Wire.write(zero); Wire.endTransmission(); // request 1st 3 bytes from the RTC address Wire.requestFrom(RTCADDR, 3); // get the s/m/h time data sec = bcdToDec(Wire.read()); mns = bcdToDec(Wire.read()); hrs = bcdToDec(Wire.read() & 0b111111); // mask 24 hour time bit } // Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return ( (val / 16 * 10) + (val % 16) ); } //=======Display routines // display freq in kHz,col c, row r, d decimal places void dispFreq(uint8_t c, uint8_t r, uint64_t f, uint8_t d) { lcd.setCursor(c, r); // clear last freq display lcd.print((float)f / 100000, d); // convert to float for print function lcd.print("kHz "); // + trailing spaces to clear previous display } // 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 a number at col c, row r void dispNum(uint8_t c, uint8_t r, uint16_t n) { lcd.setCursor(c, r); lcd.print(n); } // display time at col, row void dispTime(byte c, byte r) { lcd.setCursor(c, r); if (hrs < 10) lcd.print("0"); lcd.print(hrs); lcd.print(":"); if (mns < 10) lcd.print("0"); lcd.print(mns); lcd.print(":"); if (sec < 10) lcd.print("0"); lcd.print(sec); }
No comments:
Post a Comment