JH7UBCブログ

アマチュア無線 電子工作 家庭菜園など趣味のブログです

Raspberry Pi Pico MicroPython エレキー

2022-03-04 19:42:44 | Raspberry Pi Pico
 Raspberry Pi Picoでエレキーを作ってみました。

 エレキーには、短点長点メモリを持つBモードとメモリを持たないAモードがあります。詳しい説明はA1 CLUBのサイトのこちらのページをご覧ください。

 私が以前にプログラミングしたmicro:bitを使ったエレキーは、Aモードでした。Aモードでは、非常に簡単なプログラムでエレキーを作ることができますし、スクイーズ操作にも対応します。しかし、R(・ー・)やC(ー・ー・)を送信する時に、最後まで短点キーを押していないと、最後の短点が抜けてしまうことがあります。その欠点をカバーしてくれるのが短点長点メモリーで、少し早く短点キーや長点キーを放しても次に送出する短点または長点を記憶しているので、間違いなくRやCの符号を送信することができます。なお、スクイーズ操作の詳細は、GHDキーのこちらのpdfをご覧ください。

 今回は、短点長点メモリつきのBモードのエレキーをプログラミングします。プログラミングに際しては、「初めてのPIC & Arduino」というサイトのこちらの記事を参考にさせていただきました。ありがとうございました。

 まず、基本的なことから設計します。CW(モールス符号)の短点(dot)と長点(dash)と短点長点間のスペース(space)の時間をどのようにするかを決めます。それぞれの時間には、dot=space  dash=dot*3つまり、スペースは短点と同じ時間、長点は短点の3倍と決められています。

1dot=200msの時、6wpm=30字/分となり
1dot=40msの時、30wpm=150字/分となります。
通常のCW交信が20wpm前後で行われていますので、上記の範囲で速度を調整できるようにしました。下の回路図のようにVRの電圧をAD変換して読み込みます。(ADC0を使っています)PicoのADCは16ビットですが、読み込み値を右に8bitシフトして、0~255の値とし、その間の40~200の値を利用します。

 モールス練習機と同じようにPicoから700HzのPWM信号を出力し、直接スピーカーを接続してサイドトーンとしています。音量の調整はできません。

 パドルは、GPIO0とGPIO1に接続しています。GPIO0とGPIO1はプログラムでプルアップし、プルアップ抵抗は省略しています。

 送信モニタ用にLEDをGPIO16に接続し、送信機用の出力は、GPIO20に出力し、2SC1815のオープンコレクタ出力としてます(TX)。ADC以外のそれぞれのピンは自由に選ぶことができます。

 今回のエレキーのフローチャートです。右側の割込み処理を除けばmicro:bitの時と同じです。今回のエレキーでは、1msごとにTimer割込みをかけています。割込みサービスルーチン(ISR)の中に1msごとにカウントアップするカウンタを設け、短点(dot)・長点(dash)を出力する時間を決めています。また、このルーチンの中で1msごとに短点キー・長点キーが押されたかを見ています。
長点出力中(長点+スペース)に短点が押されたら短点フラッグ(dot_flag)を立て、長点出力の後に短点を出力します。また、短点出力中(短点+スペース)に長点が押されたら長点フラッグ(dash_flag)を立て、短点出力の後に長点を出力します。



ブレッドボードです。

 パドル(コードウォーリJr)とスピーカを接続してテストをしています。


 打ち心地は、普通のエレキーと同じで、普通にCWを送信することができました。
 このエレキーを更に発展させるには、長点の長さを変えることができるようにしたり、メモリキーヤーとして働くようにすることなどが考えられます。改良はまた次回にということにします。

 参考までにスクリプトです。
-------------------------------------------------------------------------
"""
Raspberry Pi Pico MicroPython Elekey
2022.3.3
JH7UBC Keiji Hata
"""
from machine import Pin,ADC,Timer,PWM
import utime

#setup
led = Pin(16,Pin.OUT)#エレキー出力
TX = Pin(20,Pin.OUT)#TX キーイング出力
dot_key=Pin(0,Pin.IN,Pin.PULL_UP)#パドルのドットキー
dash_key=Pin(1,Pin.IN,Pin.PULL_UP)#パドルのダシュキー
a=ADC(0)#速度調整用
timer=Timer()#割込みタイマー
count=0
gate_flag=0
led.value(0)

#PWM(side tone)設定
pwm = PWM(Pin(15))   #GP15に出力
pwm.freq(700)       #周波数700Hz
pwm.duty_u16(0)  #最初、音を出さない

mode=0 #mode 0:no signal 1:dot out 2:dash out
dot_flag=0
dash_flag=0

def ISR(t):
     global count,gate_flag,mode,dot_flag,dash_flag
     if gate_flag==1:#gateが開いていればカウントアップ
         count=count+1
     if mode==1 and dash_key.value()==0:
         dash_flag=1
     if mode==2 and dot_key.value()==0:
         dot_flag=1

timer.init(freq=1000,mode=Timer.PERIODIC,callback=ISR)#1msごとに割込み

def dot_out():#dotとspaceを出力
    global count,dot_time,gate_flag,mode
    count=0
    mode=1
    gate_flag=1    
    led.value(1)
    TX.value(1)
    pwm.duty_u16(32768)
    while count <= dot_time:
        pass
    count=0
    led.value(0)
    TX.value(0)
    pwm.duty_u16(0)
    while count <= dot_time:
        pass
    gate_flag=0
    mode=0

def dash_out():#dashとspaceを出力
    global count,dash_time,gate_flag,mode
    count=0
    mode=2
    gate_flag=1    
    led.value(1)
    TX.value(1)
    pwm.duty_u16(32768)
    while count <= dash_time:
        pass
    count=0
    led.value(0)
    TX.value(0)
    pwm.duty_u16(0)
    while count <= dot_time:
        pass
    gate_flag=0
    mode=0

#main loop
while True:
     dot_time=a.read_u16()>>8
     if dot_time <= 40:
         dot_time = 40 #最高速度を30wpm(150字/分)に制限
     elif dot_time >=200:
         dot_time = 200#最低速度を6wpm(30字/分)に制限
     dash_time=dot_time+dot_time
     dash_time=dash_time+dot_time #dash_time=dot_time * 3
     #dot_key,dash_keyが押された時、またはflagが立った時の処理
     if dot_key.value()==0 or dot_flag==1:
         dot_out()
         dot_flag=0
     if dash_key.value()==0 or dash_flag==1:
         dash_out()
         dash_flag=0
-------------------------------------------------------------------------