Подключение lcd1602 к arduino по i2c (hd44780/pcf8574)

Содержание

Low-level methods

I2c._start()

Description:
Sends out a Start Condition. This puts all slave devices on notice that a transmission is about to start. This function incorporates the timeOut function.
Parameters:
none
Returns:
uint8_t0: The start condition was successfully sent1: The function timed out2 — 0xFF: See the datasheet

I2c._sendAddress(i2cAddress)

Description:
Sends out the address byte. The address byte’s first 7 bits are the 7-bit address of the Slave you wish to communicate with, the last bit specifies if you wish to write or read to that slave, 0 = write & 1 = read.
Parameters:
i2cAddress — uint8_t
The address byte you wish to send
Returns:
uint8_t0: The address byte was successfully sent1: The function timed out2 — 0xFF: See the datasheet

I2c._sendByte(i2cData)

Description:
Sends out a byte of data to the slave.
Parameters:
i2cData — uint8_t
The data byte you wish to send
Returns:
uint8_t0: The data byte was successfully sent1: The function timed out2 — 0xFF: See the datasheet

I2c._receiveByte(ack)

Description:
Receives a byte from the slave. The ack parameter specifies whether or not to send an acknowledge signal after receiving it. If it is the last byte you want to receive it must be 0, so that the slave will stop transmitting and allow the master to send a stop.
Parameters:
ack — uint8_t
Whether or not you want the master to acknowledge the receipt of the data byte. If this is the last byte being received, do not acknowledge.0: Do not send an ACK signal on receipt1 — 0xFF: Send an ACK signal on receipt
Returns:
uint8_t0: The data byte was successfully received1: The function timed out2 — 0xFF: See the datasheet

I2c._receiveByte(ack, *target)

Description:
Receives a byte from the slave. The ack parameter specifies whether or not to send an acknowledge signal after receiving it. If it is the last byte you want to receive it must be 0, so that the slave will stop transmitting and allow the master to send a stop.
Parameters:
ack — uint8_t
Whether or not you want the master to acknowledge the receipt of the data byte. If this is the last byte being received, do not acknowledge.0: Do not send an ACK signal on receipt1 — 0xFF: Send an ACK signal on receipt
*target — uint8_t
A byte to store the received data.
Returns:
uint8_t0: The data byte was successfully received6: The function timed out1 — 5 and 7 — 0xFF: See the datasheet

I2c._stop()

Description:
Send out a stop condition
Parameters:
none
Returns:
uint8_t0: The stop condition was successfully sent1: The function timed out2 — 0xFF: See the datasheet

Как подключить нескольких устройств по I2C Arduino

В следующем примере к шине IIC Arduino будет подключено сразу три устройства — текстовый дисплей 1602, датчик давления bmp180 и RTC модуль часов. После сборки схемы можно сделать предварительное сканирование шины, но адреса у всех устройств разные и изменить адрес можно только у дисплея. У других устройств адреса «вшиты» производителем и используются в библиотеках по умолчанию.

Скетч. Подключение нескольких устройств к шине i2c


I2C интерфейс: подключение нескольких устройств

После сборки схемы, убедитесь, что у вас установлены необходимые библиотеки для работы с устройствами по IIC протоколу, и загрузите следующий пример кода в микроконтроллер. Данная программа будет выводить на текстовый экран текущую дату и время суток (устанавливаются в процедуре void setup и время можно поменять), а также данные о температуре воздуха и атмосферном давлении.

#include <Wire.h>  // подключаем библиотеку для интерфейса I2C 

#include <LiquidCrystal_I2C.h>  // подключаем библиотеку для 1602
LiquidCrystal_I2C LCD(0x27, 16, 2);  // создаем объект LCD

#include <SFE_BMP180.h>  // подключаем библиотеку для bmp180
SFE_BMP180 pressure;  // создаем объект pressure

#include <iarduino_RTC.h>  // подключаем библиотеку для часов
iarduino_RTC time(RTC_DS1307);  // создаем объект time

