TECHNICAL SPEC · I²C PROTOCOL

I²C通信仕様

FP01の中では、RS485で受けたコマンドをArduino(I²Cマスター)が解釈し、I²CでPSoC 4(出力制御)・EEPROM(設定の保存)・DMXドライバへ指示を出します(FP01 Rev1.6ではOLEDもI²C接続)。このページは、FP01ファームウェア Rev13 と PSoC Creator プロジェクトのソースを解析して、通信設定、PSoC 4のレジスタ、各コマンドのバイト列をまとめたものです。

SPEC VERSION
I2C_Rev13
BUS SPEED
100 kHz
MASTER
Arduino (Wire)
ADDRESS
7-bit
FIRMWARE
Rev13 (0013)
BUS MAP

I²Cバス構成

FP01のI²Cは2系統あります。Arduino側のI²Cは、FP01基板上のPSoC 4・EEPROMをつなぎ(FP01 Rev1.6ではOLEDも)、FFCの21・22番ピンからメイン基板にも出ています。PSoC側のI²CはFFCの19・20番ピンに出ていて、DIMX4では温度センサー用(TEMP/SDA・SCL)に割り当てられています。

FP01 基板 メイン基板(FFC 40ピン経由) Arduino I²C · SDA/SCL · 100 kHz FFC 21 / 22 Arduino I²Cマスター(Wire) RS485コマンド → I²C 0x08 PSoC 4 出力制御 0x50 EEPROM AT24C256C · 32KB 0x3C OLED FP01 Rev1.6のみ 0x0A – 0x0D DMXドライバ 1〜4 DMX対応メイン基板 PSoC I²C(PSoC 4 ピン11 / 12) FFC 19 / 20 DIMX4 温度センサー Arduino側のバスは FP01 基板上の PSoC 4 ピン15 / 16 にもつながっています(PSoC 4 = スレーブ 0x08)。 点線のOLEDは FP01 Rev1.6 の構成です。FP01 Rev2.1 ではOLEDはSPI接続で、I²Cバスにはつながっていません。

ピン番号は FFCコネクタ仕様(FFC_Rev2) によります。DMXドライバのアドレスはファームウェア内の定義で、ドライバ1がリボンケーブルにいちばん近い基板です。

SETTINGS

通信設定

マスターはArduinoだけです。Wire.begin() を引数なしで呼んでいるので、Arduinoはマスターとしてバスに参加します。速度は指定せず、Arduinoの標準の100 kHzで動きます。OLEDのライブラリ(U8x8)は何も指定しないと400 kHzに上げてしまうため、setBusClock(100000) で100 kHzにそろえています。

SLAVE · OUTPUT CONTROL
0x08

PSoC 4

調光レベル、フェードタイム、モジュールIDを書き込むレジスタ型のスレーブ。書込みだけで、Arduinoからの読出しはしていません。

i2cDIMMER.cpp · PSOC_SLAVE_ADDRESS

SLAVE · SETTINGS STORE
0x50

EEPROM(AT24C256C)

モジュールアドレス、回路ごとの設定、グループ、シーンを保存。2バイトのメモリアドレス(上位→下位)で指定します。

i2cEEPROM.cpp · SLAVE_ADDRESS_EEPROM

SLAVE · DISPLAY · FP01 Rev1.6
0x3C

OLED(SH1106)

U8x8ライブラリの U8X8_SH1106_128X64_NONAME_HW_I2C。アドレスはライブラリの標準値です。約5分操作がないと省電力モードに入ります。

FP01 Rev2.1ではOLEDはSPI接続(SCK・MOSI・CS+DC・RST)で、このI²Cアドレスは使いません。

screen.cpp

SLAVE · DMX DRIVER
0x0A–0x0D

DMXドライバ 1〜4

回路ごとに設定したドライバ番号(1〜4)のアドレスへ、4バイト固定のパケットを送ります。

Rev13.ino · I2C_SLAVEADDR_1〜4

設定値の一覧

項目値定義場所補足
役割Arduino = マスターWire.begin()引数なし=マスター。setup() 内で2回呼んでいますが動作は同じです。
クロック100 kHzArduino標準DMX対応版のコメントに「i2cの速度 100kbps(Arduinoデフォルトなので指定しない)」とあります。
OLEDのクロック100 kHzu8x8.setBusClock(100000)FP01 Rev1.6でOLEDが同じバスにつながっていたため、速度をそろえています。
アドレス形式7ビット—表の値はすべて7ビット表記です(書込み時の8ビット値は2倍:0x08 → 0x10)。
バイト順ビッグエンディアン—2バイトの値(調光レベル、EEPROMアドレス、DMXチャンネル)は上位バイトから送ります。
PSoCへの送信待ちdelay(5)i2cDIMMER.cpp各書込みで endTransmission() の前に5 ms待ちます。
EEPROM書込み待ち10〜20 msi2cEEPROM.cpp1バイト:5 ms+10 ms、2バイト:5 ms+20 ms、複数バイト:バイト数×5 ms。
PSoC 4 · 0x08

