パオさんのサイト「それ、やってみよう!」に、 「I2Cスキャナ」のアドレス変換したい という記事が書かれていて、修正方法を知りたいということだったのでプログラムを調べてみました。
14ピンのATtiny84用プログラムでAtmelStudioの環境でビルドするように作られていますが、ざっと見たところArduino IDEのArduino Nano用に変更できそうだったので試してみました。
まず、main.cのファイル名をi2cscanner.inoに変更。main()の中にwhile(1)ループがあるので、setup()とloop()に分割。ポートをNano用にA4とA5があるPORTCに変更。最初はA4/A5だけを使いましたが、後で検査用ポートにA2/A3を使っても動くことが確認できました。大体これだけでコンパイル実行できるようになりました。
さて、例えばI2Cのアドレス0x78をArduino IDEでよく使う0x3cと読み取りやすくしたいということですので、表示の縦横を入れ替えました。プログラム内で検出しているアドレスは0x3cの形式でした。
画面レイアウトのデータも修正する必要がありましたが、ラジオペンチさんが作成してくださいました。(References #2)
開発環境は Arduino IDE 1.8.19です。
動き出した時点ではOLED以外のデバイスが検出できなかったので。Wireライブラリを使用してexampleにあるi2c_scanner.inoの検出部分を抜き出し、OLED表示もWireコマンドを使うようにしたものも作ってみました。こちらはOLEDと検査用のI2Cは一つのI2Cに接続しています。オリジナル版が検出出来なかったのはATMega328が速すぎたためのようで、i2c_wait_clk()にdelayMicroseconds(5)のディレイを追加したら検出できるようになりました。
こちらは要らない処理は極力削除して一本のINOファイルにしました。
(追記 2024.07.21) SoftwareWireライブラリを使ってセカンドI2Cを使うようにしました。
SoftwareWireライブラリはIDEの「ライブラリを管理」から検索してインストールします。
(追記 2024.07.24)
SH1106にも対応できるようにしました。
bool sh1106 = true;
にすればOKです。自動判別にトライしましたが、何かの拍子にダメになるので諦めました。残骸は残してあります。
(追記 2024.07.26) 行き掛りついでに7ビットアドレスと8ビット偶数アドレスの表示切り替えも出来るようにしました。SSD1306はHorizontal Addressing ModeだったのをSH1106と同じPage Addressing Modeに変更して、自動判別を復活しました。これで自動判別をミスっても水平方向に2ドットずれるだけなので大きな問題にはならないと思います。
(追記 2024.07.25)
ATtiny85用に変更したi2cscannerがGitHubにありました。
このtinyFontブランチでは塗りつぶしバグが修正されていました。
縦横は元のままです。
avaldebe/TinyI2CScanner at tinyFont branch
(追記 2024.07.31)
PlatformIO環境のソフトですが、Arduino IDEでコンパイルするためには、
#include <ssd1306xled.h>
の前に
#define SSD1306_SCL PB4
#define SSD1306_SDA PB3
を置けばssd1306xledライブラリがPB4/PB3でOLEDを動かすのではないかと思いましたが、ライブラリのコンパイル時に定義されていないと意味がありませんでした。
ライブラリマネージャーからインストール出来るやつでは、ライブラリのソースコード ssd1306xled.h を編集すれば良さそうですが、ハードウェアI2Cを使うコードが含まれているのでダメかも。古いOLEDなら正しく動くのでしょうが、残念ながら最近のOLEDとの相性が悪いようで全画面クリアで一番下の8ラインをを消せないようです。
ssd1306xledライブラリには幾つものバリエーションがあるようで混沌としています。
Defragster/ssd1306xled の方がソフトウェアI2Cだけなので使えそうですがやはり修正が必要になります。
masterブランチではu8g2ライブラリで5x7フォントを使って描画しています。
avaldebe/TinyI2CScanner: Micro I2C-Scanner with 0.96" Oled and ATtiny85
また、タクトスイッチで7ビットアドレスと8ビット偶数アドレスの表示切り替えも出来るようになっています。
さらに、Arduino pro-miniでも使えるようになっています。ということはUNO3やNanoでも使えます。表示用OLEDはD10/D11ピンに接続するようになっていますが変更できます。試験用I2CはA4/A5ピンを使います。SH1106も使えます。つまりは4年前にすべて解決していたんですね。
(追記 2024.07.26)
u8g2ライブラリが更新で肥大化してATtiny85に収まらなくなったらしい。古いバージョンに戻しても良いんですが、
#define USE_U8X8
を定義すれば、OLEDのページ構造に合わせた8x8構造を使う簡略化ライブラリを使ってサイズを小さく出来るようになっています。この場合、画面全体をマップ表示にしますが、行0と桁0にラベルを下書きしておいて、そのアドレスが存在したらマークを上書きするようになっています。普通アドレスは数個なので、ちょっと分かりにくいですがこれでも実用的になります。
ちなみにライブラリマネージャの「バージョンを選択」のプルダウンリストで古いバージョンを選んで戻すことができます。
tinusaurブランチがあって、ラベル表示はやめて画面全体をマップ表示にしてソフトウェアを単純にしています。ラベルは画面の外に印字したシールを張り付ければ良いという発想です。ソフトは簡単にしてあとはハードで何とかするという物づくりの一つの方向として興味深いです。
avaldebe/TinyI2CScanner at tinusaur branch
(追記 2024.07.30)
PlatformIO環境のソフトですが、Arduino IDEでコンパイルするためにはtinyFontブランチと同様の設定が必要です。
古いOLEDなら正しく動くのでしょうが、残念ながら最近のOLEDとの相性が悪いようで全画面クリアで一番下の8ラインをを消せないようです。
ソースコードは一つのファイルmain.cppになっているので、TinyI2CScanner.inoに名称変更して、最初の方に
#define DISPLAY_SW_I2C 11,10
#define TACT_PIN LED_BUILTIN
#define DISPLAY_128X64 SH1106
を書き加えればSH1106に対応できるようになります。
#define DISPLAY_128X64 SH1106 の行を加えなければSSD1306用になります。
タクトスイッチを画面がクリアされるまで押すと、7ビットアドレスと8ビット偶数アドレスの切り替えが出来ます
ATtiny85用にビルドする場合はplatformio.iniの内容を参考にして環境設定します。
Arduino Nano用
ATtiny85用はこちらを参照 TinyI2CScanner - EasyEDA open source hardware lab