void setup() {
  LCD.init();  // инициализация дисплея
  LCD.backlight();  // включение подсветки

  pressure.begin();  // запускаем датчик давления

  time.begin();  // запускаем модуль часов
  time.settime(0, 30, 16, 1, 4, 21, 5);  // сек, мин, часы, дата, мес, год, день недели
}

void loop() {
  char status;
  double T, P, p0, a;

  // если прошла 1 секунда обновляем информацию
  if (millis() % 1000 == 0) {

    // выводим время с секундами и дату (день, месяц)
    LCD.setCursor(0, 0);
    LCD.print(time.gettime("H:i:s - d.m"));

    // узнаем температуру и выводим на дисплей
    status = pressure.startTemperature();
    if (status != 0) {
      delay(status);
      status = pressure.getTemperature(T);
      if (status != 0) {
        LCD.setCursor(0, 1);
        LCD.print("T:");
        LCD.print(T, 2);

        // узнаем давление и выводим на дисплей
        status = pressure.startPressure(3);
        if (status != 0) {
          delay(status);
          status = pressure.getPressure(P, T);
          if (status != 0) {
            p0 = pressure.sealevel(P, 1655.0);
            LCD.print(" D:");
            LCD.print(p0, 2);

          }
          else { LCD.setCursor(0, 1); LCD.print("error retrieving pressure"); }
        }
        else { LCD.setCursor(0, 1); LCD.print("error starting pressure"); }
      }
      else { LCD.setCursor(0, 1); LCD.print("error retrieving temperature"); }
    }
    else { LCD.setCursor(0, 1); LCD.print("error starting temperature"); }
  }

}

Пояснения к коду:

  1. обновление информации на текстовом экране происходит каждую секунду, данный интервал можно увеличить по своему желанию;
  2. время выводится с секундами, формат вывода времени и даты также можно изменить в строчке

Часть первая, I2C и библиотека «Wire».

Последовательный протокол обмена данными IIC (также называемый I2C — Inter-Integrated Circuits, межмикросхемное соединение). Разработана фирмой Philips Semiconductors в начале 1980-х как простая 8-битная шина внутренней связи для создания управляющей электроники. Так как право на использование его стоит денег фарма Atmel назвала его TWI, но смысл от этого не меняется.

Как это работает ?

Для передачи данных используются две двунаправленные лини передачи данных. SDA (Serial Data) шина последовательных данных и SCL (Serial Clock) шина тактирования. Обе шины подтянуты резисторами к плюсовой шине питания. Передача/Прием сигналов осуществляется прижиманием линии в 0, в единичку устанавливается сама, за счет подтягивающих резисторов.

В сети есть хотя бы одно ведущее устройство (Master), которое инициализирует передачу данных и генерирует сигналы синхронизации и ведомые устройства (Slave), которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Конечно понятно что Ведущий это наш микроконтроллер , а ведомый наша память. Ведущее устройство начинает прижимать шину SCL  к нулю с определенной частотой, а шину SDA прижимать или отпускать на определенное число тактов передавая Единичку или Нолик. Передача данных начинается с сигнала START потом передается 8 бит данных и 9-тым битом Ведомое устройство подтверждает прием байт  прижимая шину SDA к минусу. Заканчивается передача сигналом STOP.

Библиотека «Wire».

Для облегчения обмена данными с устройствами по шине I2C для Arduino написана стандартная библиотека Wire которая есть уже в комплекте IDE. Она имеет следующие основные функции:

Wire.begin(Address) вызывается один раз для инициализации  и подключения к шини как Ведущий или Ведомое устройство. Если Address не задан подключаемся как Мастер устройство.

Wire.beginTransmission(address)  начинает передачу на ведомое I2C устройство с заданным адресом.

Wire.endTransmission() прекращает передачу данных ведомому. Функция возвращает значение типа byte:

  • 0 — успех.
  • 1- данные слишком длинны для заполнения буфера передачи.
  • 2 — принят NACK при передаче адреса.
  • 3 — принят NACK при передаче данных.
  • 4 — остальные ошибки.

