SSD1306 OLEDディスプレイを使ってみる
2023.09.16


ESP32を使うようになって、SSD1306のOLEDモジュールを使う機会がありました。
ピン数が多いと扱いにくいのでI2Cモデルを買ってみたのですが、
意外と躓くところがあったので、備忘録的に残しておきます。

まずSSD1306はこれは0.96インチのモノクロモジュールです。
買うとケースに入って送られてきた・・
送料込み270円程度なのになかなかやるじゃん(;´Д`)
カラーモジュールはSSD1331らしく型番が違う。
カラーの影響なのか4本I2Cでの接続はできないらしい。
あと1.3インチのモノクロモジュールはSSH1106となっていて全部型番がちがう。
これに気が付かないで買ってしまうといろいろと後悔するかもしれない。
今回は白文字で表示できればよかったので、0.96インチのSSD1306で
この事実に気が付かずもトラブル回避できていた。
今回勝ったSSD1306は4pinのI2C接続なので、

VCC(5V or 3.3V)
GND
SCL
SDA

の4か所を接続するだけでOK! とても簡単。
ただし、ESP32側のプログラムではちょっとてこずった。
ネットで検索するとAdafruit社のライブラリを使ったソースコードが多々見つかる。
ChatGPTに聞いてもAdafruitを使ったコードを出してくる。
きっと書籍とかでもよく紹介している方法なんだと思うが、
私の環境ではライブラリの導入でトラブルが続出した。
Arduino IDEのライブラリマネージャーから
Adafruit SSD1306というライブラリをインストールするだけのはずが、
どうもコンパイルするとエラーが出る。何かが足りないといったメッセージだ。
結局ネットで検索し、Adafruitのサイトからダウンロードして組み込んだら動くようになった。
今この問題を解決できたとしても、ソースファイルをほかのPCに移したりPCを買い替えたりしたとき
また同じ問題に直面するとすれば時間的ロスが半端ないので、
今回はSSD1306.hを利用する方式を採用した。
このssd1306.hもArduino IDEのライブラリマネージャーから「ESP32 SSD1306」で検索し、
「ESP8266 and ESP32 OLED driver for SSD1306 displays」
をインストールするだけ。バージョンはとりあえず最新を選んだ。

ESP32のSDAは21ピン、SCLは22ピンと決まっているので

#define OLED_SDA 21 //I2C接続のSDAを21番に接続
#define OLED_SCL 22 //I2C接続のSCLを22番に接続
SSD1306 display(0x3c, OLED_SDA, OLED_SCL); //SSD1306インスタンスの作成(I2Cアドレス,SDA,SCL)

と定義してあげれば管理しやすい。
0x3cはI2Cのポートを意味する。売られている物のほとんどは0x3cになっているようだ。
実際私が購入したのは0x3Cで動いた。
ところがモジュールの背面を見ればわかるのだが、
ポートは背面をみて判断するのがお決まりらしい。



稀に0x78や0x7Aと書かれているものは抵抗がどちらに張り付いているかでわかる。
私のOLEDも裏には0x78と示している。(8がBのようにもみえるがおそらくはプリントミスだと思われる)
これはどういうことなのだろうか?
調べたところによると、I2Cのアドレスは7ビットで使われており、
8ビット目は使用されない。つまり0x78と指定しても0x3Cとして使われ、
0x7Aと指定しても0x3Dとして使われるという話。
だから最初から0x3Cと指定しているということらしい。
ここら辺も知っておかないとハマる原因になりかねない。



ちなみに1.3インチの裏面も同じようになっています。

さて上の3行が定義できれば後はもう自由に表示させることが可能。
命令の種類はネットで調べたところ

display.setPixel(x,y)で点を打つ
display.drawRect(x1,y1,x2,y2)で四角形を描く
display.fillRect(x1,y1,x2,y2)で四角形を描き中を塗る
display.drawHorizontalLine(x,y,ドット幅)でラインを引く
display.drawCircle(x,y,半径)で四角形を描く
display.fillCircle(x,y,半径)で四角形を描き中を塗る
display.setTextAlignment(TEXT_ALIGN_LEFT) 文字表示座標の起点を指示。他にTEXT_ALIGN_CENTER、TEXT_ALIGN_RIGHTがある
display.drawString(x,y,"半角文字") //文字の表示
display.setFont //フォントと文字サイズを指定
display.drawVerticalLine
display.drawProgressBar(X, Y, 幅, 高さ, 少数第2位の実数);
display.setColor(WHITE) //色を指定WHITE or BLACK
display.clear() 画面の初期化
display.display() //指定された描画命令を反映

これらが見つかった。もしかしたらもっとあるかもしれない。
これだけあれば特に困ることはないが、
Adafruitのライブラリのように改行があれば便利だったかなと思う。
フォントのサイズは3種類。実行すればそれ以降のdisplay.drawStringが対象となる。

display.setFont(ArialMT_Plain_10); //約17文字×6行 Yに対して10の倍数
display.setFont(ArialMT_Plain_16); //約10.5文字×3行 Yに対して16の倍数
display.setFont(ArialMT_Plain_24); //約7文字×2.5行 Yに対して24の倍数

フォントの種類は1種類しか見つけ出せてない。
このフォントはプロポーショナルフォントで、横幅が狭いアルファベットは詰められるので
表示できる文字数は書く文字によって変化することに注意。Iなんて文字は横幅が無いので一気に詰められる。
漢字を試しに打ち込んでみたら何も表示されず暗黒のままだった(;'∀')
display.setColorカラー指定ができるが、1306のモジュールは白と黒だけ選択できる。
他のモジュールなら細かく設定できるのかもしれない。
どの描画命令もdisplay.display()を実行しないと反映されない。
LOOP内で頻繁にdisplay.display() を繰り返すとOLEDがチカチカするので
LOOP内の最後らへんに1つだけ置いておくといいかもしれない。

画像を黒に消し去りたいときはdisplay.clear()を使う。

以下は使ってみた感想。
0.96インチは思っていた以上に小さい。
フォントサイズ10で文字を表示したら老眼の人にはかなり厳しいだろうと思う。
1.3インチを使ったほうが段違いに見やすい。コストダウンを考えて選択したのが裏目に出た(;'∀')
余分な部分が少ないので取り回しは楽。
LCDモジュールをよく使っていたけど、OLEDは画像が鮮明で見やすい。
LCDのように角度によっては見えにくいなんてことはないと思う。
基板に固定穴がついているのがいい。液晶は基板ではなくフタにつけることが多いので非常に助かる。
今のところはっきりわかるほどの熱はでてない。
これが1か月も1年もロングランさせるのであればどうなのかは今後の検証次第というとこ。
ESP32-WROVER-IEを買う。
2023.08.09


ArduinoでWiFi接続しデータをサーバーに転送、
メールで情報を送信したいという話がでてきました。
でも私は扱ったことが無いので、いろいろ躓きまくりです(;´Д`)

