デジタル差圧計は外に持っていくことを想定しているので、乾電池運用したいと考えていました。PCを持って行ってしまっては意味が無いので、液晶ディスプレイ(LCD)を使って、計測結果を表示出来るようにします。LCDは出来合いのものだし、先人達の作例も多いので、簡単に出来ると想像していましたが、なんだかんだで結構苦戦してしまいました。
LCD/AQM1602XA-RN-GBW
白黒でバックライト無しだと数百円なんですね。通信方法がパラレル通信なら最安を狙えますが、ケーブル数がちょっと多めなのでI2Cのものにしました。

改めて見るとちょっと型番が変ですね。16文字の2行なので1602っぽいですが、説明書のタイトルには1620とあります。1620だと20行もあってちょっとしたタブレットになりそうです。
これはピンのピッチを2.54mmに変換し、9本あるピンをI2Cで使う4本にまとめた上に、SDA、SCLのプルアップも選択出来る変換基板が付いています。上の写真の真ん中の基板ですね。LCDに元々ついている9本のピンは細く、間隔も1.3mm程度なので、スペースさえ許せば変換基板付きがいいですね。今回は当然自家使用なので、サイズは気になりません。
・変換基板設置

ええ、いや、まあ、確かに下手くそというのはありますが、間隔1.3mmは流石に無理筋ですよね。

はい、そうです、これは完全に言い訳ですが、はんだごてのこて先が太くて、基板上のはんだ場所2か所分くらいあります。手前の銀色の金属は1.6mmはんだ線です。普通にやると無理なので、こて先にはんだを少し乗せて、心を静めて金属部分に乗せる、という方法でやりました。3回くらいやり直したので、ちょっと変色してますね。

余分なピンを切ったら、それっぽくなりました。時すでに遅しですが、ちょっと細めのはんだごてと1mmのはんだも買いました。
上の写真の左上の凸凹入れ子にになっている2か所をはんだ付けしてショートさせることで、I2CのSDA、SCLのプルアップをすることが出来ます。これは便利ですね。
・配線

マイコンはXIAO ESP32C3を使っています。LCDはピッタリそのままのもののFritzingが見つからなかったので、1602でI2C接続のものを使っています。I2Cなので、SDAとSCLを気圧計BMP280のラインに繋げています。LCDの入力電圧が3.3Vでも行けるような感じで書いてありましたが、3.3Vでは起動しなかったのでXIAO ESP32C3の5Vから取ることにしました。どこかに設定があったのかな。
ブレッドボードのスペースには余力があって、配線は悩まないですね。
・スケッチ
いやあ、完全に舐めてましたね。世の中の電化製品に液晶ディスプレイなんて当たり前のようにあって、なんなら単なる白黒の液晶なんてノスタルジーすら感じていたりしました。いざ自分で表示させようと思うと、なかなか大変ですね。
最初に試したのは、説明書に記載のあったサンプルスケッチですね。これは、そっくりそのままコピペすればよかったです。ただ、ブレッドボードとLCDの接触があまり良くなく、無駄に時間を費やしてしまいました。
サンプルコードは購入した秋月電子さんのページに置いてある、データシート(AQM1602XA-RN-GBW).pdfの一番最後に書いてあります。
I2C接続小型キャラクターLCDモジュール(16×2行・3.3V/5V)ピッチ変換キット: オプトエレクトロニクス 秋月電子通商-電子部品・ネット通販
動かしてみるとこんな感じ。

