Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What is going on with this article?
@otesho1

RaspBerryPi3でIIC/I2C 1602シリアル液晶モジュールに文字を表示する (Pi4j)

\def\textlarge#1{%
  {\rm\Large #1}
}
\def\textsmall#1{%
  {\rm\scriptsize #1}
}

1、RaspBerryPi3を購入

  最近、遅ればせながら「RaspBerry Pi 3 Model B」と入門キット※1を購入しました。
 Pi4Jを使ってセット内の「IIC/I2C 1602シリアル液晶モジュール」へ文字を表示しようとして
 なかなかうまくいかず、大変だったので情報を残します。

 注意
 ・英数字しか表示出来ません。
 ・私は電子機器については電圧=抵抗×電流がわかる程度の全くの素人です。

$\textsmall{  ※1「Kuman 35個 Raspberry Piに適用 初心者 電子工作 1602液晶ディスプレイ+温度/湿度センサ+BMP180デジタル気圧センサー}$
$\textsmall{   +HC-SR501赤外線モーションセンサモジュール 子供遊び Raspberry Pi 3 2 model B A A+ + に対応 電子工作入門キット ラズベリーパイ K71」}$

2、Pi4JでLCDに文字を表示する

 本題に入ります。普段javaを使用しているのでPi4Jで表示処理を行います。

 (1)IIC/I2C 1602シリアル液晶モジュール

  液晶画面(QC1602Aだと思われる)とI2C通信モジュール(PCF8574と思われる)で構成されている。

  ①液晶画面(QC1602Aだと思われる)
   表
   image.png
   裏
   image.png

  ②I2C通信モジュール(PCF8574と思われる)
  image.png

 (2)ラズパイとLCDの接続

  下記のように接続します。
  ①全体画像
  image.png
  ②詳細画像
  image.png

 (3)ラズパイの設定

  I2C通信を有効にします。
  image.png

 (4)デバイスアドレスを取得

  ラズパイのターミナルで下記コマンドを実行します。
  ①コマンド:sudo i2cdetect 1
  image.png

  ②結果よりデバイスアドレス「3f」が取得できました。
    0 1 2 3 4 5 6 7 8 9 a b c d e f
   00: -- -- -- -- -- -- -- -- -- -- -- -- --
   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3f
   40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   70: -- -- -- -- -- -- -- --

 (5)実行プログラム

  下記のソースを実行することで文字が表示されます。

  ①各自修正が必要な場所が1つあります。
   (3)で取得したデバイスアドレスをソースに修正します。
   例:デバイスアドレスが3fの場合I2C_ADDRを0x3fとする
    private final static int I2C_ADDR = 0x3f; // I2C address

  ②データはENABLE項目を使用して3回送ることが仕様上必要らしい
   つまり4bit通信の場合、6回送信する
     上位4bit送信1回目(ENABLE=Low)
     上位4bit送信2回目(ENABLE=High)
     上位4bit送信3回目(ENABLE=Low)
     下位4bit送信1回目(ENABLE=Low)
     下位4bit送信2回目(ENABLE=High)
     下位4bit送信3回目(ENABLE=Low)

  ③dev.writeで送信しているデータの構造
  キャプチャ.PNG

   D:データ
    例、送信したいデータ0001ならD0=0、D1=0、D2=0、D3=1
   BL:バックライト
    1はバックライトON、0はOFF
   E:ENABLE
    1回目=0、2回目=1、3回目=0
    この項目をLow、Hight、Lowに変化させて同じデータを3回送ることで1通信が完了する仕様らしい
   Rs:送信モード
    0はコマンド送信、1はデータ送信

I2CLcdDisplay.java
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
/**
 * LCDへ文字表示(英数字)
 * @author pi
 *
 */
public class I2CLcdDisplay {
    private final static int I2C_ADDR = 0x3f;  // I2C address
    private final static int LCD_LINE_1 = 0x80;//1行目指定用
    private final static int LCD_LINE_2 = 0xc0;//2行目指定用
    private final static int LCD_CHR = 0x01;   // データ送信モード
    private final static int LCD_CMD = 0x00;   // コマンド送信モード
    private final static int LCD_ON = 0x08;    //バックライトON
    private final static int ENABLE = 0x04;    //Enable bit
    private final static int LCD_WIDTH = 16;   // 印字マックス桁数
    private static final int sleep = 2;        //2ms待つ

