728x90
728x90

1602(16x2) 또는 2004(20x4) 크기의 CLCD(Character LCD)는 텍스트 LCD(Text LCD)라고로 부르는데요. 최소로 제어해야 하는 핀이 6개여서, CLCD를 제어하려면 MCU의 핀이 최소한 6개가 필요합니다. 그런데 SPI 방식이나 I2C 방식의 port extender IC를 사용하면 각각 4개, 2개의 MCU 핀으로도 제어할 수 있어서, 제어핀의 갯수가 줄어드는 이점이 있어요. 그래서 이전 글에서 PCF8574 port extender IC가 있는 확장보드를 CLCD에 납땜으로 연결한 뒤, STM32F746 MCU로 구동했습니다.

 

이전 글: PCF8574 I/O 확장보드를 사용한 CLCD(Text LCD) 구동 (STM32F746, I2C)

 

 

 

이 글에서는 I2C 방식의 CLCD를 아두이노 레오나르도로 제어하기 위해, STM32F746에 올렸던 코드를 아두이노용으로 살짝 바꿨습니다. 같은 확장보드가 연결된 CLCD를 제어해서, 제어논리를 똑같이 쓸 수 있어서 코드의 논리적인 부분은 바꿀 필요가 없었습니다. ST사의 HAL 함수를 아두이노의 해당 함수로 바꾸고, 8자리 I2C 주소를 7자리 I2C 주소로 바꾸고, 그리고 CLCD에 나타낼 문자열을 바꾸는 것이 거의 전부였어요. 한 MCU에서 완성시킨 코드를 다른 MCU에도 쉽게 변형해서 사용할 수 있었습니다. 여기서부터는 CLCD 대신 텍스트 LCD(text LCD)라고 부르겠습니다.

 

 

 

1. 동작 동영상

 

PCF8574 확장보드의 VCC, GND, SCL, SDA 핀은 각각 아두이노 레오나르도의 5V, GND, SCL, SDA 핀에 연결했습니다. 그래서 PCF8574는 아두이노로부터 I2C 신호를 SCL, SDA 버스를 통해 받고, 5V 전원도 공급받아 텍스트 LCD에 전원을 공급합니다. PCF8574와 아두이노 레오나르도의 USB 케이블은 스위치가 있는 USB 아답터에 연결했습니다. 동영상의 2초 정도에 스위치를 눌러 아두이노 레오나르도에 전원을 공급하면, 텍스트 LCD가 켜지고 조명이 깜박이는 것을 볼 수 있어요. STM32F746으로 텍스트 LCD를 구동했을 때와 똑같이 동작시켰습니다.

 

 

  •  

 

PCF8574 I2C 확장보드로 CLCD, Text(텍스트) LCD 구동 (아두이노)

재생 수542

 

 

 

 

 

 

 

 

  

화질 선택 옵션1080p

 

 

 

 







2. PCF8574 I/O 확장보드와 회로도

 

아래 사진은 같은 PCF8574 모듈이 부착된 텍스트 LCD를 제어했던 이전 글에서 가져왔습니다. 위 동영상의 텍스트 LCD도 PCF8574 모듈이 사진처럼 연결되어 있어요. 모듈의 IC는 PCF8574 의 여러 시리즈 중 PCF8574T 이고요. 제가 사용한 코드는 STM32F746 MCU로 동작시키면서 검증이 되어서, 프로브가 연결된 사진과 다르게 이 글에서는 로직 아날라이저로 신호를 측정하지 않았습니다.






PCF8574 보드의 회로도 역시 이전 글에서 가져왔습니다. PCF8574를 사용한 확장보드는 여러 종류가 있어서, PCF8574와 텍스트 LCD가 어떻게 연결되어 있는지 회로도를 잘 봐야해요. 저 아래에 나오는 코드의 함수는 텍스트 LCD의 D[7:4]핀이 PCF8574의 P[3:0]핀에 연결된 경우 그대로 사용할 수 있습니다. D[7:4]핀이 P[7:4]에 연결된 경우는 함수를 수정해야 CLCD를 구동할 수 있어요. 어떤 확장보드는 텍스트 LCD의 A핀이 VCC에 연결되어 백라이트가 항상 켜지는 경우도 있는데, 이 경우 LCD의 백라이트 on/off 제어는 안됩니다. A[2:0]핀의 납땜상태는 GND에 연결된 상태로 그대로 놔둬서, PCF8574의 I2C 주소는 이전글과 똑같이 0x20 입니다. I2C 버스로 PCF8574의 주소와 함께 write 비트를 전송하고 나면, 그 뒤에 8비트 값이 전송될때마다 PCF8574의 P[7:0]출력상태가 바뀝니다. 8비트 값이 그대로 P[7:0]핀의 출력상태가 되어, 텍스트 LCD를 I2C 신호로 제어할 수 있어요. 자세한 내용은 PCF8574의 데이터시트를 보면 알 수 있습니다.








