Arduino同士をI2C接続 ~I2C SLAVE~
Arduino同士をI2C接続して、スレーブ側をOLED SSD1306のコントローラにしてみました。SSD1306の描画処理をスレーブに持たせることで、SSD1306の描画処理に必要なメモリーを節約できます。
I2Cスレーブ設定
1) Wire.begin( )にI2Cアドレスを設定する事でスレーブになります。2) 内蔵PULL UPを無効にする場合には Wire.begin()実行後にpinMode()を変更
3) 受信・送信要求の割り込み処理関数を定義
この3ステップだけでI2Cスレーブとして動作します。
※ <>を全角<>に置き換えています。コピペの際は注意してください。
#include<Wire,h>
void setup() {
Wire.begin(SLAVE_ADDR); // I2Cアドレスを設定
pinMode(SDA, INPUT); // 内蔵PULL UPを無効にする
pinMode(SCL, INPUT);
Wire.onReceive(i2cRecive); // 受信割り込み関数定義
Wire.onRequest(ic2Send); // 送信要求割り込み関数定義
}
// 受信割り込み関数
// numBytes - 受信したデータバイト数
void i2cRecive(int numBytes) { }
// 送信要求割り込み関数
void ic2Send(int numBytes) { }
SSD1306コントローラ
描画コマンドを決めて、I2C受信時に該当するコマンドを実行するSSD1306コントローラを作成します。描画さえできればよいので自由度は割と高めです。
描画コマンドは必要なら増やせばよいので適当に▼のように決めてみました。
コマンド | パラメタ | |||||
---|---|---|---|---|---|---|
0x01 | CLS | |||||
0x02 | SCROLL | |||||
0x03 | LINE | XS | YS | XE | YE | COLOR |
0x04 | RECT | X | Y | W | H | COLOR |
0x05 | FILLRECT | X | Y | W | H | COLOR |
0x06 | CIRCLE | X | Y | R | COLOR | |
0x07 | FILLCIRCLE | X | Y | R | COLOR | |
0x08 | LOCATE | X | Y | |||
0x09 | FONT COLOR | COLOR | ||||
0x0A | 文字列 MAX 16 | |||||
0x0B | X | Y | 文字列 MAX 16 | |||
0x0C | 7SEG DISP | X | Y | N | COLOR | |
0xFE | DEBUG MODE OFF | |||||
0xFF | DEBUG MODE ON |
I2C-SLAVE.zip
I2C-MASTER.zip (動作DEMO用)
※ <>を全角<>に置き換えています。コピペの際は注意してください。
#include <Wire.h>
#include "ssd1306SPI.h"
SSD1306SPI ssd1395spi ;
char str[128] ;
int count = 0 ;
#define SLAVE_ADDR 0x02 // 7-bit Slave Address
byte i2cRecvBuffLen;
byte i2cRecvBuff[32];
byte i2cSendBuffLen;
byte i2cSendBuff[32];
uint8_t busyFlag = 0 ; // 0-Ready : 1-Busy
bool DEBUGMODE = false ;
// --- I2C 受信 ---
void i2cRecive(int numBytes){
i2cRecvBuffLen = 0 ;
while(Wire.available()){
if(i2cRecvBuffLen < 32){
i2cRecvBuff[i2cRecvBuffLen] = Wire.read();
i2cRecvBuffLen++;
}
}
busyFlag = 1 ;
if (DEBUGMODE) {
// -- DEBUG表示
sprintf(str,"CMD %02X",i2cRecvBuff[0]) ;
ssd1395spi.Print(0,4,str) ;
for (int i=1;i<i2cRecvBuffLen;i++) {
sprintf(str,"%02X",i2cRecvBuff[i]) ;
ssd1395spi.Print((i-1)*3,6,str) ;
}
} else {
execI2CCommand( ) ;
}
busyFlag = 0 ;
}
// --I2C 送信 ---
// Ready or Busyを返す
void ic2Send(){
Wire.write(busyFlag);
}
// --- I2C 受信コマンド実行 ---
void execI2CCommand( ) {
// COMMADN
// [0] - COMMAND
// 0x01 : CLS
// 0x02 : SCROLL
// 0x03 : LINE [XS][YS][XE][YE][COLOR]
// 0x04 : RECT [X][Y][W][H][COLOR]
// 0x05 : FILLRECT [X][Y][W][H][COLOR]
// 0x06 : CIRCLE [X][Y][R][COLOR]
// 0x07 : FILLCIRCLE [X][Y][R][COLOR]
// 0x08 : LOCATE [X] [Y]
// 0x09 : FONT COLOR [COLOR]
// 0x0A : PRINT [文字列 MAX 16]
// 0x0B : PRINT [X][Y][文字列 MAX 16]
// 0x0C : 7SEG DISP [X][Y][N][COLOR]
// 0xFE : DEBUG MODE - OFF
// 0xFF : DEBUG MODE - ON
switch(i2cRecvBuff[0]) {
case 1: // 1 : CLS
ssd1395spi.cls( ) ;
break ;
case 2: // 2 : SCROLL
ssd1395spi.scroll( ) ;
break ;
case 3: // 3 : LINE [XS][YS][XE][YE][COLOR]
ssd1395spi.drawLine((int)i2cRecvBuff[1],(int)i2cRecvBuff[2],(int)i2cRecvBuff[3],(int)i2cRecvBuff[4],i2cRecvBuff[5]) ;
break ;
case 4: // 4 : RECT [X][Y][W][H][COLOR]
ssd1395spi.drawRect((int)i2cRecvBuff[1],(int)i2cRecvBuff[2],(int)i2cRecvBuff[3],(int)i2cRecvBuff[4],i2cRecvBuff[5]) ;
break ;
case 5: // 5 : FILLRECT [X][Y][W][H][COLOR]
ssd1395spi.fillRect((int)i2cRecvBuff[1],(int)i2cRecvBuff[2],(int)i2cRecvBuff[3],(int)i2cRecvBuff[4],i2cRecvBuff[5]) ;
break ;
case 6: // 6 : CIRCLE [X][Y][R][COLOR]
ssd1395spi.drawCircle((int)i2cRecvBuff[1],(int)i2cRecvBuff[2],(int)i2cRecvBuff[3],i2cRecvBuff[4]) ;
break ;
case 7: // 7 : FILLCIRCLE [X][Y][R][COLOR]
ssd1395spi.fillCircle((int)i2cRecvBuff[1],(int)i2cRecvBuff[2],(int)i2cRecvBuff[3],i2cRecvBuff[4]) ;
break ;
case 8: // 8 : LOCATE [X] [Y]
ssd1395spi.locate((int)i2cRecvBuff[1],(int)i2cRecvBuff[2]) ;
break ;
case 9: // 9 : FONT COLOR [COLOR]
ssd1395spi.setFontColor(i2cRecvBuff[1]) ;
break ;
case 10: // A : PRINT [文字列 MAX 16]
i2cRecvBuff[i2cRecvBuffLen] = 0 ;
ssd1395spi.Print((char *)&i2cRecvBuff[1]) ;
break ;
case 11: // B : PRINT [X][Y][文字列 MAX 16]
i2cRecvBuff[i2cRecvBuffLen] = 0 ;
ssd1395spi.Print((int)i2cRecvBuff[1],(int)i2cRecvBuff[2],(char *)&i2cRecvBuff[3]) ;
break ;
case 12: // C : 7SEG DISP [X][Y][N][COLOR]
ssd1395spi.disp7SEG((int)i2cRecvBuff[1],(int)i2cRecvBuff[2],(int)i2cRecvBuff[3]) ;
break ;
case 0xFE: // DEBUGMODE - OFF
DEBUGMODE = false ;
ssd1395spi.cls( ) ;
break ;
case 0xFF: // DEBUGMODE - ON
DEBUGMODE = true ;
debugmode() ;
break ;
}
}
void debugmode( ) {
ssd1395spi.cls( ) ;
sprintf(str,"I2C ADDR") ;
ssd1395spi.Print(0,2,str) ;
ssd1395spi.disp7SEG(11,0, SLAVE_ADDR % 16 ) ;
ssd1395spi.disp7SEG( 9,0, SLAVE_ADDR / 16 ) ;
}
void setup() {
i2cRecvBuffLen = 0;
i2cSendBuffLen = 0 ;
ssd1395spi.init() ;
ssd1395spi.cls( ) ;
Wire.begin(SLAVE_ADDR);
pinMode(SDA, INPUT); // disable internal pull-up
pinMode(SCL, INPUT); // disable internal pull-up
ssd1395spi.cls( ) ;
debugmode( ) ;
Wire.onReceive(i2cRecive);
Wire.onRequest(ic2Send);
}
void loop() {
}