WSPR-Transceiver mit Arduino  

Elektronik-Labor  Lernpakete  Projekte  HF  





Der vorhandene CW-QRP-Transceiver auf der Basis des SDR-Arduino-Shields soll nun erweitert werden, sodass er selbständig WSPR-Signale senden kann. Der Raspberry-Sender wird dann überflüssig. Außerdem soll erreicht werden, dass der Empfange und das Senden koordiniert ablaufen, wie es vom WSPR-Decoder vorgesehen ist. Der PC muss dazu den Sender zur richtigen Zeit starten können.

Das Projekt wurde möglich, als ich das WSPR-Projekt von Jason Milldrum in Github entdeckt habe: https://github.com/etherkit/JTEncode Derselbe Autor hat auch schon die Bibliothek <si5351.h> geschrieben, die im Gerät schon verwendet wird.

// Simple JT65/JT9/WSPR/FSQ beacon for Arduino, with the Etherkit
// Si5351A Breakout Board, by Jason Milldrum NT7S.

Die Umsetzung ist mit dem in Github beiliegenden Beispiel einfach. Weil das WSPR-Signal eine Frequenzumtastung mit vier nahe beieinanderliegenden Frequenzen verwendet, ist der SI5351 bestens geeignet, und auch der Sendeverstärker ist ideal für die Aufgabe.  Im ersten Versuch wurden nur minimale Änderungen am Beispiel durchgeführt und der Ausgang CLK2 verwendet.  Bei der späteren Integration in den CW-Sender zeigte sich ein Problem: Der Encoder verträgt sich nicht mit der LCD-Library. Die Lösung besteht darin, die nötigen Daten zunächst ohne das LCD zu kodieren und dann als Konstanten zu verwenden. Entsprechende Print-Befehle wurden in die Sende-Funktion eingebaut. Im Terminal empfängt man dann 255 mit Kommas getrennte Zahlen 0...3, die für die vier FSK-Frequenzen stehen. Diese Zahlenfolge muss dann in das Programm eingefügt werden.

Download: Si5351WSPR1.zip
// Global variables
unsigned long freq;
char message[] = "CALL1 XX00";
char call[] = "CALL1"; //das Rufzeichen
char loc[] = "XX00"; //der Lacotor wie z.B. JO31";
uint8_t dbm = 10; //10 mW, 30 für 1W, 37 für 5 W
uint8_t tx_buffer[255];
enum mode cur_mode = DEFAULT_MODE;
uint8_t symbol_count;
uint16_t ctc, tone_spacing;
uint8_t tx_buffer2[255] = {1,3,2,0,2,0,2,0,3,0,0,2,3,3,3,0,2,2,3,0,0,1,0,3,3,3,3,2,0,0,2,
2,2,0,3,2,0,1,2,1,0,0,2,2,2,0,1,0,3,1,0,2,1,3,2,3,2,2,2,3,1,2,3,0,2,0,0,1,1,2,3,2,3,0,1,2
,3,0,0,1,0,2,1,2,3,1,2,0,2,1,3,2,1,2,1,2,2,0,3,0,2,2,2,0,1,2,2,1,0,2,3,3,3,2,3,3,0,0,3,3,2
,1,2,2,0,3,1,1,0,2,0,2,0,3,0,3,2,2,3,3,0,0,0,2,0,0,0,1,1,2,1,0,1,1,2,0,2,3,3,2,0,0);

...

jtencode.wspr_encode(call, loc, dbm, tx_buffer);
//tx_buffer = tx_buffer2;

// Reset the tone to the base frequency and turn on the output
si5351.output_enable(SI5351_CLK2, 1);
digitalWrite(LED_PIN, HIGH);


for(i = 0; i < symbol_count; i++)
{
si5351.set_freq((freq * 100) + (tx_buffer2[i] * tone_spacing), SI5351_PLL_FIXED, SI5351_CLK2);
Serial.print (tx_buffer[i]); Serial.print (",");
proceed = false;
while(!proceed);
}

