「I2Cスキャナ」のアドレス変換したい

この「I2C スキャナ」は、「elektor MAG」誌のユーザフォーラムで Nickelgrass さんが公開している「Micro I2C-Scanner with 0.96″ Oled and ATtiny44」です。

前回までの3回の記事で、Arduino などの MCU へ簡単に周辺機器を接続する「I2C」のアドレスを一覧画面で表示する「I2C スキャナ」を製作してケースに入れるまでを書きました。

今回は、前回から何か進展があった訳ではなく、私の技術力ではこれ以上は無理なのでギブアップしてご協力を得たいという虫の良い企画です。

下の写真は、前回 3D プリンタで作ったケースに入れた状態です。
検出用端子には OLED をつないでいるので、上列の「7」と横軸の「8」の交点が反転して 16進数の「78」を表示しています。
この例では1つの部品ですが、複数の I2C の部品をつないでも、ちゃんと表示されます。
(部品によっては2つのアドレスを使いますが、そのような部品にも対応しています。)

なお、「I2Cスキャナ」の前回の記事は、以下のリンク先をクリックするとご覧いただけます。

改良したいところ

Nickelgrass さんの設計された「I2C スキャナ」は、大変スマートな表示方法を採用しています。
ドット数の少ないディスプレイ(128 × 64 ドット)を使いながら、一覧でアドレスを表示出来ています。

ソフトウエア的には 14 ピンの小さな ATtiny(ATtiny84 又は ATtiny44)の少ないメモリで、2つの独立した I2C チャンネルを使用できているところが凄いです。
私も Arduino で OLED を使った「I2C スキャナ」を作れないかガンバってみたことがありますが、2つのチャンネルがうまく使えなくて断念しました。(Arduino UNO R4 上位互換機の「RMC-RA4M1」ならできますが、もったいないです。)

この「I2C スキャナ」は大変素晴らしいのですが、唯一の困ったところが Arduino で使おうとするとスケッチで指定するアドレスではなく、左シフトされた値が表示されるところです。(本来の部品のアドレスを表示しているのですが。)

OLED なら「0x3C」と表示して欲しいところですが、「0x78」部分が「■」で表示されます。
Arduino IDE へ入力する時には計算すれば済むことですが、人間がやらなくても良いところは、機械にやってもらいたいところです。

これを改造しようとして、元のプログラムを色々と触ってみたのですが、現在の私の実力では修正することが出来ませんでした。

そこで今回は、これを読んでくれた方に広く知恵を借りようという大変厚かましい企画です。

ライセンスの確認

お知恵を借りようというのに、HP のアドレスを書いて、その先で会員登録をして、ダウンロードしてもらって、中身を見て協力してください。では誰も協力してくれませんので(自分でもイヤですね。)ソースの取り扱いについて確認します。

「I2C スキャナ」の公開されているソースに添付されている「LICENSE.txt」には、以下のように書かれています。

Copyright (c) 2017 M.Hirsch
I2C-Scanner

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International generic license.
Please view the license details under https://creativecommons.org/licenses/by-nc-sa/4.0/

LICENSE.txt

直訳すると、
「この作品は、クリエイティブ コモンズ の「表示 – 非営利 – 継承」の 4.0 国際一般ライセンスの下でライセンスされています。
ライセンスの詳細については、https://creativecommons.org/licenses/by-nc-sa/4.0/ をご覧ください。」

と書かれています。
「クリエイティブ・コモンズ・ライセンス」は、クリエイティブ・コモンズ・ジャパン(CCJP)という法人が HP を開設しています。
ライセンスの詳細は、こちらをご覧ください。

そちらに書かれている内容を引用すると、ライセンス中に書かれている「Attribution-NonCommercial-ShareAlike」の意味は「表示ー非営利ー継承」の項目にありました。

具体的には
「原作者のクレジット(氏名、作品タイトルなど)を表示し、かつ非営利目的に限り、また改変を行った際には元の作品と同じ組み合わせのCCライセンスで公開することを主な条件に、改変したり再配布したりすることができるCCライセンス。」
であり、マークで表すと下の図になります。

by-nc-sa

この規定を守れば改変・再配布が可能であることが分かりました。

「I2C スキャナ」のソースファイル

まだ、私の電子工作レベルは「Dランク」で Arduino IDE でLチカをしているレベルなので、「Microchip Studio」をパソコンに入れてはみましたが、いまだによく分かっていません。

こんな状態なので不足や間違いがあるかもしれませんが、作者が公開しているソースファイル類は
global.h
i2c.cpp
i2c.h
main.cpp
oled.cpp
oled.h
ports.h
の7種類です。

Nickelgrass さんが公開している「Micro I2C-Scanner with 0.96″ Oled and ATtiny44」のファイルを転載します。

この中で、アドレス変換に関係していると思われる「main.cpp」です。

// Copyright (c) 2017 M.Hirsch
// Please see LICENSE.txt for license

#include "global.h"

