goo blog サービス終了のお知らせ 

JH7UBCブログ

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

Raspberry Pi Pico MiroPython エレキーその2

2022-03-09 15:13:02 | Raspberry Pi Pico
 前の記事で製作したエレキーにメモリーキー機能を加えてみました。
 Raspberry Pi Picoは、EEPROMを持っていませんので、メッセージは、プログラム(スクリプト)の中に記載します。

 回路図です。前の記事とほぼ同じです。メモリは、とりあえずM1とM2とし、それぞれのボタンが押された時、メモリに記憶されたメッセージが送出されます。メッセージ送出中にdotまたはdashが押されれば、メッセージ送出は中断されます。単3電池2本3Vで動作するようにしました。
 

ブレッドボードです。2SC1815オープンコレクタ出力の部分は省略しています。

 パドルとスピーカーを接続して、テストをしています。


 プログラム(スクリプト)です。メモリ送信中の速度調節はできません。
 通常、モールス符号送信では、文字間は、3dot分、語間は、7dot分と決められています。今回は、dot_outでdot+space、dash_outでdash+spaceを送出しています。(dash=3dot、spaceはdotと同じ時間)したがって、文字間(char_space)=2dot分、語間(word_space)=6dot分としています。
dash_time=dot_time*3
char_space=dot_time*2
word_space=dot_time*6
とすれば、良いのですが、掛け算は時間がかかりますので、全て足し算と左シフト(2倍)で計算しています。
 文字→モールス符号送出は、メモリのメッセージを左から一文字ずつ取り出し、ASCIIコードから47を引き、/~Zの文字を0~43の数字に変換し、M_codeリストの当該数値の符号を取り出して、送出しています。
 ただし、語間を表すスペース(ASCIIで32)の時は、word_spaceを送出しています。
 M1='CQ CQ DE JH7UBC・・・・'
 M2=’’DE JH7UBC K
の部分を各局用に書き換えてください。
------------------------------------------------------------------------------------
"""
Raspberry Pi Pico MicroPython Elekey メモリキーヤー付き
2022.4.13
JH7UBC Keiji Hata
"""
from machine import Pin,ADC,Timer,PWM

#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)#パドルのダシュキー
M1_button=Pin(12,Pin.IN,Pin.PULL_UP)#メモリー1
M2_button=Pin(13,Pin.IN,Pin.PULL_UP)#メモリー2

a=ADC(0)#速度調整用
timer=Timer()#割込みタイマー
count=0
gate_flag=0
led.value(0)

#PWM(side tone)設定
pwm = PWM(Pin(15))   #GP20に出力
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
mem_flag=0

#モールス符号(/0~9~A~Z)ASCII順
M_code = ['-..-.','-----','.----','..---','...--','....-','.....',
          '-....','--...','---..','----.','---...','--..--',
          '','-...-','','..--..','.--.-.','.-','-...','-.-.','-..',
          '.','..-.','--.','....','..','.---','-.-','.-..','--','-.',
          '---','.--.','--.-','.-.','...','-','..-','...-','.--',
          '-..-','-.--','--..']

#ここにメッセージメモリーの内容を書き込む
M1='CQ CQ DE JH7UBC JH7UBC JCC 0708 PSE K'
M2='DE JH7UBC K'

#割込みサービスルーチン
def ISR(t):
    global count,dot_flag,dash_flag,mem_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
    if mem_flag==1:#メモリ送信中にdotまたはdashが押されたら送信停止
        if dot_key.value()==0 or dash_key.value()==0:
            mem_flag=0

#Timer割込み設定
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

def char_space_out():#文字間スペース出力
    global count,char_space,gate_flag
    count = 0
    gate_flag=1
    led.value(0)
    TX.value(0)
    pwm.duty_u16(0)
    while count <= char_space:
        pass
    gate_flag=0

def word_space_out():#語間スペース出力
    global count,word_space,gate_flag
    count = 0
    gate_flag=1
    led.value(0)
    TX.value(0)
    pwm.duty_u16(0)
    while count < word_space:
        pass
    gate_flag=0

