顯示具有 OLED 標籤的文章。 顯示所有文章
顯示具有 OLED 標籤的文章。 顯示所有文章

2024年9月24日 星期二

Control I2C SSD1306 by GPIO

#define OLED_SDA D2 // D2

#define OLED_SCL D1 // D1


#define OLED_ADDRESS 0x3c  // SSD1306 I2C 地址


// I2C 延遲,控制速度

#define I2C_DELAY 50  // 試著增加延遲


void i2c_start() {

  pinMode(OLED_SDA, OUTPUT);

  pinMode(OLED_SCL, OUTPUT);

  digitalWrite(OLED_SDA, HIGH);

  digitalWrite(OLED_SCL, HIGH);

  delayMicroseconds(I2C_DELAY);

  digitalWrite(OLED_SDA, LOW);

  delayMicroseconds(I2C_DELAY);

  digitalWrite(OLED_SCL, LOW);

}


void i2c_stop() {

  pinMode(OLED_SDA, OUTPUT);

  pinMode(OLED_SCL, OUTPUT);

  digitalWrite(OLED_SDA, LOW);

  digitalWrite(OLED_SCL, HIGH);

  delayMicroseconds(I2C_DELAY);

  digitalWrite(OLED_SDA, HIGH);

}



bool i2c_write_byte(uint8_t byte) {

  pinMode(OLED_SDA, OUTPUT);

  for (int i = 0; i < 8; i++) {

    digitalWrite(OLED_SCL, LOW);

    if (byte & 0x80) {

      digitalWrite(OLED_SDA, HIGH);

    } else {

      digitalWrite(OLED_SDA, LOW);

    }

    byte <<= 1;

    delayMicroseconds(I2C_DELAY);

    digitalWrite(OLED_SCL, HIGH);

    delayMicroseconds(I2C_DELAY);

  }

  digitalWrite(OLED_SCL, LOW);

  pinMode(OLED_SDA, INPUT);  // 切換到輸入檢查 ACK

  delayMicroseconds(I2C_DELAY);

  digitalWrite(OLED_SCL, HIGH);

  bool ack = !digitalRead(OLED_SDA);  // ACK 應該為低

  delayMicroseconds(I2C_DELAY);

  digitalWrite(OLED_SCL, LOW);

  return ack;  // 返回 ACK 檢查結果

}


void oled_command(uint8_t command) {

  i2c_start();

  uint8_t address = OLED_ADDRESS << 1;

  Serial.print("Sending Address: ");

  Serial.println(address, HEX);


  if (!i2c_write_byte(address)) {

    Serial.println("Address not acknowledged");

  }

  if (!i2c_write_byte(0x00)) {

    Serial.println("Control byte not acknowledged");

  }

  if (!i2c_write_byte(command)) {

    Serial.println("Command not acknowledged");

  }

  i2c_stop();

}





void oled_init() {

  oled_command(0xAE);  // 關閉顯示

  oled_command(0xA8);  // 設置多路復用比率

  oled_command(0x3F);  // 1/64

  oled_command(0xD3);  // 設置顯示偏移

  oled_command(0x00);  // 無偏移

  oled_command(0x40);  // 設置起始行位置

  oled_command(0xA1);  // 設置重映射

  oled_command(0xC8);  // 掃描方向

  oled_command(0xDA);  // 設置 COM 硬體配置

  oled_command(0x12);  // 代碼段

  oled_command(0x81);  // 設置對比度

  oled_command(0x7F);

  oled_command(0xA4);  // 關閉整體顯示

  oled_command(0xA6);  // 設置普通顯示

  oled_command(0xD5);  // 設置顯示時鐘分頻比/振盪器頻率

  oled_command(0x80);

  oled_command(0x8D);  // 啟用充電泵

  oled_command(0x14);

  oled_command(0xAF);  // 打開顯示

}