3. HD44780의 명령어와 DDRAM 주소

 

아래에 표로 설명된 명령어는 텍스트 LCD의 구동 IC인 HD44780의 데이터시트에 나옵니다. 텍스트 LCD의 E핀에 하강엣지가 입력될 때, 다른 핀의 상태에 따라 다른 명령어가 입력됩니다. 아두이노가 아래 코드를 통해 텍스트 LCD에 입력하는 명령어는 이 표를 보고 해석하면 돼요. 빨간 밑줄로 표시된 명령어는 DDRAM의 주소를 텍스트 LCD에 입력합니다.






1602(16x2) 크기의 텍스트 LCD의 위치에 따른 DDRAM의 주소는 아래와 같습니다. 입력되는 DB7(D7) 핀의 상태가 high여서 Set DDRAM address 명령어가 LCD에 입력될 때, 8비트 모드이면 표처럼 DB[6:0] 또는 D[6:0] 핀에 따라 주소가 결정돼요. 4비트 모드이면 주소가 D[7:4]핀으로 두번 전송됩니다. DDRAM 주소는 바로 다음에 문자를 출력할 위치를 가리키고, 문자가 한개씩 출력될때마다 1씩 증가해서 다음 위치를 가리킵니다. 그래서 LCD_String( ) 함수에 문자열을 입력하면, 문자열의 문자가 바로 옆 위치로 순서대로 출력됩니다. 다른 글에서 사용된 2004(20x4) 크기의 텍스트 LCD는 4줄로 구성되어 있는데요. 눈으로는 4줄이지만, 제어는 40x2 크기의 2줄 형태로 해야해요. HD44780으로 구동되는 텍스트 LCD는 1줄 또는 2줄 모드로 제어해야 하고, 4줄 모드의 제어방식은 없습니다.

 






4. 아두이노에 올린 코드

 

텍스트 LCD를 동작시키기 위해 아두이노에 올린 코드는 아래와 같습니다. I2C 방식으로 동작하는 PCF8574 IC를 통해 텍스트 LCD를 제어하기 때문에, I2C 라이브러리가 있는 Wire.h 파일을 include 했습니다. 제가 LCD 제어를 위해 직접 작성한 함수를 사용하기 위해, 많은 사람들이 사용하는 LiquidCrystal_I2C.h 파일은 include하지 않았습니다. Initialize_LCD( ) 함수는 텍스트 LCD를 초기화하기 위해 필요한데, HD44780 데이터시트에 나온 초기화 과정대로 함수의 코드를 작성했습니다. LCD_string( ) 함수의 주소를 입력하는 부분에 0x80을 더한 이유는, 위 표처럼 DDRAM의 주소를 설정하는 명령어가 0x80으로 시작하기 때문입니다. 아래 코드에 대한 더 자세한 설명은 주석에서 볼 수 있어요.

 

#include "Wire.h"  // I2C library

 

uint8_t I2C_addr_PCF8574 = 0x20 // I2C address of PCF8574

 

void I2C_LCD_command_8(unsigned char command); // 8-bit command to text LCD

void I2C_LCD_command(unsigned char command);   // 4-bit command to text LCD

void I2C_LCD_data(unsigned char data);         // Transfer 1 character to text LCD

void LCD_string(unsigned char command, char *string);  // Transfer string to text LCD

void Initialize_LCD(void);  // Initialize text LCD

 

 

 

void setup()

