GPIO接続のLCDへ表示する(基本的な接続)


Raspberry Piを使って、i2c接続のLCDモジュールへの表示はいくつか紹介されていますが、
GPIO接続のLCDモジュールへの表示に関するページはなかなか見つからなかったので紹介します。
使用するLCDはHD44780のコントローラを搭載した一般的な16文字2行表示のLCDです。
秋月電子で売られているSUNLIKE社製のSC1602BSLB(バッ クライト付き)/SC1602BS*B(バッ クライト無し)などもこれに該当します。
RaspBerryPiのGPIOは3.3V仕様ですが、入力が無いので5V仕様のLCDでも問題なく使うことができます。
同じくSUNLIKE社製3.3V駆動のSC1602BBWBも、 電源電圧だけ変更すれば動きます。


【RaspberryPIとの結線】

こ のページを参考にして結線を行いましたが、RSとEnable Signalのピン番号は変更しています。
4ピン接続と8ピン接続の例が載っていますが、私は結線が楽な4ピンを選びました。
注意する点として、LCDによっては1番ピンがVss(GND)、2番ピンがVdd(供給電源)のものと、
1番ピンがVdd(供給電源)、2番ピンがVss(GND)のものがありますので、ここはお使いのLCDのデータシートで確認してください。
私が使用したLCDは1番ピンがVss(GND)、2番ピンがVdd(供給電源)で、バックライトは15番と16番か ら供給しますので結線は以下のよ うになります。
コントラスト調整用には10KΩの可変抵抗器を使いました。


LCDのピン番号 LCDのピンのSymbol Raspberryのピン番号 WringPiでの番号 GPIOの番号
1 Vss(GND) GND

2 Vdd(※1) 3V3/5V

3 Vo(Contrast Adj)(※2) 可変抵抗器

4 RS(Register Select) 16 4 23
5 R/W(Read/Write) GND

6 Enable Signal(Clock) 18 5 24
7 DB0 N/C

8 DB1 N/C

9 DB2 N/C

10 DB3 N/C

11 DB4 11 0 17
12 DB5 12 1 18
13 DB6 13 2 27
14 DB7 15 3 22
15 LED-A(※1) 3V3/5V

16 LED-K(※3) GND


(※1)駆動電圧が3.3Vのモジュール(低電圧版)と5Vのモジュールが有ります。モジュールに合わせて電源を供給してください。5Vモジュー ルは3.3V給電では動きません
(※2)個体差があるかもしれませんがGNDでも大丈夫なぐらい低電圧です。
(※3)カソードは一般的に英語で「Cathode」ですが、LEDに関してはLED-K(ドイツ語のKathode)が使われます。

【ライブラリのインストール】

Raspberry PiにWiringPiライブラリをインストールします。
ライブラリのURLが昔と変わりました。
$ git clone https://github.com/WiringPi/WiringPi
$ cd WiringPi
$ ./build
$ gpio -v
gpio version: 2.46
Copyright (c) 2012-2018 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty

Raspberry Pi Details:
  Type: Model B, Revision: 02, Memory: 512MB, Maker: Sony
  * Device tree is enabled.
  *--> Raspberry Pi Model B Rev 2
  * This Raspberry Pi supports user-level GPIO access.

【ソースコード】

こ のページを参考に以下のコード(lcd-gpio.c)を書きました。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <lcd.h>

int main(int argc, char **argv) {
    int fd;
    int c;
    int i;

    if(wiringPiSetup() == -1) {
        printf("Setup Fail\n");
        exit(1);
    }
    fd = lcdInit(2,16,4,4,5,0,1,2,3,0,0,0,0);

    lcdClear(fd);
    lcdPuts(fd,"ABCDEFGHIJKLMNOP");
    lcdPosition(fd,0,1);
    lcdPuts(fd,"abcdefghijklmnop");

    while (1){
        printf("0:lcdDisplay test\n");
        printf("1:lcdCursor test\n");
        printf("2:lcdBlink test\n");
        printf("q:End\n");
        c=getchar();
        if(c == 'q') break;

        if(c == '0') {
            for(i=0;i<10;i++) {
                lcdDisplay(fd,0);
                sleep(1);
                lcdDisplay(fd,1);
                sleep(1);
            }
        }

        if(c == '1') {
            for(i=0;i<16;i++){
                lcdPosition(fd,i,0);
                lcdCursor(fd,1);
                sleep(1);
            }
            lcdCursor(fd,0);
        }

        if(c == '2') {
            for(i=0;i<16;i++){
                lcdPosition(fd,i,1);
                lcdCursorBlink(fd,1);
                sleep(1);
            }
            lcdCursorBlink(fd,0);
        }
    }
    lcdClear(fd);
}

