Обмен данными между arduino i2c

Урок 1. Двусторонняя связь между двумя Arduino с использованием I2C.

При разработке проектов на Arduino часто возникает потребность в увеличении возможности, а пинов не достаточно. Также бывает необходимость объединить несколько работающих узлов для обмена данными, т.е. реализовать двухстороннюю связь между двумя Arduino. Для реализации двусторонней связи между двумя Arduino отлично подойдёт шина I2C.

Интерфейс I 2 C (или по-другому IIC) — это достаточно широко распространённый сетевой последовательный интерфейс, придуманный фирмой Philips и завоевавший популярность относительно высокой скоростью передачи данных, дешевизной и простотой реализации.

Шина I2C синхронная, состоит из двух линий: данных (SDA) и тактов (SCL). При проектировании есть 2 типа устройств: ведущий (master) и ведомый (slave). Инициатором обмена всегда выступает ведущий, обмен между двумя ведомыми невозможен. Всего на одной двухпроводной шине может быть до 127 устройств.

Такты на линии SCL генерирует ведущий (master). Линией SDA могут управлять как мастер, так и ведомый (slave), в зависимости от направления передачи. Единицей обмена информации является пакет, обрамленный уникальными условиями на шине, именуемыми стартовым и стоповым условиями. Мастер в начале каждого пакета передает один байт, где указывает адрес ведомого и направление передачи последующих данных. Данные передаются 8-битными словами. После каждого слова передается один бит подтверждения приема приемной стороной.

Ведущее устройство инициирует связь с ведомым устройством. Для начала разговора требуется адрес ведомого устройства. Подчиненное устройство реагирует на ведущее устройство, когда к нему обращается ведущее устройство.

I 2 C используется во многих приложениях, таких как чтение RTC (часы реального времени), доступ к внешней памяти EEPROM. Он также используется в сенсорных модулях, таких как гироскоп, магнитометр и т. д.

Контакты Arduino I2C.

Выводы I2C расположены следующим образом на плате Arduino Uno.

Для других моделей плат соответствие выводов такое:

Источник

Урок 26.3 Соединяем две arduino по шине I2C

При создании некоторых проектов, требуется разделить выполняемые задачи между несколькими arduino.

В этом уроке мы научимся соединять две arduino по аппаратной шине I2C.

Преимущества:

  • Реализуется возможность подключения до 126 устройств.
    (не рекомендуется присваивать устройствам адреса 0x00 и 0x7F)
  • Не требуются дополнительные модули.
  • Все устройства одинаково подключаются к шине.
  • Каждое ведомое устройство имеет свой уникальный адрес на шине.

Недостатки:

  • Код программы немного сложнее чем для шины UART.

Нам понадобится:

  • Arduino х 3шт.
  • LCD дисплей LCD1602 IIC/I2C(синий) или LCD1602 IIC/I2C(зелёный) х 1шт.
  • Trema Shield х 3шт.
  • Trema кнопка x 2шт.
  • Trema светодиод x 1шт.
  • Trema потенциометр x 1шт.
  • Trema I2C Hub x 1шт.
  • Шлейф «мама-мама» (4 провода) для шины I2С х 4шт.

Для реализации проекта нам необходимо установить библиотеки:

  • Библиотека LiquidCrystal_I2C_V112 (для подключения дисплеев LCD1602 по шине I2C).
  • Библиотека iarduino_I2C_connect (для удобства соединения нескольких arduino по шине I2C).

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki — Установка библиотек в Arduino IDE, а о том, как работать с LCD дисплеями, на странице Wiki — Работа с символьными ЖК дисплеями.

Видео:

Схема подключения:

На шине i2С находятся 4 устройства: 3 arduino и 1 LCD дисплей. Все устройства шины I2C соединены через Trema I2C Hub. Для подключения Arduino используются аппаратные выводы шины I2C.

  • Arduino master — к цифровому выводу D2 подключена trema кнопка.
  • Arduino slave 0x01 — к цифровому выводу D2 подключена trema кнопка.
  • Arduino slave 0x02 — к цифровому выводу D13 подключён trema светодиод, к аналоговому выводу A0 подключён Trema потенциометр.
  • LCD I2C дисплей — является устройством slave 0x27.

На шине I2C не используются дополнительные подтягивающие резисторы (для линий SDA и SCL), так как они интегрированы в LDC I2C дисплее.

Код программы:

Arduino master:
Arduino slave 0x01:
Arduino slave 0x02:

