LCD内の文字を動かす方法をいろいろ試してみる。(I2C版)

モジュール紹介

どうもメガネです。

今回はArduinoにてよく使われる表示器「LCDディスプレイモジュール」の最安商品の紹介と、

ちょっと変わった表示をする方法を説明したいと思います。

現行(20210907現在)での最安商品のリンク等は一番下に作成したので、そちらだけを見たい人は以下の目次から参照してください。

LCDディスプレイについて

少しだけ超簡単な紹介をしておきます。

LCDディスプレイモジュールは以下のような小型のディスプレイで、Arduinoと接続して簡単に文字等を表示させることができます。

価格が液晶のくせにクソ安いのが特徴です。

小型のLCDディスプレイと比べると金属製カウルが付いているので、大きさはその分大きくなります。

基盤にはネジ穴が付いているので固定には困らないと思います。

Arduionoとの配線は以下のサイト等、多数のサイトにて解説されているので詳細は省きます。

I2Cモジュールを必ず使おう

必ず、とは言ってますが、なくても使用することはできます。

ですがI2Cの通信をビット単位で操作したいというマニアや制御ハード製作をしたいというマニア以外はやめましょう。

ArduinoのI/Oポートと配線用コードが無駄になります。

無駄、は言い過ぎかもしれませんがまぁ、それくらい便利ってことです。
数十本の必要なコードが4本まで減ります。

今回は以下の商品を購入しました。

I2Cモジュールを最初からLCDに接続して売っているタイプのものは
コスパがだいぶ悪い傾向にあります。

2,3コ持っていたところで別に困るものでもないので私は複数個ストックしておいてます。

プログラム

ArduinoとLCDディスプレイを表示した後に最低限設定として記述しなければならないコードを以下に載せます。

使用したライブラリは<LiquidCrystal_I2C.h>です。違うと動きません。

最低限必要なプログラム

#include<LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2);   //ライブラリのインクルード

void setup() {
  lcd.init();              //LCDディスプレイの初期化
  Serial.begin(9600);
}

void loop() {
  lcd.backlight();           //バックライトを点灯
  lcd.setCursor(0,0);          //カーソルを0,0にセット
  lcd.print("Hello megane!");     //表示内容
}

上記のプログラムをアップロードし、無事「Hello megane!」が表示されれば問題ないです。

ただし一発でうまくいかない、というか表示がおかしかったりされなかったりする場合が以外に多くあります。

これについてはチップの番号とアドレスに組み合わせがあるのであとで記事にまとめたいと思います。

ネットでなかなか出てこなかったコマンド

わざわざ書くまでもないかもしれないんですが、探すのが大変だったのでここにメモしておきます。

そのコマンドとはLCDディスプレイのバックライトを消すコマンドです。

いやぁ、これマジでのってなかったよ。。文面を消すコマンドはのってるんですけどね。

Arduinoのライブラリの公式リファレンス見ても載ってなかったしマジで大変でした。

コマンドは

lcd.noBacklight();

です。

もともとバックライトを消すと超絶見にくいディスプレイなのでそんな使い方をする人はほとんどいないからか、なかなか出てきませんでした。

見つけたのはどっかのよくわからんデータシートだったかな?

これだけではつまらない

LCDディスプレイに文字が表示されると結構楽しいもんですが、マジで飽きます。

ただ文字を表示しているだけですからね、、

それだけではつまらないなぁ~と思いましたし、ただただ使用方法の解説記事を書いているのもつまらないので、いろいろ表示を可変させる方法を初心者なりに考えてみました。

単純なプログラムで結構いろいろと変わるので少しは用途の幅が広がるかもですね。

文字表示の際にひとつでも「あ、これやってみたかった!」というものがあればうれしいです。
(コードは無駄が多いので適宜直してください。<m(__)m>)

以下のプログラムは“void loop(){…}”の部分のみ記載しています。

文字を点滅させる

文字全体を点滅させるプログラムです。

for文で回数指定で動かします。これだと点滅中は他の動作ができません。
(そのループ内にとどまるので)

void loop() {
  char ch1[]="Passcode clear!";
  int char_count=0;
  lcd.noCursor();
  delay(3000);
  lcd.backlight();
  
  int i,n=3;
  for(i=0;i<n;i++){
    lcd.setCursor(0,0);
    lcd.print(ch1);
    delay(500);
    lcd.clear();
    delay(500);
  }
}

なにかを動かしながら表示したい場合は、static変数を使って0なら表示1ならclearなんて言う風にすればいいと思います。

文字を一文字ずつ表示していく

流れるように文字を一文字ずつ表示していくプログラムです。

ナル文字“\0”でwhile文で条件をつけられるので、最後の文字が0になるまで配列を動かします。

表示したい文字をchar型の配列に入れてやります。

void loop() {
  char ch1[]="Passcode clear!";
  int char_count=0;
  lcd.noCursor();
  delay(3000);
  lcd.backlight();
  while(ch1[char_count]){
    lcd.setCursor(char_count,0);
    lcd.print(ch1[char_count]);
    delay(200);
    char_count++;
  }  
  delay(2000);
  lcd.clear();   
}

文字の一部分だけを動かす

こういうの、やっすいおもちゃの液晶とかでよくありましたよね。