def morse_out(n):
    global M_code
    m=M_code[n]
    l=len(m)
    for j in range(l):
        s=m[j]
        if s=='.':
            dot_out()
        elif s=='-':
            dash_out()
    char_space_out()

def memory_send(mem):
    global M1,M2,mem_flag
    mem_flag=1
    if mem==1:
        M=M1
    elif mem==2:
        M=M2
    ml=len(M)
    i=0
    while mem_flag==1:
        ascii=ord(M[i])
        if ascii==32:
            word_space_out()
        elif ascii >=47 and ascii<=90:
            ascii=ascii-47
            morse_out(ascii)
        i=i+1
        if i >= ml:
            mem_flag=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字/分)に制限
    char_space=dot_time+dot_time
    dash_time=char_space+dot_time #dash_time=dot_time * 3
    word_space=dash_time<2 # word_space=dot_time*7
    #メモリーボタンが押された時
    if M1_button.value()==0:
        memory_send(1)
    if M2_button.value()==0:
        memory_send(2)
    #dot_keyが押されたとの処理
    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
------------------------------------------------------------------------------------
 私の経験上、メモリキーヤーを使いたいときは、JCCサービスや、コンテスの時です。パソコンを立ち上げ、Thonnyでスクリプトを書き換えなければならないのは、一見面倒なようですが、運用目的に合わせて、確実に記入できますので、あらかじめ準備をしておけば、スムーズに運用できると思います。

 MicroPythonによるプログラミングは、プログラムの見通しが良く、簡単に自分なりにカスタマイズできると思います。やってみてください。

 このキーヤーをボードに組み、ケーシングすれば、実用になると思います。

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
-------------------------------------------------------------------------

Raspberry Pi Pico MicroPython スカッシュゲーム

2022-02-23 22:14:21 | Raspberry Pi Pico
 Raspberry Pi Picoに2.2インチTFTを接続し、MicroPythonでプログラミングして、懐かしい「スカッシュゲーム」を作ってみました。
 接続回路図です。



 ブレッドボードです。


 ラケットを操作する左ボタン(L Button)と右ボタン(R Button)は別なブレッドボードに取り付けました。

 ゲーム画面です。上にスコアを表示しています。
 ボールは、10×9ドットで、X方向24、Y方向30ステップで移動します。



 ゲームオーバー画面です。

スクリプトです。main.pyとしてPicoに保存します。
なお、以前にアップしたTFT表示テスト1及びテスト2を参考にして、
Picoに、ili9341.pyとxglcd_font.pyを保存し、
pico内のfontというフォルダにUnispace12x24.cとBroadway17x15.cを保存しておきます。
---------------------------------------------------------------------------------
"""
Raspberry Pi Pico MicroPython
Squash game
2022.2.23
JH7UBC Keiji Hata
"""

from machine import Pin, SPI
import ili9341
from xglcd_font import XglcdFont
import utime
from random import random, seed

#Button設定
Button_L = Pin(4,Pin.IN,Pin.PULL_UP)
Button_R = Pin(5,Pin.IN,Pin.PULL_UP)

#SPI設定
TFT_CLK_PIN = const(6)
TFT_MOSI_PIN = const(7)
TFT_MISO_PIN = const(4)
TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(15)

spiTFT = SPI(0, baudrate=51200000,
                 sck=Pin(TFT_CLK_PIN), mosi=Pin(TFT_MOSI_PIN))
display = ili9341.Display(spiTFT,dc=Pin(TFT_DC_PIN),
             cs=Pin(TFT_CS_PIN), rst=Pin(TFT_RST_PIN),
             width=240, height=320,rotation=0)
#フォントの設定
unispace = XglcdFont('fonts/Unispace12x24.c', 12, 24)
broadway = XglcdFont('fonts/Broadway17x15.c',17,15)

#score枠を描く
def display_score_bar():
     display.fill_hrect(0,0,240,20,ili9341.color565(255,255,255))
     display.draw_text(70,3,'score',broadway,ili9341.color565(0,0,255),
                   background=ili9341.color565(255,255,255))

