JH7UBCブログ

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

Raspberry Pi Pico MicroPython I2C LCD AQM0802A表示テスト

2021-11-19 07:55:25 | Raspberry Pi Pico
 Raspberry Pi Picoで、MicroPythonを使い、I2C LCD 0802Aの表示テストをします。
 これまで、AQM0802Aは、PICやArduinoで利用し、その表示プログラムはJH7UBCホームページに掲載しています。AQM0802Aのコントローラは、ST7032です。ST7032のライブラリがあれば、それを利用するのが簡単です。

 今回はMicroPythonでのI2Cの使い方の勉強なので、ライブラリを使わないで、プログラミングをします。(ライブラリがあるのか、確認していません)

 PicoとAQM0802Aの接続回路図です。id=0 SCL=GP17,SDA=GP16としました。

 I2Cデバイスへの書き込みメッソドには、writeto(addr,buf)やwriteto_mem(addr,memaddr,buf)などがあります。
 writeto(addr,buf)で、addr=0x3e,buf[0]=0x00,buf[1]=0x02としてI2CのSCLとSDAを観測してみました。赤線がSCL、青線がSDAです。OKです。

 スクリプトです。Qiitaさんの旧版スクリプト新版スクリプトTdukurelさんのスクリプトを参考にさせていただきました。
 LCDを初期化した後、1行目に「JH7UBC」が表示され、2行目に数値が0からカウントアップされます。
------------------------------------------------------------------
from machine import Pin, I2C
import utime

i2c = I2C(0,freq=100000,scl=Pin(17),sda=Pin(16))
addr=0x3e
buf=bytearray(2)

def write_cmd(cmd):
    buf[0]=0x00
    buf[1]=cmd
    i2c.writeto(addr,buf)

def write_char(char):
    buf[0]=0x40
    buf[1]=char
    i2c.writeto(addr,buf)

def print(str):
    for c in str:
        write_char(ord(c))

def LCD_cursor(x,y):
    if y==0:
        write_cmd(0x80+x)
    if y==1:
        write_cmd(0xc0+x)

def LCD_clear():
    buf[0]=0x00
    buf[1]=0x01
    i2c.writeto(addr,buf)
    utime.sleep(0.001)

def LCD_home():
    buf[0]=0x00
    buf[1]=0x02
    i2c.writeto(addr,buf)
    utime.sleep(0.001)

def LCD_init():
    orders = [b'\x38', b'\x39', b'\x14', b'\x73', b'\x56', b'\x6c',b'\x38', b'\x0c', b'\x01']
    utime.sleep(0.04)
    for order in orders:
        i2c.writeto_mem(addr, 0x00, order)
        utime.sleep(0.001)

LCD_init()
LCD_clear()
LCD_home()
print('JH7UBC')
num=0

while True:
    LCD_cursor(0,1)
    print(str(num))
    num=num+1
    utime.sleep(1)


------------------------------------------------------------------
 LCD初期化の手順について説明します。各コマンドを順番にLCDに送ります。
 0x38 #8bit,2line
  ↓
 0x39 #IS=1:extension mode set
  ↓
 0x14 #Internal OSC Frequency
  ↓
 0x73 #Contrast 私の場合この値がちょうど良いコントラスト(要調整)
  ↓
 0x56 #Power/ICON/Contrast control
  ↓
 0x6C #Follower control
  ↓
 0x38 #IS=0:extension mode cancel
  ↓
 0x0C #Display ON
  ↓
 0x01 #Clear Display

 ブレッドボードです。無事表示されました。




Raspberry Pi Pico MicroPython I2C テスト

2021-11-18 15:30:25 | Raspberry Pi Pico
Raspberry Pi PicoのI2Cのテストをします。
machineからI2Cモジュールをインポートします。
コンストラクタI2Cの仕様は、I2C(id, scl, sda, freq)です。
idだけを指定した時のデフォルト値は、

id      sda  scl   freq
0 GPIO8 GPIO9 400000(400KHz)
1 GPIO6 GPIO7 400000(400KHz)
です。
なお、I2Cはid=0か1で次の12の組み合わせで利用することができます。
id      sda  scl 
0    GPIO0   GPIO1
1    GPIO2   GPIO3
0    GPIO4   GPIO5
1    GPIO6   GPIO7 デフォルト
0    GPIO8   GPIO9 デフォルト
1    GPIO10   GPIO11
0    GPIO12   GPIO13
1    GPIO14   GPIO15
0    GPIO16   GPIO17
1    GPIO18   GPIO19
0    GPIO20   GPIO21
1    GPIO22   GPIO23

 I2CバスにI2C LCD AQM0802Aを接続して、I2Cアドレスを調べてみます。
 スクリプトです。id=0としましたので、AQM0802AのSDAはGP8にSCLはGP9に接続します。実行結果はshellに表示されます。


 shellの上段は、I2C(1)の場合、下段はI2C(0)の場合です。
 freqとSCLとSDAのピン番号が表示されます。デフォルト値ですね。
 I2Cのクロック周波数は、最大400KHzになると思ったのですが、399361Hz(399.361KHz)と表示されました。この値が最大値のようです。

 AQM0802AのI2Cスレーブアドレスは62=0x3eと表示されました。

 次に、クロック周波数frqとscl,sdaを変えてみましょう。freq=100KHz(標準の周波数)、scl=GP17,sda=GP16の場合のスクリプトです。



 次は、I2C LCD AQM0802Aの表示テストをします。