悩んだのはリンク方法です。
上記のページではWiringPiのライブラリ(WiringPi Library)にはLCDライブラリが含まれてるように見えますが、
LCDライブラリは「WiringPi Devices Library」に含まれていて、これを使うときには下線部分の指 定が 必要になります。
$ cc -o lcd-gpio lcd-gpio.c -lwiringPi -lwiringPiDev

実行するとLCDに文字が表示され以下のメニューが表示されますので選んでください。
$ sudo ./lcd-gpio
0:lcdDisplay test
1:lcdCursor test
2:lcdBlink test
q:End



wiringPiSetup()をwiringPiSetupGpio()に変更すると、GPIO番号でピン番号を指定することができます。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <lcd.h>

int main(int argc, char **argv) {
    int fd;
    int c;
    int i;

    if(wiringPiSetupGpio() == -1) {
        printf("Setup Fail\n");
        exit(1);
    }
    fd_lcd = lcdInit(2,16,4,23,24,17,18,27,22,0,0,0,0);

    lcdClear(fd);
    lcdPuts(fd,"ABCDEFGHIJKLMNOP");
    lcdPosition(fd,0,1);
    lcdPuts(fd,"abcdefghijklmnop");

    while (1){
        printf("0:lcdDisplay test\n");
        printf("1:lcdCursor test\n");
        printf("2:lcdBlink test\n");
        printf("q:End\n");
        c=getchar();
        if(c == 'q') break;

        if(c == '0') {
            for(i=0;i<10;i++) {
                lcdDisplay(fd,0);
                sleep(1);
                lcdDisplay(fd,1);
                sleep(1);
            }
        }

        if(c == '1') {
            for(i=0;i<16;i++){
                lcdPosition(fd,i,0);
                lcdCursor(fd,1);
                sleep(1);
            }
            lcdCursor(fd,0);
        }

        if(c == '2') {
            for(i=0;i<16;i++){
                lcdPosition(fd,i,1);
                lcdCursorBlink(fd,1);
                sleep(1);
            }
            lcdCursorBlink(fd,0);
        }
    }
    lcdClear(fd);
}

HD44780のデータシートを見ると、2行表示の場合、DDRAMには40文字*2行まで格納できる様ですが、
WinringPiのLCD関数では17文字目以降を表示することができません。
17文字以上の文字を表示する場合、以下の様に自力でスクロールする必要が有ります。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>
#include <lcd.h>

/*
 cc -o lcd-gpio2 lcd-gpio2.c -lwiringPi -lwiringPiDev
*/

#define INTERVAL 400

int main(int argc, char **argv) {

        if(wiringPiSetup() == -1) {
                printf("Setup Fail\n");
                exit(1);
        }
        int fd_lcd;
        fd_lcd = lcdInit(2,16,4,4,5,0,1,2,3,0,0,0,0);

        const char *message = "Wiring Pi by Gordon Henderson. HTTP://WIRINGPI.COM/";

        lcdClear(fd_lcd);
        lcdPosition(fd_lcd,0,0);
        lcdPuts(fd_lcd,"SCROLLING");

        char buf [32]  = {0};
        int timer = millis();
        int position = 0;
        while (1) {
                if (millis () < timer) continue;
                lcdPosition(fd_lcd,0,1);
                strncpy (buf, &message [position], 16);
                lcdPuts(fd_lcd,buf);
                printf("position=%d\n",position);
                timer = millis () + INTERVAL;
                position++;
                if (position > (strlen(message)-16)) break;
        }
        sleep(5);
        lcdClear(fd_lcd);
}

i2c接続に比べGPIO接続の場合、たとえば20文字*4行のLCDなど、LCDの選択肢は増えますが、接続のためのワイヤーが多くなるのが欠 点です。
そこで、I/OエクスパンダICを入手して、 i2c、またはSPI経由での表示を試してみたいと思います。

続く...