{

    char str0[] = "PCF8574 I2C CLCD";

    char str1[] = "Arduino Leonardo";

 

    Wire.begin(); // Initialize I2C bus

    delay(100);

    Initialize_LCD(); // Initialize Text LCD

 

    // 0x80: Set DDRAM address instruction

    LCD_string(0x80, str0); // 0x80: the 1st position in the 1st row

    LCD_string(0x80 + 0x40, str1); // 0x80 + 0x40: the 1st position in the 2nd row

}

 

 

 

void loop()

{

    uint8_t Backlight[] = {0x80, 0x00}; // off, on

    delay(500);

 

    // LCD backlight off

    Wire.beginTransmission(I2C_addr_PCF8574); ); // Send address to PCF8574

    Wire.write(Backlight[0]); // Transfer 0x80 signal (BJT off) to text LCD

    Wire.endTransmission();   // Transfer I2C stop signal to PCF8574

 

    delay(500);

 

    // LCD backlight on

    Wire.beginTransmission(I2C_addr_PCF8574); // Send address to PCF8574

    Wire.write(Backlight[1]); // Transfer 0x00 signal (BJT on) to text LCD

    Wire.endTransmission();   // Transfer I2C stop signal to PCF8574

}

 

 

 

void I2C_LCD_command_8(unsigned char command) // write a command(instruction) to text LCD

{

    //P0: D4  P1: D5  P2: D6  P3: D7

    //P4: E   P5: RW  P6: RS  P7: BJT base

 

    uint8_t T_buf[2]; // transmit buffer

 

    T_buf[0] = (command >> 4) | 0x10; // high 4 bit, E = 0, RS = 0, base = low (Backlight on)

    T_buf[1] = T_buf[0] & 0xEF;       // E = 0

 

    Wire.beginTransmission(I2C_addr_PCF8574); // Send address to PCF8574

    Wire.write(T_buf[0]);   // Transfer buffer to text LCD via PCF8574

    Wire.write(T_buf[1]);

    Wire.endTransmission(); // Transfer I2C stop signal to PCF8574

}

 

 

void I2C_LCD_command(unsigned char command) // write a command(instruction) to text LCD

{

    //P0: D4  P1: D5  P2: D6  P3: D7

    //P4: E   P5: RW  P6: RS  P7: BJT base

 

    uint8_t T_buf[4]; // transmit buffer

 

    T_buf[0] = (command >> 4) | 0x10; // high 4 bit, E = 1, RS = 0, base = low (Backlight on)

    T_buf[1] = T_buf[0] & 0xEF;       // E = 0

 

    T_buf[2] = (command & 0x0F) | 0x10; // low 4 bit, E = 1

    T_buf[3] = T_buf[2] & 0xEF;         // E = 0

 

    Wire.beginTransmission(I2C_addr_PCF8574); // Send address to PCF8574

    Wire.write(T_buf[0]);   // Transfer buffer to text LCD via PCF8574

    Wire.write(T_buf[1]);

    Wire.write(T_buf[2]);

    Wire.write(T_buf[3]);

    Wire.endTransmission(); // Transfer I2C stop signal to PCF8574

}

 

 

void I2C_LCD_data(unsigned char data) // display a character on text LCD

{

    //P0: D4  P1: D5  P2: D6  P3: D7

    //P4: E   P5: RW  P6: RS  P7: BJT base

 

    uint8_t T_buf[4]; // transmit buffer

 

    T_buf[0] = (data >> 4) | 0x50;   // high 4 bit, E = 1, RS = 1

    T_buf[1] = T_buf[0] & 0xEF;      // E = 0

 

    T_buf[2] = (data & 0x0F) | 0x50; // low 4 bit, E = 1, RS = 1

    T_buf[3] = T_buf[2] & 0xEF;      // E = 0

 

    Wire.beginTransmission(I2C_addr_PCF8574); // Send address to PCF8574

    Wire.write(T_buf[0]);   // Transfer buffer to text LCD via PCF8574

    Wire.write(T_buf[1]);

    Wire.write(T_buf[2]);

    Wire.write(T_buf[3]);

    Wire.endTransmission(); // Transfer I2C stop signal to PCF8574

}

 

 

void LCD_string(unsigned char command, char *string) // display a string on LCD

{

    I2C_LCD_command(command); // start position of string

    while (*string != '\0')   // display string

    {

        I2C_LCD_data(*string);

        string++;

    }

}

 

 