PSoC 4レジスタマップ

PSoC 4は先頭1バイトをレジスタアドレスとして受け取り、その後ろのデータを書き込むレジスタ型スレーブです。PSoC 4に送るのはローカルアドレス0〜7の回路だけで、8以降は送りません。

レジスタ名前サイズ値送信関数
0x00モジュールID1 byte1:IGBTX4 2:DIMX4 3:PWMX4 4:RELAYX8 5:RRX8 6:CTRL1 7:RS485Xi2c_psoc_write_reg_module_id()
0x01–0x09未使用—Rev13では書き込みません—
0x0A + LA
0x0A–0x11
フェードタイム1 byte × 80〜255(0.1秒単位。2 = 0.2秒)i2c_psoc_write_reg_fade_time()
0x12 + LA×2
0x12–0x21
調光レベル(DIRECT)2 byte × 80〜1000(実% ×0.1%。0 = 消灯、1000 = 100%)、上位バイトからi2c_psoc_write_reg_light()

LA = ローカルアドレス(モジュール内の回路番号 0〜7)。以前のバージョンにはMIN・MAXレベルのレジスタ(0x12・0x22)がありましたが、Rev13ではコメントアウトされていて、MIN・MAXの換算はArduino側の換算テーブルで行います。

送信フレーム

調光レベルを書くi2c_psoc_write_reg_light(LA, level)
S
0x08 Wスレーブ
0x12+LA×2レジスタ
level ≫ 8上位バイト
level & FF下位バイト
P
フェードタイムを書くi2c_psoc_write_reg_fade_time(LA, time)
S
0x08 Wスレーブ
0x0A+LAレジスタ
time0〜255(×0.1秒)
P
モジュールIDを書くi2c_psoc_write_reg_module_id(id)
S
0x08 Wスレーブ
0x00レジスタ
id1〜7
P

バイト列を計算する

1. フェードタイム
2. 調光レベル

論理レベル(RS485コマンドで指定する 0〜1000)は、回路ごとのMIN・MAXから作る換算テーブルで実%に直してから送ります。論理0は0、論理1はMIN、論理1000はMAX、その間は直線で割り付けます(MIN = MAX のときは 1〜1000 として扱います)。

EEPROM · 0x50

EEPROMの読み書き

設定はすべて外付けEEPROM(AT24C256C-SSHL-T、256Kbit = 32KB、ページ64バイト)に保存し、起動時に読み込みます。メモリアドレスは2バイト(0x0000〜0x7FFF)で、ローカルアドレス × 0x100 + オフセットで回路ごとのブロックを分けています。LA0〜63の64回路分(0x0000〜0x3FFF、16KB)が容量の中に収まり、ファームウェアのページ長 EEPROM_PAGE_LENGTH = 64 もこのEEPROMのページサイズと一致します。

書込み(1 / 2 / Nバイト)i2c_eeprom_write_byte / _2byte / _nbyte
S
0x50 Wスレーブ
addr ≫ 8メモリアドレス上位
addr & FFメモリアドレス下位
data…1 / 2(上位→下位)/ 最大64(1ページ)
P

書いたあとはEEPROMの内部書込みが終わるまで待ちます(1バイト 10 ms、2バイト 20 ms、Nバイト N×5 ms)。

読出し(1 / 2バイト)i2c_eeprom_read_byte / _2byte
S
0x50 Wスレーブ
addr ≫ 8上位
addr & FF下位
P
S
0x50 Rスレーブ
data1 or 2バイト(上位→下位)
P

アドレスを書いていったんSTOPし、requestFrom() で読み出します(リピートスタートは使っていません)。

主な保存項目

オフセット項目サイズ値
0x0000モジュールアドレス20〜255(LA0ブロックのみ)
0x000Eレスポンスモード1返信の種類(LA0ブロックのみ)
0x000FOLED電源10:OFF 1:ON(LA0ブロックのみ)
0x0011モジュール機種ID11〜7(PSoCのレジスタ0x00にも書く)
0x18パワーオンレベル20〜1000(論理)
0x1C / 0x1EMIN / MAXレベル2 + 20〜1000(実%)
0x22ストアドレベル2OFF前のレベル(on__で復帰)
0x24 / 0x25UP/DOWNステップ 1 / 21 + 1壁スイッチ用 / HA用(×0.1%)
0x27フェードタイム10〜255(PSoC・DMXへそのまま転送)
0x29オンディレイ10〜255(×0.1秒)
0x2B回路説明16ASCII
0x3B回路アドレス2RS485で指定するアドレス
0x40所属グループ ×1632グループn = 0x40 + n×2
0x7A / 0x7BDMXドライバ番号 / チャンネル1 + 21〜4 / 1〜512
0x80シーンテーブル ×32640〜1000、-1(0xFFFF)= 変化なし

