ArduinoとBME280、OLED、u8gで作る日本語表示の気圧・温湿度計

Arduino Uno Rev3とBME280センサ、SSD1309搭載の2.42インチOLED(有機ELディスプレイ)で作った気圧・温湿度計の表示画面をu8g.drawXBMP()で日本語表記するスケッチ(プログラム)作成時のメモです。

ArduinoとBME280、OLED、u8gで作る日本語表示の気圧・温湿度計
OLEDは黒色がくっきりで表示が鮮明、斜めからも良く見えます  
目次

準備したパーツ

昨年作った気圧・温湿度計の「ESP32-DevkitC」を「Arduino Uno Rev3」に置き換えました。ArduinoのI2C信号レベルに合わせて5Vから3.3Vへの双方向電圧レベル変換とU8glib.h対応のスケッチ修正を行います。

あわせて読みたい
ESP32-DevKitCと DS3231を使ったRTC時計& BME280を使った温湿度・気圧計を20文字x4行LCDに表示:環境モ... ESP32-DevKitCとRTCモジュールDS3231を使ったNTP時刻合わせLCD時計に、BOSCH社のBME280センサを使った温湿度・気圧計モジュールをI2C接続して20文字X4行のLCDモジュール...

OLEDの仕様、集めたパーツ

ネット通販で集めたOLEDの仕様です。サイズ、発光色の異なる2個で試しました。

#サイズ
発光色
解像度接続方式(I2Cアドレス)ドライバーIC電源電圧(V)
12.42インチ
黄色
128×64I2Cに設定変更(0x3C)
※デフォルトはSPI
SSD13093.3
20.96インチ
青色
128×64I2C(0x3C)SSD13063.3〜5.0

OLED以外のパーツです(No.1、2は秋月電子通商、他はAmazon)。モジュールの電源電圧とI2Cの電圧レベルは3.3Vで統一です。ArduinoのI2C電圧レベルは5Vなので双方向電圧レベル変換モジュールを入れて3.3Vにしています。

#パーツ個数
1Arduino Uno Rev31
2I2Cバス用双方向電圧レベル変換モジュール(PCA9306)
プルアップ抵抗付き(1kΩx4個)
1
3BME280 温湿度・気圧センサーモジュール
Vin、I2Cレベル変換回路付き
1
4サンハヤト ニューブレッドボード SAD-1011
5ジャンパーワイヤ(オス-オス、メス-オス)適量
6USBケーブル(USB A オス to B オス、PC接続用)1
(手持ち)

大型のOLEDは消費電流も増えます。Arduino Unoのバージョンによっては3.3V出力が不足するかもしれません。Uno Rev3は3.3VのレギュレータとしてLP2985-33DBVRを搭載しているのでマージンがあったものと思います。

今回購入したBME280モジュールは基板裏面に電源電圧Vccのレギュレータ(LDO:Low Dropout)と I2Cの電圧レベル変換回路を実装しているので、5V系(Arduinoなど)と3.3V 系(ESP32-DevkitCなど)のどちらとも直接つないで使えます。
このモジュールのデフォルトのI2Cアドレスは0x76です。

BME280センサモジュール
BME280センサモジュール基板の裏面(左:VccとI2Cのレベル変換回路)と表面(右)

2.42インチOLED(有機ELディスプレイ)をSPI接続からI2C接続に変更

購入した2.42インチOLED(発光色は黄色)はSPI接続がデフォルトでした。転送速度はSPIが高速ですが、気圧・温湿度計や時計などへの利用なので配線数が少ないI2C接続に変更しました。

あわせて読みたい
2.42インチOLED(有機ELディスプレイ)をSPI接続からI2C接続に変更 ネット通販で購入したSSD1309搭載の2.42インチOLED(有機ELディスプレイ)の接続インターフェースを基板裏面のランドパターンを使ってSPIからI2Cに変更した際のメモです...

ブレッドボード上で結線

モジュール間の結線は、I2Cの2線(SCL、SDA)と電源の2線(3.3V、GND)の4線なので容易です。Arduino Uno Rev3とブレッドボード上に配置した双方向電圧レベル変換モジュール、BME280モジュール、OLEDを4色に色分けしたジャンパーワイヤでつないでいきます。

それぞれのOLED単体でも動作しますが、今回両方のOLEDを同じI2CアドレスのままI2Cバスにつないで、一つのスケッチで同時表示しています。

Arduino+BME280+OLED気圧・温湿度計の結線図
Arduino+BME280+OLED気圧・温湿度計の結線図
ArduinoとBME280、OLED、u8gで作る日本語表示の気圧・温湿度計
日本語形式で表示する気圧・温湿度計  

OLED表示のスケッチ、漢字は16×16ピクセルのHEXデータをu8g.drawXBMP()で描画

OLEDモジュール表示に必要なライブラリ「U8glib.h」は、Arduino IDEメニューの ツール –> ライブラリの管理 からライブラリマネージャで「U8glib」を検索してインストールします。

u8g.setFont()で使うフォント見本は fontsize | olikraus/u8glib を参考にさせていただきました。今回は英数字の表示用フォントとして「u8g_font_helvR08」と「u8g_font_fub17」を使っています。u8g_font_helvR08は、16×16ピクセルでは表現が難しかった(hpa)表示に使っています。

気圧・温湿度計で使った漢字と記号は「気、圧、温、湿、度、(℃)、(%)」と少ないので、メモリ消費を抑えるために、利用する特定の文字のみをHEXデータで表示します。これらの漢字と記号は画像(BMPファイル)から変換した16×16ピクセルのHEXデータをu8g.drawXBMP()で描画します。