Raspberry Pi Pico Micro Python ロータリーエンコーダ テスト

2021-11-15 18:23:48 | Raspberry Pi Pico
 前の記事でテストしたピン割込みを利用して、ロータリーエンコーダの回転方向を判定するスクリプトのテストをしました。

 まず、回転報告を判定する方法を説明します。ロータリーエンコーダのA,B端子はプルアップしておきます。ロータリーエンコーダを回転させると下の図のように、各端子の電圧が時間とともに変化します。
 A,Bの状態が変化した時(割込みが発生した時)のA,Bの値を読み取り、(B<<1)+Aの前の値と現在の値のXORをとると、時計回り(右回り)の時は、その値は、0か1になり、反時計回り(左回り)の時は、2か3になります。
 つまり、判定式D<2で時計回り、D>=2の時反時計回りと判定することができます。

 スクリプトです。
  4行目5行目 ロータリーエンコーダのA,Bが接続されるGPIO14とGPIO15を入力、プルアップに設定。
 34行目35行目 ピン割込みの設定、トリガは、立下りと立ち上がり、両方で割込みがかかるように設定。

 14行目からが、割込み時に回転方向を判定する関数です。
 最初、countをインクリメント、デクリメントするのに、count++,count--を使ったのですが、これが原因でエラーがでてしまいました。この原因が分からず、数時間を無駄にしました。MicroPythonではこの記述は通らないんですね。
 それから、判定の基準ですが、今までPICなどでのプログラムでは、count>=4でRIGHT、count<=4でLEFTとしたのですが、count>=3,count<=3の方がスムーズに判定するので、この値にしました。
 このスクリプトで実際にロータリーエンコーダを動かしてみると、一番最初のクリックだけ判定しませんが、その後はロスなく判定してくれました。

2021.12.3追記
 上の問題を解決する方法が分かりました。スクリプトを次のように訂正してください。最初PinA=1,PinB=1なので
 8行目 befDat=0x11 としてください。
これで、最初からスムーズに動くはずです。

 判定された結果は、shellに表示されます。


 接続回路図です。

ブレッドボードです。ロータリーエンコーダは、中華製の安価なものを使いました。かなりチャタリングがあるのですが、今回のスクリプトは、うまく回転方向を判定できます。



Raspberry Pi Pico MicroPython Pin割込みテスト

2021-11-14 11:27:59 | Raspberry Pi Pico
 Raspberry Pi Picoのピン(状態変化)割込みのテストをします。

 例として、GPIO15のスイッチを押すたびにLEDが点灯と消灯を繰り返すスクリプトを試します。
 4行目 スイッチ(btn)は、GPIO15に接続し、入力、プルアップします。
 11行目 ピンの電圧の立下り(FALLING)で割込みがかかります。割込みがかかるとhandlerで指定された関数(ここでは、led_toggle())が実行されます。
 

 回路図です。

 ブレッドボードです。

 タクトスイッチを使っていますが、チャタリングのため、押し方によっては誤動作することがあります。


Raspberry Pi Pico MicroPython Timer割込み

2021-11-12 23:15:25 | Raspberry Pi Pico
 Raspberry Pi Pico(RP2040)は、内部に16ビットタイマを持っていて、周期的(定期的に)割込みをかけ、設定した処理を行うことができます。

 タイマの動作モード(mode)は、
 ワンショット(Timer.ONE_SHOT)と
 周期タイマ(Timer.PERIODIC)の2つです。

 割込みがかかった時に呼び出される関数(callback関数)を指定します。

 タイマ周期の指定方法は、
 freq(周波数(Hz単位))と
 tick_hz引数とperiod引数で周期を指定する方法があります。

 この割込みを使うためのmachine.Timerコンストラクタの仕様は
 Timer(id,mode,callback,period,tick_hz,freq) です。
 id=-1
 mode Timer.ONESHOTまたはTimer,PERIODIC
 period タイマのカウント数(tick_hz単位でのカウント数)
 tick_hz タイマのカウント周波数(Hz単位の整数)
 freq タイマの周波数(Hz単位の整数)

 Pico内蔵のLED(Pin25に接続されている)をタイマ割込みで点滅させる、いわゆるLチカのスクリプトです。
 Web上にあったいくつかの例をコピーさせていただきました。いずれも周期タイマ(PERIODIC)を利用しています。

例1 cllback関数tica2()を定義しています。initはタイマを初期化するメソッドです。


例2 コンストラクタTimerの中にすべての処理を記載しています。

例3 タイマ初期化メソッドの中にすべての処理を記載しています。

 例1~例3のいずれも動作しました。

 lambdaは、ラムダ式、無名関数といい、こんな風に使われるですね。まだよく理解していません。
 Python(MIcroPython)については、まだまだ勉強不足でよくわ分からないことが多いですが、様々な事例を実行していくことによって、少しずつ習得していこうと思っています。