#score表示
def display_score(s):
     display.fill_hrect(130,0,100,9,ili9341.color565(255,255,255))
     s_text = str(s)
     len_s=len(s_text)
     for i in range(4-len_s):
        s_text='0'+s_text
     display.draw_text(130,3,s_text,broadway,ili9341.color565(0,0,255),
                   background=ili9341.color565(255,255,255))

#ラケットを描く
def display_racket():
     global prev_rx,rx
     display.fill_hrect(prev_rx*10,310,50,9,0)
    display.fill_hrect(rx*10,310,50,9,ili9341.color565(255,255,255))
     prev_rx=rx

#ボールを描く
def display_ball(x,y):
     global prev_x,prev_y
     display.fill_hrect(prev_x*10,prev_y*10,10,10,0)
     display.fill_hrect(x*10,y*10,10,9,ili9341.color565(255,255,0))
     prev_x = x
     prev_y = y

#初期画面表示
start_Flag=0
display.draw_text(60,110,'Squash Game',unispace,ili9341.color565(255,255,0))
display.draw_text(20,150,'Push L or R Button',unispace,ili9341.color565(0,255,255))

#ボールのスピード設定(値を小さくすると速くなる)
speed=50

#メインループ
while True:
     if start_Flag == 0:
         #LまたはRボタンが押されるまで待つ
         while Button_L.value()==1 and Button_R.value()==1:
             pass
         start_Flag = 1
         display.clear()
        display_score_bar()
         score = 0
         display_score(score)
         rx=10
         prev_rx=rx
         display_racket()
         bx=10
         by=10
         #方向をランダムに決める
         direction=int(random()*4)
         if direction == 0:
             dx=1
             dy=1
         elif direction == 1:
             dx=1
             dy=-1
         elif direction == 2:
             dx=-1
             dy=1
         elif direction == 3:
             dx=-1
             dy=-1
         prev_x=bx
         prev_y=by
         display_ball(bx,by)

     else:
         #ボールを動かす
         #X方向に動かす
         bx = bx + dx
         if bx < 0 or bx > 23:#bx<0 またはbx>23なら
             bx = bx -dx#一つ戻す
             dx = -dx#方向を変える
             bx = bx + dx
         #Y方向に動かす
         by = by + dy
         if by<2:
             by = by - dy#一つ戻す
             dy = -dy#方向を変える
             by = by + dy
         if by == 31:
             if bx >= rx and bx <= rx+4:
                by = by - dy#一つ戻す
                dy = -dy#方向を変える
                 by = by + dy
                score = score + 1
                display_score(score)
             else:
                start_Flag=0
                display.draw_text(70,150,'GAME OVER',unispace,ili9341.color565(255,0,0))
                utime.sleep(0.5)
                while Button_L.value()==1 and Button_R.value()==1:
                    pass
         #ラケットを動かす
         if Button_L.value() == 0:
             rx=rx-1
             if rx<=0:
                rx=0
             display_racket()
         if Button_R.value() == 0:
             rx=rx+1
             if rx > 19:
                rx=19
             display_racket()

         display_ball(bx,by)
         utime.sleep_ms(speed)
---------------------------------------------------------------------------------
 とりあえず、ボールが動いてゲームができる状態です。
 音を出したり、スピードをボタンで変えられるようにしたり、改良点はたくさんあります。これを参考にしてオリジナルのゲームを作ってみてください。

 最初、ボールの動きをタイマー割込みを利用して行おうと実験しましたが、ラケットの表示に乱れが出てしまい、断念しました。後でまたチャレンジしてみようと思います。


Raspberry Pi Pico MicroPython TFT sin cos カーブを描く

2022-02-12 11:46:49 | Raspberry Pi Pico
 Raspberry Pi Pico MicroPython でTFTディスプレイにサインとコサインカーブを描いてみました。


 スクリプトです。Picoはクロックが133MHzと速く、MicroPythonインタープリタでもけっこう速くカーブを描くことができます。
-------------------------------------------------------------------------------------------------
from machine import Pin, SPI
import ili9341
from xglcd_font import XglcdFont
import math