Wire.write() запись данных  от ведомого устройства в отклик на запрос от ведущего устройства, или ставит в очередь байты для передачи от мастера к ведомому устройству.Фактически записывает данные в буфер. Размер буфера 32 байта ( минус 2 байта адрес, фактически 30 байт), а передает буфер функция Wire.endTransmission().

  • Wire.write(value) — value: значение для передачи, один байт.
  • Wire.write(string) — string: строка для передачи, последовательность байтов.
  • Wire.write(data, length) — data: массив данных для передачи, байты. length: количество байтов для передачи.

Wire.read() Считывает байт, который был передан от ведомого устройства к ведущему или который был передан от ведущего устройства к ведомому. Возвращаемое значение byte : очередной принятый байт.

Это самые основные функции библиотеке, остальные мы рассмотрим по ходу пьесы ))

Объяснение программ для Arduino

Нам будут необходимы две программы – одна для ведущей платы Arduino, а другая – для ведомой. Полные тексты обоих программ приведены в конце статьи, здесь же мы рассмотрим их основные фрагменты.

Объяснение программы для ведущей (Master) платы Arduino

1. Первым делом в программе мы должны подключить библиотеку Wire для задействования возможностей протокола I2C и библиотеку для работы с ЖК дисплеем. Также нам необходимо сообщить плате Arduino к каким ее контактам подключен ЖК дисплей.

Arduino

#include<Wire.h>
#include<LiquidCrystal.h>
LiquidCrystal lcd(2, 7, 8, 9, 10, 11);

1
2
3

#include<Wire.h>    
#include<LiquidCrystal.h>

LiquidCrystallcd(2,7,8,9,10,11);

  1. Далее в функции void setup():

—  мы инициализируем последовательную связь со скоростью 9600 бод/с;

Arduino

Serial.begin(9600);

1 Serial.begin(9600);

— инициализируем связь по протоколу I2C на контактах A4 и A5;

Arduino

Wire.begin(); //Begins I2C communication at pin (A4,A5)

1 Wire.begin();//Begins I2C communication at pin (A4,A5)

— далее мы инициализируем ЖК дисплей для работы в режим 16х2, показываем на нем приветственное сообщение и очищаем его экран через 5 секунд.

Arduino

lcd.begin(16,2); //Initilize LCD display
lcd.setCursor(0,0); //Sets Cursor at first line of Display
lcd.print(«Circuit Digest»); //Prints CIRCUIT DIGEST in LCD
lcd.setCursor(0,1); //Sets Cursor at second line of Display
lcd.print(«I2C 2 ARDUINO»); //Prints I2C ARDUINO in LCD
delay(5000); //Delay for 5 seconds
lcd.clear(); //Clears LCD display

1
2
3
4
5
6
7

lcd.begin(16,2);//Initilize LCD display

lcd.setCursor(,);//Sets Cursor at first line of Display

lcd.print(«Circuit Digest»);//Prints CIRCUIT DIGEST in LCD

lcd.setCursor(,1);//Sets Cursor at second line of Display

lcd.print(«I2C 2 ARDUINO»);//Prints I2C ARDUINO in LCD

delay(5000);//Delay for 5 seconds

lcd.clear();//Clears LCD display

  1. В функции void loop():

— сначала нам необходимо получить данные от ведомого, поэтому мы используем функцию requestFrom() с адресом ведомого равным 8 и запрашиваемым 1 байтом;

Arduino

Wire.requestFrom(8,1);

1 Wire.requestFrom(8,1);

Принятое значение считываем с помощью функции Wire.read().

Arduino

byte MasterReceive = Wire.read();

1 byteMasterReceive=Wire.read();

— далее нам необходимо считать аналоговое значение с потенциометра, подключенного к контакту A0 ведущей платы Arduino;

Arduino