サンプルスケッチの一部抜粋です。全然理解が追い付いていませんが、writeData()の引数はbyte型の整数だけなんですよね。ここに気圧計モジュールHW-611の圧力値をそのまま入れても、うまくLCDに表示できませんでした。
あー、たぶん当たり前なんだろうけど、勉強が全く追い付いていないので理解不能です。
#include <Wire.h>
#define LCD_ADRS 0x3E
char moji[] ="AQM1602XA-RN-GBW";
void setup() {
Wire.begin();
init_LCD();
CGRAM();
}
void loop() {
writeCommand(0x02); // Retern Home
//タイトル文字描画
for(int i = 0; i < 16; i++) {
writeData(moji[i]);
}
//データ書き込み
void writeData(byte t_data)
{
Wire.beginTransmission(LCD_ADRS);
Wire.write(0x40);
Wire.write(t_data);
Wire.endTransmission();
delay(1);
}
このサンプルスケッチを少し弄ったりしましたが、簡単にはHW-611の気圧データを表示できなかったので、諦めてライブラリを探すことにしました。
・LiquidCrystal_I2C
検索するとすぐに引っかかってくるのはこれですね。ArduinoでAQM1602Aを用いた作例も多いので、LiquidCrystal_I2C.hさえインストールしてしまえば、もう余裕、敗北の味が知りたい、とか思っていました。いざインストールしてサンプルスケッチ”hello world”をコンパイルしてみると・・・

うーん、なにやら警告が。ArduinoIDEで警告とか初めて見ました。内容は、
「警告:ライブラリLiquidCrystal I2Cはアーキテクチャavrに対応したものであり、アーキテクチャesp32で動作するこのボードとは互換性がないかもしれません。」
というものでした。
うーん、これまた勉強が追い付いていないのですが、ESP32ってArduinoと互換があるものだと思い込んでいました。ちょっと時間が掛かるけど、arduinoIDEで開発できるし。なるほど、アーキテクチャが違うんですね。ふむふむ、で、アーキテクチャって一体な(略)。
警告通り、XIAO ESP32C3ではLiquidCrystal_I2C.hは機能しませんでした。何も表示できない、というかLCDは起動すらしていない様子。ぐぅぅ、これが敗北の味なのか。。。
・arduino_ST7032-master
もう少し調べてみると、AQM1602XA-RN-GBWに使われているコントローラIC、ST7032iに対応したライブラリを作ってくれている、オレ工房さんのサイトを見つけました。
ううう、なんてありがたいんだ。
早速使わせてもらうと、

おお!簡単に表示できた!
こちらの環境だと、コントラストは10でちょうどいいですね。
lcd.print()が使えるので、Sirial.print()と同じ感覚で表示できるはずです。
・オリジナル文字作成
LCDとかの表示で一番悩むのが温度の単位、℃、ですね。丁度いい位置の〇が無いので、Cだけとか、文字数に余裕がある時はdegreeCとかになります。AQM1602Aはオリジナルの文字を8個まで使うことができるので、作ってみることにします。
参考にしたのは、megetonさんの記事”LCDモジュールの使い方”です。
https://zenn.dev/megeton/articles/639a021f909a09
これを参考に℃の〇を作ってみます。形としては文字のマスの右上に〇を表示して、続くCとあわせて℃にする方針です。
byte degree[] = {
0b00111,
0b00101,
0b00111,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
};
lcd.createChar(0, degree);
lcd.setCursor(11,1);
lcd.write(byte(0));
スケッチはこんな感じ。LCDの一文字分は横5×縦8で表現されています。上のスケッチの0bから始まる数字が8段ありますが、それに相当しています。”0b”は”二進数の数字”という宣言ですので、そのあとの数字5個×8段ですね。右上の1になっているところを黒くする指示です。アルファベットのCと組み合わせてみるとこんな感じ。

おお!いい感じ!
この記事のサムネ(アイキャッチ画像)の顔文字の口も同じ方法で作りました。あと、カタカナやキリル文字、ギリシャ文字の一部も表示できますが、換算表で対応する番号を探さないといけないので、ちょっと面倒臭いですね。
・(単独)デジタル気圧計組み立て
既に同じブレッドボード上にある気圧計モジュールHW-611の計測結果をLCDに表示できれば、組み立て完了です。ST7032.hを使ってスケッチを修正します。修正後のスケッチはこんな感じ。
#include <Wire.h>
#define SDA D4
#define SCL D5
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp; // I2C
#include <ST7032.h>
ST7032 lcd(0x3E);
void setup() {
Wire.begin();
pinMode(SDA, INPUT_PULLUP); //D4 --SDA pin, pullup
pinMode(SCL, INPUT_PULLUP); //D5 --SCL pin, pullup
lcd.begin(16,2);
lcd.setContrast(10);
lcd.setCursor(0,0);
lcd.print("1P");
lcd.setCursor(13,0);
lcd.print("Pa");
lcd.setCursor(0,1);
lcd.print("TEMP");
lcd.setCursor(12,1);
lcd.print("C");
byte degree[] = {
0b00111,
0b00101,
0b00111,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
};
lcd.createChar(0, degree);
lcd.setCursor(11,1);
lcd.write(byte(0));
Serial.begin(115200);
while ( !Serial ) delay(100); // wait for native usb
Serial.println("BMP280 test");
unsigned status;
status = bmp.begin(0x76); // I2C address
if (!status) {
Serial.println("Could not find a valid BMP280 sensor, check wiring or "
"try a different address!");
Serial.print("SensorID was: 0x"); Serial.println(bmp.sensorID(),16);
Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n");
Serial.print(" ID of 0x60 represents a BME 280.\n");
Serial.print(" ID of 0x61 represents a BME 680.\n");
while (1) delay(10);
}
/* Default settings from datasheet. */
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
}
void loop() {
Serial.print("Temperature = ");
Serial.print(bmp.readTemperature());
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bmp.readPressure());
Serial.println(" Pa");
Serial.print("Approx altitude = ");
Serial.print(bmp.readAltitude(1013.25)); //Adjusted to local forecast!
Serial.println(" m");
Serial.println();
lcd.setCursor(3,0);
lcd.print(bmp.readPressure());
lcd.setCursor(5,1);
lcd.print(bmp.readTemperature());
delay(2000);
}
なんといっても一番最後のlcd.print()ですね。Serial.print()と全く同じように使えるので、初心者に優しい仕様になっています。
lcd上での表示位置は、列と行の番号で指定します。番号は下の図のように決まっています。左上隅が0行0列、右下隅が1行15列ですね。

