1-Wireスレーブ化IC「DS28E18」のテスト

1月も中旬ですが新年1発目、明けましておめでとうございます。
今年の抱負は代表作を作ることとその製品化、さらに販売してここのサーバー代くらい捻出したい。。。これ毎回、言ってるな。

さて、屋外に複数配置する環境データ取得デバイスが作りたいものの一つですが、デバイス間の通信を1-Wireにしたいと考え、1-WireをI2C/SPIに変換するIC、DS28E18を試しています。

1-Wireスレーブ-I2C/SPIマスターブリッジデバイスモジュールキット
https://akizukidenshi.com/catalog/g/gK-15790/

 

現状、まだ使いこなせてませんが、ログだけ残しときます。

内容としては、公式のチュートリアルのコマンドの例をRaspberryPi PicoのMicroPythonでトレースしたっというだけになります。

■ 構成

【デバイス】
・Raspberry Pi Pico
・AE-DS28E18(1-Wireスレーブモジュール)

【配線】

RPi Pico        AE-DS28E18
3V3 (36pin)------1WPU(1pin)
GP22(29pin)------1WIO(2pin)
GND (28pin)------GND (3pin)

チュートリアルの条件としては、温度湿度センサーSHTC3とDS28E18が接続されているべきですが、持っていないのでつけていません。

 

■ プログラム

下記のしたチュートリアルのI2Cのサンプルコマンドを、MicroPythonで記述しました。

The Basics of Using the DS28E18
https://www.analog.com/en/design-notes/the-basics-of-using-the-ds28e18.html

from machine import Pin
import utime
import onewire

ow = onewire.OneWire(Pin(22))
roms = ow.scan()
rom = roms[0]

def init_step1():
    # ダミーの Write GPIO Configuration (83h) コマンドを実行して
    # 1-Wire ライン上のすべてのデバイスの一意の ROM ID を入力する
    # (結果は無視する)
    print('Step1: Sending a dummy Write GPIO Configuration Command------------')
    ow.reset()
    ow.writebyte(0xCC) # Skip ROM
    ow.writebyte(0x66) # Command Start
    ow.writebyte(5)    # Length Byte
    ow.writebyte(0x83) # Write GPIO Configuration
    ow.writebyte(0x0B) # Sets Access to the GPIO control Register
    ow.writebyte(0x03) # Only value allowed
    ow.writebyte(0xA5) # GPIO_CTRL_HI Value
    ow.writebyte(0x0F) # GPIO_CTRL_LO Value
    ow.writebyte(0x75) # CRC16
    ow.writebyte(0x02) # CRC16
    ow.writebyte(0xAA) # Release Byte
    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 01: Length Byte
    print(hex(ow.readbyte())) # 77:
    print(hex(ow.readbyte())) # BE:
    print(hex(ow.readbyte())) # 49:

def init_step2():
    # ROM コマンドの検索を実行して、バスに接続されている
    # 各DS28E18 デバイスを見つける
    print('Step2: Search ROM Command to find each DS28E18 device--------------')
    roms = ow.scan()
    print(roms)

def init_step3():
    # Write GPIO Configuration コマンドを発行して、GPIO を既知の状態に設定する
    print('Step3: Write GPIO Configuration------------------------------------')
    ow.reset()
    ow.select_rom(rom)
    ow.writebyte(0x66) # Command Start
    ow.writebyte(5)    # Length Byte
    ow.writebyte(0x83) # Write GPIO Configuration
    ow.writebyte(0x0B) # Sets Access to the GPIO control Register
    ow.writebyte(0x03) # Only value allowed
    ow.writebyte(0xA5) # GPIO_CTRL_HI Value
    ow.writebyte(0x0F) # GPIO_CTRL_LO Value
    ow.writebyte(0x75) # CRC16
    ow.writebyte(0x02) # CRC16
    ow.writebyte(0xAA) # Release Byte
    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 01: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    print(hex(ow.readbyte())) # 7E: CRC16
    print(hex(ow.readbyte())) # 10: CRC16

def init_step4():
    # デバイス ステータス コマンドを実行して、
    # POR ステータス ビットをクリアする
    print('Step4: Device Status Command (Clear POR)---------------------------')
    ow.reset()
    ow.select_rom(rom)
    ow.writebyte(0x66) # Command Start
    ow.writebyte(1)    # Length Byte
    ow.writebyte(0x7A) # Device Status Command
    ow.writebyte(0x9F) # CRC16
    ow.writebyte(0x93) # CRC16
    ow.writebyte(0xAA) # Release Byte
    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 05: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    print(hex(ow.readbyte())) # 02: POR Has occurred
    print(hex(ow.readbyte())) # 00: Device Version
    print(hex(ow.readbyte())) # E6: CRC16
    print(hex(ow.readbyte())) # 0A: CRC16

