Віримо в перемогу ЗСУ!
Працюємо з 09:00 до 18:00 Пн-Пт

Давайте разберемся с самой удобной коммуникацией физически заложенной в контроллеры Arduino

I2C это последовательная асимметричная шина для связи между интегральными схемами внутри электронных приборов. Тоесть данный протокол связи был разработан для внутренней связи внутри коробки устройства или внутри щита. Перед ним не ставилось задание передавать данные на большие расстояния, поэтому ходит множество мифов о максимальной дальности связи - у кого-то плохо работает уже при 50см, у кого-то при 2м.

На шине I2C может сидеть до 128 устройств. Адреса от 0 до 127.

В контроллерах Arduino заложена физическая коммуникация I2C, которая позволяет по двум информационным проводам подключать к ним как различные датчики, расширители дискретных входов-выходов, цифро-аналоговые и аналого-цифровые преобразователи, так и другие контроллеры.

О скорости передачи на сайте производителя не пишут. Но по общей документации на протокол она должна составлять как минимум 100 кбит/с



Теперь хотелось бы потестировать на сколько действительно хороша шина I2C, и на сколько сложно по ней обмениваться данными между несколькими контроллерами Arduino

Я возьму три контроллера Arduino Nano, объединю их шиной I2C, и разберусь, как по ней обмениваться данными. Первый контроллер будет выполнять роль ведущего, а остальные два - роль ведомого.

Для отображения данных буду использовать LCD-индикатор 1602 с модулем I2C, который будет подключен на ту же коммуникационную шину.

Ведущий контроллер будет последовательно опрашивать второго и третьего контроллера. Принятые данные первый контроллер должен выводить на индикатор. Опрос ведомых Arduino Nano будет проводиться с частотой 1 раз/сек.

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


Четыре провода от каждого из 4-х устройств нужно соединить параллельно. Вывод А4 платы Arduino Nano - это шина SDA протокола I2C, а А5 - это SCL.

Я буду использовать монтажные шилды под контроллеры Nano для удобства соединений.

Питание будет подаваться просто на один из контроллеров через mini USB вход.

У LCD адрес в сети I2C по умолчанию 27. У второго контроллера установим адрес 2 и у третьего 3. У ведущего первого контроллера адрес не нужен.

Программа контроллера - мастера.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
int nano1=0;
int nano2;
int nano3;

void setup()
{ 
  Wire.begin();
  Serial.begin(9600);
	// initialize the LCD
	lcd.begin();

	// Turn on the blacklight and print a message.
	lcd.backlight();
}

void loop()
{
  lcd.setCursor(0, 0);
  lcd.print(nano1);

  Wire.requestFrom(2, 2);    // request 6 bytes from slave device #8
  int i=0;nano2=0;
  while (Wire.available()) { // slave may send less than requested
    byte c = Wire.read(); // receive a byte as character
    Serial.print(c);
    if (i==0) nano2 = ((c & 0xff) << 8); else nano2 = nano2 | c;
    i++;
  }
  Serial.println("");
  Serial.println(nano2);
  lcd.setCursor(9, 0);
  lcd.print(nano2);
  delay(100);

  Wire.requestFrom(3, 2);    // request 6 bytes from slave device #8
  i=0;nano3=0;
  while (Wire.available()) { // slave may send less than requested
    byte c = Wire.read(); // receive a byte as character
    Serial.print(c);
    if (i==0) nano3 = ((c & 0xff) << 8); else nano3 = nano3 | c;
    i++;
  }
  lcd.setCursor(0, 1);
  lcd.print(nano3);
  delay(100);
  
  nano1++;
  delay(800);
}

Первый контроллер изменяет свою переменную типа integer и выводит ее значение на индикатор. Так же он поочереди опрашивает слейв со 2-м и 3-м адресом. Запрашивает у них два байта информации, преобразовывает их в переменную integer. В результате в первом контроллере крутятся три переменные с трёх Nano и он может вывести их на индикатор.

Программа второго контроллера

#include <Wire.h>

int nano2=0;
byte high[2];
void setup() {
  Wire.begin(2);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
}

void loop() {
  delay(1000);
  nano2--;
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  high[0] = (nano2 >> 8);
  high[1] = (nano2 & 0xff);
  Wire.write(high[0]); // respond with message of 2 bytes
  Wire.write(high[1]);
}

Программа третьего Arduino Nano

#include <Wire.h>

int nano2=0;
byte high[2];
void setup() {
  Wire.begin(3);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
}

void loop() {
  delay(1500);
  nano2--;
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  high[0] = (nano2 >> 8);
  high[1] = (nano2 & 0xff);
  Wire.write(high[0]); // respond with message of 2 bytes
  Wire.write(high[1]);
}

Отличаются последние две программы просто адресом в функции Wire.begin(3); и частотой изменения переменной.

Эти программы постоянно изменяют переменную integer и ожидают запроса от мастера. При запросе эта переменная раскладывается на два байта и отправляется как ответ на запрос ведущему контроллеру.

Таким образом работу связи по I2C можно контролировать по изменяющимся значениям трех переменных на жидкокристаллическом индикаторе. 

Выводы

Прекрасно все работает - цифры на дисплее меняются. Я попробовал удлиннять шлейф проводов между вторым и третьим контроллерами Arduino. Проверил работу шины связи при длине 3 м - без притензий. Длиннее не пробовал, но многие мне утверждали, что I2C не работает дальше 0,5 ... 2 м и меня воодушевила длина 3 м.

Для себя я уже вижу, где применю такую связь именно между тремя Nano.

Я здесь ещё не попробовал передачу данных от мастера слейву. Если попробуете - отпишитесь. 

Недостатков здесь на небольших расстояниях ощутимо меньше чем превосходств.


Продолжение Arduino Nano I2C двухсторонняя связь между контроллерами


<< Проекты << Все товары >> Статьи, уроки >>

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Муфта на шаговый двигатель 6x8x25мм

Муфта на шаговый двигатель 6x8x25мм

Данная муфта служит переходником между валами 6 мм и 8 мм. Тоесть имеет с одной стороны отверстие ди..

60.56грн.

Припой-паста для пайки SMD-компонентов

Припой-паста для пайки SMD-компонентов

Паста-припой в шприце XG-Z40Намазывается на контактные площадки платы, плавится при температуре >..

241.00грн.

Модуль реле одноканальный 5В 10А

Модуль реле одноканальный 5В 10А

Одноканальный модуль реле для подключения напрямую к дискретному выходу контроллера. Светодиодная ин..

41.38грн.

Преобразователь RS232 в TTL

Преобразователь RS232 в TTL

Преобразователь для подключения устройств с коннектором DB9 к любительскому контроллеру. Для обмена ..

53.02грн.

3-осевой акселерометр ADXL345

3-осевой акселерометр ADXL345

Трёхосевой гравитационный акселерометр. Напряжение питания 3 ... 5 В Диапазон измерения настраивае..

97.04грн.