void loop() {
  lcd.noCursor();
  lcd.backlight();
  
  lcd.setCursor(0,0);
  lcd.print("Please wait");
  
  static int i=11;   //カーソルを11から開始

  
  lcd.setCursor(i,0);
  delay(300);
  lcd.print(".");
  delay(300);
  i++;
  
  if(i==14){
    i=11;
    lcd.setCursor(11,0);
    lcd.print("   ");
    delay(300);
  }
}

上記のプログラムでは文字の列のカーソルを指定し、

Please wait は空白も含めて11文字なので、0からカウントが始まる列カーソルにおいて、カーソル(11,0)が一行目の12文字目、ということになるので、

そこから「.」を表示させることで、文字列「Please wait」の後ろから上書きして表示させてます。

lcd.clear()は使わずに空白を出力している(カーソルは同じく11から)ので、消えるのは「. . .」のみになります。

関数ではなくstatic変数にしてloop内全体で回しているため、値の取得をしながら、といったことも一応できます。モーター等、別の関数に移った場合は無理ですが、、、(引数として指定すれば行けそう?)

文字を表示してその後表示した文字から順次消していく

表示した文字からフェードアウト、、みたいな感じです。

案外書かれていないんですが、
LCDディスプレイに何も表示したくないときは空白(スペース)を出力します。

void loop() {
  char ch1[]="Passcode clear!";
  int char_count=0;
  lcd.noCursor();
  delay(3000);
  lcd.backlight();
  while(ch1[char_count]){
    lcd.setCursor(char_count,0);
    lcd.print(ch1[char_count]);
    delay(100);
    char_count++;
  }  
  delay(2000);

  int i=0;
  while(i<char_count){
    lcd.setCursor(i,0);
    lcd.print(" ");
    delay(100);
    i++;    
  }
  lcd.clear();   
}

文字をディスプレイモジュールの中で流す?

ぐるぐると液晶ディスプレイの中で流します。

setCursorコマンドで最初の表示位置をずらしてもよかったんですが、それだと最初の一回きりでその後の動作がおかしくなるので他の方法を考えてみました。

 //※このプログラムは動きません。
 static int row=0;   //カーソル行用
  static int col;   //カーソル列用

  //1文字目まで表示
  lcd.setCursor(row,0);
  lcd.print(ch[word_length-1]);

  //2文字目まで表示
  lcd.setCursor(row,0);
  lcd.print(ch[word_length-1-1]);
  lcd.setCursor(row+1,0);
  lcd.print(ch[word_length-1]);

  //3文字目まで表示
  lcd.setCursor(row,0);
  lcd.print(ch[word_length-1-1-1-1]);
  lcd.setCursor(row+1,0);
  lcd.print(ch[word_length-1-1]);
  lcd.setCursor(row+1+1,0);            //→setCursor(2,0)
  lcd.print(ch[word_length-1]);

  //続く...

これを延々とやっていくわけにもいきませんねぇ、、、

と思ったんですが、案外簡単にまとまりました。以下のプログラムです。

void loop() {
  String putstring;
  String s="loading...";
  //        0123456789  10文字
  
  lcd.backlight();

  static int n_row;                   //カーソルのバイアス
  static int row=s.length()-1;        //文字数を入力、何文字目から表示するかの指標
  //Serial.println(row);
  
  lcd.setCursor(n_row,0);             //空白が入らない内はカーソル0,0からスタートする。
  putstring=s.substring(row);         //表示する文字列(row文字目以降)
  lcd.print(putstring);

  delay(200);                   //待ち時間=流れの速度
  
  if(row==0){
    n_row++;                    //rowが0になった。つまり設定文字数を全部出力したらカーソルを移動
  }else{
    row--;                      //9文字目から、8文字目から、7文字目から、、、と、移動。
  }

  if(n_row==16){                //カーソルの設定値が15文字目、つまりn_row=16で
    n_row=0;                    //lが15文字目に出力されているので、初期化してまた最初から
    row=9;
  }
  lcd.clear();                  //カーソル移動時“l”がllllloading、とならないように削除。
}

Arduinoだとloop関数がいちいち呼び出されている、ということを考えなくてはならないのでちょっとこういうところは面倒ですね。

まぁ、平行してモータを動かす、とかをやらなければfor文一つでまとまるので簡単ですが。。。

それだと「動作中」みたいな表示ができなくなるので使いどころが限られてしまいますよねぇ、、、

ひとまず完成しましたが、プログラム的に無駄が多いと思うので適宜変更してください。


案外LCDディスプレイで単純に文字を表示する以外のことをやっている人が少なかったので簡単にまとめてみました。

カーソルの動きを理解すればいろいろな表示ができるかと思いますのでやってみましょ~う。

単純なコードですが、コマンドプロンプトで表示される文字とは感動が違うなと思いました。

まとめ

文字を簡単に動かす方法は以上です。

以下にお勧めのLCDモジュールやI2Cモジュールのリンクを掲載しておきます。

参考にしてください。

中華モジュールだと正規品に比べて異様に安いのが多いですが、
それに関してはあまり心配する必要はないかと思います。

以下の記事で中華モジュールを購入する際の個人的な注意点をまとめてみました。

説明は以上になります。

読んでいただきありがとうございました。

それでは。(人”▽`)

タイトルとURLをコピーしました