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駆動)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 件のコメント:
コメントを投稿