int potvalue = analogRead(A0);

1 intpotvalue=analogRead(A0);

Затем мы конвертируем это полученное значение к диапазону одного байта – от 0 до 127 (байт у нас 7-битный).

Arduino

byte MasterSend = map(potvalue,0,1023,0,127);

1 byteMasterSend=map(potvalue,,1023,,127);

— после этого нам необходимо передать это конвертированное значение, поэтому мы начинаем передачу ведомой плате с адресом 8;

Arduino

Wire.beginTransmission(8);
Wire.write(MasterSend);
Wire.endTransmission();

1
2
3

Wire.beginTransmission(8);

Wire.write(MasterSend);

Wire.endTransmission();

— затем мы отобразим на экране ЖК дисплея принятое значение от ведомой платы с задержкой 500 микросекунд и в дальнейшем мы будем непрерывно принимать и отображать эти значения.

Arduino

lcd.setCursor(0,0); //Sets Currsor at line one of LCD
lcd.print(«>> Master <<«); //Prints >> Master << at LCD
lcd.setCursor(0,1); //Sets Cursor at line two of LCD
lcd.print(«SlaveVal:»); //Prints SlaveVal: in LCD
lcd.print(MasterReceive); //Prints MasterReceive in LCD received from Slave
Serial.println(«Master Received From Slave»); //Prints in Serial Monitor
Serial.println(MasterReceive);
delay(500);
lcd.clear();

1
2
3
4
5
6
7
8
9

lcd.setCursor(,);//Sets Currsor at line one of LCD

lcd.print(«>>  Master  <<«);//Prints >> Master << at LCD

lcd.setCursor(,1);//Sets Cursor at line two of LCD

lcd.print(«SlaveVal:»);//Prints SlaveVal: in LCD

lcd.print(MasterReceive);//Prints MasterReceive in LCD received from Slave

Serial.println(«Master Received From Slave»);//Prints in Serial Monitor

Serial.println(MasterReceive);

delay(500);

lcd.clear();

Why another I2C library?

  • the I2C pins SDA/SCL are in use already for other purposes,
  • the code shall run on an ATtiny processor with 1 MHz on arbitrary pins,
  • you are short on memory (flash and RAM), or
  • you do not want to use the implicitly enabled pull-up resistors
    because your devices are run with 3 volts.

If you want a solution running on an ARM MCU (Due, Zero, Teensy 3.x), you want to use pins
on port H or above on an ATmega256, or you want to use many different I2C buses,
this library is not the right solution for you. In these cases, another
bit-banging I2C library written in pure C++ could perhaps help you: SlowSoftI2CMaster.

1Описание интерфейса I2C

Последовательный протокол обмена данными IIC (также называемый I2C – Inter-Integrated Circuits, межмикросхемное соединение) использует для передачи данных две двунаправленные линии связи, которые называются шина последовательных данных SDA (Serial Data) и шина тактирования SCL (Serial Clock). Также имеются две линии для питания. Шины SDA и SCL подтягиваются к шине питания через резисторы.

В сети есть хотя бы одно ведущее устройство (Master), которое инициализирует передачу данных и генерирует сигналы синхронизации. В сети также есть ведомые устройства (Slave), которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Адрес устройства указывается в паспорте (datasheet). К одной шине I2C может быть подключено до 127 устройств, в том числе несколько ведущих. К шине можно подключать устройства в процессе работы, т.е. она поддерживает «горячее подключение».

Описание интерфейса I2C

Давайте рассмотрим временную диаграмму обмена по протоколу I2C. Есть несколько различающихся вариантов, рассмотрим один из распространённых. Воспользуемся логическим анализатором, подключённым к шинам SCL и SDA.

