Популярният I2C протокол позволява на две или повече Arduino платки да комуникират. Открийте как да ги свържете и кодирате.

Въпреки че един Arduino може да изпълни много задачи, някои проекти може да изискват използването на повече от една платка за обработка на различни функционалности. Така че, за да се даде възможност за пренос на данни между двата микроконтролера, трябва да се настрои комуникационен протокол като CAN, SPI, I2C или UART.

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

Какво е I2C?

Inter-Integrated Circuit (I2C) е широко използван комуникационен протокол във вградени системи и микроконтролери за позволяване на трансфер на данни между електронни устройства. За разлика от SPI (Serial Peripheral Interface), I2C ви позволява да свържете повече от едно главно устройство към шина с едно или множество подчинени устройства. Той е използван за първи път от Philips и е известен също като двупроводен комуникационен протокол (TWI).

instagram viewer

Как работи I2C комуникацията?

I2C използва две двупосочни линии: Серийни данни (SDA) и Сериен часовник (SCL) за прехвърляне на данни и синхронизиране на комуникацията между устройствата. Всяко устройство, свързано към I2C шината, има уникален адрес, който го идентифицира по време на комуникация. Протоколът I2C позволява на множество устройства да споделят една и съща шина и всяко устройство може да действа като главно или подчинено.

Комуникацията се инициира от главното устройство и неправилното адресиране на подчинените устройства може да причини грешки при прехвърлянето. Вижте нашето задълбочено ръководство за как работят серийните комуникации UART, SPI и I2C за да ви дам някакъв контекст.

Основно предимство на I2C комуникацията, което си струва да се отбележи, е гъвкавостта, която предлага, когато става въпрос за управление на захранването. Устройствата, които работят на различни нива на напрежение, все още могат да комуникират ефективно с помощта на превключватели на напрежението. Това означава, че устройствата, работещи на 3,3 V, се нуждаят от превключватели на напрежението, за да се свържат към 5V I2C шина.

Библиотеката на Wire

Библиотеката Wire е вградена библиотека на Arduino, която предоставя функции за комуникация през I2C. Той използва два пина - SDA и SCL - на платката Arduino за I2C комуникация.

I2C щифтове на Arduino Uno:

Arduino Nano I2C щифтове:

За да използвате библиотеката, трябва да включите Тел.ч заглавен файл в началото на вашата скица на Arduino.

#включват

Библиотеката Wire предоставя функции за иницииране на комуникация с I2C устройство, изпращане на данни и получаване на данни. Някои важни функции, които трябва да знаете, включват:

  • Wire.begin(): използва се за присъединяване към I2C шината и иницииране на комуникация.
  • Wire.beginTransmission(): използва се за указване на подчинен адрес и започване на предаване.
  • Wire.write(): използва се за изпращане на данни към I2C устройството.
  • Wire.endTransmission(): използва се за прекратяване на предаването и проверка за грешки.
  • Wire.requestFrom(): използва се за изискване на данни от I2C устройството.
  • Wire.available(): използва се за проверка дали има налични данни за четене от I2C устройството.
  • Wire.read(): използва се за четене на данни от I2C устройството.

Използвай Wire.beginTransmission() функция за задаване на адреса на сензора, който се вмъква като аргумент. Например, ако адресът на сензора е 0x68, бихте използвали:

Тел.започнете предаване(0x68);

Хардуерна настройка на Arduino I2C

За да свържете две платки Arduino с помощта на I2C, ще ви трябват следните хардуерни компоненти:

  • Две платки Arduino (главна и подчинена)
  • Бредборд
  • Джъмперни проводници
  • Два издърпващи резистора 4,7 kΩ

Свържете SDA и SCL щифтове на двете Arduino платки към макет. Свържете издърпващите резистори между SDA и SCL щифтове и 5V захранваща шина на макетната платка. Накрая свържете двете дъски за тестване заедно с помощта на джъмпери.

Arduino Uno схема

Arduino Nano Circuit

Кредит за изображение: Arduino I2C документация

Настройване на платките Arduino като I2C главни и подчинени устройства

Използвай Wire.requestFrom() функция за указване на адреса на подчиненото устройство, с което искаме да комуникираме. След това използвайте Wire.read() функция за получаване на данни от подчиненото устройство.

Главен код на устройството:

#включват
невалиденнастройвам(){
Тел.започвам(); // присъединете се към i2c шина
Сериен.започвам(9600); // стартира сериен за изход
}
невалиденreceiveData(){
вътр адрес = 8;
вътр bytesToRead = 6;
Тел.requestFrom(адрес, bytesToRead);
докато (Тел.на разположение()) {
въглен данни = Тел.Прочети();
Сериен.печат(данни);
}
забавяне(500);
}
невалиденцикъл(){
receiveData();
}

The Wire.onReceive() функцията се използва за указване какво да се прави, когато подчиненото устройство получи данни от главното устройство. В горния код, Wire.available() функцията проверява дали има налични данни и Wire.read() функция чете данните, изпратени от главното устройство.

Код на подчинено устройство:

#включват
невалиденнастройвам(){
Тел.започвам(8); // присъединете се към I2C шината с адрес 8
Тел.onReceive(receiveEvent); // извикване на receiveEvent при получаване на данни
}
невалиденцикъл(){
забавяне(100);
}
невалиденreceiveEvent(вътр байтове){
Тел.пишете("Здравейте "); // отговаря със съобщение от 6 байта, както се очаква от главния
}