Алгоритм работы:

  • Arduino master проверяет состояние собственной кнопки.
  • Arduino master опрашивает две Arduino Slave.
    • Arduino Slave 0x01 возвращает состояние кнопки.
    • Arduino Slave 0x02 возвращает значение падения напряжения плеча потенциометра.
  • Arduino master мастер отправляет состояние своей кнопки в Arduino Slave 0x02.
    • Arduino Slave 0x02 включает или выключает светодиод, в соответствии с полученными данными.
  • Arduino master отправляет данные о состояниях кнопки Arduino Slave 0x01 и потенциометра Arduino Slave 0x02 на LCD I2C дисплей.

Настройка параметров шины I2C:

Максимальная, аппаратно реализуемая частота передачи данных, может достигать 1/16 от тактовой частоты.

Библиотека Wire позволяет устанавливать скорость передачи данных через функцию setClock(), которую требуется вызвать до функции begin().

Библиотека Wire позволяет аппаратно подключить Arduino к шине I2C с указанием роли Arduino на шине: ведущий или ведомый.

  • Wire.setClock(400000); // скорость передачи данных 400 кБит/с.
  • Wire.begin(); // подключение к шине I2C в роли ведущего.
  • Wire.begin(адрес); // подключение к шине I2C в роли ведомого, с указанием адреса.

Функции библиотеки iarduino_I2C_connect:

В библиотеке iarduino_I2C_connect реализованы 4 функции: 2 для ведущего и 2 для ведомого.

На ведомом устройстве достаточно вызвать функцию begin() с указанием массива, данные которого требуется сделать доступными для мастера. Далее можно работать с этим массивом, «забыв» про шину I2C. Мастер обращаясь к ведомому сможет получать и изменять данные элементов указанного массива (обращаясь к номеру элемента массива как к номеру регистра).

Если требуется запретить мастеру менять значения некоторых ячеек массива, то достаточно вызвать «необязательную» функцию writeMask() с указанием маскировочного массива, каждый элемент которого является флагом, разрешающим запись в соответствующий элемент массива доступного по шине I2C.

На ведущем устройстве доступны функции readByte() и writeByte(). Указывая в качестве параметров функций, адрес ведомого устройства и номер регистра, можно побайтно читать и записывать данные.

Функции для ведомого:

begin():

  • Назначение: указание массива, элементы которого будут доступны для чтения/записи по шине I2C.
  • Синтаксис: begin(массив); // тип данных массива — byte.
  • Возвращаемые значения: Нет.
  • Примечание: Вызывается 1 раз в коде функции Setup().

writeMask():

  • Назначение: указание маскировочного массива, каждый элемент которого является флагом разрешения записи по шине I2C.
  • Синтаксис: writeMask(маскировочный_массив); // тип данных массива — bool.
  • Возвращаемые значения: Нет.
  • Примечание: Вызывается 1 раз в коде функции Setup().
  • Пример:
    #include
    #include
    iarduino_I2C_connect ccc;
    byte aaa[5]; // объявляем 5 элементов массива, к которому разрешим доступ.
    bool bbb[5] = <0,1,1,1,0>; // объявляем 5 элементов маскировочного массива.
    Wire.begin(0x33); // подключаемся к шине I2C в роли ведомого с адресом 0x33.
    ccc.begin(aaa); // разрешаем доступ к массиву aaa по шине I2C.
    ccc.wtiteMask(bbb); // маскируем разрешение на запись в массив aaa.
    • В соответствии со значениями массива bbb, мастер сможет записывать данные в ячейки 1,2,3 массива aaa, а попытка записи в 0 и 4 элементы будет проигнорирована.
    • Если массив aaa имеет больше элементов чем массив bbb, то попытка мастера записать данные в «лишние» элементы будет проигнорирована.
    • Если не объявлять маскировочный массив (не вызывать функцию writeMask() вообще), то все элементы массива aaa будут доступны для записи мастером.
Функции для ведущего:

readByte():

  • Назначение: Чтение одного байта данных из устройства на шине I2C.
  • Синтаксис: readByte(адрес_устройства, адрес_регистра);
  • Возвращаемые значения: uint8_t байт — данные считанные из указанного адреса, указанного устройства.
  • Примечание: Если производится чтение по шине I2C из массива объявленного функцией begin(), то адрес регистра соответствует номеру элемента массива.

Источник

Использование интерфейса I2C в Arduino – полное руководство

