Продолжаем разбор технологии обмена данными по коммуникации I2C
В попередній статті розглядався приклад збору даних одним контролером Arduino NANO з двох інших таких же контролерів по шині I2C та відправка їх по цій же шині у рідкокристалічний індикатор. Тепер хотілося би розібратися з двохстороннім майже рівнозначним обміном між контролерами по I2C. Я візьму на цей раз два контролери Nano. Один буде виступати в ролі майстра, другий - слейву. Майстер періодично спочатку буде відправляти значення одної змінної integer підлеглому Arduino Nano, після чого робити запит на значення такої ж змінної від нього. А слейв при надходженні даних від майстра буде їх зчитувати, а при надходженні запиту буде відправляти один integer.
Відео щодо попередньої статті.
Програма майстра виглядає наступним чином
#include <Wire.h>
#define SLAVE_ADDRESS 0x01
byte high[2];
int com = 223;
int i;
int nano3;
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
high[0] = (com >> 8);
high[1] = (com & 0xff);
Wire.beginTransmission(0x01);
Wire.write(high[0]);
Wire.write(high[1]);
Wire.endTransmission();
Serial.println("Requesting Data");
Wire.requestFrom(SLAVE_ADDRESS, 2);
i=0;nano3=0;
while (Wire.available()) {
byte c = Wire.read();
if (i==0) nano3 = ((c & 0xff) << 8); else nano3 = nano3 | c;
i++;
}
Serial.print("nano3 ");
Serial.println(nano3);
delay(2000);
}
Перетворення даних виконано за мотивами попередньої статті.
Адреса слейву буде мати значення 01.
Відправляти будемо ціле число 223.
Програма контролера - слейва.
#include <Wire.h>
#define SLAVE_ADDRESS 0x01
int temp=22;
byte high[2];
int nano3;
void setup()
{
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Serial.begin(9600);
}
void loop()
{
delay(100);
}
void requestEvent()
{
Serial.println("Request from Master. Sending: ");
high[0] = (temp >> 8);
high[1] = (temp & 0xff);
Wire.write(high[0]);
Wire.write(high[1]);
}
void receiveEvent(int bytes)
{
int i=0;
nano3=0;
while (Wire.available()) {
byte c = Wire.read();
if (i==0) nano3 = ((c & 0xff) << 8); else nano3 = nano3 | c;
i++;
}
Serial.print("nano3 ");
Serial.println(nano3);
}
Слейв Arduino Nano приймає дані від головного контролера. В нашому випадку приймає цифру 223 та виводить її у монітор порта. А при запиті даних від майстра цей Нано відправляє ціле число 22. Усі запити від головного оброблюються за допомогою окремих функцій.
При правильному підключенні майстер у монітор порту буде виводити отримані цифри 22, а слейв 223.
Висновки
Виявилось, що в інтернеті за цією тематикою опубліковані або відверто не працюючі приклади програм або працюючі тільки з байтами. Довелося зробити по своєму та в результаті вийшло пречудове рішення.
Мені в наступному проекті буде необхідно підключити 10 Arduino Nano до головного контролера. При чому 8 з них повинні будуть обмінюватися з головним двохсторонніми даними. Для цього ідеально підійде комуникація I2C. Так що я в циклі контролера-майстра буду послідовно, можливо в циклі FOR опитувати слейвів та посилати їм керуючі дані. Буде весело!