maruaのアイコン画像
marua 2022年09月19日作成 © CC BY-SA 4+
製作品 製作品 閲覧数 1146
marua 2022年09月19日作成 © CC BY-SA 4+ 製作品 製作品 閲覧数 1146

I2C デバイス・スキャン

I2C デバイス・スキャン

I2Cバス上で認識できるデバイスを調べるツールです。
電源を入れると、ArduinoのI2Cバスにアドレス(0x08 ~ 0X77)を出力して、ACKを返したデバイスが有ると、そのアドレスをシリアルで出力します。
(7bitアドレスのフォーマットでのみ確認)
配線ミスや断線の確認用に 活用してください。

I2Cデバイスを2個搭載した 「土壌の水分/温度センサ」基板で実行すると、
 0x32: RTC
 0x3E: LCD
のアドレスが、シリアルポートに出力されます。
シリアル出力結果

ACK応答を返さないケース

ACkを返すケース

ソースコード

#include <Wire.h> #define dLED 0x04 // ■ cmd1() char cmd1_task = 0; // cmd1 タスクNo. unsigned long cmd1_tim0 = 0; // コマンド1 基準時間 unsigned char i2c_adr; // I2C スキャンアドレス // ■ LED_ctrl() char LED_task = 0; // LED制御 タスクNo. unsigned long LED_tim0 = 0; // LED制御 基準時間 // ■■ void setup() { Serial.begin(9600); Wire.begin(); DDRC |= dLED; // PC2 = 出力 Serial.println("I2C Scan v0.01"); LED_task = 20; // LED 点滅(50ms ON) } // ■ void loop() { LED_ctrl(); // LED 点滅制御 cmd1(); // コマンド1処理 } // ■■ void cmd1() { int val; unsigned long tim; switch (cmd1_task) { case 0: cmd1_tim0 = millis(); // 基準時間セット i2c_adr = 0x08; // cmd1_task ++; break; case 1: case 8: cmd1_task ++; break; case 3: case 5: if (TWCR & (1<<TWINT)) { // cmd1_task ++; } break; case 2: TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // I2C Start cmd1_task ++; break; case 4: TWDR = i2c_adr<<1; // TWCR = (1<<TWINT)|(1<<TWEN); // cmd1_task ++; break; case 6: if ((TWSR & 0xf8) == 0x18) { Serial.print(' '); Serial.println(i2c_adr,HEX); } cmd1_task ++; break; case 7: TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN); // I2C Stop cmd1_task ++; break; case 9: cmd1_tim0 = millis(); // 基準時間セット cmd1_task ++; break; case 10: tim = abs(millis() - cmd1_tim0); if ( tim > 10 ) { cmd1_task ++; } break; case 11: i2c_adr ++; if (i2c_adr > 0x77) { cmd1_task ++;} else { cmd1_task = 1; } break; case 12: break; default: cmd1_task = 0; break; } } // ■■ void LED_ctrl(void) { switch(LED_task) { case 0: break; // 1秒周期の点滅 (Duty=50%) case 10: LED_tim0 = millis(); LED_on(); LED_task ++; break; case 11: if ( (millis() - LED_tim0) > 500) { LED_task ++; } break; case 12: LED_tim0 = millis(); LED_off(); LED_task ++; break; case 13: if ( (millis() - LED_tim0) > 500) { LED_task = 10; } break; // 1秒周期の点滅 (ON 50ms) case 20: LED_tim0 = millis(); LED_on(); LED_task ++; break; case 21: if ( (millis() - LED_tim0) > 10) { LED_task ++; } break; case 22: LED_tim0 = millis(); LED_off(); LED_task ++; break; case 23: if ( (millis() - LED_tim0) > 950) { LED_task = 20; } break; case 99: default: LED_off(); LED_task = 0; break; } } void LED_on(void) { PORTC |= dLED; } void LED_off(void) { PORTC &= ~dLED; }
  • marua さんが 2022/09/19 に 編集 をしました。 (メッセージ: 初版)
ログインしてコメントを投稿する