
RPi-Pico Raster-VFO
Elektronik-Labor
Projekte
Mikrocontroller
Raspberry
Ein RPi Pico kann ganz ohne zusätzliche Hardware zu einem
programmierbaren Oszillator für den Kurzwellenbereich werden. Hier
wurde versucht, möglichst kleine Frequenzschritte zu erreichen. Das
Geheimnis liegt in der internen PLL des Pico, mit der man
unterschiedliche Taktfrequenzen einstellen kann. Die Stufung ist zwar
nicht sehr eng, aber zusammen mit unterschiedlichen Teilerfaktoren
durch die PWM-Einheit können sehr viele unterschiedliche Frequenzen
erzeugt werden. Das Verfahren beruht aus einem Ausprobieren, welche
Einstellung am besten zur Wunschfrequenz passt.
Das folgende Rechenprogramm gibt einen Überblick, welche
Ausgangsfrequenzen möglich werden, wenn man die Systemfrequenz in
ganzen MHz zwischen 32 MHz und 130 MHz variiert.
# Mögliche PWM-Frequenzen zwischen 3,5 MHz und 3,6 MHz
min1=3499
clock =0
divisor=1
for l in range(100):
delta1=100
for m in range (32,130):
for n in range(1,50):
f=m/n*1000
if f>min1:
if f<3600:
delta2=f-min1
if delta2<delta1:#
delta1=delta2
min2=f
divisor=n
clock=m
min1=min2
print (clock, divisor, min1)
Das Ergebnis zeigt einige glatte Frequenzen, wie z.B. 88 MHz / 25 =
3,520 MHz, aber auch viele andere, krummere Werte. Man sieht aber
schon, dass es insgesamt eine enge Abstufung gibt.
35 10 3500.0
123 35 3514.286
116 33 3515.152
109 31 3516.129
102 29 3517.241
95 27 3518.518
88 25 3520.0
81 23 3521.739
74 21 3523.809
67 19 3526.316
127 36 3527.777
60 17 3529.412
113 32 3531.25
53 15 3533.333
99 28 3535.714
46 13 3538.461
85 24 3541.667
124 35 3542.857
39 11 3545.455
110 31 3548.387
71 20 3550.0
103 29 3551.724
32 9 3555.556
121 34 3558.823
89 25 3560.0
...
Tatsächlich sind nicht nur glatte MHz-Frequenzen möglich, sondern auch
Vielfache von 0,8, 1,2 und 1,5 MHz. Damit ergeben sich noch mehr
Möglichkeiten und insgesamt ein engeres Raster möglicher
Ausgangsfrequenzen. Die Berechnung und Ausgabe der Frequenzen läuft in
einer Interrupt-Funktion, damit das Hauptprogramm jederzeit auf
Eingaben des Benutzers reagieren kann. Er kann eine Wunschfrequenz
eingeben und erhält dann die Ausgabe der genauen VFO-Frequenz und
zusätzlich die zugehörige Empfangsfrequenz bei einer ZF von 455 kHz. Im
Bereich 100 kHz bis 2 MHz ist die Treffergenauigkeit besser als 1 kHz.
Je höher die Ausgangsfrequenz wird, desto größer werden die
Abweichungen. Bei 3,5 MHz kann man noch sinnvoll Abstande von 5 kHz
einstellen, bei 7 MHz noch Abstände von 10 kHz.
#VFO1.py Kurzwellen VFO, Out P2
from machine import Pin, PWM, Timer
import time
pwm1 = PWM(Pin(2))
f=6255
fout=f
sp=0
df=5
fa=0
def tune(value):
global f, df, sp, fout
clock = 100000
min2=0
delta1=500
if sp==1:
f=f+df
for j in range (80,120):
m=j*0.8
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
for j in range (60,120):
m=j*1
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
for j in range (50,100):
m=j*1.2
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
for j in range (40,80):
m=j*1.5
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
fout=min2
if fa!=f:
clk = 100*int(clock*10)
#print (f,clk, fout)
machine.freq(clk*1000)
pwm1.freq(int(fout)*1000)
pwm1.duty_u16(32767)
timer = Timer(period=1000, mode=Timer.PERIODIC, callback=tune)
while 1:
fnew=input("f=")
fin=int(fnew)
if fin>100:
f=fin
df=0
else:
if fin==0:
sp=0
if fin==1:
df=fin
sp=1
if fin==2:
f=f-df
sp=0
if fin==3:
f=f+df
sp=0
if fin>3:
df=fin
sp=1
time.sleep (1.2)
print (fout,fout-455)
Zusätzlich
gibt es die Möglichkeit, einen Suchlauf ab der zuletzt gewählten
Frequenz zu starten. Man gibt dazu die Schrittweite 1 kHz, 5 kHz oder
mehr ein. Eine 0 stoppt den Suchlauf. Weil man dann manchmal über das
Ziel hinaus gesucht hat, geht die 2 einen Schritt zurück und die 3
einen Schritt vor.
Der VFO wurde als Hautoszillator für den RX2003
getestet. Zwischen dem Empfänger und dem RPi Pico liegt ein kleiner
Ringkern-Trenntrafo, der aus einer defekten Energiesparlampe ausgebaut
wurde. Die Trennung reduziert Störungen, die sonst über das USB-Kabel
vom PC in den Empfänger gelangen können. Hier wurden mit dem Suchlauf
interessante AM-Rundfunksender im 49-, 41 und 31-m-Band gefunden.
Rpi Pico Stand Alone VFO
Diesmal wird der VFO ohne USB-Verbindung verwendet und kann mit einer
einzelnen Taste abgestimmt werden. Nur die Betriebsspannung wird über
die USB-Buchse zugeführt. Der VFO wurde für meinen 80m-Direktmischer
verwendet, um die Drehkoabstimmung durch die PLL-Variante zu ersetzen.
damit erreicht man eine sehr viel bessere Frequenzkonstanz, die den
Direktmischer auch für digitale Betriebsarten tauglich macht.
#HFgen4.py 80 m Raster-VFO
from machine import Pin, PWM, Timer
import time
from machine import Pin, I2C, ADC, PWM, freq as CPU_freq
from ssd1306 import SSD1306_I2C
i2c = I2C(0, scl=Pin(1),sda=Pin(0),freq=100000)
oled = SSD1306_I2C(128,64,i2c)
p5 = Pin(5, Pin.IN, Pin.PULL_UP)
p7 = Pin(7, Pin.IN, Pin.PULL_UP)
machine.freq(32000000)
pwm1 = PWM(Pin(2))
pwm1.freq(3555000) #3555 kHz
pwm1.duty_u16(32767)
for i in range (3500,3800):
f=i*1
delta1=100
for j in range (80,120):
m=j*0.8
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
for j in range (60,120):
m=j*1
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
for j in range (50,100):
m=j*1.2
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
for j in range (40,80):
m=j*1.5
n = round(1000*m/f)
f2=1000*m/n
delta2=abs(f2-f)
if delta2<delta1:
delta1=delta2
min2=f2
divisor=n
clock=m
fout=min2
clk = 100*int(clock*10)
print (f,clk, fout)
machine.freq(clk*1000)
pwm1.freq(int(fout)*1000)
pwm1.duty_u16(32767)
fout = round(fout*10)/10
text = str(fout) + " kHz"
oled.fill(0)
oled.text(text,25,2)
oled.show()
time.sleep (0.05)
while p5.value()==1:
time.sleep (0.05)
Die
Sollfrequenz zwischen 3500 kHz und 3800 kHz wird hier in 1kHz-Sprüngen erhöht,
wenn man auf den Taster drückt. Das Programm gibt die Sollfrequenz, den
eingestellten Prozessortakt in kHz und die tatsächliche Ausgangsfrequenz aus.
Auf dem OLED-Display wird nur die tatsächliche VFO-Frequenz angezeigt. Man
sieht hier die Einstellungen für den Bereich 3520 kHz bis 3580 kHz. Die
Frequenz wird nur an wenigen Stellen genau getroffen, die Abweichung bleibt
aber meist kleiner als 1 kHz.
3520 70400 3520.0
3521 81000 3521.739
3522 81000 3521.739
3523 109200 3522.581
3524 74000 3523.809
3525 112800 3525.0
3526 95200 3525.926
3527 77600 3527.273
3528 77600 3527.273
3529 60000 3529.412
3530 60000 3529.412
3531 113000 3531.25
3532 109500 3532.258
3533 84800 3533.333
3534 63600 3533.334
3535 99000 3535.714
3536 99000 3535.714
3537 67200 3536.842
3538 92000 3538.461
3539 92000 3538.461
3540 70800 3540.0
3541 85000 3541.667
3542 85000 3541.667
3543 74400 3542.857
3544 74400 3542.857
3545 78000 3545.455
3546 78000 3545.455
3547 81600 3547.826
3548 81600 3547.827
3549 110000 3548.387
3550 71000 3550.0
3551 103000 3551.724
3552 88800 3552.0
3553 67500 3552.631
3554 92400 3553.846
3555 64000 3555.556
3556 64000 3555.556
3557 99600 3557.143
3558 103200 3558.621
3559 103200 3558.621
3560 89000 3560.0
3561 110400 3561.291
3562 114000 3562.5
3563 114000 3562.5
3564 117600 3563.637
3565 82000 3565.217
3566 85600 3566.667
3567 85600 3566.667
3568 103500 3568.966
3569 103500 3568.966
3570 92800 3569.231
3571 75000 3571.428
3572 75000 3571.428
3573 75000 3571.428
3574 118000 3575.758
3575 118000 3575.758
3576 118000 3575.758
3577 93000 3576.923
3578 68000 3578.947
3579 68000 3578.947
3580 111000 3580.645
Der VFO war auf Anhieb und ohne Trenntrafo tauglich für den
80m-Direktmischer. Der Ausgang des Empfängers wurde an die
PC-Soundkarte angeschlossen und das Signal dann mit SDR-Software
verarbeitet.
Hier wurden FT8-Signale empfangen. Die dafür nötige Konstanz der
Frequenz wurde problemlos eingehalten. Die VFO-Frequenz sollte
eigentlich 3573 kHz sein, Der VFO konnte an dieser Stelle allerdings
nur 3571,4 kHz liefern. Den Ausgleich besorgt SDRSharp. In der
Betriebsart USB wurde die Frequenz passend eingestellt. Das empfangene
Signal wurde dann über den Lautsprecher und ein Mirofon an WSJT-X
übergeben. Das geht zwar auch direkter, funktionierte aber auch so
recht gut.