Мастер инициирует обмен. Для этого он начинает генерировать тактовые импульсы и посылает их по линии SCL пачкой из 9-ти штук. Одновременно на линии данных SDA он выставляет адрес устройства, с которым необходимо установить связь, которые тактируются первыми 7-ми тактовыми импульсами (отсюда ограничение на диапазон адресов: 27 = 128 минус нулевой адрес). Следующий бит посылки – это код операции (чтение или запись) и ещё один бит – бит подтверждения (ACK), что ведомое устройство приняло запрос. Если бит подтверждения не пришёл, на этом обмен заканчивается. Или мастер продолжает посылать повторные запросы.

Это проиллюстрировано на рисунке ниже. Задача такая: подключиться к ведомому устройству с адресом 0x27 и передать ему строку «SOLTAU.RU». В первом случае, для примера, отключим ведомое устройство от шины. Видно, что мастер пытается установить связь с устройством с адресом 0x27, но не получает подтверждения (NAK). Обмен заканчивается.

Попытка мастера установить соединение с ведомым по I2C

Теперь подключим к шине I2C ведомое устройство и повторим операцию. Ситуация изменилась. На первый пакет с адресом пришло подтверждение (ACK) от ведомого. Обмен продолжился. Информация передаётся также 9-битовыми посылками, но теперь 8 битов занимают данные и 1 бит – бит подтверждения получения ведомым каждого байта данных. Если в какой-то момент связь оборвётся и бит подтверждения не придёт, мастер прекратит передачу.

Временная диаграмма обмена по протоколу I2C

Описание методов библиотеки LiquidCrystal I2C

LiquidCrystal_I2C(uint8_t, uint8_t, uint8_t)

Конструктор для создания экземпляра класса, первый параметр это I2C адрес устройства, второй — число символов, третий — число строк.

LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);

1 LiquidCrystal_I2C(uint8_tlcd_Addr,uint8_tlcd_cols,uint8_tlcd_rows);

init()

Инициализация ЖК-дисплея.

void init();

1 voidinit();

backlight()

Включение подсветки дисплея.

void backlight();

1 voidbacklight();

setCursor(uint8_t, uint8_t)

Установка позиции курсора.

void setCursor(uint8_t, uint8_t);

1 voidsetCursor(uint8_t,uint8_t);

clear()

Возвращает курсор в начало экрана.

void clear();

1 voidclear();

home()

Возвращает курсор в начало экрана и удаляет все, что было на экране до этого.

void home();

1 voidhome();

write(uint8_t)

Позволяет вывести одиночный символ на экран.

#if defined(ARDUINO) && ARDUINO >= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif

1
2
3
4
5

#if defined(ARDUINO) && ARDUINO >= 100

virtualsize_twrite(uint8_t);

#else

virtualvoidwrite(uint8_t);

#endif

cursor()

Показывает курсор на экране.

void cursor();

1 voidcursor();

noCursor()

Скрывает курсор на экране.

void noCursor();

1 voidnoCursor();

blink()

Курсор мигает (если до этого было включено его отображение).

void blink();

1 voidblink();

noBlink()

Курсор не мигает (если до этого было включено его отображение).

void noBlink();

1 voidnoBlink();

display()

Позволяет включить дисплей.

void display();

1 voiddisplay();

noDisplay()

Позволяет отключить дисплей.

void noDisplay();

1 voidnoDisplay();

scrollDisplayLeft()

Прокручивает экран на один знак влево.

void scrollDisplayLeft();

1 voidscrollDisplayLeft();

scrollDisplayRight()

Прокручивает экран на один знак вправо.

void scrollDisplayRight();

1 voidscrollDisplayRight();

autoscroll()

Позволяет включить режим автопрокручивания. В этом режиме каждый новый символ записывается в одном и том же месте, вытесняя ранее написанное на экране.

void autoscroll();

1 voidautoscroll();

noAutoscroll()

Позволяет выключить режим автопрокручивания. В этом режиме каждый новый символ записывается в одном и том же месте, вытесняя ранее написанное на экране.

void noAutoscroll();

1 voidnoAutoscroll();

leftToRight()

Установка направление выводимого текста — слева направо.

void leftToRight();

1 voidleftToRight();

rightToLeft()