最大32256バイトのフラッシュメモリのうち、スケッチが25710バイト(79%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が763バイト(37%)を使っていて、ローカル変数で1285バイト使うことができます。

記号や漢字のBMPファイルは、Windows標準アプリのペイント3Dで100×100ピクセル程度で作った後、キャンパスを16×16ピクセルに変更して圧縮します。このBMPファイルをHEXデータに変換します。HEXデータへの変換にはProgramResource.netサイトの「nfBmptoHex.exe」を利用させていただきました。

arduino_bme280_oled.ino  ※ここをクリックするとコード表示を開閉できます。
#include <Wire.h>
#include <U8glib.h>  // U8gライブラリ
#include <Adafruit_Sensor.h>  // https://github.com/adafruit/Adafruit_Sensor
#include <Adafruit_BME280.h>  // https://github.com/adafruit/Adafruit_BME280_Library

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST);
Adafruit_BME280 bme;

float temp;
float pressure;
float humid;

// 漢字画像(BMP)から変換したHEXデータ
const unsigned char kii_bmp[] PROGMEM = {0x08, 0x00, 0x0C, 0x00, 0xFC, 0x3F, 0x06, 0x00, 0xFA, 0x1F, 0x00, 0x00, 0xFE, 0x1F, 0x00, 0x10, 0x04, 0x12, 0x1C, 0x13, 0x30, 0x11, 0xE0, 0x11, 0x60, 0x93, 0x18, 0xB6, 0x0E, 0xE4, 0x00, 0x60, };
const unsigned char atu_bmp[] PROGMEM = {0x00, 0x00, 0xFC, 0x7F, 0x06, 0x00, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0xF6, 0x7F, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0xF9, 0x7F, 0x00, 0x00, };
const unsigned char onn_bmp[] PROGMEM = {0x00, 0x00, 0xE2, 0x1F, 0x24, 0x20, 0x24, 0x20, 0xE0, 0x3F, 0x22, 0x20, 0xE4, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x3F, 0x94, 0x24, 0x94, 0x24, 0x96, 0x24, 0x92, 0x24, 0xFA, 0x7F, 0x00, 0x00, };
const unsigned char doo_bmp[] PROGMEM = {0x00, 0x00, 0x00, 0x01, 0xF8, 0x7F, 0x44, 0x08, 0x44, 0x08, 0xF4, 0x7F, 0x44, 0x08, 0xC4, 0x0F, 0x04, 0x00, 0xF4, 0x1F, 0x64, 0x10, 0xC4, 0x18, 0x00, 0x07, 0x82, 0x0F, 0x78, 0x70, 0x00, 0x00, };
const unsigned char stu_bmp[] PROGMEM = {0x00, 0x00, 0xC0, 0x3F, 0x24, 0x20, 0x28, 0x20, 0xE0, 0x3F, 0x22, 0x20, 0xE4, 0x3F, 0x00, 0x05, 0x20, 0x25, 0x20, 0x25, 0x28, 0x25, 0x04, 0x25, 0x44, 0x05, 0x06, 0x0D, 0xF0, 0x7F, 0x00, 0x00, };
const unsigned char pac_bmp[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x58, 0x8A, 0x4C, 0x8A, 0x46, 0x8B, 0x82, 0x71, 0x81, 0x81, 0x8E, 0xC3, 0x92, 0x42, 0x93, 0x22, 0x53, 0x34, 0x4C, 0x00, 0x00, 0x00, 0x00, };
const unsigned char dig_bmp[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x3A, 0x40, 0xAA, 0x47, 0x7A, 0x48, 0x63, 0x80, 0x21, 0x80, 0x21, 0x80, 0x23, 0xC0, 0x62, 0x50, 0xC2, 0x4C, 0x82, 0x47, 0x04, 0x20, 0x00, 0x00, };

void setup(void) {
   u8g.setColorIndex(1);
   u8g.setContrast(0);  // 明るさも多少変わる(0~255)@2022-05-19追加
 bool status;
 status = bme.begin(0x76);
 while (!status) {
 Serial.println("BME280 sensorが使えません");
 delay(1000);
 }
}

void loop() {
  u8g.firstPage();
  do {   
// BME280センサ
 temp=bme.readTemperature();
 pressure=bme.readPressure() / 100.0F;
 humid=bme.readHumidity(); 
// OLECD表示
 u8g.drawXBMP( 0, 1, 16, 16, kii_bmp);
 u8g.drawXBMP(16, 1, 16, 16, atu_bmp);
u8g.setFont(u8g_font_helvR08);
  u8g.setPrintPos(33,14);
  u8g.print("(hPa)");
u8g.setFont(u8g_font_fub17);
  u8g.setPrintPos(65,17);
  u8g.print(pressure,0);  // 気圧
 u8g.drawXBMP( 0, 24, 16, 16, onn_bmp);
 u8g.drawXBMP(16, 24, 16, 16, doo_bmp);
 u8g.drawXBMP(34, 24, 16, 16, dig_bmp);
  u8g.setPrintPos(65,39);
  u8g.print(temp,1);  // 気温
 u8g.drawXBMP( 0, 48, 16, 16, stu_bmp);
 u8g.drawXBMP(16, 48, 16, 16, doo_bmp);
 u8g.drawXBMP(34, 48, 16, 16, pac_bmp);
  u8g.setPrintPos(65,63);
  u8g.print(humid,1); // 湿度
      } while ( u8g.nextPage() );
delay(1000);
}
よかったらシェアしてね!
  • URLをコピーしました!
目次