Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
10 Milliwatt Si5351A WSPR Beacon
import serial
import sys
import time
# Arduino serial dev paramaters
DEVICE = '/dev/ttyUSB0' # Change this as necessary
BAUD = 9600
# Open serial port
try:
ser = serial.Serial(port=DEVICE, baudrate=BAUD, timeout=1, writeTimeout=1)
except:
print('Cannot open serial port')
sys.exit(0)
#Wait for ASCII bell, then send the Unix time string
while True:
ser_in = ser.read()
if('\a' in ser_in):
ser.write('T' + str(int(time.time())))
// Si5351_WSPR
//
// Simple WSPR beacon for Arduino Uno, with the Etherkit Si5351A Breakout
// Board, by Jason Milldrum NT7S.
//
// Original code based on Feld Hell beacon for Arduino by Mark
// Vandewettering K6HX, adapted for the Si5351A by Robert
// Liesenfeld AK6L <ak6l@ak6l.org>. Timer setup
// code by Thomas Knutsen LA3PNA.
//
// Time code adapted from the TimeSerial.ino example from the Time library.
// Hardware Requirements
// ---------------------
// This firmware must be run on an Arduino AVR microcontroller
//
// Required Libraries
// ------------------
// Etherkit Si5351 (Library Manager)
// Etherkit JTEncode (Library Manager)
// Time (Library Manager)
// Wire (Arduino Standard Library)
//
// License
// -------
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#include <si5351.h>
#include <JTEncode.h>
#include <int.h>
#include <TimeLib.h>
#include "Wire.h"
#define TONE_SPACING 146 // ~1.46 Hz
#define WSPR_CTC 10672 // CTC value for WSPR
#define SYMBOL_COUNT WSPR_SYMBOL_COUNT
#define CORRECTION 0 // Change this for your ref osc
#define TIME_HEADER "T" // Header tag for serial time sync message
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
#define TX_LED_PIN 12
#define SYNC_LED_PIN 13
// Global variables
Si5351 si5351;
JTEncode jtencode;
unsigned long freq = 10140200UL; // Change this
char call[7] = "N0CALL"; // Change this
char loc[5] = "AB12"; // Change this
uint8_t dbm = 10;
uint8_t tx_buffer[SYMBOL_COUNT];
// Global variables used in ISRs
volatile bool proceed = false;
// Timer interrupt vector. This toggles the variable we use to gate
// each column of output to ensure accurate timing. Called whenever
// Timer1 hits the count set below in setup().
ISR(TIMER1_COMPA_vect)
{
proceed = true;
}
// Loop through the string, transmitting one character at a time.
void encode()
{
uint8_t i;
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
// Reset the tone to 0 and turn on the output
si5351.set_clock_pwr(SI5351_CLK0, 1);
digitalWrite(TX_LED_PIN, HIGH);
// Now do the rest of the message
for(i = 0; i < SYMBOL_COUNT; i++)
{
si5351.set_freq((freq * 100) + (tx_buffer[i] * TONE_SPACING), SI5351_CLK0);
proceed = false;
while(!proceed);
}
// Turn off the output
si5351.set_clock_pwr(SI5351_CLK0, 0);
digitalWrite(TX_LED_PIN, LOW);
}
void processSyncMessage()
{
unsigned long pctime;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
if(Serial.find(TIME_HEADER))
{
pctime = Serial.parseInt();
if( pctime >= DEFAULT_TIME)
{ // check the integer is a valid time (greater than Jan 1 2013)
setTime(pctime); // Sync Arduino clock to the time received on the serial port
}
}
}
time_t requestSync()
{
Serial.write(TIME_REQUEST);
return 0; // the time will be sent later in response to serial mesg
}
void setup()
{
// Use the Arduino's on-board LED as a keying indicator.
pinMode(TX_LED_PIN, OUTPUT);
pinMode(SYNC_LED_PIN, OUTPUT);
digitalWrite(TX_LED_PIN, LOW);
digitalWrite(SYNC_LED_PIN, LOW);
Serial.begin(9600);
// Set time sync provider
setSyncProvider(requestSync); //set function to call when sync required
// Initialize the Si5351
// Change the 2nd parameter in init if using a ref osc other
// than 25 MHz
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, CORRECTION);
// Set CLK0 output
si5351.set_freq(freq * 100, SI5351_CLK0);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power
si5351.set_clock_pwr(SI5351_CLK0, 0); // Disable the clock initially
// Set up Timer1 for interrupts every symbol period.
noInterrupts(); // Turn off interrupts.
TCCR1A = 0; // Set entire TCCR1A register to 0; disconnects
// interrupt output pins, sets normal waveform
// mode. We're just using Timer1 as a counter.
TCNT1 = 0; // Initialize counter value to 0.
TCCR1B = (1 << CS12) | // Set CS12 and CS10 bit to set prescale
(1 << CS10) | // to /1024
(1 << WGM12); // turn on CTC
// which gives, 64 us ticks
TIMSK1 = (1 << OCIE1A); // Enable timer compare interrupt.
OCR1A = WSPR_CTC; // Set up interrupt trigger count;
interrupts(); // Re-enable interrupts.
}
void loop()
{
if(Serial.available())
{
processSyncMessage();
}
if(timeStatus() == timeSet)
{
digitalWrite(SYNC_LED_PIN, HIGH); // LED on if synced
}
else
{
digitalWrite(SYNC_LED_PIN, LOW); // LED off if needs refresh
}
// Trigger every 10th minute
// WSPR should start on the 1st second of the minute, but there's a slight delay
// in this code because it is limited to 1 second resolution.
if(timeStatus() == timeSet && minute() % 10 == 0 && second() == 0)
{
encode();
delay(1000);
}
//delay(100);
}
@sv1onw