Установка направление выводимого текста — справа налево.

void rightToLeft();

1 voidrightToLeft();

createChar(uint8_t, uint8_t[])

Создает символ. Первый параметр — это номер (код) символа от 0 до 7, а второй — массив 8 битовых масок для создания черных и белых точек.

void createChar(uint8_t, uint8_t[]);

1 voidcreateChar(uint8_t,uint8_t);

5Создание собственных символов для ЖК дисплея

Немного подробнее рассмотрим вопрос создания собственных символов для ЖК экранов. Каждый символ на экране состоит из 35-ти точек: 5 в ширину и 7 в высоту (+1 резервная строка для подчёркивания). В строке 6 приведённого скетча мы задаём массив из 7-ми чисел: {0x0, 0xa, 0x1f, 0x1f, 0xe, 0x4, 0x0}. Преобразуем 16-ричные числа в бинарные: {00000, 01010, 11111, 11111, 01110, 00100, 00000}. Эти числа – не что иное, как битовые маски для каждой из 7-ми строк символа, где «0» обозначают светлую точку, а «1» – тёмную. Например, символ сердца, заданный в виде битовой маски, будет выглядеть на экране так, как показано на рисунке.

Создание собственного символа для LCD экрана

Features

This library has the following features:

  • supports only master mode
  • compatible with all 8-bit AVR MCUs
  • no bus arbitration (i.e., only one master allowed on bus)
  • clock stretching (by slaves) supported
  • timeout on clock stretching
  • timeout on ACK polling for busy devices (new!)
  • internal MCU pullup resistors can be used (new!)
  • can make use of almost any pin (except for pins on port H and above on large ATmegas)
  • very lightweight (roughly 500 bytes of flash and 0 byte of RAM, except for call stack)
  • it is not interrupt-driven
  • very fast (standard and fast mode on ATmega328, 33 kHz on ATtiny
    with 1 MHz CPU clock)
  • Optional library compatible interface
  • GPL license

7Что находится «за» шиной I2C

В качестве бонуса рассмотрим временную диаграмму вывода латинских символов «A», «B» и «С» на ЖК дисплей. Эти символы имеются в ПЗУ дисплея и выводятся на экран просто передачей дисплею их адреса. Диаграмма снята с выводов RS, RW, E, D4, D5, D6 и D7 дисплея, т.е. уже после преобразователя FC-113 «I2C параллельная шина». Можно сказать, что мы погружаемся немного «глубже» в «железо».

Временная диаграмма вывода латинских символов «A», «B» и «С» на LCD дисплей 1602

На диаграмме видно, что символы, которые имеются в ПЗУ дисплея (см. стр.11 даташита, ссылка ниже), передаются двумя полубайтами,
первый из которых определяет номер столбца таблицы, а второй – номер строки. При этом данные «защёлкиваются» по фронту сигнала на линии E (Enable), а линия RS (Register select, выбор регистра) находится в состоянии логической единицы, что означает передачу данных. Низкое состояние линии RS означает передачу инструкций, что мы и видим перед передачей каждого символа. В данном случае передаётся код инструкции возврата каретки на позицию (0, 0) ЖК дисплея, о чём также можно узнать, изучив техническое описание дисплея.

И ещё один пример. На этой временной диаграмме показан вывод символа «Сердце» на ЖК дисплей.

Временная диаграмма вывода символа «Сердце» из ПЗУ на ЖК дисплей 1602

Опять, первые два импульса Enable соответствуют инструкции Home() (0000 00102) – возврат каретки на позицию (0; 0), а вторые два – вывод на ЖК дисплей хранящийся в ячейке памяти 310 (0000 00112) символ «Сердце» (инструкция lcd.createChar(3, heart); скетча).

How to find the I2C address of my LCD?

Most I2C LCDs ship with the default address ‘0x27’, but it can be different depending on the batch/manufacturer. If this is the case, you will need to find the actual address of the LCD before you can start using it.