int main(void)
{
	bool adr[128] = {0};
	uint8_t val, m, da, a, nx, fill, fillcn, cn;

	OSCCAL = 0xFF;
	init_i2c();
	init_oled();

	bitclr(ssda_port, sda_bit);
	bitclr(ssda_port, scl_bit);
	ssda_hi;
	sscl_hi;
 
 	while (1)
	{
		for(cn = 0; cn < 128; cn++)
		{
			ssda_lo;
			i2c_wait();
			sscl_lo;
			i2c_wait();
			i2c_wait();
			val = cn<<1;
			m = 0x80;
			while(m)
			{
				if(val & m)
					ssda_hi;
				else
					ssda_lo;
				i2c_wait_clk();
				sscl_hi;
				i2c_wait_clk();
				m >>= 1;
				sscl_lo;
			}
			m = SUCCESS;
			i2c_wait_clk();
			ssda_hi;
			i2c_wait_clk();
			sscl_hi;
			i2c_wait_clk();
			if(ssda_tst) m = FAIL;
			sscl_lo;
			i2c_wait();
			if(m == SUCCESS) adr[cn] = 1;
			else adr[cn] = 0;
			ssda_lo;
			i2c_wait();
			sscl_hi;
			i2c_wait();
			ssda_hi;
			i2c_wait();
			_delay_ms(5);
		}
		oled_xy(0, 0);
		da = 0;
		a = 0;
		nx = 17;
		fill = 0;
		fillcn = 4;
		i2c_start();
		i2c_write(0x78);
		i2c_write(0x40);
		for(uint16_t y = 0; y < 8; y++)
		{
			nx = 17;
			for(uint16_t x = 0; x < 128; x++)
			{
				da = rb(&frame[x+(y*128)]);
				if((x == nx) && (y > 0))
				{
					a = (((nx-17) / 7)<<3)+y;
					nx = nx+7;
					fillcn = 4;
					if(y == 1)
					{
						if(adr[a-1])		fill = 0b00011110;
					}else if(y == 2){
						if(adr[a-1])		fill = 0b00001111;
						if(adr[a])			fill = 0b10000000;
					}else if(y == 3){
						if(adr[a-1])		fill = 0b00000111;
						if(adr[a])			fill = 0b11000000;
					}else if(y == 4){
						if(adr[a-1])		fill = 0b00000011;
						if(adr[a])			fill = 0b11100000;
					}else if(y == 5){
						if(adr[a-1])		fill = 0b00000001;
						if(adr[a])			fill = 0b11110000;
					}else if(y == 6){
						if(adr[a])			fill = 0b01111000;
					}else if(y == 7){
						if(adr[a])			fill = 0b00111100;
					}else{
						fillcn = 0;
					}
				}
				if(fillcn)
				{
					 da |= fill;
					 fillcn--;
				}else{
					fill = 0;
				}
				i2c_write(da);
			}
		}
		i2c_stop();
	}
	_delay_ms(500);
}


この中で、29行目以降が I2C アドレスを取得してきて処理をしているのかな?とは思ったのですが、色々と変更してみてもシフトした値を OLED に表示することが出来ませんでした。

もう1つの疑問

このファイルが公開された頃(7年以上前?)に出回っていた 0.96 インチの OLED では問題ないらしいのですが、最近の OLED を使用すると表示不良が発生します。
これと同じ症状は、ユーザフォーラムで他の方も書き込んでいました。

具体的には、8ドット分表示が上にずれます。
(こんな感じになります。)

これでは最上段に表示されるべき1桁目のアドレスが見えないので実用的ではありません。
そこで、色々と試してみたら、プログラムを一部修正すると表示の不具合が解消されました。
(詳しくはリンク先をご覧ください。)

具体的には、「oled.cpp」の一部を書き換えるという応急処置です。
実際にはもっと適正な修正方法があるのでしょうが、私の能力不足で応急処置から進展はありません。

お願い

以上が「アドレスを変換して表示する方法」と「OLED 表示不良の修正方法」に関する現状です。
この2つが修正できれば、この「I2C スキャナ」は大変便利な器材になると思います。
(慣れない英語で公開先の「elektor MAG」誌のユーザフォーラムで作者に質問もしてみましたが、7年以上前に公開された作品なので、今のところ返答などはありません。)

どなたか、プログラム修正のヒントをいただけないでしょうか?
ご協力をお待ちしています。

コメント

  1. ヒントになるかどうか判りませんが、これの画面表示のロジックを調べてみました。
    ややこしいのでこちらの記事にしています。
    http://radiopench.blog96.fc2.com/blog-entry-1302.html

    あと、画面が8ビット分上にズレるのは、oledの初期化手続きの init_oled() が怪しい気がしますが、よく判らないです。

    • パオさん より:

      ラジオペンチさん、わざわざ解析して頂きありがとうございます。
      さらに、お忙しい中、その結果をブログの記事にして頂きありがとうございます。
      全然進展していなかったので、大変助かります。

  2. siliconvalley4066さんからコメントで修正方法を教えて頂きました。
    同じURLでうが下記記事の追記とコメントをご覧ください。
    http://radiopench.blog96.fc2.com/blog-entry-1302.html

    • パオさん より:

      返信した後に、ラジオペンチさんの書き込みでないことに気付きました。
      (siliconvalley4066さん、ラジオペンチさん、ごめんなさい)
      早速、教えていただいた修正を試したところ正常に動作しています。
      ありがとうございます。

  3. お願いです。
    ラジオペンチさんからi2cscanner.zipが動かないという御報告がありました。
    動くか動かないか確認していただけないでしょうか。

    • パオさん より:

      コメント欄のお名前に半角数字が入力できない件が解決できていないようで、すみません。
      (WordPress の設定を色々触ってみたのですが・・・)

      取り急ぎ、ブログのゲストブックに書き込みさせていただきました。
      私のところでは、siliconvalley4066 さんの「i2cscanner」2種類は正常動作しています。