    private static I2CDevice dev = null;

    public static void main(String[] args) throws Exception{
        try{
            System.out.println("表示処理開始");
            I2CBus bus = I2CFactory.getInstance(I2CBus.BUS_1); //
            dev = bus.getDevice(I2C_ADDR); //Address 

            lcdInit();
            Thread.sleep(sleep);

            lcd_string("TEST1",LCD_LINE_1);
            Thread.sleep(sleep);
            lcd_string("test2",LCD_LINE_2);
            Thread.sleep(sleep);


            System.out.println("表示処理終了");
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * LCD初期設定
     * @throws Exception
     */
    public static void lcdInit() throws Exception{
        lcd_byte((byte)0x33,LCD_CMD); // 110011 Initialise
        lcd_byte((byte)0x32,LCD_CMD); // 110010 Initialise
        lcd_byte((byte)0x28,LCD_CMD); // 101000 Data length, number of lines, font size
        lcd_byte((byte)0x08, LCD_CMD); // don't shift, hide cursor
        lcd_byte((byte)0x01,LCD_CMD); // 000001 Clear display       
        lcd_byte((byte)0x06,LCD_CMD); // 000110 Cursor move direction
        lcd_byte((byte)0x0C,LCD_CMD); // 001100 Display On,Cursor Off, Blink Off 

        Thread.sleep(sleep);
    }

    /**
     * コマンド送信
     * @param bInput コマンド
     * @param mode 送信モード
     * @throws Exception
     */
    private  static void lcd_byte(byte bInput,int mode) throws Exception{
        int bits_high = mode |  (bInput & 0xf0) | LCD_ON; // |:OR &:AND
        int bits_low = mode |  ((bInput<<4) & 0xf0) | LCD_ON; // |:OR &:AND

        dev.write(0x13,(byte) bits_high);
        lcd_toggle_enable((byte)bits_high);
        dev.write(0x13,(byte) bits_low);
        lcd_toggle_enable((byte)bits_low);
    }

    /**
     *ENABLE項目を使って2、3回目のデータを送信
     *1回目Low、2回目High、3回目Lowと3回送ることで送信データが確定できる仕様らしい
     * @param bInput
     * @throws Exception
     */
    private  static void lcd_toggle_enable(byte bInput) throws Exception{
        Thread.sleep(sleep);
        dev.write(0x13,(byte)( bInput | ENABLE));
        Thread.sleep(sleep);
        dev.write(0x13,(byte)( bInput & ~ENABLE));

        Thread.sleep(sleep);
    }
    /**
     * 文字データ送信
     * @param strInput
     * @param line
     * @throws Exception
     */
    private  static void lcd_string(String strInput , int line) throws Exception{
        int length = 0;
        if(LCD_WIDTH>=strInput.length()){
            length=strInput.length();
        }else{
            length=LCD_WIDTH;
        }
        lcd_byte((byte)line, LCD_CMD);
        for(int i=0;i<length;i++){
            lcd_byte((byte)strInput.charAt(i), LCD_CHR);
        }
    }
}

 (6)実行結果

  2行の文字を表示します。
  image.png
  
  ちなみに印字がとても$\textlarge{薄い}$場合があります。
  実行して表示されてないと思っても角度を変えてみるとうっすら表示されているかもしれません。
  下記つまみを回すことで濃さを調節できます。
  image.png

3、おわりに

 Pi4JでLCDを印字する情報がほとんどなくて手探りでなんとか表示にたどり着きました。
 他言語で成功した先人の方々のおかげです。感謝です!!!
 今後Pi4Jで挑戦する方がこれを参考にうまく表示できることを願います。

参考サイト
[1]1602 I2C Serial LCD Moduleをラズベリーパイ3(Raspberry Pi 3)で使う
 $\textsmall{Pythonのプログラムを参考にjavaに置き換えることができました。}$
[2]キャラクタLCDモジュールの使いかた
 $\textsmall{I2C通信のイメージがわかりやすくまとめられていました。上のソースは4bitモードでやっているみたいです。}$
[3]I2CエキスパンダPCF8574を使ったキャラクタLCD表示のテスト(2)
なぜ同じコマンド、データを3回送信しているのか分かりました。
[4]LCDモジュール データシート

13
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
otesho1
言語は主にjavaを使用しています。 興味のあること自由にいろいろやります!

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
13
Help us understand the problem. What is going on with this article?