一番悩ませられたのが、技適の問題。
Arduinoで一般的に使われているモジュールはESP8266や
MKR WiFi 1010を使ったものが多いですが、
これらは技術基準適合証明、いわゆる技適が取得されてないので
国内で使用することはできません。
いきなり躓いたわけですが、ちょっと調べていくうちに、
Arduinoではなく、ESP32シリーズならWiFiを搭載しており、
技適も取れているということを知りました。
Arduinoではないけど、使い方やプログラム、ライブラリ等、
ほぼ一緒なので問題ないでしょう。
で、選んだESP32はコレ

ESP32-WROVER-IE 8MB FLASH【ESP32-DEVKITC-VIE】

互換製品がたくさんありますが、なぜ正規品を選んだかというと
互換品はWiFiがまともに動くものは少ない(特に感度問題)、
書き込みエラーが起きることがある。
USB変換チップにCP2102ではなくCH340を使っているものがある。
なにかしら正規の方法とは違う手段でないと機能しない部分がある。
などで

値段も数百円しか違わないなら
正規品を買っといたほうが安心。
あと技適を本当にとっているか互換品は怪しいというのもあります。
ESP32-WROVER-IEは令和3年4月28日に取得しています(211-200403)

あとWROOMではなく、WROVERを選んだのはメモリの問題。
WROVERには32mbit spi psramが追加装備されているのです。
これだけならなんのこっちゃという感じですが、
仕様で搭載メモリのところに8MB FLASHと書かれていても実際に使えるのは4MB程度らしいので、
重いデータを扱うとなるとパワー不足。それを補うための拡張メモリとして
psramが8MB(実際は4MB?)付いていると考えればまぁ大きく外れてはいないでしょう。
将来カメラを接続して画像を送信なんてことを始めるならメモリは多いに越したことはないですからね(;'∀')

ではIEを選んだ理由はなにか?
それは電波状況が悪い場合、外付けアンテナを接続できるので保険として重要だと思ったから。
基板のアンテナ部分だけだとどうも頼りないですからね。

