ラズPicoにディスプレイ〜その2〜

2023年10月20日(金)は、7割ほどの出席率でした。

  • 18時00分~18時25分 タイピング練習
  • 18時25分~19時50分 SSD1306互換OLEDのプログラミング
  • 19時50分~20時00分 あとかたづけ

本日も引き続き、SSD1306互換OLEDのプログラミングに取り組みました。手が速いメンバーでOLEDの表示が終わったら、自分の課題に取り組みます。

タイピング練習

今回のタイピングの練習は、英語入力です。使う教材は、下のサイトのWebアプリです。

https://manabi.benesse.ne.jp/gakushu/typing/

おおよそ100字/分の入力速度で、95%くらいの正タイプ率だと実用十分です。拙速に入力速度向上を目指しても、実用場面であまり役に立ちません。現実には、間違って入力した文字は「消してから入力し直さないといけない」からです。

まずは、手元を見ずに、正タイプ率を95%くらいに持っていくことが重要です。時間はかかりますが、結果として早くタッチタイピングを習得できます。

SSD1306互換OLEDのプログラミング〜その2〜

前回でOLEDの表示ができたメンバーは、OLEDに別の情報を表示することに取り組みます。

前回の取り組みは、下記からどうぞ。

ラズPicoでディスプレイを使おう

2023年10月13日(金)は、8割ほどの出席率でした。 光都ICTクラブの定例会は、出席自由です。自分の都合に合わせて出席できるときに、出席すればかまいません。参加費も一…

表示機能を応用してプログラムす

OLEDを活用した表示はいろいろありますが、まずはこれだけ。

  • 「RaspberryPi Pico」以外の文字列を表示する
  • 文字列を右下に表示する
  • 温度を表示する

ちなみに、わたしも答えを知りません。「できない」という意味ではなくて、この日のクラブ活動までに実際にコードを書いて確かめたわけではないので、「確実に動く保証のあるコードを知りません」。

もちろん「こう書いたら動くだろうな……」という仮説を持っています。仮説にそって、わたしもメンバーと一緒に考えながらプログラミングしています

OLED(SSD1306)に「RaspberryPi Pico」以外の文字列を表示する

OLED(SSD1306)の表示は、前回同様「最新Pico W対応!ラズパイPico完全ガイド(福田和宏著)」を参考に、下記のコードで動きます。

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

WIDTH = 128
HEIGHT = 64

i2c = I2C(0)
i2c.scan()

print('i2c address      : '+hex(i2c.scan()[0]).upper())
print('i2c configuration: '+str(I2C))

oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)
oled.fill(0)

oled.text('Raspberry Pi', 5, 5)
oled.text('Pico', 5, 15)

oled.show()

表示文字列を示すところは、16行目17行目です。したがって、「RaspberryPi Pico」の表示を変えたければ、同行のこの部分を変更します。

たとえば、「This is a pen.」と表示したければ、下記のように書き換えます。

oled.text('This is a', 5, 5)
oled.text('pen', 5,15)

つまり、「oled.text()」の中の1番目の引数を文字列で指定すればOKです。

ちなみに、日本語は表示できません。なんで?というのは良い質問です。その答えは「日本語が表示できるように作られていないから」です。自分でも試してみてください。

OLED(SSD1306)で文字列の表示位置を変える

表示する文字列を変えたら、次は文字列の表示位置を変えます。oled.text()の書式は、下記のとおりです。

oled.text(表示文字列, 横方向の開始位置, 縦方向の開始位置)

したがって、5と15の数字を変更すれば、表示位置を変えられます。たとえば、下記のように変更します。

oled.text('Raspberry Pi', 20,40)
oled.text('Pico', 20, 50)

これを実行すると、文字列が右下に移動したはずです。

ちなみに、インポートしたssd1306.pyを読んでいけば、引数の何がどのような意味を持つ設定値なのかわかります。そして、インポートモジュールが読めなくても、サンプルコードから何が設定してあるのかを読み取れます。

わからなければ、実際にコードを書き換えて試してみればよいのです。プログラムはいくら失敗してもコストがかかりません。自分なりに仮説を立てながら、いろいろ試してみると早く上達します。

OLED(SSD1306)で温度を表示する

最後は、温度表示をしてみます。できあがりは下の写真。小学生のメンバーが作ったプログラムで動いています。2行〜4行の「20.02224」が室温です。

温度を取得するには、Raspberry Pi Pico Python SDK(公式ドキュメント)のプログラムを使います。このプログラムは、クラブに入ったときの導入で写経するプログラムです。

import machine
import utime

sensor_temp = machine.ADC(4)
conversion_factor = 3.3 / (65535)

while True:
    reading = sensor_temp.read_u16() * conversion_factor

    temperature = 27 - (reading - 0.706)/0.001721
    print(temperature)
    utime.sleep(2)

temp.pyの10行目で定義しているtemperatureを、さきほどのoled.text()の第一引数に指定すればOKです。

graphdisp.pyとtemp.pyを適切に組み合わせてプログラムをしてください。コードに書く内容は、ほぼここに書いた2つのファイルのとおりです。1箇所注意点がありますが、それは次の項に書きます。答えを求めるのではなくて、自分なりの仮説を立てて、コードを考えてみてください。

OLED(SSD1306)が表示されないよくあるエラー(例外)

プログラミングにエラーはつきもの。エラーを解決するのを楽しめると、プログラムが一層楽しくなります。ここでは、OLED(SSD1306)を動かす上で、わたしがクラブで見かけたエラー(例外)と解決方法を書きます。

・ModuleNotFoundError: No module named 'ssd1306.py'

SSD1306のモジュールを適切に保存できていません。ラズPicoに保存したつもりで、パソコン本体に保存していたり、名前を間違っていたり、何かしらのまちがいがあります。もう一度保存場所を確認してください。

・IndexError: list index out of range

graphdisp.pyの10行目でこのエラーが出たら、OLEDとラズPicoのI2C接続がなされていません。配線・結線が正しいか確認してください。配線・結線が正しければ、接触不良の可能性があります。線を変えるか、ブレッドボードの線を差し込んでいる位置を変えてください。

だいたい自分の結線ミスが原因です。まず、自分の目と腕を疑ってください。

・TypeError: can't convert 'float' object to str implicitly

温度表示をするときに、ただ2つのファイルを写して順番を変えるだけだとこのエラーがでます。oled.text()の第一引数には、文字列を与えないといけないからです。

公式ドキュメントで取得したtemperatureは浮動小数点型(float型)なので、これを文字列に変換する必要があります。例えば、下のように書きます。

temperature = 27 - (reading - 0.706)/0.001721
oled.text(str(temperature), 5, 5)

一方、temperatureを定義したときに文字列型に変換しても良さそうです。具体的には、下記のコードです。

temperature = str(27 - (reading - 0.706)/0.001721)
oled.text(temperature, 5, 5)

これでも良さげですが、温度は数値として扱いたいことが多いので、cast1.pyのほうが使いやすく読みやすいコードです。もちろん、temperatureを文字列としてしか扱わないよ! という場面ではcast2.pyも間違いではありません。要は、どのようにかける場合であっても理由があるということです。

今後の展望

さて、一通りOLED(SSD1306)を使えるようになりました。メンバーの中には、まだ最後まで到達していない人もいるので、来週も進捗に合わせてサポートします。次は、テンキーと合わせて電卓を作ってみようかと思います。

それとは別に、スロットを作りたいと要望がありました。パソコンの画面で作りたいということでしたが、OLEDで作っても面白そうです。例のごとく、わたしも答えを知りません。メンバーと一緒に考えてみたいと思います。