void Initialize_LCD(void) // initialize text LCD module

{

    // 8-bit mode

    I2C_LCD_command_8(0x30);

    delay(10);

    I2C_LCD_command_8(0x30);

    delay(6);

    I2C_LCD_command_8(0x30);

    I2C_LCD_command_8(0x20); // changes to 4-bit mode

 

    // 4-bit mode

    I2C_LCD_command(0x28); // function set(4-bit, 2 line, 5x7 dot)

    I2C_LCD_command(0x0C); // display control(display ON, cursor OFF)

    I2C_LCD_command(0x06); // entry mode set(increment, not shift)

    I2C_LCD_command(0x01); // clear display

    delay(3);

}

 

 

 

I2C 방식의 PCF8574 확장보드가 연결된 텍스트 LCD는 아두이노로 이렇게 구동할 수 있습니다. 제가 텍스트 LCD를 다른 MCU로 구동하는 코드를 이미 작성해서 가지고 있어서, LiquidCrystal_I2C.h 헤더파일을 사용하는 대신 기존의 코드를 조금만 수정해서 손쉽게 텍스트 LCD를 동작시켰습니다. 제가 직접 작성한 코드를 사용해서 신뢰감이 더 느껴지는군요. 텍스트 LCD를 STM32F746 MCU로 구동한 이전 글의 코드와 비교하면, 이 글의 코드는 거의 복사 + 붙여넣기 수준입니다^^

 

이 글에서는 I2C 핀과 텍스트 LCD의 각 핀의 신호를 로직 아날라이저로 측정하지 않았는데요. 각 핀으로 전달되는 신호를 보고 싶으시면, 같은 방식으로 텍스트 LCD를 구동했던 이전 글의 로직 아날라이저 화면을 보세요. 이 글과 이전 글은 확장보드와 I2C 클럭 주파수가 같고 코드도 유사해서, 신호도 거의 같습니다.

 

이전 글: PCF8574 I/O 확장보드를 사용한 CLCD(Text LCD) 구동 (STM32F746, I2C)

'홍익인간 프로젝트 > Arduino C' 카테고리의 다른 글

What's means F() function ?  (0) 2021.01.14
u8g2setupcpp  (0) 2020.12.25
LiquidCrystal I2C - 3 Arguments Type  (0) 2020.12.25
Software Serial Example  (0) 2020.12.16
Arduino Uno TM1637 Display  (0) 2020.12.16
728x90

 

 

 

그림1. LCD 1602(16X2) 4(I2C제어) 디스플레이 모듈

 

 

 

  LCD 1602(16x2) 4(I2C제어) 디스플레이 모듈

 

LCD 가장보편적이고초보자, 입문자분들이쉽게활용할있는모델인LCD 1602 입니다. 또한 16핀의제어핀을LCD뒤에부착된I2C변환모듈을통해 4개의핀으로제어가가능하도록쉽게만들어진모델입니다.

 

 

 

그림2. LCD 1602(16X2) 4(I2C제어) 디스플레이 모듈 핀맵

 

 

 

 

 

LCD 1602(16x2) 4(I2C)제어 레이 모듈 보러가기(클릭)

 

 

 

 

 

1. LCD 1602(16x2) 4(I2C)제어 디스플레이 모듈  

 

쉽게사용할있는 4모델로I2C통신을통해제어되는 LCD 디스플레이모듈입니다. 해상도는16x2 케릭터(Character Type)입니다.

 

디스플레이 타입(Display Type)

LCD(Liquid Crystal Display)

동작 전압(Operating Volate)

5V

해상도(Resolution)

16x2

I2C 주소

0x3F or 0x27

통신 인터페이스

I2C 통신 지원

백라이트

파란색(Blue)

색상

흰색(White)

소비전력

0.4W

무게(Weight)

3.2g

크기(Size)

82 x 35 x 18mm

 

 

 

2. 라이브러리 다운로드  설치하기  

 

LCD_I2C사용하기위해서는라이브러리를다운받아야합니다. 다운경로는아래와같습니다.

 

 

 

LCD I2C 라이브러리 다운받기(클릭)

 

 

 

 

 

 

