さて突然ですが、Season 1は今回で終わりです。ここまでで、フィールドでセンサーの電圧を測るという目標に、実装まで含めてたどり着いたからです。最後に、LCD(液晶ディスプレイ)に情報を表示させる方法を紹介します。フィールド用ロガーには、基本的に情報を表示するインターフェイスは不要(誰も見ていないので)ですし、その場で計測値を知りたければ、PCにつないでシリアル通信で表示するという方法をとってきました。しかし、PCをいちいちつなぐのは面倒ですし、小さなLCDに出力できると便利なこともあります。特に、センサーを地盤に埋設する前後でのオフセットの変化などを記録しておくときに便利です。
LCDにもいくつか製品があるわけですが、16文字×2行のものと20文字×4行のものが多く売っています。後者のほうが少しだけ高いですが、表示できる情報量が大きく違うので、多チャンネルのロガーに対しては後者のほうが便利なことが多いです。「LCD Arduino」など打ち込んでAmazonなどで検索してください。
左が16文字×2行、右が20文字×4行
基盤の端にたくさんの端子がありますが、ここにArduinoを直接つなぐよりも、コントローラーをつけてI2C通信で制御するのが便利です。LCDを買ったら、このコントローラーが最初からはんだ付けされている場合もありますが、別途購入して、自分でつけないといけないこともあります。
持っているのがコントローラー。安いもんです。
その後、下図のように接続してみて下さい。ここでは、アナログピンA0に入力する電圧を1秒おきにLCDに時刻とともに表示します。RTCモジュールを接続していないので、Arduinoのデフォルトの時間から始まってしまいますが(だいたい1970/1/1 0:00)、RTCを使って現在の時間を正しく表示する方法は第7回で説明しています。
以下のスケッチを使ってください。ここで、LCDのアドレスですが、製品によって異なります。0x27か0x3Fのどちらかのことが多いので試してください。これらのどちらでも動かない場合、下記「参考1」のスケッチで調べることができます。また、ここでLiquidCrystal_I2Cというライブラリが必要になりますが(ライブラリの保存については第7回参照)、以下から手に入ります。
OsoyooのHP
https://osoyoo.com/ja/2016/11/09/16x2-i2c-liquidcrystal-displaylcd-for-uno-r3-and-mega2560/
GitHub
https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
これらの場所から落としてくるLiquidCrystal_I2Cというライブラリは、名前は同じようですが、中身は少し違うようです。ここではOsoyooのものを使っていますが、おそらくどちらも同じような使い方をするはずです。
#include <Wire.h>
#include <TimeLib.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);
void setup(void)
{
/* ----- Setting up serial communication with PC ------ */
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
/* ----- Initialisation of LCD display ------ */
lcd.init();
lcd.backlight();
}
void loop(void)
{
/* Read voltage to A0 pin and convert it to [mV] */
float millivolt;
millivolt=analogRead(A0)*5000.0/1023;
/* Clear display of text from previous loop */
lcd.clear();
/* LCD 1st row: Time */
lcd.setCursor(0, 0);lcd.print(year());
lcd.setCursor(4, 0);lcd.print("/");
lcd.setCursor(5, 0);lcd.print(month());
lcd.setCursor(7, 0);lcd.print("/");
lcd.setCursor(8, 0);lcd.print(day());
lcd.setCursor(10, 0);lcd.print(" ");
lcd.setCursor(11, 0);lcd.print(hour());
lcd.setCursor(13, 0);lcd.print(":");
lcd.setCursor(14, 0);lcd.print(minute());
lcd.setCursor(16, 0);lcd.print(":");
lcd.setCursor(17, 0);lcd.print(second());
/* LCD 2nd row: Voltage */
lcd.setCursor(0, 1);lcd.print(millivolt);
lcd.setCursor(6, 1);lcd.print("mV");
delay(1000);
}
ここで、lcd.setCursorという関数でlcd.setCursor(0, 0)などとしてカーソル位置(文字開始位置)を決めますが、0列0行から数えることに注意してください。20文字4行のLCDなら、(19, 3)が最後の文字ということになります。
このように表示されましたか?
参考1
Osoyooさんが公開している、I2C機器のアドレスを探すスケッチです。アドレスを知りたいI2C機器をつないで走らせてみて下さい。PCのシリアルモニタにアドレスが表示されます。
/* this program is to detect IC2 device connected to Arduino
* project tutorial see http://osoyoo.com/?p=72
*/
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknow error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}
参考2
このOsoyooさんのページにはLCDの使い方が詳しく書いてあります。おそらく日本語のうまい中国人?が書いたと思われるので微妙な日本語ですが、わかりやすいです。
https://osoyoo.com/ja/2016/11/09/16x2-i2c-liquidcrystal-displaylcd-for-uno-r3-and-mega2560/
参考3
LCDのコントローラーにはポテンショメーターがついていて、+ドライバーで回すとバックライトの輝度を変えられます。あれ、つかない?と思ったら、単にディスプレイのコントラストが低くて見えていなかっただけ、ということがあるので、回してみてください。また、私の持っているLCDは、3.3V系では薄すぎて見えません。5Vで動かす必要があります。Arduino Pro Mini 3.3Vモデルにも、RAW(3.3Vに下げてから入力する端子)ではなくVcc(与えた電圧をそのままかける端子)に無理やり5V流して(不思議なことに、壊れたことがありません)使わないと、表示が見えません。