def init_step5():
    # Read Configuration コマンドを実行して、既存のデバイス設定を確認する
    print('Step5: Read Configuration Command ---------------------------------')
    ow.reset()
    ow.select_rom(rom)
    ow.writebyte(0x66) # Command Start
    ow.writebyte(1)    # Length Byte
    ow.writebyte(0x6A) # Read Configuration Command
    ow.writebyte(0x9E) # CRC16
    ow.writebyte(0x5F) # CRC16
    ow.writebyte(0xAA) # Release Byte
    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 02: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    print(hex(ow.readbyte())) # 01: Configuration Register Value
    print(hex(ow.readbyte())) # E1: CRC16
    print(hex(ow.readbyte())) # 5F: CRC16

def init_step6_i2c_1():
    # Write Configurationコマンドを実行して、I2C 速度を 1MHz に設定する
    # (デフォルトで既にI2C モードに設定されているが、練習として実施)
    print('Step6-1: Write Configuration Command to set the I2C speed to 1MHz--')
    ow.reset()
    ow.writebyte(0xCC) # Skip ROM (With one divice on the bus)
    ow.writebyte(0x66) # Command Start
    ow.writebyte(2)    # Length Byte
    ow.writebyte(0x55) # Write Configuration Command
    ow.writebyte(0x02) # onfiguration Register
                       # PROT:I2C INACK:Do not ignore SPD:1MHz
    ow.writebyte(0xFE) # CRC16
    ow.writebyte(0x26) # CRC16
    ow.writebyte(0xAA) # Release Byte
    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 02: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    print(hex(ow.readbyte())) # E1: CRC16
    print(hex(ow.readbyte())) # 5F: CRC16

def init_step6_i2c_2():
    # Read ConfigurationコマンドでI2C速度が1MHzに設定されているか確認する
    print('Step6-2: Read Configuration Command to check the speed is set to 1MHz')
    ow.reset()
    ow.select_rom(rom) # Match ROM
    ow.writebyte(0x66) # Command Start
    ow.writebyte(1)    # Length Byte
    ow.writebyte(0x6A) # Read Configuration Command
    ow.writebyte(0x9E) # CRC16
    ow.writebyte(0x5F) # CRC16
    ow.writebyte(0xAA) # Release Byte
    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 02: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    print(hex(ow.readbyte())) # 02: Configuration Register Value
    print(hex(ow.readbyte())) # A1: CRC16
    print(hex(ow.readbyte())) # 5E: CRC16

def i2c_step1():
    # コマンド シーケンスを構築し、シーケンサーを書き込む
    # 1. ウェイクアップ コマンド 0x3517 を送信する
    # 2. 測定コマンド 0x5C24 を送信する
    # 3. 6 バイトのデータを読み戻す
    print('Step1: Build the command sequence and write the sequencer----------')
    ow.reset()
    ow.writebyte(0xCC) # Skip ROM
    ow.writebyte(0x66) # Command Start
    ow.writebyte(34)   # Length Byte
    ow.writebyte(0x11) # Write Sequencer Command
    ow.writebyte(0x00) # ADDR_LO
    ow.writebyte(0x00) # ADDR_HI
    ow.writebyte(0x02) # I2C Start – This is the start of the sequencer data
    ow.writebyte(0xE3) # I2C Write Data – DS28E18 Sequencer Command
    ow.writebyte(3)    # Write Length – Number of Bytes – 3 bytes sent to the SHTC3
    # i2c command
    ow.writebyte(0xE0) # SHTC3 I2C Write Address
    ow.writebyte(0x35) # SHTC3 Wakeup Command byte 1
    ow.writebyte(0x17) # SHTC3 Wakeup Command byte 2
    # -----
    ow.writebyte(0x03) # I2C Stop
    ow.writebyte(0xDD) # DS28E18 Delay Command – SHTC2 Wakeup Delay
    ow.writebyte(0x00) # 1ms delay
    ow.writebyte(0x02) # I2C Start – This is the start of the sequencer data
    ow.writebyte(0xE3) # I2C Write Data – DS28E18 Sequencer Command
    ow.writebyte(3)    # Write Length – Number of Bytes – 3 bytes sent to the SHTC3
    # i2c command
    ow.writebyte(0xE0) # SHTC3 I2C Write Address
    ow.writebyte(0x5C) # Measure Command byte 1
    ow.writebyte(0x24) # Measure Command byte 1
    # -----
    ow.writebyte(0x03) # I2C Stop
    ow.writebyte(0xDD) # DS28E18 Delay Command – SHTC2 Measurement Delay
    ow.writebyte(0x04) # 16ms delay
    ow.writebyte(0x02) # I2C Start – This is the start of the sequencer data
    ow.writebyte(0xE3) # I2C Write Data – DS28E18 Sequencer Command
    ow.writebyte(1)    # Write Length – Number of Bytes – 1 byte will be sent to the SHTC3
    # i2c command
    ow.writebyte(0xE1) # SHTC3 I2C Read Address
    # -----
    ow.writebyte(0xD4) # DS28E18 I2C Read Data Command
    ow.writebyte(0x06) # Number of Bytes to Read
    ow.writebyte(0xFF) # Place holder for Byte 1 – DS28E18 will read the data back and put it in here
    ow.writebyte(0xFF) # Place holder for Byte 2
    ow.writebyte(0xFF) # Place holder for Byte 3
    ow.writebyte(0xFF) # Place holder for Byte 4
    ow.writebyte(0xFF) # Place holder for Byte 5
    ow.writebyte(0xFF) # Place holder for Byte 6
    ow.writebyte(0x03) # I2C Stop
    ow.writebyte(0x9E) # CRC16
    ow.writebyte(0x5F) # CRC16
    ow.writebyte(0xAA) # Release Byte

    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 01: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    print(hex(ow.readbyte())) # 7E: CRC16
    print(hex(ow.readbyte())) # 10: CRC16

