Raspberry Pi Pico+Micropython
前の記事でC言語での開発環境を整えた割に、環境が複雑(=面倒くさ)すぎて開発を始めるモチベーションが沸かない。もっと簡単にThonny+Micropythonを使ってみることにする。ThonnyのインストールやPicoへのMicropythonの書き込みなどは他の記事に任せるとして、この記事は実際のコーディングについて整理してみた。
MicroPythonでプログラミングする際に、この「RP2 用クイックリファレンス」がとても参考になる。
これまで何度かプログラムを書いてみたが、そのうち飽きてPICとか触り出すわけで、気が向いたらPicoに戻って何度も再発見を行うことになる。どうせすぐに書き方を忘れてしまうので、自分用の備忘録としてこの記事を書いておく。
この部品、動くのか?
例えばI2Cのディスプレイを部品箱から久しぶりに取り出したとする。
これをPICで動かそうとした時に表示できなかったりすると、PICに書いたファームウェアが悪いのか部品が壊れているのかわからない場合が多い(大抵は接続ミスだけど)。以前はArdiono UNOに繋いでサンプルを動かすようにしていたが、イマドキならPicoかもと思い直したので、これからのためにお馴染みの(?)開発ボードを作ってみた。
開発ボード
PicoとThonyを組み合わせるならデバッグ用のシリアルモニタは必要ないので、ADC用のボリューム、リセットスイッチ、電源モニタ用LEDおよびトグルスイッチを基板に載せた。Picoの各ピンはソケットで引き出せるようにして、信号モニタはPico側に実装した連結ピンを利用する。
台に使用した百均Seriaのアクリル板がちょっと小さいので基板側がかなり窮屈になってしまった。
まずはLチカ
よくあるタイプのLチカをやってみる。ArduinoのExamples Blinkとほぼ同じ内容だ。Pythonチュートリアルだとimport machineと書くようだが、例えばGPIOの表記が「machine.Pin」とか長すぎるので、fromを使ってみた。
from machine import Pin
from time import sleep
led = Pin("LED", Pin.OUT)
while True:
led.toggle()
sleep(0.5)
オシロでモニタしてみると周期は安定しており、精度も意外にちゃんとしている。
次はPWMで
マイコンなんだから周期処理は無限ループ中ではなく、ハードウェアで実現すべきだ。ここではPWM機能を使ってみよう。たった3行でいい。
from machine import PWM,Pin
led=Pin("LED",Pin.OUT)
pwm=PWM(led,freq=9,duty_u16=32768)
周波数は2にしたかったが最小で9しか設定できなかった。かなり忙しなく点滅するが、これはこれでいい。
タイマー割り込み
PWMでは1秒点滅ができないので、タイマー割り込みを使ってみた。周期2Hzのトグル動作なので1Hzで点滅する。無限ループがないので実行するとすぐ終了して戻ってくるが、LEDはずっと点滅する。
from machine import Pin,Timer
led = Pin("LED", Pin.OUT)
def toggle(timer):
led.toggle()
timer=Timer()
timer.init(mode=Timer.PERIODIC, freq=2, callback=toggle)
柔らかホタル点滅
ここまでのLED点滅はビシッと点灯し同じように消灯するが、ふんわりと点灯と消灯を繰り返す点滅にしてみる。無限ループ内に2つのforループを入れて、PWMのデューティで点滅動作をさせてみた。
from machine import PWM,Pin
from time import sleep
led=Pin("LED",Pin.OUT)
pwm=PWM(led, freq=256000)
while True:
for i in range(0,256):
pwm.duty_u16(256*i)
sleep(0.5/256)
for i in range(0,256):
pwm.duty_u16(256*(255-i))
sleep(0.5/256)
何となく点滅が速いのでオシロで見てみると、どうも計算通りになっていない。
正弦波点滅
もう少し柔らかな点滅を目指して正弦波で点滅させてみた。
from machine import PWM,Pin
from time import sleep
from math import sin,pi
led=Pin(0,Pin.OUT)
pwm=PWM(led, freq=256000)
s=[]
for i in range(0,256):
s.append(int(32767*(sin(2*pi*i/256)+1)))
while True:
for i in range(0,256):
pwm.duty_u16(s[i])
sleep(1/256)
それでも無限ループ内でsleep頼りだと計算通りの周期で点滅しない。そして明るさがデューティに比例しないので三角波だろうが正弦波だろうが違いが見た目ではわからない。
ADCで明るさ調整
点滅ではなくボリュームでLED輝度を調整してみた。ADC入力もMicropythonなら簡単に書ける。
from machine import Pin,PWM,ADC
from time import sleep
led=Pin("LED", Pin.OUT)
pwm=PWM(led,freq=200000)
adc=ADC(Pin(26))
while True:
pwm.duty_u16(adc.read_u16())
sleep(0.1)
点滅速度切り替え
スイッチを押すと点滅速度が切り替わるようにしてみた。ミソは切り替えるのはタイマーの周期ではなく、異なる速さを持つタイマーを2つ用意して、トグル動作を切り替えてみた。スイッチもタイマーも割り込みであり無限ループはない。
なお、チャタリング対策をしていないので、切り替えは安定しない。
from machine import Pin,Timer
def chgstate(p):
global fast
fast= not fast
def tglslow(timer):
global fast,led
if not fast:
led.toggle()
def tglfast(timer):
global fast,led
if fast:
led.toggle()
led = Pin("LED", Pin.OUT)
fast=False;
sw = Pin(22,Pin.IN,Pin.PULL_UP)
sw.irq(trigger=Pin.IRQ_FALLING, handler=chgstate)
timer1=Timer()
timer1.init(mode=Timer.PERIODIC, freq=2, callback=tglslow)
timer2=Timer()
timer2.init(mode=Timer.PERIODIC, freq=10, callback=tglfast)
投稿者の人気記事
-
akira.kei
さんが
前の日曜日の14:27
に
編集
をしました。
(メッセージ: 初版)
-
akira.kei
さんが
前の日曜日の15:56
に
編集
をしました。
-
akira.kei
さんが
前の日曜日の16:10
に
編集
をしました。
-
akira.kei
さんが
前の月曜日の0:46
に
編集
をしました。
-
akira.kei
さんが
前の月曜日の0:49
に
編集
をしました。
ログインしてコメントを投稿する