ロジックアナライザを試すその６：ハードウェアI2CとソフトウェアI2C

# ハードウェアI2CとソフトウェアI2Cの比較
[その４](https://qiita.com/infinite1oop/items/b24cc42d78d5d50c94dc)では、ハードウェアSPIとソフトウェアSPIとの差異が見られたので、I2Cではどうなるか試す。

## 用いたもの
いつもと[同じロジックアナライザ](https://qiita.com/infinite1oop/items/508873f660812e52f324)、Arduino、ESP32搭載のM5Stackおよび光センサー（TLS2561搭載）。Arduino IDE開発環境利用。

## ソースコード

### ハードウェアI2C
```c++
#include <Wire.h>

void setup() [
  Wire.begin();
  .....
}
```
ハードウェアI2Cは、ArduinoおよびM5Stackで共通。

### ソフトウェアI2C(Arduino)
```c++
#define SDA_PORT PORTD
#define SDA_PIN 2
#define SCL_PORT PORTD
#define SCL_PIN 3
#include <SoftI2CMaster.h>
#include <SoftWire.h>

SoftWire Wire = SoftWire();

void setup() [
  Wire.begin();
  .....
}
```
ArduinoのソフトウェアI2Cについては、[ArduinoとESP32のWire.begin()の差異](https://qiita.com/infinite1oop/items/63722503f60a4bdd0d0c)参照。

### ソフトウェアSPI(M5Stack)
```c++
void setup() {
  Wire.begin(16, 17);
  ....
}
```
M5Stack(ESP32)のソフトウェアI2Cについては、[ArduinoとESP32のWire.begin()の差異](https://qiita.com/infinite1oop/items/63722503f60a4bdd0d0c)参照。

### ハードウェアSPIとソフトウェアSPIに共通部分
```c++
#include "TLS2561.h"

void writeRegisterValue(int deviceAddress, int address, uint8_t val) {
  Wire.beginTransmission(deviceAddress);  // start transmission to device
  Wire.write(address);                    // send register address
  Wire.write(val);                        // send value to write
  Wire.endTransmission();                 // end transmission
}
uint8_t readRegisterValue(int deviceAddress, int address) {
  uint8_t value;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address);                // register to read
  Wire.endTransmission();
  Wire.requestFrom(deviceAddress, 1); // read a byte
  while (!Wire.available());
  value = Wire.read();
  return value;
}

void setup() {
  // 上述のハードウェアSPIおよびソフトウェアSPIの部分がここに入る。 Wire.begin()など。

  Serial.begin(9600);
  writeRegisterValue(TSL2561_Address, TSL2561_Control, 0x03); // POWER UP
  writeRegisterValue(TSL2561_Address, TSL2561_Timing, 0x00); //No High Gain (1x), integration time of 13ms
  writeRegisterValue(TSL2561_Address, TSL2561_Interrupt, 0x00);
  writeRegisterValue(TSL2561_Address, TSL2561_Control, 0x00); // POWER Down
}

void loop() {
  writeRegisterValue(TSL2561_Address, TSL2561_Control, 0x03); // POWER UP
  delay(14);
  Serial.print("Channel 0 Low value: ");
  Serial.println(readRegisterValue(TSL2561_Address, TSL2561_Channal0L));
  writeRegisterValue(TSL2561_Address, TSL2561_Control, 0x00); // POWER Down
  delay(2000);
}
```
TLS2561のハンドリングについては、[以前の記事](https://qiita.com/infinite1oop/items/df0e90480a20e9c6ffd5)参照。ここでは、チャネル０のLow値を定期的に取得している。

## ロジックアナライザで計測
### Arduino
Hardware I2C：460μs
![Arduino_HardI2C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/69acfe2a-8caf-583e-115a-057e97f6ed8e.png)

Software I2C：480μs
![Arduino_SoftI2C(2,3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/15ddc990-b184-d6f0-1acd-cea1b484b0db.png)

### M5Stack(ESP32)
Hardware I2C：460μs
![M5Stack_HardI2C(21,22).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/269cb257-f027-ab70-7937-2a73ebd20d72.png)

Software I2C：480μs
![M5Stack_SoftI2C(16,17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/bf717e3b-cc9f-12db-8a90-f49f965ad59e.png)

## 考察
差がほとんど見られず。まずは比較のみで、その詳細調査はしていない。Wire.setClock()を用い、同一クロックにすれば同じになるかもしれない。いつかやってみるかも。