В предыдущей статье на нашем сайте мы рассмотрели использование интерфейса SPI в плате Arduino. А здесь мы рассмотрим еще один очень популярный в настоящее время протокол последовательной связи I2C (Inter Integrated Circuits — последовательная шина обмена данными между интегральными схемами ) и как его использовать в плате Arduino. Если сравнивать протоколы I2C и SPI, то I2C использует только 2 линии (провода), а SPI использует 4 линии, I2C может иметь несколько ведущих (Master) и несколько ведомых (Slave), а SPI может иметь только одного ведущего и нескольких ведомых. То есть если в вашем проекте сразу несколько микроконтроллеров должны быть ведущими, то тогда вам нужно использовать интерфейс (протокол) I2C. Протокол I2C обычно используется для взаимодействия с гироскопами, акселерометрами, датчиками давления, LED дисплеями и т.д.

В этом проекте мы будем использовать протокол I2C для обмена данными между двумя платами Arduino и передавать между ними значения (от 0 до 127) с помощью потенциометра. Эти принятые значения будут отображаться на ЖК дисплеях, подключенных к каждой плате Arduino. Одна из плат Arduino будет выступать в роли ведущего (Master), а другая – в роли ведомого (Slave).

Что такое протокол I2C и как он работает

Термин IIC расшифровывается как “Inter Integrated Circuits” и часто обозначается как I2C или даже как TWI (2-wire interface protocol), но во всех случаях за этими обозначениями скрывается один и тот же протокол. I2C представляет собой протокол синхронной связи – это значит что оба устройства, которые обмениваются информацией с помощью данного протокола должны использовать общий сигнал синхронизации. Поскольку в этом протоколе используются всего 2 линии (провода), то по одной из них должен передаваться сигнал синхронизации, а по другой – полезная информация.

Впервые протокол I2C был предложен фирмой Phillips. Протокол в самом простом случае соединяет с помощью 2-х линий 2 устройства, одно из устройств должно быть ведущим, а другое – ведомым. Связь возможна только между ведущим и ведомым. Преимуществом протокола (интерфейса) I2C является то, что к одному ведущему можно подключить несколько ведомых.

Схема связи с помощью протокола I2C представлена на следующем рисунке.

Назначение линий данного интерфейса:

  • Serial Clock (SCL): по ней передается общий сигнал синхронизации, генерируемый ведущим устройством (master);
  • Serial Data (SDA): по ней осуществляется передача данных между ведущим и ведомым.

В любой момент времени только ведущий может инициировать процесс обмена данными. Поскольку в этом протоколе допускается несколько ведомых, то ведущий должен обращаться к ним, используя различные адреса. То есть только ведомый с заданным (указанным) адресом должен отвечать на сигнал ведущего, а все остальные ведомые в это время должны «хранить молчание». Таким образом, мы можем использовать одну и ту же шину (линию) для обмена данными с несколькими устройствами.

Уровни напряжений для передаваемых сигналов в интерфейсе I2C жестко не определены. В этом плане I2C является достаточно гибким, то есть если устройство запитывается от напряжения 5v, оно для связи с помощью протокола I2C может использовать уровень 5v, а если устройство запитывается от напряжения 3.3v, то оно для связи с помощью протокола I2C может использовать уровень 3v. Но что делать если с помощью данного протокола необходимо связать между собой устройства, работающие от различных питающих напряжений? В этом случае используются преобразователи/переключатели напряжения (voltage shifters).

Существует несколько условий для осуществления передачи данных в протоколе I2C. Инициализация передачи начинается с падения уровня на линии SDA, которое определяется как условие для начала передачи (‘START’ condition) на представленной ниже диаграмме. Как видно из этого рисунка, в то время как на линии SDA происходит падение уровня, в это же самое время на линии SCL ведущий поддерживает напряжение высокого уровня (high).

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

Аналогичным образом, повышение уровня на линии SDA останавливает передачу данных, что на представленной диаграмме обозначено как условие окончания передачи данных (‘STOP’ condition). В это же самое время ведущим на линии SCL поддерживается напряжение высокого уровня (high).

На следующем рисунке представлена структура адреса ведомого в протоколе I2C.

Бит R/W показывает направление передачи следующих за ним байт, если он установлен в HIGH – это значит что будет передавать ведомый (slave), а если он установлен в low – это значит что будет передавать ведущий (master).

Каждый бит передается в своем временном цикле, то есть нужно 8 временных циклов чтобы передать байт информации. После каждого переданного или принятого байта 9-й временной цикл используется для подтверждения/не подтверждения (ACK/NACK) приема информации. Этот бит подтверждения (ACK bit) формируется либо ведомым, либо ведущим в зависимости от ситуации. Для подтверждения приема информации (ACK) на линии SDA ведущим или ведомым устанавливается низкий уровень (low) в 9 временном цикле, в противном случае происходит не подтверждение приема информации (NACK).

На следующем рисунке представлена структура передаваемого сообщения в протоколе I2C.