Изпращане и получаване на данни чрез I2C

В този пример нека прочетем температурата от температурен сензор DHT11, свързан с подчинения Arduino, и да го отпечатаме на серийния монитор на главния Arduino.

Нека модифицираме кода, който написахме по-рано, за да включва измерването на температурата, което след това ще изпратим до главната платка през I2C шината. След това главната платка може да прочете стойността, която изпратихме, след което да я покаже на серийния монитор.

Главен код на устройството:

#включват
невалиденнастройвам(){
Тел.започвам();
Сериен.започвам(9600);
Сериен.println(„Мастерът е инициализиран!“);
}
невалиденцикъл(){
Тел.requestFrom(8, 1); // Изискване на данни за температурата от slave
ако (Тел.на разположение()) {
байт температура = Тел.Прочети(); // Прочетете данни за температурата от подчинен
Сериен.печат("Температура:");
Сериен.печат(температура);
Сериен.println("° C");
}
забавяне(2000); // Изчакайте 2 секунди, преди да поискате отново температура
}

Код на подчинено устройство:

#включват
#включват

#дефинирам DHTPIN 4 // Пин, свързан към DHT сензор
#дефинирам DHTTYPE DHT11 // DHT тип сензор
DHT dht(DHTPIN, DHTTYPE);
байт температура;

невалиденнастройвам(){
Тел.започвам(8); // Адресът на подчинения е 8
Тел.onRequest(requestEvent);
dht.започвам();
}

невалиденцикъл(){
забавяне(2000); // Изчакайте 2 секунди DHT да се стабилизира
температура = dht.readTemperature(); // Прочетете температурата от DHT сензора
}

невалиденrequestEvent(){
Тел.пишете(температура); // Изпращане на данни за температурата до мастера
}

Можете да персонализирате този код, за да отговаря на сензорите, които може да имате във вашия проект, или дори да показвате стойностите на сензора на дисплейния модул, за направете свой собствен стаен термометър и влагомер.

Подчинено адресиране с I2C на Arduino

За да прочетете стойности от компоненти, добавени към I2C шина в такъв проект, е важно да включите правилния подчинен адрес при кодирането. За щастие, Arduino предлага библиотека за скенери, която опростява процеса на идентифициране на подчинено устройство адреси, елиминирайки необходимостта от преглеждане на дълги информационни листове за сензори и объркване онлайн документация.

Използвайте следния код, за да идентифицирате адреса на подчинено устройство, присъстващ в I2C шината.

#включват // Включете Wire библиотеката за I2C комуникация

невалиденнастройвам(){
Тел.започвам(); // Инициализиране на I2C комуникацията
Сериен.започвам(9600); // Инициализиране на серийната комуникация със скорост на предаване от 9600 бода
докато (!Сериен); // Изчакайте серийната връзка да се установи
Сериен.println("\nI2C скенер"); // Отпечатване на съобщение, указващо началото на I2C сканиране
}

невалиденцикъл(){
байт грешка, адрес; // Деклариране на променливи за съхраняване на грешки и адреси на устройства
вътр nУстройства; // Деклариране на променлива за съхраняване на броя на намерените устройства

Сериен.println(„Сканиране...“); // Отпечатване на съобщение, указващо началото на I2C сканиране

nУстройства = 0; // Задайте броя на намерените устройства на 0
за (адрес = 1; адрес < 127; адрес++) { // Итериране на всички възможни I2C адреси
Тел.започнете предаване(адрес); // Стартиране на предаване към текущия адрес
грешка = Тел.endTransmission(); // Прекратете предаването и запазете всички грешки

ако (грешка == 0) { // Ако не са намерени грешки
Сериен.печат(„I2C устройство намерено на адрес 0x“); // Отпечатване на съобщение, показващо, че е намерено устройство
ако (адрес < 16) Сериен.печат("0"); // Ако адресът е по-малък от 16, добавете водеща 0 за целите на форматирането
Сериен.печат(адрес, HEX); // Отпечатайте адреса в шестнадесетичен формат
Сериен.println(" !"); // Отпечатване на съобщение, показващо, че е намерено устройство

nDevices++; // Увеличете броя на намерените устройства
}
другоако (грешка == 4) { // Ако е открита грешка
Сериен.печат(„Неизвестна грешка на адрес 0x“); // Отпечатване на съобщение, показващо, че е открита грешка
ако (адрес < 16) Сериен.печат("0"); // Ако адресът е по-малък от 16, добавете водеща 0 за целите на форматирането
Сериен.println(адрес, HEX); // Отпечатайте адреса в шестнадесетичен формат
}
}
ако (nУстройства == 0) { // Ако не са намерени устройства
Сериен.println(„Няма намерени I2C устройства\n“); // Отпечатване на съобщение, показващо, че не са намерени устройства
}
друго { // Ако са намерени устройства
Сериен.println("готово\n"); // Отпечатване на съобщение, указващо края на I2C сканирането
}
забавяне(5000); // Забавяне за 5 секунди преди започване на следващото сканиране
}

Разширете проекта си днес

Взаимодействието на две платки Arduino с помощта на комуникационния протокол I2C предлага гъвкав и ефективен начин за постигане на сложни задачи, които не могат да бъдат обработени от една платка. С помощта на библиотеката Wire комуникацията между двете платки, използващи I2C, е лесна, което ви позволява да добавяте повече компоненти към вашия проект.