さて次に考えるはセキュリティのこと。
WiFi接続に必要なSSIDや暗号キー、
メール送信に必要なアドレスとSMTPのサーバーアドレスとパスワード、
これらをソースに入れ込むのは安全なのだろうかと・・
さらに設置場所を変えるたびに、ソースを書き換えコンパイルするのかと・・
それはちょっと勘弁してほしいところ。
なので、WPS接続で何とかできないかと思案する・・(;'∀')
どうやらライブラリはあるっぽい。
なんか救われた気がする。

ESP32からのメール送信はどうしようか。
接続するWiFi先でいちいちプロバイダメールを確認するわけにもいかないので、
フリーで取得できるなかから最も信頼できるものを選ぶしかないか・・・
Microsoft、Google、Yahooあたりか。
どれもすぐ仕様変更したり、突然本人確認ができるまで停止とかやりかねないので
信頼は薄いんだけど、やむを得ないか。
メールのパスワードをソースに入れ込むのはやむを得ない(;´Д`)

そして、どうせならってことで1分ごとに情報をレンタルWebサーバーに送って
スマホかPCで情報のログも閲覧できればなんて要望もでたり・・
そうなると、サーバー側でもある程度処理するプログラムを
用意しておかないといけないな・・ウホ

ちなみにESP32のデータシートはこちら
https://www.espressif.com/sites/default/files/documentation/esp32-wrover-e_esp32-wrover-ie_datasheet_en.pdf

Amazonでは売ってませんね。今のところマルツで買うのが良さそうです。
【Python】スクレイピングしたあとのデータ保存
2023.07.05
うまくいかないグチです(;´Д`)
年のせいか物覚えと理解力の低下が著しいです・・

スクレイピングといえば、Rubyか、Pythonが流行りと聞いて
どうせならとPythonでSeleniumとBeautiful Soupを試してます。
私の得意言語、Delphiで出来ればいいのだけどいいライブラリが無いのでね仕方ないね(;´Д`)

試してみて思ったこと・・・
Pythonでも1つで完璧にこなすのは無理なのね(;´Д`)


Seleniumはブラウザのバージョンと合致したドライバーを持っていないと使えない弱点があり、
動作も遅い。
しかし最近はJava Scriptを通さないと重要な部分は見せないページが増えてきたので、
Seleniumの機能が無いと始まらない(;´Д`)


Beautiful Soupは軽快且つ単独でHTMLを読みにいき
解析を行ったあとに対して検索を行うので
ドライバーがいらない快適性があるも、
Xpathに対応してないので、
裏技的にlxmlで変換してからなんて面倒なことをする・・
素人にはこれがストレス極まりない(;´Д`)

そして、SeleniumとBeautiful Soupどちらをうまく使っても
XPATHで拾えないデータが結構出てくる。
もちろんCSSセレクタ使ってもダメ・・・
これがまたストレス(;´Д`)
データを捨てるわけにもいかないので、
階層を一つ上げて全部を吸い上げ、コードでゴリゴリ分解とか
ホームページの仕様変更に耐性が弱すぎるので
信用に値しないものを作る意味は?と考え込む・・
そして拾ったデータを整理し2次元配列に仕舞い込んで
最後、CSV出力しようと思ったときにもうまくいかないで躓く・・・
慣れない言語をあつかうときの窮屈感たるや吐き気を催すレベル(;´Д`)
とりあえず、一般的なCSV吐き出しで使われる

csv.writer(出力ファイル)

と私は相性が悪いらしい・・・・
delimiterとquotecharを設定してもうまく機能しない・・・
空白が文字コード化されて保存されたり面倒くさい事件が多く起きる。
しかもカンマで区切ってほしいのにスペースでも区切ってしまう現象もおきて
文字列がコマ切れ状態に(;´Д`)

これについては解決策を見つけることができて、
煩わしいことをきれいに全部解決してくれたpandasに拍手。

import pandas as pd

columns = ["date", "serial", "name", "tanka", "kosu", "kingaku"]
df = pd.DataFrame(配列 , columns=columns)
df.to_csv('d:\output.csv' , index=False, encoding="shift_jis")


これだけで配列があっさりCSVファイルを出力できるのでコードもすっきり。
項目名がいらないのならさらに1行消せる。大満足(;´Д`)

しかしXPathもCSSセレクタでも拾えないデータはどうしようか・・・
ある意味これが対策されているってことなんだと思うけど、
正規表現でなら正確に抜け出せるのだろうか・・

1つ1つ解決していくのにえらい時間かかる。
まだまだ迷走中(;´Д`)

- CafeNote -