This comment has been minimized.

Show comment
Hide comment
@sv1onw

sv1onw Mar 12, 2018

Hi Jason,
When I try to compile with Arduino IDE 1.8.2 I get issues with the libraries.
I have installed EtherkitJTEncode ver 1.1.2
EtherkitSi5351 ver 2.1.0
Time ver 1.4
Is that ok or do you recommend other versions.
Thanks in advance,
73 de Konstantinos, SV1ONW

sv1onw commented Mar 12, 2018

Hi Jason,
When I try to compile with Arduino IDE 1.8.2 I get issues with the libraries.
I have installed EtherkitJTEncode ver 1.1.2
EtherkitSi5351 ver 2.1.0
Time ver 1.4
Is that ok or do you recommend other versions.
Thanks in advance,
73 de Konstantinos, SV1ONW

@sv1onw

This comment has been minimized.

Show comment
Hide comment
@sv1onw

sv1onw Mar 12, 2018

Hi Jason,
I downloaded new versions of JTEncode 1.1.4 and Si5351 2.1.1 . The issues remained.
I then changed to an older Si5351 that I had, ver 2.0.2 and most of the issues were gone. There must have been due to correction method change from one to two parameters I think.
The only remained issues are with JTEncode which they remain even with version 1.1.2.
I attach the error log file and wait for your kind feedback.

Arduino: 1.8.2 (Linux), Board: "Arduino/Genuino Uno"

JTEncode.cpp:58: error: prototype for 'void JTEncode::jt65_encode(char*, uint8_t*)' does not match any in class 'JTEncode'
void JTEncode::jt65_encode(char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:210: error: candidate is: void JTEncode::jt65_encode(const char*, uint8_t*)
void jt65_encode(const char , uint8_t );
^
JTEncode.cpp:98: error: prototype for 'void JTEncode::jt9_encode(char
, uint8_t
)' does not match any in class 'JTEncode'
void JTEncode::jt9_encode(char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:211: error: candidate is: void JTEncode::jt9_encode(const char*, uint8_t*)
void jt9_encode(const char , uint8_t );
^
JTEncode.cpp:143: error: prototype for 'void JTEncode::jt4_encode(char
, uint8_t
)' does not match any in class 'JTEncode'
void JTEncode::jt4_encode(char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:212: error: candidate is: void JTEncode::jt4_encode(const char*, uint8_t*)
void jt4_encode(const char , uint8_t );
^
JTEncode.cpp:182: error: prototype for 'void JTEncode::wspr_encode(char
, char
, uint8_t, uint8_t*)' does not match any in class 'JTEncode'
void JTEncode::wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:213: error: candidate is: void JTEncode::wspr_encode(const char*, const char*, uint8_t, uint8_t*)
void wspr_encode(const char , const char , const uint8_t, uint8_t );
^
JTEncode.cpp:219: error: prototype for 'void JTEncode::fsq_encode(char
, char
, uint8_t
)' does not match any in class 'JTEncode'
void JTEncode::fsq_encode(char * from_call, char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:214: error: candidate is: void JTEncode::fsq_encode(const char*, const char*, uint8_t*)
void fsq_encode(const char , const char , uint8_t );
^
JTEncode.cpp:306: error: prototype for 'void JTEncode::fsq_dir_encode(char
, char
, char, char
, uint8_t*)' does not match any in class 'JTEncode'
void JTEncode::fsq_dir_encode(char * from_call, char * to_call, char cmd, char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:215: error: candidate is: void JTEncode::fsq_dir_encode(const char*, const char*, char, const char*, uint8_t*)
void fsq_dir_encode(const char , const char , const char, const char , uint8_t );
^
sketch/JTEncode.cpp: In member function 'void JTEncode::rs_encode(uint8_t
, uint8_t
)':
JTEncode.cpp:974: error: no matching function for call to 'JTEncode::encode_rs_int(void
&, unsigned int [12], unsigned int [51])'
encode_rs_int(rs_inst, dat1, b);
^
sketch/JTEncode.cpp:974:33: note: candidate is:
In file included from sketch/JTEncode.cpp:24:0:
/home/kostas/Arduino/libraries/Etherkit_JTEncode/src/JTEncode.h:236:8: note: void JTEncode::encode_rs_int(void
, data_t*, data_t*)
void encode_rs_int(void ,data_t , data_t );
^
/home/kostas/Arduino/libraries/Etherkit_JTEncode/src/JTEncode.h:236:8: note: no known conversion for argument 2 from 'unsigned int [12]' to 'data_t
{aka unsigned char
}'
exit status 1
prototype for 'void JTEncode::jt65_encode(char
, uint8_t*)' does not match any in class 'JTEncode'