def i2c_step2():
    # Read Sequencer コマンドを発行して、データを読み戻す
    print('Step2: Read Sequencer Command to read back the data----------------')
    ow.reset()
    ow.writebyte(0xCC) # Skip ROM
    ow.writebyte(0x66) # Command Start
    ow.writebyte(3) # Number of Bytes
    ow.writebyte(0x22) # Read Sequencer Command
    ow.writebyte(0x00) # ADDR_LO
    ow.writebyte(0x3E) # SLEN:ADDR_HI
    ow.writebyte(0xD6) # CRC16
    ow.writebyte(0x69) # CRC16
    ow.writebyte(0xAA) # Release Byte

    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 20: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    datablock = ''
    for i in range(31):
        datablock += hex(ow.readbyte())
    print(datablock)
    print(hex(ow.readbyte())) # 14: CRC16
    print(hex(ow.readbyte())) # F1: CRC16

def i2c_step3():
    # Run Sequencer コマンドを発行して、シーケンスを実行する
    #(シーケンサーが正しく構築されていない場合、このコマンドはエラーになる)
    print('Step3: Run Sequencer Command to execute the sequence---------------')
    ow.reset()
    ow.writebyte(0xCC) # Skip ROM
    ow.writebyte(0x66) # Command Start
    ow.writebyte(0x04) # Number of Bytes
    ow.writebyte(0x33) # Read Sequencer Command
    ow.writebyte(0x00) # ADDR_LO
    ow.writebyte(0x3E) # SLEN_LO:ADDR_HI
    ow.writebyte(0x00) # SLEN_HI
    ow.writebyte(0xD6) # CRC16
    ow.writebyte(0x69) # CRC16
    ow.writebyte(0xAA) # Release Byte

    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 01: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    print(hex(ow.readbyte())) # 14: CRC16
    print(hex(ow.readbyte())) # F1: CRC16

def i2c_step4():
    # 読み取りシーケンサー コマンドを発行して、DS28E18 シーケンサー アドレス
    # 0x0018 ~ 0x001D から格納された湿度と温度のデータを読み取る
    print('Step4: Read Sequencer Command to read back the stored data---------')
    ow.reset()
    ow.writebyte(0xCC) # Skip ROM
    ow.writebyte(0x66) # Command Start
    ow.writebyte(0x03) # Number of Bytes
    ow.writebyte(0x22) # Read Sequencer Command
    ow.writebyte(0x18) # ADDR_LO
    ow.writebyte(0x0C) # SLEN:ADDR_HI
    ow.writebyte(0xD6) # CRC16
    ow.writebyte(0x69) # CRC16
    ow.writebyte(0xAA) # Release Byte

    utime.sleep_ms(10)
    print(hex(ow.readbyte())) # FF: Dummy Byte
    print(hex(ow.readbyte())) # 07: Length Byte
    print(hex(ow.readbyte())) # AA: Result Byte - Success
    datablock = ''
    for i in range(6):
        datablock += hex(ow.readbyte())
    print(datablock) # [73][CB][3A][65][38][DF]
    print(hex(ow.readbyte())) # 14: CRC16
    print(hex(ow.readbyte())) # F1: CRC16

def setup():
    init_step1()
    init_step2()
    init_step3()
    init_step4()
    init_step4()
    init_step5()
    init_step6_i2c_1()
    init_step6_i2c_2()
    i2c_step1()
    i2c_step2()

def measure():
    i2c_step3()
    i2c_step4()

def main():
    setup()
    for i in range(10):
        measure()
        utime.sleep(1)

if __name__ == '__main__':
    main()

温度湿度センサーSHTC3はもっていないので、i2c_step3以降がちゃんと実行できるかは試していません。
それまでのコマンドはDS28E18からは成功を返してくるので、操作は出来ていると思ってます。

コマンドを変えて、手持ちのI2C温度湿度センサーDHT20との通信を試みましたが、今だ成功していません。

 

既にノーアイディアでできる気がしませんが、2本線で長距離、並列接続可能というのは諦めきれない。。。もうちょい粘ってデータシートを熟読してみよう。。。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です