差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン | ||
| gimmickkouza:electronic_basic:6:3_oled_i2c [2024/06/16 20:27] – [サンプルコード解説] matsuhachi | gimmickkouza:electronic_basic:6:3_oled_i2c [2024/06/20 22:47] (現在) – ★動画追加 lutamesta | ||
|---|---|---|---|
| 行 2: | 行 2: | ||
| ===== ディスプレイについての基礎知識 ===== | ===== ディスプレイについての基礎知識 ===== | ||
| ==== ディスプレイの違い ==== | ==== ディスプレイの違い ==== | ||
| - | ディスプレイと一口に言っても、その仕組みや表示できるものの違い等、非常に幅が広いです。 | + | ディスプレイと一口に言っても、その仕組みや表示できるものの違い等、非常に幅が広いです。 |
| === ディスプレイの種類 === | === ディスプレイの種類 === | ||
| - | 電子工作用途で使われるディスプレイでは「LCD」と「OLED」が一般的です。 | + | 電子工作用途で使われるディスプレイでは「LCD」と「OLED」が一般的です。 |
| あと最近では「電子ペーパー」なんてのもありますが、講師非所持のため説明は割愛します。 | あと最近では「電子ペーパー」なんてのもありますが、講師非所持のため説明は割愛します。 | ||
| 行 29: | 行 29: | ||
| 文字や数字をのみを表示できるLCDキャラクタディスプレイ。 | 文字や数字をのみを表示できるLCDキャラクタディスプレイ。 | ||
| 工作物に組み込み、情報表示用途に使われます。 | 工作物に組み込み、情報表示用途に使われます。 | ||
| - | <alert type="danger"> | + | <panel type="info" title=" |
| + | characterが文字集合の意味なんですよね。</panel> | ||
| == グラフィック == | == グラフィック == | ||
| 行 54: | 行 55: | ||
| ===== 6-3-1_OLED_I2C ===== | ===== 6-3-1_OLED_I2C ===== | ||
| + | {{youtube> | ||
| + | |||
| + | (この動画は6-3-2と6-3-1を繋げています。0: | ||
| + | |||
| ==== I2Cの仕組み ==== | ==== I2Cの仕組み ==== | ||
| UARTに続く二つめのシリアル通信、I2Cの登場です! | UARTに続く二つめのシリアル通信、I2Cの登場です! | ||
| 行 60: | 行 65: | ||
| 「I2C」はInter-Integrated Circuitの略で、「アイ・スクエアド・シー」と呼びます。 | 「I2C」はInter-Integrated Circuitの略で、「アイ・スクエアド・シー」と呼びます。 | ||
| 「アイ・アイ・シー」「アイ・ツー・シー」とも呼ばれます。アイスクエアドシーの方がかっこいいのに… | 「アイ・アイ・シー」「アイ・ツー・シー」とも呼ばれます。アイスクエアドシーの方がかっこいいのに… | ||
| - | 信号線が2本だけという点はUARTと同じですが、I2CはUARTにはない特徴がたくさんあります。 | + | |
| + | __**I2Cの最大の特徴は、2本1組の信号線で複数のI2C機器を操れる**__という点です。 | ||
| + | (信号線が2本1組という点ではUARTと同じですが、UARTは1組の信号線で操れる機器は1つだけでしたね!) | ||
| I2Cの特徴は以下の4つです。 | I2Cの特徴は以下の4つです。 | ||
| 行 69: | 行 76: | ||
| 順番にひとつずつ解説します。 | 順番にひとつずつ解説します。 | ||
| - | <alert type=" | + | /*<alert type=" |
| もちろん下記でも書いてあるんですが、その特徴があってこそのこの仕組みなので・・ | もちろん下記でも書いてあるんですが、その特徴があってこそのこの仕組みなので・・ | ||
| - | </ | + | </ |
| == 信号線「SCL」と「SDA」 == | == 信号線「SCL」と「SDA」 == | ||
| 行 93: | 行 99: | ||
| 例えば本項での「コントローラ」はArduinoです。そこにOLEDディスプレイを「ターゲット」として繋ぎます。 | 例えば本項での「コントローラ」はArduinoです。そこにOLEDディスプレイを「ターゲット」として繋ぎます。 | ||
| **「ターゲット」として複数のディスプレイや他のI2C機器を繋ぐことも可能です。** | **「ターゲット」として複数のディスプレイや他のI2C機器を繋ぐことも可能です。** | ||
| - | <alert type="danger"> | + | <panel type="info" title=" |
| + | そういったマイコンであれば、I2C機器を繋ぎすぎたりする場合などに、複数のI2Cコントローラを用意して分割して繋ぐ手も使えます。</panel> | ||
| == クロック信号で同期を取る == | == クロック信号で同期を取る == | ||
| 行 111: | 行 118: | ||
| こういった部品を扱う際には、自分でI2Cアドレスを調べる必要があります。 | こういった部品を扱う際には、自分でI2Cアドレスを調べる必要があります。 | ||
| いつかそんなシーンに遭遇した時のために、I2Cアドレスの調べ方を掲載しておきます。 | いつかそんなシーンに遭遇した時のために、I2Cアドレスの調べ方を掲載しておきます。 | ||
| - | + | ||
| - | ---- | + | ===i2c_scannerでI2Cアドレスを調べる=== |
| I2Cアドレスを確認するには、i2c_scannerというスケッチを使用します。 | I2Cアドレスを確認するには、i2c_scannerというスケッチを使用します。 | ||
| 行 143: | 行 150: | ||
| 下記の検索ワードを打ち込み、2つのライブラリをインストールしてください。 | 下記の検索ワードを打ち込み、2つのライブラリをインストールしてください。 | ||
| - | * " | + | * " |
| * " | * " | ||
| ちなみに~GFXはディスプレイ用のグラフィックスライブラリ、~SSD1306はSSD1306ドライバを搭載した電子部品を使用するためのライブラリです。 | ちなみに~GFXはディスプレイ用のグラフィックスライブラリ、~SSD1306はSSD1306ドライバを搭載した電子部品を使用するためのライブラリです。 | ||
| - | <alert type=" | + | /*<alert type=" |
| + | |||
| ==== 配線図 ==== | ==== 配線図 ==== | ||
| {{: | {{: | ||
| 行 160: | 行 167: | ||
| また他のサイトや店舗で販売している似たようなディスプレイは、個別に確認が必要です。 | また他のサイトや店舗で販売している似たようなディスプレイは、個別に確認が必要です。 | ||
| ネット情報ではプルアップ抵抗のない商品も存在するようです) | ネット情報ではプルアップ抵抗のない商品も存在するようです) | ||
| + | |||
| + | ===使う部品リスト=== | ||
| + | ^ 部品 | ||
| + | | OLEDディスプレイ | 1個 | | ||
| ==== サンプルコード解説 ==== | ==== サンプルコード解説 ==== | ||
| サンプルコード6-3-1_OLED_I2C.inoを開いてください。 | サンプルコード6-3-1_OLED_I2C.inoを開いてください。 | ||
| - | <alert type=" | + | /*<alert type=" |
| 下のコードをコピペすると「}」が足りないです | 下のコードをコピペすると「}」が足りないです | ||
| {{: | {{: | ||
| - | </ | + | </ |
| < | < | ||
| 行 197: | 行 207: | ||
| display.display();// | display.display();// | ||
| delay(1000); | delay(1000); | ||
| + | } | ||
| </ | </ | ||
| 行 308: | 行 319: | ||
| 全く同じコードを、サンプルコード「6-3-2_OLED_I2C_from_sample.ino」として収録してありますので、興味のある方はぜひ実行してみてください。 | 全く同じコードを、サンプルコード「6-3-2_OLED_I2C_from_sample.ino」として収録してありますので、興味のある方はぜひ実行してみてください。 | ||
| + | |||
| ==== 配線図 ==== | ==== 配線図 ==== | ||
| {{: | {{: | ||
| 直前の6-3-1で作った回路そのままでOKです! | 直前の6-3-1で作った回路そのままでOKです! | ||
| + | |||
| + | ===使う部品リスト=== | ||
| + | ^ 部品 | ||
| + | | OLEDディスプレイ | 1個 | | ||
| ==== サンプルコード解説(しないよ!) ==== | ==== サンプルコード解説(しないよ!) ==== | ||
| サンプルコード6-3-2_OLED_I2C_from_sample.inoを開いてください。 | サンプルコード6-3-2_OLED_I2C_from_sample.inoを開いてください。 | ||
| + | |||
| + | < | ||
| + | / | ||
| + | This is an example for our Monochrome OLEDs based on SSD1306 drivers | ||
| + | |||
| + | Pick one up today in the adafruit shop! | ||
| + | | ||
| + | |||
| + | This example is for a 128x64 pixel display using I2C to communicate | ||
| + | 3 pins are required to interface (two I2C and one reset). | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | with contributions from the open source community. | ||
| + | BSD license, check license.txt for more information | ||
| + | All text above, and the splash screen below must be | ||
| + | | ||
| + | | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #define SCREEN_WIDTH 128 // OLED display width, in pixels | ||
| + | #define SCREEN_HEIGHT 64 // OLED display height, in pixels | ||
| + | |||
| + | // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) | ||
| + | // The pins for I2C are defined by the Wire-library. | ||
| + | // On an arduino UNO: | ||
| + | // On an arduino MEGA 2560: 20(SDA), 21(SCL) | ||
| + | // On an arduino LEONARDO: | ||
| + | #define OLED_RESET | ||
| + | |||
| + | // | ||
| + | #define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 | ||
| + | |||
| + | |||
| + | Adafruit_SSD1306 display(SCREEN_WIDTH, | ||
| + | |||
| + | #define NUMFLAKES | ||
| + | |||
| + | #define LOGO_HEIGHT | ||
| + | #define LOGO_WIDTH | ||
| + | static const unsigned char PROGMEM logo_bmp[] = | ||
| + | { 0b00000000, 0b11000000, | ||
| + | 0b00000001, 0b11000000, | ||
| + | 0b00000001, 0b11000000, | ||
| + | 0b00000011, 0b11100000, | ||
| + | 0b11110011, 0b11100000, | ||
| + | 0b11111110, 0b11111000, | ||
| + | 0b01111110, 0b11111111, | ||
| + | 0b00110011, 0b10011111, | ||
| + | 0b00011111, 0b11111100, | ||
| + | 0b00001101, 0b01110000, | ||
| + | 0b00011011, 0b10100000, | ||
| + | 0b00111111, 0b11100000, | ||
| + | 0b00111111, 0b11110000, | ||
| + | 0b01111100, 0b11110000, | ||
| + | 0b01110000, 0b01110000, | ||
| + | 0b00000000, 0b00110000 }; | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(9600); | ||
| + | |||
| + | // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally | ||
| + | if(!display.begin(SSD1306_SWITCHCAPVCC, | ||
| + | Serial.println(F(" | ||
| + | for(;;); // Don't proceed, loop forever | ||
| + | } | ||
| + | |||
| + | // Show initial display buffer contents on the screen -- | ||
| + | // the library initializes this with an Adafruit splash screen. | ||
| + | display.display(); | ||
| + | delay(2000); | ||
| + | |||
| + | // Clear the buffer | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | // Draw a single pixel in white | ||
| + | display.drawPixel(10, | ||
| + | |||
| + | // Show the display buffer on the screen. You MUST call display() after | ||
| + | // drawing commands to make them visible on screen! | ||
| + | display.display(); | ||
| + | delay(2000); | ||
| + | // display.display() is NOT necessary after every single drawing command, | ||
| + | // unless that's what you want...rather, | ||
| + | // drawing operations and then update the screen all at once by calling | ||
| + | // display.display(). These examples demonstrate both approaches... | ||
| + | |||
| + | testdrawline(); | ||
| + | |||
| + | testdrawrect(); | ||
| + | |||
| + | testfillrect(); | ||
| + | |||
| + | testdrawcircle(); | ||
| + | |||
| + | testfillcircle(); | ||
| + | |||
| + | testdrawroundrect(); | ||
| + | |||
| + | testfillroundrect(); | ||
| + | |||
| + | testdrawtriangle(); | ||
| + | |||
| + | testfilltriangle(); | ||
| + | |||
| + | testdrawchar(); | ||
| + | |||
| + | testdrawstyles(); | ||
| + | |||
| + | testscrolltext(); | ||
| + | |||
| + | testdrawbitmap(); | ||
| + | |||
| + | // Invert and restore display, pausing in-between | ||
| + | display.invertDisplay(true); | ||
| + | delay(1000); | ||
| + | display.invertDisplay(false); | ||
| + | delay(1000); | ||
| + | |||
| + | testanimate(logo_bmp, | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | } | ||
| + | |||
| + | void testdrawline() { | ||
| + | int16_t i; | ||
| + | |||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(i=0; i< | ||
| + | display.drawLine(0, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | for(i=0; i< | ||
| + | display.drawLine(0, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | delay(250); | ||
| + | |||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(i=0; i< | ||
| + | display.drawLine(0, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | for(i=display.height()-1; | ||
| + | display.drawLine(0, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | delay(250); | ||
| + | |||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(i=display.width()-1; | ||
| + | display.drawLine(display.width()-1, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | for(i=display.height()-1; | ||
| + | display.drawLine(display.width()-1, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | delay(250); | ||
| + | |||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(i=0; i< | ||
| + | display.drawLine(display.width()-1, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | for(i=0; i< | ||
| + | display.drawLine(display.width()-1, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testdrawrect(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=0; i< | ||
| + | display.drawRect(i, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testfillrect(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=0; i< | ||
| + | // The INVERSE color is used so rectangles alternate white/black | ||
| + | display.fillRect(i, | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testdrawcircle(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=0; i< | ||
| + | display.drawCircle(display.width()/ | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testfillcircle(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=max(display.width(), | ||
| + | // The INVERSE color is used so circles alternate white/black | ||
| + | display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE); | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testdrawroundrect(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=0; i< | ||
| + | display.drawRoundRect(i, | ||
| + | display.height()/ | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testfillroundrect(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=0; i< | ||
| + | // The INVERSE color is used so round-rects alternate white/black | ||
| + | display.fillRoundRect(i, | ||
| + | display.height()/ | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testdrawtriangle(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=0; i< | ||
| + | display.drawTriangle( | ||
| + | display.width()/ | ||
| + | display.width()/ | ||
| + | display.width()/ | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testfilltriangle(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | for(int16_t i=max(display.width(), | ||
| + | // The INVERSE color is used so triangles alternate white/black | ||
| + | display.fillTriangle( | ||
| + | display.width()/ | ||
| + | display.width()/ | ||
| + | display.width()/ | ||
| + | display.display(); | ||
| + | delay(1); | ||
| + | } | ||
| + | |||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testdrawchar(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | display.setTextSize(1); | ||
| + | display.setTextColor(SSD1306_WHITE); | ||
| + | display.setCursor(0, | ||
| + | display.cp437(true); | ||
| + | |||
| + | // Not all the characters will fit on the display. This is normal. | ||
| + | // Library will draw what it can and the rest will be clipped. | ||
| + | for(int16_t i=0; i<256; i++) { | ||
| + | if(i == ' | ||
| + | else display.write(i); | ||
| + | } | ||
| + | |||
| + | display.display(); | ||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testdrawstyles(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | display.setTextSize(1); | ||
| + | display.setTextColor(SSD1306_WHITE); | ||
| + | display.setCursor(0, | ||
| + | display.println(F(" | ||
| + | |||
| + | display.setTextColor(SSD1306_BLACK, | ||
| + | display.println(3.141592); | ||
| + | |||
| + | display.setTextSize(2); | ||
| + | display.setTextColor(SSD1306_WHITE); | ||
| + | display.print(F(" | ||
| + | |||
| + | display.display(); | ||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void testscrolltext(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | display.setTextSize(2); | ||
| + | display.setTextColor(SSD1306_WHITE); | ||
| + | display.setCursor(10, | ||
| + | display.println(F(" | ||
| + | display.display(); | ||
| + | delay(100); | ||
| + | |||
| + | // Scroll in various directions, pausing in-between: | ||
| + | display.startscrollright(0x00, | ||
| + | delay(2000); | ||
| + | display.stopscroll(); | ||
| + | delay(1000); | ||
| + | display.startscrollleft(0x00, | ||
| + | delay(2000); | ||
| + | display.stopscroll(); | ||
| + | delay(1000); | ||
| + | display.startscrolldiagright(0x00, | ||
| + | delay(2000); | ||
| + | display.startscrolldiagleft(0x00, | ||
| + | delay(2000); | ||
| + | display.stopscroll(); | ||
| + | delay(1000); | ||
| + | } | ||
| + | |||
| + | void testdrawbitmap(void) { | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | display.drawBitmap( | ||
| + | (display.width() | ||
| + | (display.height() - LOGO_HEIGHT) / 2, | ||
| + | logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, | ||
| + | display.display(); | ||
| + | delay(1000); | ||
| + | } | ||
| + | |||
| + | #define XPOS 0 // Indexes into the ' | ||
| + | #define YPOS 1 | ||
| + | #define DELTAY 2 | ||
| + | |||
| + | void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) { | ||
| + | int8_t f, icons[NUMFLAKES][3]; | ||
| + | |||
| + | // Initialize ' | ||
| + | for(f=0; f< NUMFLAKES; f++) { | ||
| + | icons[f][XPOS] | ||
| + | icons[f][YPOS] | ||
| + | icons[f][DELTAY] = random(1, 6); | ||
| + | Serial.print(F(" | ||
| + | Serial.print(icons[f][XPOS], | ||
| + | Serial.print(F(" | ||
| + | Serial.print(icons[f][YPOS], | ||
| + | Serial.print(F(" | ||
| + | Serial.println(icons[f][DELTAY], | ||
| + | } | ||
| + | |||
| + | for(;;) { // Loop forever... | ||
| + | display.clearDisplay(); | ||
| + | |||
| + | // Draw each snowflake: | ||
| + | for(f=0; f< NUMFLAKES; f++) { | ||
| + | display.drawBitmap(icons[f][XPOS], | ||
| + | } | ||
| + | |||
| + | display.display(); | ||
| + | delay(200); | ||
| + | |||
| + | // Then update coordinates of each flake... | ||
| + | for(f=0; f< NUMFLAKES; f++) { | ||
| + | icons[f][YPOS] += icons[f][DELTAY]; | ||
| + | // If snowflake is off the bottom of the screen... | ||
| + | if (icons[f][YPOS] >= display.height()) { | ||
| + | // Reinitialize to a random position, just off the top | ||
| + | icons[f][XPOS] | ||
| + | icons[f][YPOS] | ||
| + | icons[f][DELTAY] = random(1, 6); | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| 37行目のI2CアドレスをみなさんのディスプレイのI2Cアドレスに書き換えてArduinoに書き込んでください。 | 37行目のI2CアドレスをみなさんのディスプレイのI2Cアドレスに書き換えてArduinoに書き込んでください。 | ||
| ※今回のコードはライブラリ付属のサンプルスケッチそのまんまですので、解説は致しません! | ※今回のコードはライブラリ付属のサンプルスケッチそのまんまですので、解説は致しません! | ||
| + | |||
| {{: | {{: | ||
| + | |||
| + | /*<alert type=" | ||
| + | |||