#SPI設定
TFT_CLK_PIN = const(6)
TFT_MOSI_PIN = const(7)
TFT_MISO_PIN = const(4)
TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(15)

spiTFT = SPI(0, baudrate=51200000,
                 sck=Pin(TFT_CLK_PIN), mosi=Pin(TFT_MOSI_PIN))
display = ili9341.Display(spiTFT,dc=Pin(TFT_DC_PIN),
             cs=Pin(TFT_CS_PIN), rst=Pin(TFT_RST_PIN),
             width=320, height=240,rotation=90)
#font設定
unispace = XglcdFont('fonts/Unispace12x24.c', 12, 24)
bally7x9 = XglcdFont('fonts/Bally7x9.c',7,9)

#title表示
display.draw_text(100, 0, 'sin', unispace,
                  ili9341.color565(255, 255, 255))
display.draw_text(200, 0, 'cos', unispace,
                  ili9341.color565(255, 255, 0))
#軸線の表示
display.draw_hline(20,120,270,ili9341.color565(255,255,255))
display.draw_vline(20,20,200,ili9341.color565(255,255,255))
display.draw_text(5, 115, '0', bally7x9,ili9341.color565(255, 255, 255))
display.draw_text(5, 20, '1', bally7x9,ili9341.color565(255, 255, 255))
display.draw_text(0, 215, '-1', bally7x9,ili9341.color565(255, 255, 255))

#sine waveを描く
for x in range(0,270):
     y=-int(math.sin(6.283185*x/270)*100)
     display.draw_pixel(x + 20,y+120,ili9341.color565(255,255,255))
#cos waveを描く
for x in range(0,270):
     y=-int(math.cos(6.283185*x/270)*100)
     display.draw_pixel(x + 20,y+120,ili9341.color565(255,255,0))    
-------------------------------------------------------------------------------------------------

Raspberry Pi Pico MicroPython 2.2インチTFT表示テストその2

2022-02-11 21:13:55 | Raspberry Pi Pico
 前の記事に続き、Raspberry Pi Picoで2.2インチTFTの表示テストをします。
 今回は、表示できるフォントのテストをしました。
 GitHubのrdagger/micropython-ili9341 のページのfontsには、15種類のフォントがあります。そのうちいくつかはうまく表示できませんでしたが、今後使えそうなフォントで表示させてみました。


 スクリプトです。比較ができるように色は黄色だけにしました。フォントがロードされるまで、若干時間がかかります。
------------------------------------------------------------------------------------
from machine import Pin, SPI
import ili9341
from xglcd_font import XglcdFont

#SPI設定
TFT_CLK_PIN = const(6)
TFT_MOSI_PIN = const(7)
TFT_MISO_PIN = const(4)
TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(15)

spiTFT = SPI(0, baudrate=51200000,
                 sck=Pin(TFT_CLK_PIN), mosi=Pin(TFT_MOSI_PIN))
display = ili9341.Display(spiTFT,dc=Pin(TFT_DC_PIN),
             cs=Pin(TFT_CS_PIN), rst=Pin(TFT_RST_PIN),
             width=240, height=320,rotation=0)
#font設定
unispace = XglcdFont('fonts/Unispace12x24.c', 12, 24)
bally7x9 = XglcdFont('fonts/Bally7x9.c',7,9)
espresso = XglcdFont('fonts/EspressoDolce18x24.c', 18, 24)
arcadepix = XglcdFont('fonts/ArcadePix9x11.c', 9, 11)

#テキストの表示
display.draw_text(10, 0, 'Unispace12x24', unispace,
                  ili9341.color565(255, 255, 0),spacing=2)
display.draw_text(10, 50, 'Bslly7x9', bally7x9,
                  ili9341.color565(255, 255, 0))
display.draw_text(10, 100, 'EspressoDolce18x24', espresso,
                  ili9341.color565(255, 255, 0))
display.draw_text(10, 150, 'ArcadePix9x11', arcadepix,
                  ili9341.color565(255, 255, 0),spacing=2)
------------------------------------------------------------------------------------