2018年11月9日金曜日

Nucleo(mbed)からI2Cで通信してArduinoでOLEDに表示させてみる。

mbedのSSD1306のライブラリはいくつかありますが、フォントが貧弱で、きれいな文字を表示しようと思うとやはりUoogやu8g2を使いたくなります。

U8g2はArduinoでは使いやすいですが、mbedでは少々やっかいです。

そこで、U8g2を使うためだけにArduinoを一個用意するという贅沢なことを思いつきました。

Nucleo本体は波形生成に専念し、パラメーターに変更があった場合にOLED表示用のAruduinoにI2C経由でデーターを投げるというイメージです。

I2Cは仕様が複雑でほんとは使いたくないんですが、AVRにもSTM32にも専用のハードウェアが用意されているのでパフォーマンスを考えると使わざるを得ないと思います。なにせ信号線2本で双方向通信できますから。

SSD1306 OLEDも、やりくりすればI2Cタイプでもかまわないのですが(Nucleo - Arduino間の通信と信号線を共用)、速度と手数を減らすためにSPIタイプのものを使いました。

配線図

I2Cマスター側 Nucleo(mbed)のプログラムは前回と同じです。

https://os.mbed.com/users/ryood/code/Nucleo_i2c_master_writer/

I2Cスレーブ側 Arduino Pro mini (3.3V/8MHz駆動)

/*
* Nucleo DCO I2C Slave / OLED Module Test.
*
* 2018.11.07
*
*/
#include <Wire.h>
#include <U8g2lib.h>
#define TITLE_STR1 ("I2C Slave Test")
#define TITLE_STR2 ("20181107")
#define I2C_ADDR (0x08)
#define I2C_CLOCK (400000)
//U8G2_SSD1306_128X32_UNIVISION_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED
U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
void setup()
{
Serial.begin(9600); // start serial for output
Serial.println();
Serial.println(TITLE_STR1);
Serial.println(TITLE_STR2);
// OLED
u8g2.begin();
u8g2.clearBuffer();
u8g2.firstPage();
u8g2.setFont(u8g2_font_8x13_tf);
do {
u8g2.drawStr(0,10,TITLE_STR1);
u8g2.drawStr(0,25,TITLE_STR2);
} while (u8g2.nextPage());
u8g2.sendBuffer();
// I2C
Wire.begin(8); // join i2c bus with address #8
pinMode(A4, INPUT); // disable pullup
pinMode(A5, INPUT); // disable pullup
Wire.setClock(I2C_CLOCK);
Wire.onReceive(receiveEvent); // register event
delay(2000);
}
void loop()
{
delay(100);
}
void receiveEvent(int howMany)
{
char buff1[20];
char buff2[30];
int i = 0;
while (1 < Wire.available()) {
char c = Wire.read();
Serial.print(c);
if (i < 18) {
buff1[i] = c;
i++;
}
buff1[i] = '\0';
}
int x = Wire.read();
Serial.println(x);
sprintf(buff2, "%s%d", buff1, x);
u8g2.firstPage();
u8g2.setFont(u8g2_font_10x20_mf);
do {
u8g2.drawStr(0,32, buff2);
} while (u8g2.nextPage());
}

I2C経由で、マスター側が生成したデータをスレーブ側のOLEDで表示することができました。

I2Cクロック=400kHzの場合

ch1:Nucleo(D2) ch2:SCL

ch1はNucleo(マスター)側でI2C通信の開始時、終了時でH/Lしています。

I2C通信に要した時間: 220u秒~230u秒程度。

I2Cクロック=100kHzの場合

ch1:Nucleo(D2) ch2:SCL

I2C通信に要した時間: 675u秒

I2Cクロックは、Nucleo(マスター)側で変更すれば、Arduino(スレーブ)側は400kHzの設定のままで大丈夫でした。

0 件のコメント:

コメントを投稿