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倍と決められています。
以前にRaspberry Pi Pico MicroPythonモールス符号練習機の記事に書きましたが、
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
-------------------------------------------------------------------------
※コメント投稿者のブログIDはブログ作成者のみに通知されます