-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathmultibandWSPR_nodeMCU.ino
More file actions
313 lines (251 loc) · 9.96 KB
/
multibandWSPR_nodeMCU.ino
File metadata and controls
313 lines (251 loc) · 9.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
// Si5351_WSPR
//
// Simple WSPR beacon for ESP8266, with the Etherkit or SV1AFN Si5351A Breakout
// Board.
//
// Original code based on the work by Jason Milldrum NT7S and the 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.
//
// Hardware info
// ---------------------
// serial debug port baud rate: 74880
// Si5351A is connected via I2C on pin D1 (SCL) and D2 (SDA) as marked on Wemos D1 mini Lite
// freq0 is used in clock0 output, freq1 in clock1, freq2 in clock2
// on SV1AFN board clock0 is marked J1, clock1 J2, clock2 J3.
//
// Hardware Requirements
// ---------------------
// This firmware must be run on an ESP8266 compatible board
// testde on Wemos D1 Mini Lite
//
// Required Libraries
// ------------------
// Etherkit Si5351 (Library Manager) 2.0.6
// Etherkit JTEncode (Library Manager) 1.1.3
// Time (Library Manager)
// Wire (Arduino Standard Library)
// NTPtimeESP
// ESP8266WiFi 1.0.0
//
// ESP8266 framework by esp8266 community 2.4.1 or 2.5.0beta2
//
// 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 "Wire.h"
#include <JTEncode.h>
#include <int.h>
#include <TimeLib.h>
#include <NTPtimeESP.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#define TONE_SPACING 146 // ~1.46 Hz
#define WSPR_DELAY 683 // Delay value for WSPR
#define WSPR_CTC 10672 // CTC value for WSPR
#define SYMBOL_COUNT WSPR_SYMBOL_COUNT
#define CORRECTION -12242 // Change this for your ref osc -12000
#define TX_LED_PIN 2 //integrated onboard led, marked as D4 on Wemos D1 mini lite
#define SYNC_LED_PIN 16 //marked as D on Wemos D1 mini lite
//****************************************************
//* SYNCRONIZE SYSTEM TIME with NTP SERVERS
//* need to be modified, obsolete library in use...
//****************************************************
#define SEND_INTV 10
#define RECV_TIMEOUT 10
//Jack1 (clock0 of si5351) is enabled by default and is not possibile to deactivate it.
//If you want use more than one jack output uncomment relative define:
#//define clock1 //if uncommented this define enables jack 2 (clock1 of si5351) outputREMEMBER TO CHANGE FREQUENCY BELOW
//#define clock2 //if uncommented this define enables jack 3 (clock2 of si5351) output
//****************************************************
//list of frequencies for jack 1 (clock0 of si5351) output
#define MAXCH 5 //Change this according to the number of bands inserted below
unsigned long freq0[] = {14097158UL, 10140258UL, 7040158UL, 5366258UL, 3594158UL}; //CHANGE THIS: is the freq of multiband output on jack 1 (clock0)
// frequency for jack 2 (clock1 of si5351) output
#ifdef clock1
unsigned long freq1 = 7040158UL; // Change this: if used is the freq of single band output on jack 2 (clock1)
#endif
// frequency for jack 3 (clock2 of si5351) output
#ifdef clock2
unsigned long freq2 = 28126158UL; // Change this: if used is the freq of single band output on jack 3 (clock2)
#endif
#define SI5351_REF 27000000UL //change this to the frequency of the crystal on your si5351’s PCB, usually 25 or 27 MHz
char call[7] = "IW5EJM"; // Change this
char loc[5] = "JN53"; // Change this
uint8_t dbm = 10;
uint8_t tx_buffer[SYMBOL_COUNT];
const char* ssid = "SSIDofWIFI"; //SSID of your Wifi network: Change this
const char* password = "PASSWORDofWIFI"; //Wi-Fi Password: Change this
//**** How the station is named in your NET
const char* WiFi_hostname = "WSPRmultiTX";
//**** Sync the soft clock every 12 hours
#define NTPSYNC_DELAY 12
//**** NTP Server to use
const char* NTP_Server = "ntp1.inrim.it"; //italian national institute for measures
//**** Your time zone UTC related (floating point number)
#define TIME_ZONE 1.0f
//some system variable. Anything to touch from here
// Global variables
Si5351 si5351;
JTEncode jtencode;
int ch=0; // automatic frequency switch index
bool warmup=0;
NTPtime NTPch(NTP_Server);
strDateTime dateTime;
// --------------------------------------
// epochUnixNTP set the UNIX time
// number of seconds sice Jan 1 1970
// --------------------------------------
time_t epochUnixNTP()
{
Serial.println(">>>>>>>> Time Sync function called <<<<<<<<<");
//**** BIG ISSUE: in case of poor connection, we risk to remain in this loop forever
NTPch.setSendInterval(SEND_INTV);
NTPch.setRecvTimeout(RECV_TIMEOUT);
do
{
dateTime = NTPch.getNTPtime(TIME_ZONE, 1);
delay(1);
}
while(!dateTime.valid);
NTPch.printDateTime(dateTime);
setTime(dateTime.hour,dateTime.minute,dateTime.second,dateTime.day,dateTime.month,dateTime.year);
Serial.println(now());
return 0;
}
// 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 //unused portion of code due to warmup
// si5351.set_clock_pwr(SI5351_CLK0, 1);
// si5351.set_clock_pwr(SI5351_CLK1, 1);
//si5351.set_clock_pwr(SI5351_CLK2, 1);
digitalWrite(TX_LED_PIN, LOW);
Serial.println("TX ON");
// Now do the rest of the message
for(i = 0; i < SYMBOL_COUNT; i++)
{
si5351.set_freq((freq0[ch] * 100) + (tx_buffer[i] * TONE_SPACING), SI5351_CLK0);
#ifdef clock1
si5351.set_freq((freq1 * 100) + (tx_buffer[i] * TONE_SPACING), SI5351_CLK1);
#endif
#ifdef clock2
si5351.set_freq((freq2 * 100) + (tx_buffer[i] * TONE_SPACING), SI5351_CLK2);
#endif
delay(WSPR_DELAY);
}
// Turn off the output
si5351.set_clock_pwr(SI5351_CLK0, 0);
#ifdef clock1
si5351.set_clock_pwr(SI5351_CLK1, 0);
#endif
#ifdef clock2
si5351.set_clock_pwr(SI5351_CLK2, 0);
#endif
digitalWrite(TX_LED_PIN, HIGH);
Serial.println("TX OFF");
//change band on clock0 for next tx
ch++;
if (ch==MAXCH) ch=0; //reset band index to start again from first band the in array
}
void ssidConnect()
{
Serial.println(ssid);
Serial.println(password);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(700);
Serial.print(".");
}
Serial.println();
Serial.print(F("Connected to "));
Serial.println(ssid);
Serial.print(F("IP address: "));
Serial.println(WiFi.localIP());
}
void setup()
{
Serial.begin(74880); while (!Serial);
Serial.println("COM setup successful");
delay(10);
WiFi.mode(WIFI_STA);
// connect to WiFi network
ssidConnect();
// Use the LED as a keying indicator.
pinMode(TX_LED_PIN, OUTPUT);
pinMode(SYNC_LED_PIN, OUTPUT);
digitalWrite(TX_LED_PIN, HIGH);
digitalWrite(SYNC_LED_PIN, HIGH);
// Set time sync provider
setSyncProvider(epochUnixNTP); //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
Serial.println("start radio module setup");
si5351.init(SI5351_CRYSTAL_LOAD_8PF, SI5351_REF, CORRECTION);
Serial.println("Module intializated");
// Set CLK0 output
si5351.set_freq(freq0[ch] * 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
#ifdef clock1
// Set CLK1 output
si5351.set_freq(freq1 * 100, SI5351_CLK1);
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA); // Set for max power
si5351.set_clock_pwr(SI5351_CLK1, 0); // Disable the clock initially
#endif
#ifdef clock2
// Set CLK2 output
si5351.set_freq(freq2 * 100, SI5351_CLK2);
si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_8MA); // Set for max power
si5351.set_clock_pwr(SI5351_CLK2, 0); // Disable the clock initially
#endif
Serial.println("Radio Module setup successful");
Serial.println("Entering loop...");
}
void loop()
{
// Trigger every 4 minute
// WSPR should start on the 1st second of the even minute, but there's a slight delay
// in this code because it is limited to 1 second resolution.
// 30 seconds before trigger enable si5351a output to eliminate startup drift
if((minute() + 1) % 4 == 0 && second() == 30 && !warmup)
{ warmup=1; //warm up started, bypass this if for the next 30 seconds
si5351.set_freq(freq0[ch] * 100, SI5351_CLK0);
si5351.set_clock_pwr(SI5351_CLK0, 1);
#ifdef clock1
si5351.set_clock_pwr(SI5351_CLK1, 1);
#endif
#ifdef clock2
si5351.set_clock_pwr(SI5351_CLK2, 1);
#endif
}
if(minute() % 4 == 0 && second() == 0)
{ //time to start encoding
Serial.println(now()); //prints on serialport actual time
encode();
warmup=0; //reset bool variable for next warmup cycle wich will start in 4 minutes and 30 seconds
delay(1000);
}
}