RPi Pico WSPR-Sender                     

            

Elektronik-Labor  Projekte  Mikrocontroller  Raspberry     





WSPR-Sender erreichen mit kleinen Leistungen sehr große Reichweiten. Es gibt bereits seit langem eine Lösung für den Rapberry Pi, aber der RPi Pico schafft das auch. Ich konnte dabei auf Versuche mit dem Elektor SDR-Shield zurückgreifen, und natürlich auf die VFO-Software für den Pico. 

Das WSPR-Signal verwendet vier Frequenzen im Abstand von jeweils 1,46 Hz. Man kommt also nicht mit der VFO-Auflösung von 1 Hz aus. In den 32 Bit der Variable periods ist unten noch reichlich Platz für eine genauere Unterteilung. Hier wird der Abstand dwsfr zwischen zwei WSPR-Signalen berechnet, um dann die vier genauen Frequenzen  in wsfr festzulegen. JTEencode bereitet dann den Puffer tx_buffer mit 162 Einträgen 0...3 vor. Sie bestimmen beim eigentlichen Sendedurchlauf, welche der vier Frequenzen gerade ausgebeben werden soll. Jeder Zustand bleibt für 683 ms stehen. Einschließlich Restwartezeit werden zwei Minuten für einen Durchgang benötigt.


//PicoWSPR 40m/30m
#include "vfo2.pio.h"
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include <JTEncode.h>
JTEncode jtencode;

char call[] = "T2EST";  //Rufzeichen
char loc[] = "JO31";    //Lacotor
uint8_t dbm = 10;       //10 mW
uint8_t tx_buffer[255];


uint32_t clk_khz = 125000;
volatile uint32_t f=7040100;  //40m
//volatile uint32_t f=10140200;   //30m
volatile uint32_t periods;
 
void setup(void){
  set_sys_clock_khz(clk_khz,true);
  Serial.begin(9600);
}

void set_freq(void){
  uint64_t ratio = (uint64_t)clk_khz*1000LL *(1<<24)/(uint64_t)f;
  periods=(uint32_t)ratio;
}

void encode(){
  uint32_t wsfr[4];
  set_freq();
  uint32_t dwsfr= 146L * (periods/f)/ 100L ;
  wsfr[0]= periods-(10<<24);  // + 3 x Abstand 1,46 Hz
  wsfr[1]= wsfr[0]-dwsfr;
  wsfr[2]= wsfr[1]-dwsfr;
  wsfr[3]= wsfr[2]-dwsfr;
  memset(tx_buffer, 0, 255);
  jtencode.wspr_encode(call, loc, dbm, tx_buffer);
  uint16_t n=0;
  while(1){
    for(uint8_t i = 0; i < 162; i++)
    {
      periods=wsfr[tx_buffer[i]];
      delay(683);
    }
    periods = 200<<24;
    n++;
    delay(9350);             //Restzeit bis 2 Min
    if (n>2){delay(360000);} //6 Min Pause
  }
}

void loop(){
  delay (50);
  encode();
  while(1){}
}

void setup1(void){
  uint16_t t;
  uint32_t delta;
  PIO pio = pio0;
  gpio_init(0);
  gpio_set_dir(0, GPIO_OUT);
  pio_gpio_init(pio0, 15);         
  uint offset = pio_add_program(pio0, &vfo_program);         
  pio_sm_set_consecutive_pindirs(pio0, 0, 15, 1, true);          
  pio_sm_config c = vfo_program_get_default_config(offset);
  sm_config_set_set_pins(&c, 15, 1);                  
  pio_sm_init(pio0, 0, offset, &c);       
  pio_sm_set_enabled(pio0, 0, true);
  set_freq();
  periods=periods-10L<<24;
  for(;;){
    t = (periods+delta) >> 24;  
    pio_sm_put_blocking(pio0, 0, t);
    delta += periods-(t << 24);      
  }
}

void loop1(){} 


Die entscheidenden Parameter werden als Konstanten festgelegt. Darunter ist auch das Rufzeichen, das aber nur lizensierte Funkamateure haben. Damit mein eigenes Rufzeichen nicht versehentlich aus anderen Antennen gehört wird, habe ich das Rufzeichen "T2EST" erfunden und dabei sorgfältig darauf geachtet, dass es dieses nicht real gibt. Ohne eigenes Rufzeichen zu senden, ist streng verboten. Aber man kann den Pico ohne angeschlossene Antenne neben einen Empfänger stellen und das Signal im Nahfeld empfangen. Wenn die Daten korrekt empfangen werden, weiß man, dass alles funktioniert.


Das Empfangsergebnis zeigt, dass jeweils sechs Minuten zwischen den Aussendungen liegen. Nur die ersten drei Durchläufe haben keine zusätzlichen Pausen, damit man in Ruhe eine Antenne abstimmen kann und möglichst schnell zu ersten Empfangsergebnissen kommt. Das Programm muss zwei Sekunden nach dem Anfang einer geraden Minute gestartet werden. Es läuft dann beliebig lange autonom weiter. Die nötigen Verzögerungen wurden allein mit delay() erzeugt, wobei erst nicht klar war, ob die Genauigkeit reicht. In der Praxis hat sich jedoch gezeigt, dass die WSPR-Bake über mehr als drei Stunden laufen kann, ohne dass man eine merkliche Abweichung erkennt.



Wenn man das Ausgangsignal in einem SDR anschaut und die höchste mögliche Frequenzauflösung einstellt, kann man das Umschalten in die verschieden Signalfrequenzen direkt verfolgen. Nur mit dem Gehör nimmt man die engen Frequenzsprünge kaum wahr.

Für einen realen Sendeversuch habe ich das Signal ohne Verstärker direkt vom Pin 19 des Pico über 22 nF ausgekoppelt und an ein vorhandenes Pi-Filter zur Antennenpassung übergeben. Im 40m-Band wird ein endgespeister Dipol verwendet. Die Ausgangsleistung beträgt dann nur ca. 10 mW. Trotzdem konnte ich am Nachmittag damit zahlreiche Stationen in Deutschland und fünf weiteren Ländern erreichen. Bei dieser geringen Leistung muss ich nicht befürchten, dass jemand durch 30 dB schwächere Nebenausstrahlungen gestört wird. Ein Endverstärker mit 1 W oder mehr könnte allerdings schon problematisch werden. Macht aber nichts, Versuche mit extrem kleiner Sendeleistung sind besonders spannend. Im 30m-Band konnte ich damit bereits 1000 km überbrücken. Die Verbindung nach Schweden sieht man im Bild ganz oben.




Download: PicoWSPR.zip

Alternative WSPR-Lösungen für den Pico:
https://github.com/RPiks/pico-WSPR-tx/tree/main/WSPRbeacon
https://github.com/Jochen-bit/pico-WSPR-tx


Elektronik-Labor  Projekte  Mikrocontroller  Raspberry