====== Расширитель I2C (хаб) ======
===== Описание =====
Расширитель I2C - представляет из себя плату, на которой имеется несколько выводов для подключения устройств по интерфейсу I2C. Данный модуль позволит подключить до 6 устройств, работающих по I2C одновременно, задействовав для этого только один интерфейс контроллера. 

Подключать расширитель к контроллеру будет удобно через Sensor Shield - на нем уже предусмотрен готовый разъем I2C - просто подсоедините к шилду разъем "I2C IN" модуля посредством четырехпроводного шлейфа.

Избегайте подключения нескольких устройств с одинаковыми адресами - это может привести к конфликту устройств и их некорректной работе.

==== Технические характеристики ====
  * Интерфейс подключения к контроллеру: I2C
  * Максимальное количество подключаемых устройств: 6

==== Физические размеры ====
  * Модуль Д х Ш х В (мм): 30 х 20 х 10

==== Плюсы использования ====
  * Удобное подключение к Sensor shield
  * Возможность увеличить количество подключенных устройств к контроллеру
  * Удобное подключение к расширителю с помощью 4-ёх проводных шлейфов

==== Минусы использования ====
  * Модуль немного дороже, чем подключение проводами через макетную плату

===== Примеры использования и подключения =====
**Пример 1:** В примере демонстрируется подключение нескольких устройств к расширителю. Далее, с помощью скетча ниже, определяются адреса устройств, которые подключены к модулю.