다운받은 ZIP파일안에들어있는폴더를컴퓨터의아두이노 IDE 설치경로로들어가아래그림과같이라이브러리폴더아래에복사해넣어줍니다. 아두이노 IDE껐다실행하면자동으로아래경로의라이브러리가포함되어실행됩니다.

 

 

 

 

 

 

 주의사항

  - 라이브러리 추가시 경로설정을 정확하게 해야합니다.

    아래 그림과 같이 ' C:\Program Files (x86)\Arduino\libraries\LiquidCrystal_I2C-master ' 경로 안에

    example 폴더와 헤더파일을 포함한 파일들이 들어있어야 합니다.

    (경로설정을 잘못하면 아두이노 IDE에서 컴파일 오류가 발생할 수 있습니다.)

 

 

 

 

 

 

 

3. 회로도 구성  

 

아두이노우노와I2C 통신을구성해봅시다. 회로도는아래와같이연결해줍니다.

 

5V – VCC

GND – GND

A4 – SDA

A5 - SCL

 

 

 

 

4. 예제 따라하기1 – Hellow world  

 

 이제디스플레이해봅시다!!

 

 

예제소스는다음과같습니다.

 

#include <Wire.h>                        // i2C 통신을 위한 라이브러리

#include <LiquidCrystal_I2C.h>        // LCD 1602 I2C 라이브러리

LiquidCrystal_I2C lcd(0x3F,16,2);     // 접근주소: 0x3F or 0x27

void setup()

{

  lcd.init();                      // LCD 초기화

  // Print a message to the LCD.

  lcd.backlight();                // 백라이트 켜기

  lcd.setCursor(0,0);             // 1번째, 1라인

  lcd.print("Hello, world!");

  lcd.setCursor(0,1);             // 1번째, 2라인

  lcd.print("Enjoy - Eduino");

}

void loop()

{

}

 

실제동작모습은다음과같습니다.

 

 

 

그림3. LCD 1602 4핀제어 디스플레이 모듈 실행 예제1. Hellow world

'홍익인간 프로젝트 > Arduino C' 카테고리의 다른 글

u8g2setupcpp  (0) 2020.12.25
PCF8574 I2C 확장보드로 CLCD, Text(텍스트) LCD 구동 (아두이노)  (0) 2020.12.25
Software Serial Example  (0) 2020.12.16
Arduino Uno TM1637 Display  (0) 2020.12.16
Arduino Basic  (0) 2020.12.12
728x90

Arduino boards have built in support for serial communication on pins 0 and 1, but what if you need more serial ports? The SoftwareSerial Library has been developed to allow serial communication to take place on the other digital pins of your boards, using software to replicate the functionality of the hardwired RX and TX lines. This can be extremely helpful when the need arises to communicate with two serial enabled devices, or to talk with just one device while leaving the main serial port open for debugging purpose.

In the example below, digital pins 10 and 11 on your Arduino boards are used as virtual RX and TX serial lines. The virtual RX pin is set up to listen for anything coming in on via the main serial line, and to then echo that data out the virtual TX line. Conversely, anything received on the virtual RX is sent out over the hardware TX.

Hardware Required

  • Arduino Board

Circuit

There is no circuit for this example. Make sure that your Arduino board is attached to your computer via USB to enable serial communication through the serial monitor window of the Arduino Software (IDE).

 

Schematics

image developed using Fritzing. For more circuit examples, see the Fritzing project page

Code

/*
  Software serial multple serial test

 Receives from the hardware serial, sends to software serial.
 Receives from software serial, sends to hardware serial.

 The circuit:
 * RX is digital pin 2 (connect to TX of other device)
 * TX is digital pin 3 (connect to RX of other device)

 Note:
 Not all pins on the Mega and Mega 2560 support change interrupts,
 so only the following can be used for RX:
 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69

 Not all pins on the Leonardo support change interrupts,
 so only the following can be used for RX:
 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).

 created back in the mists of time
 modified 25 May 2012
 by Tom Igoe
 based on Mikal Hart's example

 This example code is in the public domain.

 */
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Native USB only
  }


  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(38400);
  mySerial.println("Hello, world?");
}

void loop() // run over and over
{
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
    mySerial.write(Serial.read());
}

www.arduino.cc/en/Tutorial/LibraryExamples/SoftwareSerialExample

+ Recent posts