JH7UBCブログ

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

Raspberry Pi Pico MicroPython モールス符号練習機

2021-11-27 21:18:12 | Raspberry Pi Pico
 今まで勉強してきたRaspberry Pi Picoの機能活用とMicroPythonのプログラミングの練習としてモールス符号練習機(Morse Trainer)を作ってみました。

 電池2本でスタンドアローンで動作します。モードはランダムモードとABC順モードの2つです。速度は10kΩボリュームで6wpm~24wpmの間で調整できます。文字はOLEDに表示します。モールス音は、GPIO0に接続したスピーカーから出ます。周波数は700Hz固定としました。スタートボタンを押すと符号の送出が始まり、途中でこのボタンを押すと止まります。
  

 プログラミングの前に、モールス符号について説明します。モールス符号は、短点(dot)と長点(dash)の組み合わせで文字を表現します。文字内のdotまたはdashの間は1dotの時間、文字間は3dotの時間、語間は、7dotの時間と定められています。

 モールス通信の速度は、語/分(wpm(word per minute) )で表します。1語として「PARIS」という語を使い、下の図のように語間スペースも含めると50dot分になります。
 従って、1dotの時間(ms)は、1200/wpmで計算できます。逆に速度wpmは、1200/1dot(ms)で計算できます。良く使われる字/分は、wpm×5字/分となります。

 今回速度の可変範囲は、6wpm(30字/分)~24wpm(120字/分)としました。コンテストなどでも20wpmを聞き取れれば大丈夫です。

 スクリプトです。音を出すときは、pwm.duty_u16(0x8000)とし、700Hzデューティ比50%のPWM信号をGPIO0に出力します。spaceなど音を出さないときは、pwm.duty_u16(0)としてPWM信号を出しません。
 Picoの出力ポートは力持ちで、直接スピーカーをつないで音を出すことができます。ただし、音量は変えられません。
 なお、スクリプトは、main.pyとしてPicoに保存します。ssd1306というライブラリーを利用しますので、前のOLEDテストの記事に記載したようにダウンロードしてPicoにインストールしておきます。
-----------------------------------------------------------------------------------
"""
Morse Trainer Ver1
2021.11.27
JH7UBC Keiji Hata
"""

from machine import I2C,Pin,PWM,ADC
import random
import utime
import ssd1306

M_code = [".-","-...","-.-.","-..",".","..-.","--.","....","..",
           ".---","-.-",".-..","--","-.","---",".--.","--.-",".-.",
           "...","-","..-","...-",".--","-..-","-.--","--.."]
moji = ["A","B","C","D","E","F","G","H","I","J","K","L","M",
         "N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
mode_txt=["RAND","ABCD"]

def text_clr():
     oled.fill_rect(0,8,127,63,0)

def random_txt():
    global x0
    global y0
    column = 0
    row=0
    count=0
    while True:
         speed_read()
        x = x0 + 8 * column
        y = y0 + 8 * row
         i=int(random.random() * 26)
         oled.text(moji[i],x,y)
         oled.show()
         morse_out(i)
         column =column + 1
         count = count +1
        if count > 3:
             column = column +1
             count =0
        if column >14:
             column = 0
             row = row + 1
        if row > 5:
             break
        if start_sw.value()==0:
             break

def abcd_txt():
    global x0
    global y0
    column = 0
    row=0
    count=0
    for i in range(26):
        speed_read()
        x = x0 + 8 * column
        y = y0 + 8 * row
         oled.text(moji[i],x,y)
         oled.show()
         morse_out(i)
         column =column + 1
         count = count +1
        if count > 3:
             column = column +1
             count =0
        if column >14:
             column = 0
             row = row + 1
        if start_sw.value()==0:
             break

def dot():
     pwm.duty_u16(0x8000)
     utime.sleep_ms(dot_time)

def space():
     pwm.duty_u16(0)
    utime.sleep_ms(dot_time)

def dash():
     pwm.duty_u16(0x8000)
     utime.sleep_ms(dot_time)
     utime.sleep_ms(dot_time)
     utime.sleep_ms(dot_time)

def char_space():
     pwm.duty_u16(0)
     utime.sleep_ms(dot_time)
     utime.sleep_ms(dot_time)

def morse_out(n):
     m=M_code[n]
     l=len(m)
    for j in range(l):
         s=m[j]
        if s==".":
             dot()
         elif s=="-":
             dash()
         space()
     char_space()


def mode_disp(m):
     oled.fill_rect(16,0,32,8,0)
    oled.show()
     oled.text(mode_txt[m],16,0)
     oled.show()

def mode_change():
     utime.sleep_ms(10)
    global mode
    mode = mode +1
    if mode>1:
         mode=0
     mode_disp(mode)

def start_morse():
    global mode
     utime.sleep_ms(10)
     text_clr()
    if mode==0:
         mode_disp(mode)
         random_txt()
    elif mode==1:
         abcd_txt()

def speed_read():
    global wpm
    global dot_time
    global dash_time
     dot_time=speed.read_u16() >> 8
    if dot_time < 50:
         dot_time=50
    if dot_time >200:
         dot_time=200
     wpm=int(1200/dot_time)
     wpm_disp()

def wpm_disp():
    global wpm
    global old_wpm
    if wpm != old_wpm:
         oled.fill_rect(96,0,32,8,0)
         oled.show()
         oled.text(str(wpm),96,0)
         oled.show()
     old_wpm=wpm        

#setup
i2c=I2C(0,sda=Pin(16),scl=Pin(17),freq=400000)
oled=ssd1306.SSD1306_I2C(128,64,i2c)

#ピン割り当てと設定
start_sw=Pin(15,Pin.IN,Pin.PULL_UP)
mode_set=Pin(14,Pin.IN,Pin.PULL_UP)
speed=ADC(0)

#PWM設定
pwm=PWM(Pin(0))#morse音をPin0に出力
pwm.freq(700)   #tone=700Hz
pwm.duty_u16(0)#最初、音を出さない

x0 = 8
y0 = 16
mode = 0
mvalue=0
old_mvalue= 0
svalue=0
old_svalue=0
wpm = 10
old_wpm =0

#初期画面表示
oled.text("M:      WPM:",0,0)
oled.show()   
mode_disp(mode)
wpm_disp()


#main loop
while True:
     speed_read()
     mvalue=mode_set.value()
    if mvalue==0 and old_mvalue==1:
         mode_change()
     old_mvalue=mvalue
     svalue=start_sw.value()
    if svalue==0 and old_svalue==1:
         start_morse()
     old_svalue=svalue
     utime.sleep_ms(10)

-----------------------------------------------------------------------------------

 ブレッドボードです。


 ABC順モードです。

 白いボタンがSTART/STOP、青いボタンがモードボタンです。速度は右上に表示されます。

 電池は、39番ピンVSYSに接続します。

最新の画像もっと見る

コメントを投稿