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

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

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

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

двухстороннюю связь между двумя Arduino

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

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

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

Контакты Arduino I2C.

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

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

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

Плата

Пин SDA

Пин SCL

Arduino Uno, Nano, Pro и Pro Mini

A4

A5

Arduino Mega

20

21

Arduino Leonardo

2

3

Arduino Due

20, SDA1

21, SCL1

Библиотека "Wire".

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

Функция

Назначение

begin(address)

Инициализация библиотеки и подключение к шине I2C,

если не указан адрес, то присоединённое устройство считается ведущим. Используется 7-битная адресация.

requestFrom()

Используется ведущим устройством для запроса определённого количества байтов от ведомого.

beginTransmission(address)

Начало передачи данных к ведомому устройству по определённому адресу.

endTransmission()

Прекращение передачи данных ведомому.

write()

Запись данных от ведомого в ответ на запрос.

available()

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

read()

Чтение байта, переданного от ведомого ведущему или от ведущего ведомому.

onReceive()

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

onRequest()

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

Более подробное описание функций с примерами смотрите на странице библиотеки Wire.

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

I2C связь двух Arduino.

I2C связь двух Arduino.

Передача данных от ведущего к ведомому устройству. Здесь будем использовать две Arduino UNO: одна как ведущая, а другой как ведомая.
Для реализации нашего урока за основу возьмем пример библиотеки Wire, предоставленный Arduino, вместе с IDE.
Из библиотеки Wire мы используем master_writer для Arduino в качестве главного и slave_receiver для Arduino в качестве подчиненного устройства. В этом примере числовое значение будет передаваться от ведущего к ведомому, и ведомый отобразит его в последовательном мониторе порта.
Используемые примеры можно найти:
Файл -> Примеры -> Wire -> master_writer

#include <Wire.h>
void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
}
byte x = 0;
void loop() {
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write("x is ");        // sends five bytes
  Wire.write(x);              // sends one byte
  Wire.endTransmission();    // stop transmitting
  x++;
  delay(500);
}

Файл -> Примеры -> Wire -> slave_receive

#include <Wire.h>
void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}
void loop() {
  delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

При использовании данного примера в мониторе порта ведомого (slave) устройства получим вот такие данные.

При использовании данного примера в мониторе порта ведомого (slave) устройства получим вот такие данные.

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

Для реализации двусторонней связи между двумя Arduino с помощью шины I2C напишем программу, в которой будем отправлять сообщение "Hello" ведомому устройству, а ведомое устройство ответит на полученное сообщение словом "Hi". В данном примере две Arduino Uno используются как ведущий (master) и ведомый (slave).

Скетч для Master.

    #include <wire.h>
    void setup() {
 Serial.begin(9600); /* begin serial comm. */
 Wire.begin(); /* join i2c bus as master */
 Serial.println("I am I2C Master");
}
void loop() {
 Wire.beginTransmission(8); /* begin with device address 8 */
 Wire.write("Hello Slave");  /* sends hello string */
 Wire.endTransmission();    /* stop transmitting */
 Wire.requestFrom(8, 9); /* request & read data of size 9 from slave */
 while(Wire.available()){
    char c = Wire.read();/* read data received from slave */
  Serial.print(c);
 }
 Serial.println();
 delay(1000);
}
    </wire.h>

Скетч для Slave.

#include <Wire.h>
void setup() {
 Wire.begin(8);                /* join i2c bus with address 8 */
 Wire.onReceive(receiveEvent); /* register receive event */
 Wire.onRequest(requestEvent); /* register request event */
 Serial.begin(9600);           /* start serial comm. */
 Serial.println("I am I2C Slave");
}
void loop() {
 delay(100);
}
// function that executes whenever data is received from master
void receiveEvent(int howMany) {
 while (0 <Wire.available()) {
    char c = Wire.read();      /* receive byte as a character */
    Serial.print(c);           /* print the character */
  }
 Serial.println();             /* to newline */
}
// function that executes whenever data is requested from master
void requestEvent() {
 Wire.write("Hi Master");  /*send string on request */
}

В мониторе порта мастера будет выводить ответ ведомого устройства.

В мониторе порта мастера будет выводить ответ ведомого устройства.

А в ведомом устройстве будет отвечать приветом на запрос.

А в ведомом устройстве будет отвечать приветом на запрос.

Вывод.

Как видим из примера, двустороннюю связь двух Arduino по I2C реализовать достаточно просто. Но тут есть и свои подводные камни. Wire.read() работают с одним байтом информации, поэтому больше 255 не передать. Для передачи большого числа, и числа с плавающей запятой не получиться без применения дополнительных алгоритмов обработки. Данный пример разберем в следующем уроке по данной теме. А также подключим 5-7 различных устройств по I2C и научим их общаться друг с другом.

Мы рады объявить о нашем присутствии на Boosty! Arduino-Tex приглашает всех наших друзей и последователей поддержать нас на этой замечательной платформе. Здесь вы найдете эксклюзивный контент, уникальные проекты и возможность стать частью нашей творческой команды. Присоединяйтесь к нам на Boosty и вместе мы сделаем мир Arduino еще удивительнее!

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

А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в группу на Facebook.

Спасибо за внимание!

Технологии начинаются с простого!

Фотографии к статье

Файлы для скачивания

Скетч для Master Скетч для Master.ino1 Kb 836 Скачать
Скетч для Slave Скетч для Slave.ino1 Kb 810 Скачать

Комментарии

Ваше Имя*

Сергей

Гость: Сергей (21 декабря, 2021 в 13:10)

Интересно! Спасибо!

Михаил

Гость: Михаил (18 ноября, 2021 в 18:06)

Доброе время суток.

Спасибо за вашу статью, понятно описано. Хоть и не нашёл второй урок по I2C с описанием передали чисел с плавающей запятой.

прочитал урок как связать две или более ардуины по i2c - вопросов вроде пока нет

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

Но как теперь это вот всё соеденить? Чтоб и датчик работал от ардуины, и связь была с другой ардуиной?

причём скорее всего ардуина с датчиком должна быть слейвом, т.е. тактовые импульсы генерирует мастер.... но эта же слейв ардуина должна каким-то макаром по этому же протоколу опрашивать датчик!



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

Уроки Arduino
18 сентября , 2020
Комментариев:2
Файлов для скачивания:2
Фото:4
Понравилась статья? Нажми


Разработка проектов