見出し画像

温度湿度データをLCDに表示した際の覚書

先日センサーを壊してしまいましたが、それにもめげずいろいろいじってます。
今回はタイトル通り、温度センサーから得られたデータをLCDに表示してみたので、それらをまとめてみます。

利用したパーツ類

  • マイコン:M5Stamp Pico

  • センサー:BME280 温湿度センサー

  • LCD:OLED LCDディスプレイ 0.96in 128×64 SSD1306

その他、ブレッドボードや配線材、電源はM5Atom用を流用、、トグルスイッチとLED(抵抗入り)は特に意味はありません。付けてみたかっただけです😆
マイコンとの接続はセンサー LCDともI2Cで、G21(SDA) G22(SCL) につなげています。

プログラムに利用したライブラリ

  • センサー:Adafruit_BME280

  • LCD: LovyanGFX

これらで一通り組んでみて、LCDに表示されたもののセンサーデータが更新されない。。。LCDをはずしてシリアルモニタに出力するとちゃんと更新されてるよ???
いろいろ調べてみたところ、センサーとLCDが同じピンを使っているために、毎回センサーをリセットする必要があるようでした。
そのために、まず試してみたコードは
void loop() {
 bme.begin(0x76);
 …
}
ですが、確かにこのコードならセンサーデータが更新されます。でもbme.begin()はsetup()内で使うのがスジだと思ったので、じゃぁどうしようとAdafruit_BME280のインクルードファイルの中をのぞいてみたら、ネット上で説明されているサンプルコードには記載されていないメソッドがいっぱいあるじゃないですか。その中の bme.init() を利用してみたら、こちらの意図した通りの動きをしたので、やっと完成の目処がたちました。
あと、Twitterでつぶやいていた BMEライブラリの I2C接続時のピン指定方法は結局わからずじまいでしたが、ここは時間をかけるトコロではないので、現時点では追求はしないことにします。

完成したコード

1行目のインクルードは、本来は <M5Atom.h> とするようですが、FastLEDや本体ボタン等の不要なコードが含まれているので、 <Arduino.h> にしちゃいました。
2行目は I2C接続のお約束。
BME280 関連は、サンプルコードや公開されている方々のコードとは違い、I2C専用?ということで、 <SPI.h> <Adafruit_Sensor.h> は削除です。
LovyanGFXライブラリは不要部分は極力削除して、逆にコンストラクタ内の設定は外出しにしてみました。
メインループ内は、まずは bme.init() でセンサーをリセットして、前半はセンサーデータを変数に代入し、後半に変数データをLCDに出力します。
これを前半後半を分けずに、例えば
display.printf("温度:%2.1fC\n", bme.readTemperature());
というように、センサーデータ取得とLCD出力を混在させると、以降センサーデータを取得できません。。
ということで、書き上げたコードは以下の通りです。

#include <Arduino.h>
#include <Wire.h>

const int delayTime = 1000;					// 画面描画更新頻度

// BME280をI2C利用での設定 
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;						// I2C

// LovyanGFXでの設定 コンストラクタ内の設定は、直書きから外出しにしてみた
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#define D_PANEL_TYPE Panel_SSD1306			// 接続するパネルの型にあったインスタンスを用意
#define D_BUS_TYPE   Bus_I2C				// パネルを接続するバスのインスタンスを用意 I2Cバスのインスタンス(ESP32のみ)
const int C_I2C_PORT		=    1;			// 使用するI2Cポートを選択 (0 or 1)
const int C_PIN_SDA			=   21;			// SDAを接続しているピン番号
const int C_PIN_SCL			=   22;			// SCLを接続しているピン番号
const int C_I2C_ADDR		= 0x3C;			// I2Cデバイスのアドレス
const int C_PANEL_WIDTH		=  128;			// 実際に表示可能な幅
const int C_PANEL_HEIGHT	=   64;			// 実際に表示可能な高さ
const int C_OFFSET_ROTATION	=    0;			// 回転方向の値のオフセット 0~7 (4~7は上下反転)

class LGFX : public lgfx::LGFX_Device {		// 独自クラスをLGFX_Deviceから継承
	lgfx::D_PANEL_TYPE	_panel_instance;
	lgfx::D_BUS_TYPE	_bus_instance;

  public:
	LGFX(void) {							// コンストラクタ
		{ // I2Cバス制御設定
		auto cfg = _bus_instance.config();	// I2Cバス設定用の構造体を取得
		cfg.i2c_port    = C_I2C_PORT;
		cfg.freq_write  = 400000;			// 送信時のクロック
		cfg.freq_read   = 400000;			// 受信時のクロック
		cfg.pin_sda     = C_PIN_SDA;
		cfg.pin_scl     = C_PIN_SCL;
		cfg.i2c_addr    = C_I2C_ADDR;
		_bus_instance.config(cfg);			// 設定値をバスに反映
		_panel_instance.setBus(&_bus_instance);	// バスをパネルにセット
		}

		{ // 表示パネル制御の設定を行います。
		auto cfg = _panel_instance.config();	// 表示パネル制御設定用の構造体を取得
		cfg.panel_width      = C_PANEL_WIDTH;
		cfg.panel_height     = C_PANEL_HEIGHT;
		cfg.offset_rotation  = C_OFFSET_ROTATION;
		_panel_instance.config(cfg);
		}

		setPanel(&_panel_instance);			// 使用するパネルをセットします。
	}
};
LGFX display;								// 準備したクラスのインスタンスを作成

void setup() {
	bme.begin(0x76);
	display.init();
}

void loop() {
	bme.init();								// センサーをリセットする
	float tmp = bme.readTemperature();
	float hum = bme.readHumidity();
	float prs = bme.readPressure() / 100;
	float alt = bme.readAltitude(SEALEVELPRESSURE_HPA);

	display.setCursor(0, 0);
	display.setFont(&fonts::lgfxJapanGothic_16); // ゴシック体(8,12,16,20,24,28,32,36,40)
	display.printf("温度:%2.1fC\n湿度:%2.0f%%\n気圧:%2.0fhPa\n高度:%2.0fm\n", tmp, hum, prs, alt);

	delay(delayTime);
}

個人的には、bme.init() じゃなくて bme.update() という記述の方が好きなんですが。だからといって意図的にライブラリファイルを書き換えるのもね。。

おまけ

たまたま見つけたAdafruit_BME280のリファレンスです。すごく便利😊
http://adafruit.github.io/Adafruit_BME280_Library/html/class_adafruit___b_m_e280.html


いいなと思ったら応援しよう!