On the Arduino website, you can find a simple example sketch that scans the I2C-bus for devices. If a device is found, it will display the address in the serial monitor.

You can copy the code by clicking on the button in the top right corner of the code field.

/*I2C_scanner
  This sketch tests standard 7-bit addresses.
  Devices with higher bit address might not be seen properly.*/
  
#include <Wire.h>

void setup() {
  Wire.begin();

  Serial.begin(9600);
  while (!Serial);
  Serial.println("\nI2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for (address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.print(address, HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error == 4) {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);
}

If you upload this sketch to the Arduino and run it, you should see the following output in the Serial Monitor (Ctrl + Shift + M).

I2C address scanner Serial Monitor output

Write down the address you find, you will need it later when programming the LCD.

Creating the Program

1. Setting up

First start by connecting your Arduino Nano 33 BLE board to the computer and opening the Arduino Create Web Editor. This board will act as the reader. Start a new sketch and name it Nano_I2C_Reader.

2. Reader code explanation

Let’s start by adding the

The

Instead the focus is on the

onoff

3. Uploading the code to the reader

Once we have finished the code, let’s upload it to our Arduino Nano 33 BLE board. This board is now programmed to act as the reader in this scenario. Once the code is uploaded, let’s connect the other board to the computer.

4. Writer code

It is time to open a new sketch and name it as Nano_I2C_Writer, then let’s add the Wire library as we did in the previous code.

In the

Next, in the

With

The

5. Uploading the code to the writer

Once we have finished the code, let’s upload it to our Arduino Nano 33 BLE board. This board is now programmed to act as the writer.

6. Complete code

If you choose to skip the code building section, the complete code for both the reader and the writer can be found below:

I2C LCD Basics

This type of LCD is ideal for displaying text and numbers, hence the name ‘character LCD’. The I2C LCD that we are using in this tutorial comes with a small add-on circuit mounted on the back of the module. This module features a PCF8574 chip (for I2C communication) and a potentiometer to adjust the LED backlight. The advantage of an I2C LCD is that the wiring is very simple. You only need two data pins to control the LCD.

Standard LCDs typically require around 12 connections, which can be a problem if you do not have many GPIO pins available. Luckily, you can also buy the I2C add-on circuit separately on Amazon, so you can easily upgrade a standard LCD as well.

For a tutorial and wiring diagram for standard character LCDs, please see the following article:

How to use a 16×2 character LCD with Arduino

If you look closely at the LCD, you can see the small rectangles that form the individual characters of the LCD. Each rectangle is made up of a grid of 5×8 pixels. Later in this tutorial, I will show you how you can control the individual pixels to display custom characters on the LCD.

1Описание FC-113 преобразователя последовательного интерфейса в параллельный

  • Модуль FC-113 сделан на базе микросхемы PCF8574T, которая представляет собой 8-битный сдвиговый регистр – «расширитель» входов-выходов для последовательной шины I2C. На рисунке микросхема обозначена DD1.
  • R1 – подстроечный резистор для регулировки контрастности ЖК дисплея.
  • Джампер J1 используется для включения подсветки дисплея.
  • Выводы 1…16 служат для подключения модуля к выводам LCD дисплея.
  • Контактные площадки А1…А3 нужны для изменения адреса I2C устройства. Запаивая соответствующие перемычки, можно менять адрес устройства. В таблице приведено соответствие адресов и перемычек: «0» соответствует разрыву цепи, «1» – установленной перемычке. По умолчанию все 3 перемычки разомкнуты и адрес устройства 0x27.

I2C модуль FC-113 для подключения ЖК экрана

Conclusion

In this article, I have shown you how to use a character I2C LCD with Arduino. I hope you found it useful and informative. If you did, please share it with a friend that also likes electronics and making things!

I would love to know what projects you plan on building (or have already built) with these LCDs. If you have any questions, suggestions or if you think that things are missing in this tutorial, please leave a comment down below.

Note that comments are held for moderation to prevent spam.

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Beginner