Das Beispiel enthält ein verändertes Rufzeichen und einen veränderten Locator, damit nicht versehentlich jemand mein Rufzeichen in die Luft sendet.  Man beachte, dass der Betrieb auf den Amateurfunkfrequenzen nur für lizensierte Funkamateure erlaubt ist. Mit dem Fake-Rufzeichen kann man aber immerhin schon Versuche ohne Antenne direkt neben einem Empfänger durchführen. Denkbar ist auch, dass man mit kleiner Leistung bis 100 mW auf 13,56 MHz oder 27,12 MHz experimentiert. Ob das mit Eigenbaugeräten legal ist, müsste noch genauer untersucht werden. Eine weitere interessante ISM-Frequenz ist 6,78 MHz.

In der endgültigen Software für CW und WSPR ist jtencode.wspr_encode(call, loc, dbm, tx_buffer) auskommentiert. Stattdessen wird die vordefinierte WSPR-Nachricht in tx_buffer2[255] verwendet. Deshalb kann das LCD-Shield verwendet werden um die aktuelle Frequenz anzuzeigen. Die Taste S1 wählt wie bisher die WSPR-Frequenzen auf den einzelnen Bändern aus. Die Taste S2 startet einen WSPR-Sendelauf von zwei Minuten. Beim Senden müssen das Antennenrelais und die Träger-Tastung eingeschaltet werden.

Man kann den Sender manuell mit der Taste S2 starten und braucht dazu nur eine Uhr, damit man genau zu einer geraden Minute beginnt. Das Startsignal kann aber auch von der WSPR-Software kommen. Dazu dient ein keines Interface mit einem Transistor zwischen der seriellen Schnittstelle und dem Eingang A2, an dem auch die Taste S2 liegt.






Unter den WSPR-Einstellungen habe ich festgelegt, dass die DTR-Leitung an COM1 den WSPR-Sender starten soll. In der Software kann man dann z.B. einstellen, dass der Sender 20% der Zeit laufen soll, also viermal empfangen und einmal senden. So erreiche ich endlich den vorgesehenen Modus, bei dem man auf der gleichen Frequenz auch hört. Interessant sind nämlich besonders die Fälle, wo eine Station sowohl erreicht aus auch empfangen werden kann. In dem Fall ist es spannend, Leistungen und Empfangsergebnisse zu vergleichen.




Mit dem Gerät verwende ich jetzt meist eine Leistung von 33 dBm (2 W). Man kann schon sehen, dass das besser geht als die bisherigen 100 mW. Im WSPR-Betrieb verwende ich getrennte Antennen für Senden und Empfang. Die Dipolantenne im Garten bringt auf allen Bändern den besseren Störabstand, während die Vertikalantenne sich besser als Sendeantenne anpassen lässt. Das funktioniert jetzt sehr gut zwischen 80 m und 20 m. Im Empfangsverlauf sieht man die Sende-Phasen als hellgrüne Striche, in denen nicht empfangen wird. Das Beispiel zeigt etwa eine Stunde Sende-und Empfangsbetrieb im 80m-Band am Abend.







Download: Si5351vfo10WSPR2.zip

// Loop through the string, transmitting one character at a time.
void encode()
{
uint8_t i;
// 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 = ctc; // Set up interrupt trigger count;
interrupts(); // Re-enable interrupts.
digitalWrite (txOn,1); //Relais
digitalWrite (keyOut,1); //keyOut
delay (20);
// Reset the tone to the base frequency and turn on the output
si5351.output_enable(SI5351_CLK2, 1);
// Now transmit the channel symbols
for(i = 0; i < symbol_count; i++)
{
si5351.set_freq(((freqHz+1460) * 100) + (tx_buffer2[i] * tone_spacing), SI5351_PLL_FIXED, SI5351_CLK2);
proceed = false;
while(!proceed);
}
// Turn off the output
si5351.output_enable(SI5351_CLK2, 0);
digitalWrite (keyOut,0); //keyOut
digitalWrite (txOn,0); //Relais
delay(5000);
}

void morseKey(void)
{
timeTx = 100;
digitalWrite (txOn,1); //Relais
delay (20);
si5351.output_enable(SI5351_CLK2, 1);
while (timeTx > 0){
if (digitalRead(key) == 0) {

timeTx = 100;
digitalWrite (keyOut,1); //keyOut
analogWrite(buz, 2);
delay (5);
}
if (digitalRead(key) == 1) {
digitalWrite (keyOut,0); //keyOut
analogWrite(buz, 0);
delay (5);
timeTx--;
}
}
digitalWrite (txOn,0); //Relais
}




Mit 2 W im 30m-Band


Elektronik-Labor  Lernpakete  Projekte  HF