Где применяется протокол I2C

Протокол I2C используется для передачи информации только на короткие расстояния. Он обеспечивает достаточно надежную передачу данных из-за наличия в нем сигнала синхронизации. Обычно данный протокол используется для передачи информации от датчиков или других устройств ведущим устройствам. В данном случае несомненным удобством использования протокола I2C является то, что при обмене данными с ведомыми устройствами ведущий микроконтроллер использует минимум линий (контактов). Если вам нужна связь на более далекие расстояния, то вам необходимо присмотреться к протоколу RS232, если же вам нужна более надежная связь чем в протоколе I2C, то вам лучше использовать протокол SPI.

Протокол I2C в Arduino

На следующем рисунке показаны контакты платы Arduino UNO, которые используются для связи по протоколу I2C.

Линия протокола I2C Контакт платы Arduino UNO
SDA A4
SCL A5

Для осуществления связи по протоколу I2C в плате Arduino используется библиотека . В ней содержатся следующие функции для связи по протоколу I2C.

1. Wire.begin(address).

Эта команда производит инициализацию библиотеки Wire и осуществляет подключение к шине I2C в качестве ведущего (master) или ведомого (slave). 7-битный адрес ведомого в данной команде является опциональным и если он не указан [Wire.begin()], то устройство (плата Arduino) подключается к шине I2C в качестве ведущего (master).

2. Wire.read().

Эта функция используется для считывания байта, принятого от ведущего или ведомого.

3. Wire.write().

Эта функция используется для записи данных в устройство, являющееся ведомым или ведущим.

От ведомого ведущему (Slave to Master): ведомый записывает (передает) данные ведущему когда в ведущем работает функция Wire.RequestFrom().

От ведущему ведомому (Master to Slave): в этом случае функция Wire.write() должна использоваться между вызовами функций Wire.beginTransmission() и Wire.endTransmission().

Функцию Wire.write() можно использовать в следующих вариантах:

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

4. Wire.beginTransmission(address).

Эта функция используется для начали передачи по протоколу I2C устройству с заданным адресом ведомого (slave address). После этого вызывается функция Wire.write() с заданной последовательностью байт для передачи, а после нее функция endTransmission() для завершения процесса передачи.

5. Wire.endTransmission().

Эта функция используется для завершения процесса передачи ведомому устройству, который до этого был инициирован функциями beginTransmission() и Wire.write().

6. Wire.onRequest().

Эта функция вызывается когда ведущий запрашивает данные с помощью функции Wire.requestFrom() от ведомого устройства. В этом случае мы можем использовать функцию Wire.write() для передачи данных ведущему.

7. Wire.onReceive().

Эта функция вызывается когда ведомое устройство получает данные от ведущего. В этом случае мы можем использовать функцию Wire.read() для считывания данных передаваемых ведущим.

8. Wire.requestFrom(address,quantity).

Эта функция используется в ведущем устройстве чтобы запросить байты (данные) с ведомого устройства. После этого используется функция Wire.read() чтобы принять данные переданные ведомым устройством.
address: 7-битный адрес устройства, с которого запрашиваются байты (данные).
quantity: число запрашиваемых байт.

Необходимые компоненты

  1. Плата Arduino Uno – 2 шт. (купить на AliExpress).
  2. ЖК дисплей 16х2 – 2 шт. (купить на AliExpress).
  3. Потенциометр 10 кОм – 4 шт. (купить на AliExpress).
  4. Макетная плата.
  5. Соединительные провода.

Работа схемы

Схема проекта по применению интерфейса I2C в плате Arduino представлена на следующем рисунке.

Для демонстрации возможностей использования связи по протоколу I2C мы использовали две платы Arduino Uno с подключенными к ним ЖК дисплеями и потенциометрами. С помощью потенциометров будут определяться значения, передаваемые между платами в направлениях ведущий-ведомый и ведомый-ведущий.

Мы будем считывать аналоговое значение напряжения, подаваемое на контакт A0 платы Arduino с помощью потенциометра и преобразовывать его в цифровое значение в диапазоне от 0 до 1023 (с помощью АЦП на этом контакте). В дальнейшем эти значения с выхода АЦП (аналогово-цифрового преобразователя) будут преобразовываться в диапазон 0-127 поскольку мы можем передавать только 7-битные данные при помощи протокола I2C. Интерфейс I2C мы будем использовать на выделенных для него в плате Arduino контактах A4 и A5.

Значения на ЖК дисплее, подключенном к ведомой плате Arduino, будут изменяться в зависимости от положения потенциометра на ведущей стороне и наоборот.

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

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

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

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

Источник

Adblock
detector