さて、今日はLEDを光らせる時の小ワザの話です。
Breatheエフェクト(呼吸をするようにフェードイン・アウトを繰り返す、Macbookの待機中ランプとかで見る光らせ方)って、たまに使いたくなりますよね?
いつも、前回どうやったか忘れる絶妙なタイミングで必要になってサンプルコードを検索するんですが、だいたいfor文を使った同期処理的なのが出てくるので、少し気の利いたことをやろうとすると物足りなくなります。
それで、結局毎度その時の思いつきで実装していて時間の無駄な感じがするので、今回自分の中ではよくできたなってものを、コピペして使えるようにスニペットとして記録しておきます。
プログラムと解説
ではさっそく、こちらが自分史上いちばんよく書けたBreatheエフェクトプログラムです。
MicroPythonで動作確認していますが、CircuitPythonでも使えるはず。
いままで苦手意識があって、なかなか手を出せなかった「クラス」ってのを使ってみました。
われながらけっこうちゃんと書けたんじゃないかと思いますが、有識者の方からのツッコミがあればぜひ教えてください。
class Breath: def __init__(self): self.step = 100 self.count = self.value = 0 def count_up(self): # カウンターを0~step*2の間でインクリメントする self.count = (self.count + 1) % (self.step * 2) # 0~countの往復に変換する self.value = 1.0 - (abs(self.step - self.count) / self.step) def reset(self): self.count = self.value = 0 # ガンマコレクション GAMMA_FACTOR = 2.8 GAMMA_TABLE = [int(pow(i / 255, GAMMA_FACTOR) * 255) for i in range(256)] # 使ってみる MyBreath = Breath() MyBreath.step = 15 for i in range(MyBreath.step * 2): MyBreath.count_up() value = GAMMA_TABLE[int(MyBreath.value * 255)] print('■'* int(value/10),value)
しくみの解説
しくみを言葉で説明しにくいので、図解で表してみました。
見ての通り、-x〜xのカウントの絶対値を±反転するというアプローチです。
図解はp5jsのWEBエディターを使って描きました。こういう時に手軽に使えるプログラマブルなお絵描き環境、とても便利ですね。
ガンマ補正は、以前も書いた通り、明るさの階調を人間の感覚に合わせて補正する処理です。
Chat-GPTにアドバイスをもらって、計算量を減らすために、プログラム冒頭でリスト内包表記を使ってガンマテーブルを生成するようにしてみました。
ATTinyのときは、フラッシュメモリに8bitガンマテーブルを置く倹約生活でしたが、そもそもPython動かせてる時点でメモリ富豪環境のはずなので、細かいことは気にしません。
係数の2.8は、環境によってだいたい2.2〜2.8くらいの範囲で適当に調整するらしいですが、まあ2.8のままで良さそうです。
実行結果
そして見ての通り、Printで動作を確認するコードにしたので、このまま実行してみます。
>>> %Run breath_effect.py 0 0 2 6 ■ 11 ■ 19 ■■■ 30 ■■■■ 43 ■■■■■■ 61 ■■■■■■■■ 81 ■■■■■■■■■■ 107 ■■■■■■■■■■■■■ 136 ■■■■■■■■■■■■■■■■■ 170 ■■■■■■■■■■■■■■■■■■■■■ 210 ■■■■■■■■■■■■■■■■■■■■■■■■■ 255 ■■■■■■■■■■■■■■■■■■■■■ 210 ■■■■■■■■■■■■■■■■■ 170 ■■■■■■■■■■■■■ 136 ■■■■■■■■■■ 107 ■■■■■■■■ 81 ■■■■■■ 61 ■■■■ 43 ■■■ 30 ■ 19 ■ 11 6 2 0 0 0
ばっちりガンマコレクションの効いたカーブが見えますね。あとはこれをLEDのPWMに突っ込めばOKです。
うまく動いたので、今後はこれをコピペして使っていこうと思います。
ではまた〜!