void oled_clear() {

  for (uint8_t page = 0; page < 8; page++) {

    oled_command(0xB0 + page);  // 設置頁地址

    oled_command(0x00);         // 設置低列地址

    oled_command(0x10);         // 設置高列地址

    i2c_start();

    i2c_write_byte(OLED_ADDRESS << 1);  // 發送地址

    i2c_write_byte(0x40);               // 控制位元 (0x40 表示後面是數據)

    for (uint8_t col = 0; col < 128; col++) {

      i2c_write_byte(0x00);             // 清空顯示

    }

    i2c_stop();

  }

}



// 定義 5x7 點陣字體

const uint8_t font5x7[][6] = {

  

{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // sp

{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00}, // !

{0x00, 0x00, 0x07, 0x00, 0x07, 0x00}, // "

{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14}, // #

{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12}, // $

{0x00, 0x62, 0x64, 0x08, 0x13, 0x23}, // %

{0x00, 0x36, 0x49, 0x55, 0x22, 0x50}, // &

{0x00, 0x00, 0x05, 0x03, 0x00, 0x00}, // '

{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00}, // (

{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00}, // )

{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14}, // *

{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08}, // +

{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00}, // ,

{0x00, 0x08, 0x08, 0x08, 0x08, 0x08}, // -

{0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, // .

{0x00, 0x20, 0x10, 0x08, 0x04, 0x02}, // /

{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0

{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00}, // 1

{0x00, 0x42, 0x61, 0x51, 0x49, 0x46}, // 2

{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31}, // 3

{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10}, // 4

{0x00, 0x27, 0x45, 0x45, 0x45, 0x39}, // 5

{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6

{0x00, 0x01, 0x71, 0x09, 0x05, 0x03}, // 7

{0x00, 0x36, 0x49, 0x49, 0x49, 0x36}, // 8

{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E}, // 9

{0x00, 0x00, 0x36, 0x36, 0x00, 0x00}, // :

{0x00, 0x00, 0x56, 0x36, 0x00, 0x00}, // ;

{0x00, 0x08, 0x14, 0x22, 0x41, 0x00}, // <

{0x00, 0x14, 0x14, 0x14, 0x14, 0x14}, // =

{0x00, 0x00, 0x41, 0x22, 0x14, 0x08}, // >

{0x00, 0x02, 0x01, 0x51, 0x09, 0x06}, // ?

{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E}, // @

{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}, // A

{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36}, // B

{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22}, // C

{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C}, // D

{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41}, // E

{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01}, // F

{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A}, // G

{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F}, // H

{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00}, // I

{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01}, // J

{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41}, // K

{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40}, // L

{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M

{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F}, // N

{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E}, // O

{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06}, // P

{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q

{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46}, // R

{0x00, 0x46, 0x49, 0x49, 0x49, 0x31}, // S

{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01}, // T

{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F}, // U

{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F}, // V

{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F}, // W

{0x00, 0x63, 0x14, 0x08, 0x14, 0x63}, // X

{0x00, 0x07, 0x08, 0x70, 0x08, 0x07}, // Y

{0x00, 0x61, 0x51, 0x49, 0x45, 0x43}, // Z

{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00}, // [

{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55}, // backslash

{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00}, // ]

{0x00, 0x04, 0x02, 0x01, 0x02, 0x04}, // ^

{0x00, 0x40, 0x40, 0x40, 0x40, 0x40}, // _

{0x00, 0x00, 0x01, 0x02, 0x04, 0x00}, // '

{0x00, 0x20, 0x54, 0x54, 0x54, 0x78}, // a

{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38}, // b

{0x00, 0x38, 0x44, 0x44, 0x44, 0x20}, // c

{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F}, // d

{0x00, 0x38, 0x54, 0x54, 0x54, 0x18}, // e

{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02}, // f

{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C}, // g

{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78}, // h

{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00}, // i

{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00}, // j

{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00}, // k

{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00}, // l

{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78}, // m

{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78}, // n

{0x00, 0x38, 0x44, 0x44, 0x44, 0x38}, // o

{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18}, // p

{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC}, // q

{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08}, // r

{0x00, 0x48, 0x54, 0x54, 0x54, 0x20}, // s

{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20}, // t

{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C}, // u

{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C}, // v

{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C}, // w

{0x00, 0x44, 0x28, 0x10, 0x28, 0x44}, // x

{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C}, // y

{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44}, // z


  {0x7E, 0x10, 0x10, 0x10, 0x7E, 0x00},  // 'H'

  {0x7E, 0x4A, 0x4A, 0x4A, 0x42, 0x00},  // 'E'

  {0x7E, 0x40, 0x40, 0x40, 0x40, 0x00},  // 'L'

  {0x3C, 0x42, 0x42, 0x42, 0x3C, 0x00},  // 'O'

  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},  // '#'

};



const char ssd1306oled_font[][6] PROGMEM = {

{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // sp

{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00}, // !

{0x00, 0x00, 0x07, 0x00, 0x07, 0x00}, // "

{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14}, // #

{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12}, // $

{0x00, 0x62, 0x64, 0x08, 0x13, 0x23}, // %

{0x00, 0x36, 0x49, 0x55, 0x22, 0x50}, // &

{0x00, 0x00, 0x05, 0x03, 0x00, 0x00}, // '

{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00}, // (

{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00}, // )

{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14}, // *

{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08}, // +

{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00}, // ,

{0x00, 0x08, 0x08, 0x08, 0x08, 0x08}, // -

{0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, // .

{0x00, 0x20, 0x10, 0x08, 0x04, 0x02}, // /

{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0

{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00}, // 1

{0x00, 0x42, 0x61, 0x51, 0x49, 0x46}, // 2

{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31}, // 3

{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10}, // 4

{0x00, 0x27, 0x45, 0x45, 0x45, 0x39}, // 5

{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6

{0x00, 0x01, 0x71, 0x09, 0x05, 0x03}, // 7

{0x00, 0x36, 0x49, 0x49, 0x49, 0x36}, // 8

{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E}, // 9

{0x00, 0x00, 0x36, 0x36, 0x00, 0x00}, // :

{0x00, 0x00, 0x56, 0x36, 0x00, 0x00}, // ;

{0x00, 0x08, 0x14, 0x22, 0x41, 0x00}, // <

{0x00, 0x14, 0x14, 0x14, 0x14, 0x14}, // =

{0x00, 0x00, 0x41, 0x22, 0x14, 0x08}, // >

{0x00, 0x02, 0x01, 0x51, 0x09, 0x06}, // ?

{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E}, // @

{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}, // A

{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36}, // B

{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22}, // C

{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C}, // D

{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41}, // E

{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01}, // F

{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A}, // G

{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F}, // H

{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00}, // I

{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01}, // J

{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41}, // K

{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40}, // L

{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M

{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F}, // N

{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E}, // O

{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06}, // P

{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q

{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46}, // R

{0x00, 0x46, 0x49, 0x49, 0x49, 0x31}, // S

{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01}, // T

{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F}, // U

{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F}, // V

{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F}, // W

{0x00, 0x63, 0x14, 0x08, 0x14, 0x63}, // X

{0x00, 0x07, 0x08, 0x70, 0x08, 0x07}, // Y

{0x00, 0x61, 0x51, 0x49, 0x45, 0x43}, // Z

{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00}, // [

{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55}, // backslash

{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00}, // ]

{0x00, 0x04, 0x02, 0x01, 0x02, 0x04}, // ^

{0x00, 0x40, 0x40, 0x40, 0x40, 0x40}, // _

{0x00, 0x00, 0x01, 0x02, 0x04, 0x00}, // '

{0x00, 0x20, 0x54, 0x54, 0x54, 0x78}, // a

{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38}, // b

{0x00, 0x38, 0x44, 0x44, 0x44, 0x20}, // c

{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F}, // d

{0x00, 0x38, 0x54, 0x54, 0x54, 0x18}, // e

{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02}, // f

{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C}, // g

{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78}, // h

{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00}, // i

{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00}, // j

{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00}, // k

{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00}, // l

{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78}, // m

{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78}, // n

{0x00, 0x38, 0x44, 0x44, 0x44, 0x38}, // o

{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18}, // p

{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC}, // q

{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08}, // r

{0x00, 0x48, 0x54, 0x54, 0x54, 0x20}, // s

{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20}, // t

{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C}, // u

{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C}, // v

{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C}, // w

{0x00, 0x44, 0x28, 0x10, 0x28, 0x44}, // x

{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C}, // y

{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44}, // z

{0x00, 0x00, 0x08, 0x77, 0x41, 0x00}, // {

{0x00, 0x00, 0x00, 0x63, 0x00, 0x00}, // ¦

{0x00, 0x00, 0x41, 0x77, 0x08, 0x00}, // }

{0x00, 0x08, 0x04, 0x08, 0x08, 0x04}, // ~

/* end of normal char-set */

/* put your own signs/chars here, edit special_char too */

/* be sure that your first special char stand here */

{0x00, 0x3A, 0x40, 0x40, 0x20, 0x7A}, // ü, !!! Important: this must be special_char[0] !!!

{0x00, 0x3D, 0x40, 0x40, 0x40, 0x3D}, // Ü

{0x00, 0x21, 0x54, 0x54, 0x54, 0x79}, // ä

{0x00, 0x7D, 0x12, 0x11, 0x12, 0x7D}, // Ä

{0x00, 0x39, 0x44, 0x44, 0x44, 0x39}, // ö

{0x00, 0x3D, 0x42, 0x42, 0x42, 0x3D}, // Ö

{0x00, 0x02, 0x05, 0x02, 0x00, 0x00}, // °

{0x00, 0x7E, 0x01, 0x49, 0x55, 0x73}, // ß

{0x00, 0x7C, 0x10, 0x10, 0x08, 0x1C}, // µ

{0x00, 0x30, 0x48, 0x20, 0x48, 0x30}, // ω

{0x00, 0x5C, 0x62, 0x02, 0x62, 0x5C} // Ω

};


// 顯示字符的功能

void oled_display_char(uint8_t c) {

    i2c_start();

    i2c_write_byte(OLED_ADDRESS << 1);  // 發送地址

    i2c_write_byte(0x40);               // 控制位元 (0x40 表示後面是數據)

    

    // 發送 5x7 字符數據

    c = c - ' ';

    for (uint8_t i = 0; i < 6; i++) {

      i2c_write_byte(font5x7[c][i]);

    }

  

    // 6th byte is space between characters

    //i2c_write_byte(0x00);

  

    i2c_stop();

  

}


// 顯示字符串

void oled_display_string(uint8_t x, uint8_t y, const char* str) {

  oled_command(0xB0 + y);  // 設置頁地址

  oled_command(0x00);         // 設置低列地址

  oled_command(0x10 + x);         // 設置高列地址

    

  while (*str) {

    oled_display_char(*str);

    /*

    if (*str == 'H') oled_display_char(0);

    if (*str == 'E') oled_display_char(1);

    if (*str == 'L') oled_display_char(2);

    if (*str == 'O') oled_display_char(3);

    if (*str == '#') oled_display_char(4);

    */

    str++;

  }

}


void setup() {

  Serial.begin(9600);

  delay(100);


  //setup2();


  pinMode(OLED_SDA, OUTPUT);

  pinMode(OLED_SCL, OUTPUT);

  

  // 初始化 OLED

  oled_init();

  

  // 測試顯示,打開所有像素

  //oled_command(0xA5);  // 這個指令讓所有像素點亮


  // 清空顯示屏

  oled_clear();


  // 顯示 "HELLO"

  oled_display_string(0, 0, "12345678901234567890");

  oled_display_string(0, 1, "ABCDEFGHIJKLMNOPQRST");

  oled_display_string(0, 2, "abcdefghijklmnopqrst");

  oled_display_string(0, 3, "!@#$%^&*()_+-=,./;'?");

  oled_display_string(0, 7, "H####");

}


void loop() {

  // 空的 loop

}


/*

#include <Wire.h>


void setup2() {

  Wire.begin();

  Serial.begin(9600);

  Serial.println("\nI2C Scanner");

  for (uint8_t address = 1; address < 127; address++) {

    Wire.beginTransmission(address);

    if (Wire.endTransmission() == 0) {

      Serial.print("I2C device found at address 0x");

      if (address < 16) {

        Serial.print("0");

      }

      Serial.println(address, HEX);

    }

  }

  Serial.println("Done");

}

*/

2022年8月23日 星期二

OLED 圖形顯示接口與 NodeMCU

 

介紹

OLED顯示模塊

OLED顯示模塊

上圖所示的 OLED 模塊是市場上非常流行的模塊。

市場上有許多該模塊的變體,具有不同的分辨率、通信協議或像素顏色。

它們不需要背光,因為顯示器會產生自己的光。因此,它們消耗的功率更少。市場上有基於 I2C 和 SPI 的 OLED 模塊。

有關 OLED 顯示結構及其命令的更多信息,請參閱SD1306 OLED 顯示

NodeMCU 可以使用 I2C 通信協議與該模塊進行通信。要了解有關 NodeMCU 中 I2C 功能的更多信息,請參閱 NodeMCU I2C with ESPlorer IDE或NodeMCU I2C with Arduino IDE

 

引腳說明

OLED顯示引腳

 

上圖顯示了一個基於 128x64 I2C 的 OLED 模塊。

 

VCC:這是模塊的電源引腳。可向該引腳提供 3.3V 或 5V 電源為顯示器供電。

GND: 這是模塊的接地引腳。

SCL 和 SDA: 這些是 I2C 接口的串行時鐘和串行數據引腳。

 

接口圖

OLED 與 NodeMCU 的接口

連接 OLED 顯示器與 NodeMCU

例子

在 128x64 OLED 顯示模塊上顯示基於延遲功能的計時器。

 

首先,按照上面的接口圖進行連接。

我們可以用 Lua 腳本或 C/C++ 語言為 NodeMCU DevKit 編寫代碼。我們使用 ESPlorer IDE 用 Lua 腳本編寫代碼,使用 Arduino IDE 用 C/C++ 編寫代碼。要了解更多信息,請參閱 使用 ESPlorer IDE 開始使用 NodeMCU(對 NodeMCU 使用 Lua 腳本)和使用 Arduino IDE 開始使用 NodeMCU(對 NodeMCU 使用基於 C/C++ 語言的 Arduino 草圖)。

 

讓我們首先使用 ESPlorer IDE 為 NodeMCU 編寫 Lua 腳本

 

NodeMCU 的 Lua 腳本

sda = 2 -- SDA Pin
scl = 1 -- SCL Pin

s=0
m=0
h=0
         
function init_OLED(sda,scl) --Set up the u8glib lib
    sla = 0x3C
    i2c.setup(0, sda, scl, i2c.SLOW)
    disp = u8g.ssd1306_128x64_i2c(sla)
    disp:setFont(u8g.font_6x10)
    disp:setFontRefHeightExtendedText()
    disp:setDefaultForegroundColor()
    disp:setFontPosTop()
    --disp:setRot180()           -- Rotate Display if needed
end

function write_OLED() -- Write Display
    disp:firstPage()
    repeat
     disp:drawStr(50, 10, "Timer")
     disp:drawStr(40, 30,  string.format("%02d:%02d:%02d",h,m,s))
     disp:drawStr(20, 50, "ElectronicWings")
    until disp:nextPage() == false
end

-- Main Program 
init_OLED(sda,scl)

tmr.alarm(0, 1000, 1, function() -- Every second increment clock and display
    s = s+1
    if s==60 then
     s=0
     m=m + 1
    end
    if m==60 then
     m=0
     h=h + 1
    end
    if h==13 then
     h=1
    end
    write_OLED()
end)

 

現在讓我們使用 Arduino IDE 為 NodeMCU 編寫一個 Arduino 草圖。

在這裡,我們使用 SSD1306 的 Adafruit 庫。這個庫在 GitHub 上可用。

從這裡下載 Adafruit ssd1306 庫。

注意:此庫僅適用於單色顯示器。

 

我們將需要 Adafruit GFX 庫以及我們將在顯示屏上顯示的模式和文本。

從這裡下載 Adafruit GFX 庫。

 

提取這些庫並將它們添加到 Arduino IDE 的庫文件夾路徑中。

有關如何將自定義庫添加到 Arduino IDE 並使用其中的示例的信息,請參閱 基礎部分中的將庫添加到 Arduino IDE。

 

SSD1306 的 Adafruit 庫帶有 4 個示例草圖。您可以直接將其中一個草圖(取決於您的設備和支持的通信協議)上傳到您的設備。

 

在這裡,我們根據兩個庫中定義的函數編寫了自己的示例草圖。

 

注意:如果您使用示例草圖,請確保使用適當的 I2C 設備地址。在 Adafruit 庫中,使用的設備地址是 0x3C 或 0x3D。使用這些地址之一。您必須找出哪一個是您設備的地址。該地址不是 8 位設備地址;它是由 7 位組成的地址,不考慮讀取或寫入位。嘗試這些地址之一,如果它不起作用,請使用另一個。

 

用於 NodeMCU 的 Arduino 草圖

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET D5
/* Object named display, of the class Adafruit_SSD1306 */
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

uint8_t s = 0, m = 0, h = 0;

void setup()   {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); /* Initialize display with address 0x3C */
  display.clearDisplay();  /* Clear display */
  display.setTextSize(1);	/* Select font size of text. Increases with size of argument. */
  display.setTextColor(WHITE);	/* Color of text*/
}

void loop() {
  updateWatch();/* Every second increment clock and display */
  delay(1000);
}

void updateWatch() {
  s = s + 1;
  if (s == 60) {
    s = 0;
    m = m + 1;
  }
  if (m == 60) {
    m = 0;
    h = h + 1;
  }
  if (h == 13)
    h = 1;

  writeOLED();
}

void writeOLED(){
  char time[30];
  display.clearDisplay();  /* Clear display */
  sprintf(time, "%02d:%02d:%02d", h, m, s);
  drawStr(50, 10, "Timer");
  drawStr(40, 30, time);
  drawStr(20, 50, "ElectronicWings");
  display.display();
}

void drawStr(uint8_t x, uint8_t y, char* str){
  display.setCursor(x, y);  /* Set x,y coordinates */
  display.println(str);
}

 

筆記:

如果在 Arduino IDE 中編譯程序時出現以下錯誤

adafruit ssd1306 驅動庫錯誤

 

然後它會告訴我們我們選擇了不正確的顯示高度。

128x64 顯示器有 64 高,

128x32 顯示器有 32 高,

因此,我們需要選擇合適的顯示器。

 

我們可以在 Adafruit ssd1306 庫文件夾中的 Adafruit_SSD1306.h 文件中選擇顯示幀大小(我們之前已將其複製到 Arduino 庫文件夾中)。

 

只需取消註釋我們正在使用的正確顯示行並註釋掉其他人。這裡我們使用的是 128x64 幀大小的顯示器,因此我們取消了它的註釋,如下圖所示。

在 adafruit 庫中選擇顯示類型

 

視頻

 


資料來源:https://www.electronicwings.com/nodemcu/oled-graphic-display-interfacing-with-nodemcu