^ Что нужно                                                                                                               ^  Кол-во, шт  ^
| [[http://smartelements.ru/collection/kontrollery/product/kontroller-smart-uno|Контроллер Smart UNO]]                            |  1           |
| [[http://smartelements.ru/collection/shildy/product/sensor-shield|Sensor Shield]]             |  1           |
| [[http://smartelements.ru/collection/moduli/product/rasshiritel-i2c-hab|Расширитель I2C]]             |  1           |
| [[https://smartelements.ru/collection/moduli/product/modul-chasov-pcf8563|Модуль часов PCF8563]]             |  1           |
| [[http://smartelements.ru/collection/displei-i-indikatory/product/displey-lcd1602-2-strochnyy-s-i2c-modulem-2|Дисплей 2-строчный с I2C модулем]]             |  1           |
| [[http://smartelements.ru/collection/displei-i-indikatory/product/displey-lcd2004-4-strochnyy-s-i2c-modulem|Дисплей 4-строчный с I2C модулем]]             |  1           |
| [[http://smartelements.ru/collection/provoda-i-kabeli/product/shleyf-mama-mama-h4-20-sm|Шлейф "мама-мама" х4]]  |  4           |

**Схема подключения:**
Подключение расширителя и устройств к нему происходит напрямую, для этого удобно использовать [[http://smartelements.ru/collection/provoda-i-kabeli/product/shleyf-mama-mama-h4-20-sm|4-ёх проводной шлейф]]. Если на устройстве выводы расположены в другом порядке, подключите к расширителю с помощью обычных проводов мама-мама (или тех, которые подходят к Вашему устройству).
{{ :главная:модули:i2c.jpg?nolink |}}

**Скетч для загрузки:**
<file Arduino>
#include <Wire.h> //подключение библиотеки


void setup()
{
  Wire.begin(); //инициализация шины
  Serial.begin(9600); //инициализация монитора Serial-порта
  while (!Serial); //ожидание доступности порта
  Serial.println("I2C Scanner");
}


void loop()
{
  //вспомогательные переменные
  byte error; //хранение кода ошибки
  byte address; //хранение адреса устройства
  int nDevices = 0; //счётчик устройств

  Serial.println("Scanning..."); //вывод надписи

  for (address = 1; address < 127; address++ )
  {
    /* Для поиска устройств воспользуемся функцией коммуникации и
     *  окончания коммуникации с устройством на адресе от 1 до 127. 
     *  При окончании коммуникации возвращается код ошибки.
     *  Если он не равен нулю, то коммуникация прошла успешно,
     *  и устройство на данном адресе найдено.
     *  В противном случае выводится информация об ошибке.
     */
    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) { //если код ошибки равен 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");
  } else {
    Serial.print("Found ");
    Serial.print(nDevices);
    Serial.println(" devices");
  }

  delay(5000);  //пауза в 5 секунд между сканированием
}
</file>

**Результат:**
<file>
Scanning...
I2C device found at address 0x27  !
I2C device found at address 0x51  !
Found 2 devices
</file>

<WRAP center round info 80%>
В результате подключения, в мониторе Serial-порта видно два подключенных устройства. И тут возникает логичный вопрос:

**Было подключено три устройства, куда одно пропало?**

Мы специально добавили такие устройства, чтобы продемонстрировать одну особенность шины I2C. Дело в том, что если устройства имеют одинаковый адрес, то шиной они определяются как одно. Так как плата модуля I2C, которая имеется на дисплеях, имеет один и тот же адрес (0x27), то оба дисплея определяются как одно и то же устройство.

**Как понять, какое из устройств какой адрес имеет?**

Здесь не существует универсального способа, но самое простое что приходит в голову, это отсоединить от Расширителя I2C все устройства кроме одного, и проверить именно его адрес. Так Вы сможете определить адреса требуемых устройств. Помните, что даже разные устройства могут иметь один и тот же адрес I2C, имейте это ввиду в своих проектах и избегайте подключения на одну шину устройств с одинаковым адресом!
В нашем примере Дисплеи имеют адрес **0x27**, а часы имеют адрес **0x51**.
</WRAP>

**Пример 2:** В примере демонстрируется подключение часов и дисплея к Расширителю I2C. Далее происходит вывод времени, дня недели и даты на дисплей.

^ Что нужно                                                                                                               ^  Кол-во, шт  ^
| [[http://smartelements.ru/collection/kontrollery/product/kontroller-smart-uno|Контроллер Smart UNO]]                            |  1           |
| [[http://smartelements.ru/collection/shildy/product/sensor-shield|Sensor Shield]]             |  1           |
| [[http://smartelements.ru/collection/moduli/product/rasshiritel-i2c-hab|Расширитель I2C]]             |  1           |
| [[https://smartelements.ru/collection/moduli/product/modul-chasov-pcf8563|Модуль часов PCF8563]]             |  1           |
| [[http://smartelements.ru/collection/displei-i-indikatory/product/displey-lcd1602-2-strochnyy-s-i2c-modulem-2|Дисплей 2-строчный с I2C модулем]]             |  1           |
| [[http://smartelements.ru/collection/provoda-i-kabeli/product/shleyf-mama-mama-h4-20-sm|Шлейф "мама-мама" х4]]  |  3           |

**Схема подключения:**
Подключение расширителя и устройств к нему происходит напрямую, для этого удобно использовать [[http://smartelements.ru/collection/provoda-i-kabeli/product/shleyf-mama-mama-h4-20-sm|4-ёх проводной шлейф]]. Если на устройстве выводы расположены в другом порядке, подключите к расширителю с помощью обычных проводов мама-мама (или тех, которые подходят к Вашему устройству.
{{ :главная:модули:i2c.jpg?nolink |}}

**Скетч для загрузки:**
<file Arduino>
#include <LiquidCrystal_I2C.h> //подключение библиотеки для работы с дисплеем
#include <Wire.h>  //библиотека для работы с I2C
#include <Rtc_Pcf8563.h> //библиотека для работы с часами

LiquidCrystal_I2C lcd(0x27, 16, 2); //создание объекта дисплея с адресом и количеством символов/строк
Rtc_Pcf8563 rtc; //создание объекта для работы с часами

void setup() {
  lcd.init(); //инициализация дисплея
  /* Следующие строки кода нужны только один раз,
   *  для установки времени на часах. 
   *  Поэтому закомментируйте эти строки, вызывая их повторно.
   *  И не забудьте при первом включении,
   *  подставить свои значения, соответствующие
   *  текущей дате и времени.
   */
  //очистка регистров часов
  //rtc.initClock();
  //установка даты:
  //день месяца, день недели, месяц, век(1=1900, 0=2000), год(0-99)
  //в следующей строке установлена дата 20 ноября 2018 года (вторник)
  //rtc.setDate(20, 2, 11, 0, 18);
  //Установка времени
  //часы, минуты, секунды
  //rtc.setTime(14, 55, 0);
}

void loop() {
  lcd.home(); //установка курсора в верхний левый угол
  lcd.print(rtc.formatTime()); //вывод текущего времени на дисплее
  lcd.setCursor(0, 1); //установка курсора на вторую строку
  lcd.print(rtc.getWeekday()); //вывод текущего дня недели
  lcd.setCursor(2, 1); //установка курсора на третью ячейку
  lcd.print(rtc.formatDate()); //вывод даты
}
</file>