スケッチの中では、setCursor(3, 0); の様に指定します。カーソルを合わせて表示、の流れなんですね。
このスケッチで起動してみると、下のような感じ。

光の反射を避けようとして斜めから写真を撮ったので、lcdの表示に影が付いてしまってぼやけて見えますが、想像通りの物が出来ました。
ところで、今はまだPCからのUSB給電で動かしていますが、乾電池運用を考えているのでとりあえず手持ちのモバイルバッテリーに繋ぎなおしてみました。すると、

あ、あれ?
気圧計モジュールからの計測値が表示されない。。。
これはあせりました。スケッチを作っていたノートPCから給電を受けている限りはちゃんと測定値が表示されますが、モバイルバッテリやコンセントに繋いだUSB充電器、別のPCからのUSB給電では表示されませんでした。
なにかマイコンがノートPCとやり取りしてるのかと思いましたが、再起動しても変わらないし、機内モードにしても変わらないし。
丸一日困っていましたが、ライブラリを頂戴したオレ工房さんのページのコメント欄を見ると、Serialと同時使用できない環境が存在する様子。ひょっとしてこれかも、と思って、スケッチからSerialに関する部分をワイプアウトすると、

おお!モバイルバッテリでもちゃんと表示できた!
ライブラリの中身は検証できていませんが、多分Serialとコンフリクトするケースがあるんだと思います。PCのUSBに繋いでarduinoIDEのシリアルモニタとLCDは同時に表示出来るので、自動的にどこかが内部プルアップとかされているのかもしれませんね。
いずれにしても、(単独)デジタル気圧計や、この先の完成形になるデジタル差圧計は乾電池運用を予定していてPCのシリアルモニタと同時に見る必要はないので、スケッチからSerial部分削除して、次の検討に進みます。
Serial削除後のスケッチはこんな感じ。
#include <Wire.h>
#define SDA D4
#define SCL D5
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp; // I2C
#include <ST7032.h>
ST7032 lcd(0x3E);
void setup() {
Wire.begin();
pinMode(SDA, INPUT_PULLUP); //D4 --SDA pin, pullup
pinMode(SCL, INPUT_PULLUP); //D5 --SCL pin, pullup
lcd.begin(16,2);
lcd.setContrast(10);
lcd.setCursor(0,0);
lcd.print("1P");
lcd.setCursor(13,0);
lcd.print("Pa");
lcd.setCursor(0,1);
lcd.print("TEMP");
lcd.setCursor(12,1);
lcd.print("C");
byte degree[] = {
0b00111,
0b00101,
0b00111,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
};
lcd.createChar(0, degree);
lcd.setCursor(11,1);
lcd.write(byte(0));
unsigned status;
status = bmp.begin(0x76); // I2C address
/* Default settings from datasheet. */
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
}
void loop() {
lcd.setCursor(3,0);
lcd.print(bmp.readPressure());
lcd.setCursor(5,1);
lcd.print(bmp.readTemperature());
delay(2000);
}
スゴクすっきりしましたね。
ただ、消費電力が小さすぎてモバイルバッテリはオートパワーオフになってしまうので、やっぱり目指すのは乾電池運用ですね。
本当はBluetooth接続もこの回でやってしまいたかったですが、全く手が回っておらず、これからどうやるか調べるくらいなので、今回はここまで。
次回はbluetooth接続かな。








コメントを残す