73 de SV1ONW, Konstantinos

sv1onw commented Mar 12, 2018

Hi Jason,
I downloaded new versions of JTEncode 1.1.4 and Si5351 2.1.1 . The issues remained.
I then changed to an older Si5351 that I had, ver 2.0.2 and most of the issues were gone. There must have been due to correction method change from one to two parameters I think.
The only remained issues are with JTEncode which they remain even with version 1.1.2.
I attach the error log file and wait for your kind feedback.

Arduino: 1.8.2 (Linux), Board: "Arduino/Genuino Uno"

JTEncode.cpp:58: error: prototype for 'void JTEncode::jt65_encode(char*, uint8_t*)' does not match any in class 'JTEncode'
void JTEncode::jt65_encode(char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:210: error: candidate is: void JTEncode::jt65_encode(const char*, uint8_t*)
void jt65_encode(const char , uint8_t );
^
JTEncode.cpp:98: error: prototype for 'void JTEncode::jt9_encode(char
, uint8_t
)' does not match any in class 'JTEncode'
void JTEncode::jt9_encode(char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:211: error: candidate is: void JTEncode::jt9_encode(const char*, uint8_t*)
void jt9_encode(const char , uint8_t );
^
JTEncode.cpp:143: error: prototype for 'void JTEncode::jt4_encode(char
, uint8_t
)' does not match any in class 'JTEncode'
void JTEncode::jt4_encode(char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:212: error: candidate is: void JTEncode::jt4_encode(const char*, uint8_t*)
void jt4_encode(const char , uint8_t );
^
JTEncode.cpp:182: error: prototype for 'void JTEncode::wspr_encode(char
, char
, uint8_t, uint8_t*)' does not match any in class 'JTEncode'
void JTEncode::wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:213: error: candidate is: void JTEncode::wspr_encode(const char*, const char*, uint8_t, uint8_t*)
void wspr_encode(const char , const char , const uint8_t, uint8_t );
^
JTEncode.cpp:219: error: prototype for 'void JTEncode::fsq_encode(char
, char
, uint8_t
)' does not match any in class 'JTEncode'
void JTEncode::fsq_encode(char * from_call, char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:214: error: candidate is: void JTEncode::fsq_encode(const char*, const char*, uint8_t*)
void fsq_encode(const char , const char , uint8_t );
^
JTEncode.cpp:306: error: prototype for 'void JTEncode::fsq_dir_encode(char
, char
, char, char
, uint8_t*)' does not match any in class 'JTEncode'
void JTEncode::fsq_dir_encode(char * from_call, char * to_call, char cmd, char * message, uint8_t * symbols)
^
In file included from sketch/JTEncode.cpp:24:0:
JTEncode.h:215: error: candidate is: void JTEncode::fsq_dir_encode(const char*, const char*, char, const char*, uint8_t*)
void fsq_dir_encode(const char , const char , const char, const char , uint8_t );
^
sketch/JTEncode.cpp: In member function 'void JTEncode::rs_encode(uint8_t
, uint8_t
)':
JTEncode.cpp:974: error: no matching function for call to 'JTEncode::encode_rs_int(void
&, unsigned int [12], unsigned int [51])'
encode_rs_int(rs_inst, dat1, b);
^
sketch/JTEncode.cpp:974:33: note: candidate is:
In file included from sketch/JTEncode.cpp:24:0:
/home/kostas/Arduino/libraries/Etherkit_JTEncode/src/JTEncode.h:236:8: note: void JTEncode::encode_rs_int(void
, data_t*, data_t*)
void encode_rs_int(void ,data_t , data_t );
^
/home/kostas/Arduino/libraries/Etherkit_JTEncode/src/JTEncode.h:236:8: note: no known conversion for argument 2 from 'unsigned int [12]' to 'data_t
{aka unsigned char
}'
exit status 1
prototype for 'void JTEncode::jt65_encode(char
, uint8_t*)' does not match any in class 'JTEncode'

73 de SV1ONW, Konstantinos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment