はじめに

LiquidCrystal_I2C.hを使わず、LCD2004でHello Worldしました。
前回記事では、LiquidCrystal_I2C.hを使用してLCDを制御しました。
LCD2004やI2Cアダプタについては前回記事を御覧ください。同じものを使用します。結線も同じです。

Arduino I2C LCD2004 HelloWorld | atooshi-note

ArduinoでLCDを制御する例を調べるとLiquidCrystal_I2C.hを使った記事がたくさんヒットしますが、LiquidCrystal_I2C.hを使わない例はあまり見かけませんでした。
RaspberrypiやPICやSTM32で駆動している例はそこそこ見つかりました。

気をつける点(自分めも)

  • LiquidCrystal_I2C.hを使わない例としてはACM1602NIを駆動している例がありました。これもI2C接続ですが、LCDモジュールとI2Cアダプタがセットになっています。今回私が使用しているのはLCDとI2Cアダプタ(PCF8574T)が別で接続したものですのでプログラムそのままでは動きません。
  • 以下はLiquidCrystal_I2C.hがいい感じにやってくれていますが、自分で組むときに気をつけた点です。
    • 適切なディレイが必要
    • 初期化手順が決まっている
    • 4bitモードで制御する
    • enable信号のL→H→Lは0.22us以上あける

PCF8574TとLCD2004の結線

LCDDB7DB6DB5DB4バックライトのトランジスタのGateER/WRS
PCF8574TP7P6P5P4P3P2P1P0

プログラム

/*
wire.h使用(i2c)
#include <LiquidCrystal_I2C.h>は不使用
*/

#include <Wire.h>

#define lcdaddr 0x27
#define lcdEN 0b00000100 // Enable
#define lcdBL 0b00001000 // Back light ON
#define setDDRAMaddr 0b10000000 // Set DDRAM Address
#define setRS 0b00000001 // RS=1
#define unsetRS 0b00000000 // RS=0

void lcdinit()
{
  // 一旦8bitモードに設定(3回繰り返す)
  // 1回目
  lcdwrite0(0x30,unsetRS); // Funcition Set DL=1:8bitバス
  delay(5); // Wait for more than 4.1 ms

  // 2回目
  lcdwrite0(0x30,unsetRS);
  delayMicroseconds(150); // Wait for more than 100 µs

  // 3回目
  lcdwrite0(0x30,unsetRS);
  delayMicroseconds(100); // Wait for more than 40 µs

  lcdwrite0(0x20,unsetRS); // 4bitモードに設定 Funcition Set DL=0:4bitバス
  lcdwrite(0x28,unsetRS); // 2行表示モードに設定 Funcition Set DL=0:4bitバス,Set N=1:2桁表示
  lcdwrite(0x0F,unsetRS); // 表示ON/OFF D=1:文字表示ON,C=1:下線カーソルON,B=1:ブロックカーソルON
  lcdwrite(0x06,unsetRS); // エントリモードセット I/D=1:インクリメント
  lcdwrite(0x01,unsetRS); // 表示クリア
  lcdwrite(0x02,unsetRS); // カーソルホーム
}

// 8bit用
void lcdwrite0(byte bits,byte mode){
  i2cwrite(bits | mode);
}

// 4bit用
void lcdwrite(byte bits,byte mode){
  i2cwrite((bits & 0xF0) | mode); // 上位4bit
  i2cwrite(((bits << 4) & 0xF0) | mode); // 下位4bit
}

void i2cwrite(byte val){
  Wire.beginTransmission(lcdaddr);
  Wire.write(val | lcdBL);
  delayMicroseconds(1); // 0.22us以上
  Wire.write(val | lcdBL | lcdEN);
  delayMicroseconds(1); // 0.22us以上
  Wire.write(val | lcdBL);
  Wire.endTransmission();
  delayMicroseconds(100); // Wait for more than 40 µs とは言いつつ50usec待ちでは動かない 100usecぐらい余裕を持っておく
}

// row:行 col:列
void setCursor(int row, int col){
  int row_offsets[] = {0x00, 0x40, 0x14, 0x54}; // 0から数え始め
  lcdwrite((col + row_offsets[row]) | setDDRAMaddr,unsetRS);
}

void lcdText(String s){
  for(int i = 0; i < s.length(); i++){
    lcdwrite(s.charAt(i),setRS);
  }
}

void setup() {
  delay(50); // Wait for more than 15 ms after VCC rises to 4.5 V
  Wire.begin();
  lcdinit();

  setCursor(0,0); // カーソルを0行目0列目に移動
  lcdwrite(0x30,setRS); // 数字の0を出力 HD44780 Table 4 Correspondence between Character Codes and Character Patterns (ROM Code: A00)

  setCursor(1,1);
  lcdwrite(0x31,setRS); // 数字の1を出力

  setCursor(2,2);
  lcdText("2_hello world!");

}

void loop() {
  setCursor(3,0);
  lcdText("3_Hello World!");
  delay(1000);
  setCursor(3,0);
  lcdText("3_World!");
  delay(1000);
}

結果

参考

参考にさせていただき、ありがとうございました。

以上:)