0x18以降のオフセットは回路ごとの値で、実際のアドレスは LA × 0x100 + オフセットです。

DMX DRIVER · 0x0A–0x0D

DMXドライバへのパケット

DMXチャンネルが設定された回路は、PSoC 4への送信と同時に、DMXドライバにも4バイトのパケットを送ります。送り先はEEPROMの「DMXドライバ番号」で決まり、1→0x0A、2→0x0B、3→0x0C、4→0x0Dです。

DMXレベルを送るi2c_DMX(LA, level) → i2c_send_4byte_n()
S
0x0A–0D Wドライバ1〜4
ch ≫ 8DMXチャンネル上位
ch & FFDMXチャンネル下位(1〜512)
level ≫ 2明るさ 0〜250
fadeフェードタイム 0〜255
P

明るさは実%(0〜1000)を4で割った値です。最大は250で、DMXの255までは届きません。UP/DOWN操作のときはフェードタイムを2(0.2秒)に固定して送ります。

ファームウェアには、ドライバから12バイトを読み出してRS485へ中継するポーリング処理(Polling_Slave_1〜4)も残っていますが、loop() からの呼出しはコメントアウトされていて、Rev13では動きません。

COMMAND → I²C

RS485コマンドとI²C送信

RS485のコマンドは12文字(vコマンドは8文字)のASCIIで、[モード1文字][アドレス3桁][命令4文字][引数4桁] の形です。どのコマンドを受けたときにI²Cで何が送られるかをまとめました。

コマンド内容PSoC 4(0x08)DMXEEPROM
m dire / a sccc / g sccc直接レベル指定・シーン呼出しレベル送信読出しのみ
v on__ / v off_ / v toggグループのON・OFF・トグルレベル送信OFF時にストアドレベルを書込み
v up__ / down / up_2 / dn_2グループのUP・DOWNフェード=2 レベル送信ステップ値を読出し
a fade / g fade一時的なフェードタイムフェード—書き込まない
s wftt / x wfttフェードタイムの設定フェード—0x27
a idon識別点滅の開始フェード=15 → 0 / 1000 を交互に——
a idof識別点滅の停止レベル=0——
OLED 機種選択モジュール機種の変更モジュールID—0x0011
s wmin / wmax / wpol など設定値の書込み——各項目

レベルを上げるとき(0より大きい値を送るとき)は、送信前にオンディレイ(×0.1秒)だけ待ちます。

起動時のシーケンス

01

設定を読む

EEPROMからモジュールアドレス、機種ID、レスポンスモード、OLED電源を読み込みます。

02

フェードタイム

LA0〜7のフェードタイムをEEPROMから読み、PSoCの 0x0A+LA に書きます。

03

パワーオンレベル

パワーオンレベルを読み、30 ms間隔でPSoCの 0x12+LA×2 に書いて点灯させます。

04

モジュールID

MIN・MAXを読んで換算テーブルを作り、最後に機種IDをPSoCの 0x00 に書きます。

PSoC CREATOR PROJECTS

PSoCプロジェクトのI²C設定

スイッチ(ROTARY03・ROTARY02N)のPSoC 5LPプロジェクトにもI²C部品の設定が残っています。ただし、現在のビルドでは配置配線レポートでI²Cの使用が0%で、FP01との通信はRS485(UART)で行っています。以前の設計でFP01と同じアドレス 0x08・100 kbps をそろえていた名残です。

プロジェクト部品モード速度アドレス状態
ROTARY03 Rev1.1.5
CY8C5888LTQ-LP097
I2Cマスター(UDB)100 kbps(0x08)未使用 呼出しはコメントアウト
I2C_1マルチマスター100 kbps0x08未使用
ROTARY02N Rev1.3EZI2C_Slave / EZI2C_1EZI2Cスレーブ(サブアドレス8ビット)100 kbps0x08未使用

FP01に載っているPSoC 4(CY8C4245PVI-482)側のファームウェアはこの解析の対象に含まれていません。PSoC 4のレジスタマップは、マスター(Arduino)が送っている内容から読み取ったものです。

NOTES

実装上の注意

Rev13のソースを読んでわかった、使うときに気をつけたい点です。