第二世代　バッテリー保護回路のEEPROM読み取り

「aibo ers-11x/210で遊ぶ Advent Calendar 2023」の18日目です。

ERS-210のバッテリーについて、Loïc POLLIERさんのレポジトリbattmonを参考に、一から勉強したメモをまとめています。
https://github.com/lpollier/battmon/tree/master

ERS-210のバッテリーの保護回路のGas gage ICによる監視部分にはEEPROMが使われており、電池容量や充電回数などの情報が記録されているようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/afc59a53-d55b-dfe1-54dd-df39f172dae3.png)

24LC01B
https://ww1.microchip.com/downloads/en/devicedoc/21711j.pdf

今回はESP32を使いEEPROMの内容を確認してみました。

:::note alert
警告
この記事について作者はいかなる責任も負いません。
バッテリーの分解、改造は非常に危険な行為です。
:::

:::note
業務外の個人的な検討活動です。
:::


#### テストクランプによる接続
SO-8用のテストクランプを使い、24LC01BとESP32を直接接続しました。
GPIO22をSCLに、GPIO21をSDAに接続しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/7dac25b8-92a5-c4cc-f1c1-58b8c1fcade2.png)

#### ESP32のスクリプト
chatGPT先生と対話しながら、下記のようなスクリプトを作成しました。

```
#include <Wire.h>

// EEPROMのI2Cアドレス
const int eepromAddress = 0x50; // A0, A1, A2がGNDに接続されている場合

// GPIO22 SCL
// GPIO21 SDA

void setup() {
  Wire.begin(); // I2Cの初期化
  Serial.begin(115200); // シリアル通信の初期化
  while (!Serial); // シリアルポートが開くのを待つ
  Serial.println("ESP32 with 24LC01B EEPROM");
}

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n'); // 改行まで読み込む
    input.trim(); // 余分な空白や改行を削除

    if (input == "readall") {
      readAllEEPROM();
    } else if (input.startsWith("read ")) {
      String addrStr = input.substring(5);
      int addr = strtol(addrStr.c_str(), NULL, 16); // 16進数としてアドレスを解析
      readEEPROM(addr);
    } else if (input.startsWith("write ")) {
      int commaIndex = input.indexOf(','); // コンマの位置を見つける
      if (commaIndex != -1) {
        String addrStr = input.substring(6, commaIndex);
        String valStr = input.substring(commaIndex + 1);
        int addr = strtol(addrStr.c_str(), NULL, 16); // 16進数としてアドレスを解析
        int val = strtol(valStr.c_str(), NULL, 16); // 16進数として値を解析

        Serial.print("Parsed address: ");
        Serial.println(addr, HEX);
        Serial.print("Parsed value: ");
        Serial.println(val, HEX);

        writeEEPROM(addr, val);
      } else {
        Serial.println("Invalid command format. Use 'write [address],[value]'.");
      }
    }
  }
}


void readEEPROM(int address) {
  Wire.beginTransmission(eepromAddress);
  Wire.write((byte)address); // 読み出すアドレスを指定
  Wire.endTransmission();
  Wire.requestFrom(eepromAddress, 1); // 1バイト読み出す
  if (Wire.available()) {
    byte data = Wire.read(); // データを読み取る
    Serial.print("Read from address ");
    Serial.print(address);
    Serial.print(": ");
    Serial.println(data, HEX); // 読み取ったデータを16進数で表示
  }
}

void writeEEPROM(int address, int data) {
  Wire.beginTransmission(eepromAddress);
  Wire.write((byte)address); // 書き込むアドレスを指定
  Wire.write((byte)data); // 書き込むデータを指定
  Wire.endTransmission();
  delay(5); // EEPROMがデータを書き込むのを待つ

  // 書き込むデータをシリアルモニタに表示
  Serial.print("Attempting to write ");
  Serial.print(data);
  Serial.print(" (0x");
  Serial.print(data, HEX);
  Serial.print(") to address ");
  Serial.println(address);

  // 実際に書き込まれたことを確認するために読み出し
  readEEPROM(address);
}


void readAllEEPROM() {
  Serial.println("Reading all EEPROM data:");
  for (int i = 0; i < 128; i++) { // 64バイト全てを読み出す
    Wire.beginTransmission(eepromAddress);
    Wire.write(i); // 読み出すアドレスを指定
    Wire.endTransmission();
    Wire.requestFrom(eepromAddress, 1); // 1バイト読み出す
    while (Wire.available()) {
      byte data = Wire.read(); // データを読み取る
      Serial.print("0x");
      if (data < 0x10) {
        Serial.print("0"); // 1桁の場合は0を先頭に付ける
      }
      Serial.print(data, HEX); // 読み取ったデータを16進数で表示
      Serial.print(" ");
    }
    if ((i + 1) % 16 == 0) {
      Serial.println(); // 16バイトごとに改行
    }
  }
  Serial.println("\nRead complete.");
}
```

#### 動作確認
全体を読みだす"readall"をシリアルモニタで入力したところ、battmonにも紹介されている値と同様なデータが出力されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/04353654-08f5-70d0-8eb3-f9622711edf0.png)


#### 警告をもう一度
今回のAdvent Calenderでバッテリーセルの交換について考察しますが、非常に危険ですので知識と教養を深める目的で調べたことをまとめました。
十分な安全対策を講じなければ、実行することはお勧めできません。
重要なことなので、もう一度書きます。

:::note alert
警告
この記事について作者はいかなる責任も負いません。
バッテリーの分解、改造は非常に危険な行為です。
:::

#### 備考
上記に示した図面はLoïc POLLIERさんが作成したものです。
Copyright (c) 2020-2022 Loïc POLLIER
Released under the MIT license
https://github.com/lpollier/battmon/blob/master/LICENSE