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

Использование

// ===== СЕРВИС =====
void init();                    // инициализация
void clear();                   // очистить дисплей
void clear(int x0, int y0, int x1, int y1); // очистить область
void setContrast(uint8_t value);    // яркость 0-15
void setPower(bool mode);       // вкл/выкл
void flipH(bool mode);          // отразить по горизонтали
void invertDisplay(bool mode);  // инвертировать дисплей
void flipV(bool mode);          // отразить по вертикали

// ===== ПЕЧАТЬ =====
// наследует класс Print, то есть print/println любой тип данных

void autoPrintln(bool mode);    // автоматически переносить текст
void home();                    // отправить курсор в 0,0
void setCursor(int x, int y);   // поставить курсор для символа столбец 0-127, строка 0-8(4)
void setCursorXY(int x, int y); // поставить курсор для символа столбец 0-127, пиксель 0-63(31)
void setScale(uint8_t scale);   // масштаб шрифта (1-4)
void invertText(bool inv);      // инвертировать текст (0-1)
bool isEnd();                   // возвращает true, если дисплей "кончился" - при побуквенном выводе

void textMode(byte mode);       // режим отрисовки текста
BUF_ADD - добавить
BUF_SUBTRACT - вычесть
BUF_REPLACE - заменить

// ===== ГРАФИКА =====
// далее fill:
OLED_CLEAR - очистить область под фигурой
OLED_FILL - залить фигуру
OLED_STROKE - обвести фигуру

void dot(int x, int y, byte fill);                      // точка (заливка 1/0)
void fastLineH(int y, int x0, int x1, byte fill);       // горизонтальная линия
void fastLineV(int x, int y0, int y1, byte fill);       // вертикальная линия
void rect(int x0, int y0, int x1, int y1, byte fill);   // прямоугольник (лев. верхн, прав. нижн)	
void roundRect(int x0, int y0, int x1, int y1, byte fill);  // прямоугольник скруглённый (лев. верхн, прав. нижн)
void circle(int x, int y, int radius, byte fill);       // окружность (центр х, центр у, радиус, заливка)
void bezier(int* arr, uint8_t size, uint8_t dense, uint8_t fill);   // кривая Безье

// вывести битмап
// invert - BITMAP_NORMAL/BITMAP_INVERT инвертировать
// mode BUF_ADD / BUF_SUBTRACT / BUF_REPLACE
void drawBitmap(int x, int y, const uint8_t *frame, int width, int height, uint8_t invert = , byte mode = );

void fill(uint8_t data);                        // залить весь дисплей указанным байтом
void drawByte(uint8_t data);                    // шлёт байт в "столбик" setCursor() и setCursorXY()
void drawBytes(uint8_t* data, byte size);       // вывести одномерный байтовый массив (линейный битмап высотой 8)
void update();                                  // полностью обновить дисплей из буфера
void update(int x0, int y0, int x1, int y1);    // выборочно обновить дисплей из буфера (x0, y0, x1, y1)

Объяснение программы для Arduino

Полный код программы для нашего pH метра на основе Arduino приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.

Первым делом в программе мы должны подключить все используемые библиотеки. В нашем случае мы подключили библиотеку “LiquidCrystal_I2C.h” для использования интерфейса I2C с целью обмена данными с ЖК дисплеем и библиотеку “Wire.h” для использования функционала интерфейса I2C в плате Arduino.

Arduino

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

1
2
3

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

LiquidCrystal_I2Clcd(0x27,16,2);

Далее определим калибровочное значение, которое в дальнейшем можно будет изменить (переопределить, откалибровать) для получения более точных значений pH.

Arduino

float calibration_value = 21.34;

1 floatcalibration_value=21.34;

Внутри функции setup() мы будем отображать на экране ЖК дисплея приветственное сообщение.

Arduino

lcd.init();
lcd.begin(16, 2);
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(» Welcome to «);
lcd.setCursor(0, 1);
lcd.print(» Circuit Digest «);
delay(2000);
lcd.clear();

1
2
3
4
5
6
7
8
9

lcd.init();

lcd.begin(16,2);

lcd.backlight();

lcd.setCursor(,);

lcd.print(»   Welcome to      «);

lcd.setCursor(,1);

lcd.print(» Circuit Digest    «);

delay(2000);

lcd.clear();

Внутри функции loop() мы будем считывать 10 аналоговых значений (отсчетов) и сохранять их в массив – это необходимо для сглаживания результата измерений.

Arduino

for(int i=0;i<10;i++)
{
buffer_arr=analogRead(A0);
delay(30);
}

1
2
3
4
5

for(inti=;i<10;i++)

{

buffer_arri=analogRead(A0);

delay(30);

}

Затем мы отсортируем принятые аналоговые значения по возрастанию. Это необходимо для расчета скользящего среднего отсчетов на более поздней стадии (в дальнейшем).

Arduino

for(int i=0;i<9;i++)
{
for(int j=i+1;j<10;j++)
{
if(buffer_arr>buffer_arr)
{
temp=buffer_arr;
buffer_arr=buffer_arr;
buffer_arr=temp;
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12

for(inti=;i<9;i++)

{

for(intj=i+1;j<10;j++)

{

if(buffer_arri>buffer_arrj)

{

temp=buffer_arri;

buffer_arri=buffer_arrj;

buffer_arrj=temp;

}

}

}

Наконец, мы рассчитаем среднее 6-ти центральных отсчетов в наших аналоговых значениях. Затем это рассчитанное среднее мы преобразуем (конвертируем) в значение pH и выводим его на экран ЖК дисплея.

Arduino

for(int i=2;i<8;i++)
avgval+=buffer_arr;
float volt=(float)avgval*5.0/1024/6;
float ph_act = -5.70 * volt + calibration_value;
lcd.setCursor(0, 0);
lcd.print(«pH Val:»);
lcd.setCursor(8, 0);
lcd.print(ph_act);
delay(1000);
}

1
2
3
4
5
6
7
8
9
10

for(inti=2;i<8;i++)

avgval+=buffer_arri;

floatvolt=(float)avgval*5.010246;

floatph_act=-5.70*volt+calibration_value;

lcd.setCursor(,);

lcd.print(«pH Val:»);

lcd.setCursor(8,);

lcd.print(ph_act);

delay(1000);

}

Сравнение BH1750 и TSL2561

Спектр видимого света колеблется от 380 нм (фиолетовый) до 780 нм (красный) (в вакууме). Короче говоря, BH1750 просто измеряет это. TSL2561, помимо видимого спектра, также измеряет инфракрасное излучение. Он имеет два диода, один для видимого, а второй для инфракрасного. На мой взгляд, BH1750 соответствует большинству требований, тогда как TSL2561 предлагает более широкий спектр, большую чувствительность и большую точность.

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

Более подробно о том, как работать с TSL2561 в Ардуино, можете найти в отдельной статье Подключение цифрового датчика освещенности TSL2561 к Arduino.

На следующем рисунке показана схема подключения датчиков внешней освещенности TSL2561 и BH1750 к Arduino UNO.

Пример скетча

#include <Wire.h>
#include <BH1750.h>
#include <Adafruit_TSL2561_U.h>

BH1750 bh1750;
Adafruit_TSL2561_Unified tsl2561 = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);

void setup() {
Serial.begin(9600);
Wire.begin();

/*
TSL2561
*/
if (!tsl2561.begin()) {
Serial.print(F(«При обнаружении TSL2561 возникла проблема … проверьте подключение!»));
while (1);
}

tsl2561.setGain(TSL2561_GAIN_1X);
tsl2561.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);

/*
BH1750
*/
bh1750.begin(BH1750::ONE_TIME_HIGH_RES_MODE);

Serial.println(F(«BH1750 vs TSL2561»));
}

void loop() {
/*
Считываем показания с TSL2561
*/
sensors_event_t event;
tsl2561.getEvent(&event);
/*
Считываем показания с BH1750
*/
float lux = bh1750.readLightLevel();
/*
Отправляем значение освещенности в последовательный порт
*/
if (event.light) {
Serial.print(F(«TSL2561: «));
Serial.print(event.light);
Serial.println(F(» lx»));
} else {
/*
Если event.light = 0 люкса датчик, вероятно, насыщенные
и достоверные данные не может быть сгенерированы!
*/
Serial.println(F(«Насыщенные TSL2561»));
}
Serial.print(F(«BH1750 : «));
Serial.print(lux);
Serial.println(F(» lx»));

delay(1000);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

#include <Wire.h>
#include <BH1750.h>
#include <Adafruit_TSL2561_U.h>
 

BH1750bh1750;

Adafruit_TSL2561_Unifiedtsl2561=Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT,12345);

voidsetup(){

Serial.begin(9600);

Wire.begin();

/*

     TSL2561
  */

if(!tsl2561.begin()){

Serial.print(F(«При обнаружении TSL2561 возникла проблема … проверьте подключение!»));

while(1);

}

tsl2561.setGain(TSL2561_GAIN_1X);

tsl2561.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);

/*

    BH1750
  */

bh1750.begin(BH1750::ONE_TIME_HIGH_RES_MODE);

Serial.println(F(«BH1750 vs TSL2561»));

}
 

voidloop(){

/*

    Считываем показания с TSL2561
  */

sensors_event_tevent;

tsl2561.getEvent(&event);

/*

    Считываем показания с BH1750
  */

floatlux=bh1750.readLightLevel();

/*

    Отправляем значение освещенности в последовательный порт
  */

if(event.light){

Serial.print(F(«TSL2561: «));

Serial.print(event.light);

Serial.println(F(» lx»));

}else{

/*

      Если event.light = 0 люкса датчик, вероятно, насыщенные
      и достоверные данные не может быть сгенерированы!
    */

Serial.println(F(«Насыщенные TSL2561»));

}

Serial.print(F(«BH1750 : «));

Serial.print(lux);

Serial.println(F(» lx»));

delay(1000);

}

Результат

По результатам TSL2561 и BH1750 дают практически идентичные показатели в одинаковых условиях. Это говорит о том, что сами датчики идут откалиброванными с завода.

Методы библиотеки

begin()

Инициализация библиотеки Wire и подключение к шине I2C в качестве ведущего или ведомого устройства. Как правило, вызывается только один раз.

Параметры

address: 7-битный адрес устройства (если работаем в режиме ведомого). Если не указано, то контроллер подключается к шине в роли ведущего (master).

requestFrom()

Используется ведущим устройством для запроса байта от ведомого устройства. Байты могут быть получены с помощью методов available() и read().

Параметры

  • address: 7-битный адрес устройства для запроса байтов данных
  • quantity: количество запрошенных байт

Возвращает число считанных байт.

beginTransmission()

Начало передачи I2C для ведомого устройства с заданным адресом. Затем, нужно вызвать метод write() для добавления последовательности байт в очередь предназначенных для передачи, и выполнить саму передачу данных методом endTransmission().

Параметры

address: 7-битный адрес устройства для передачи.

endTransmission()

Завершает передачу данных для ведомого устройства, которое было начато beginTransmission() и, фактически, осуществляет передачу байт, которые были поставлены в очередь методом write().

Параметры

Нет

Возвращает байт, который указывает статус передачи:

  • 0: успех
  • 1: данных слишком много и они не помещается в буфер передачи/размер буфера задаётся определением #define BUFFER_LENGTH 32
  • 2: получили NACK на передачу адреса
  • 3: получили NACK на передачу данных
  • 4: другая ошибка

write()

Записывает данные от ведомого устройства в ответ на запрос мастера, или записывает очередь байт для передачи от мастера к ведомому устройству (в промежутках между вызовами beginTransmission() и endTransmission()).

Параметры

  • value: значение для отправления как единичный байт
  • string: строка для отправления как последовательность байт
  • data: массив байт для отправления
  • length: число байт для передачи

Возвращает число записанных байт.

available()

Метод available() наследуется от класса Stream. Возвращает количество байт, доступных для получения. Этот метод должно быть вызван на мастере, после вызова requestFrom() или ведомым внутри обработчика onReceive().

Параметры

Нет.

Число байт, доступных для чтения.

read()

Метод read() наследуется от класса Stream. Считывает байт, который был передан от ведомого устройства к мастеру, после вызова requestFrom() или был передан от мастера к ведомому.

Параметры

Нет.

Следующий полученный байт.

onReceive()

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

Параметры

function: функция, которая вызывается, когда ведомый получает данные; обработчик должен принимать один параметр — int (число байт, считанных от мастера) и ничего не возвращать. Например:
void MyHandler (int numBytes);

Параметры

function: функция, которая будет вызываться; не имеет параметров и ничего не возвращает.
например:
void MyHandler();

Способ 2: чтение датчика DS18B20 по адресу

Мы знаем, что каждому DS18B20 назначен уникальный 64-битный адрес, чтобы отличать их друг от друга. В этом методе мы найдем этот адрес для соответствующей маркировки каждого датчика. Затем этот адрес можно использовать для считывания каждого датчика в отдельности.

Поиск адресов датчиков DS18B20s на шине

Следующий скетч обнаруживает все DS18B20, присутствующие на шине, и печатает их адреса на 1-Wire в монитор последовательного порта.

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

Теперь откройте монитор последовательного порта. Вы должны получить что-то подобное:

Рисунок 6 – Нахождение адресов 1-Wire всех датчиков DS18B20 на шине

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

Чтение показаний датчиков DS18B20 по адресу

Следующий скетч считывает температуру датчиков DS18B20 по их адресам. Прежде чем приступить к загрузке скетча, вам нужно изменить адреса датчиков DS18B20 на те, которые вы определили в предыдущем скетче.

Вывод вышеприведенного эскиза выглядит так

Рисунок 7 – Вывод показаний нескольких датчиков DS18B20 методом адреса

Объяснение кода

Как обычно, скетч начинается с включения библиотек, объявления вывода, к которому подключена шина датчиков, и создания объекта библиотеки .

Далее мы вводим адреса, которые были найдены ранее для каждого датчика температуры. В нашем случае имеем следующее.

Во фрагменте настройки мы инициализируем библиотеку путем вызова функции и инициализируем последовательную связь с ПК.

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

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

Вышеприведенная функция просто вызывает библиотечные функции для отображения температуры в градусах Цельсия и для отображения температуры в градусах Фаренгейта.

1Описание интерфейса I2C

Последовательный протокол обмена данными IIC (также называемый I2C – Inter-Integrated Circuits, межмикросхемное соединение) использует для передачи данных две двунаправленные линии связи, которые называются шина последовательных данных SDA (Serial Data) и шина тактирования SCL (Serial Clock). Также имеются две линии для питания. Шины SDA и SCL подтягиваются к шине питания через резисторы.

В сети есть хотя бы одно ведущее устройство (Master), которое инициализирует передачу данных и генерирует сигналы синхронизации. В сети также есть ведомые устройства (Slave), которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Адрес устройства указывается в паспорте (datasheet). К одной шине I2C может быть подключено до 127 устройств, в том числе несколько ведущих. К шине можно подключать устройства в процессе работы, т.е. она поддерживает «горячее подключение».

Описание интерфейса I2C

Давайте рассмотрим временную диаграмму обмена по протоколу I2C. Есть несколько различающихся вариантов, рассмотрим один из распространённых. Воспользуемся логическим анализатором, подключённым к шинам SCL и SDA.

Мастер инициирует обмен. Для этого он начинает генерировать тактовые импульсы и посылает их по линии SCL пачкой из 9-ти штук. Одновременно на линии данных SDA он выставляет адрес устройства, с которым необходимо установить связь, которые тактируются первыми 7-ми тактовыми импульсами (отсюда ограничение на диапазон адресов: 27 = 128 минус нулевой адрес). Следующий бит посылки – это код операции (чтение или запись) и ещё один бит – бит подтверждения (ACK), что ведомое устройство приняло запрос. Если бит подтверждения не пришёл, на этом обмен заканчивается. Или мастер продолжает посылать повторные запросы.

Это проиллюстрировано на рисунке ниже. Задача такая: подключиться к ведомому устройству с адресом 0x27 и передать ему строку «SOLTAU.RU». В первом случае, для примера, отключим ведомое устройство от шины. Видно, что мастер пытается установить связь с устройством с адресом 0x27, но не получает подтверждения (NAK). Обмен заканчивается.

Попытка мастера установить соединение с ведомым по I2C

Теперь подключим к шине I2C ведомое устройство и повторим операцию. Ситуация изменилась. На первый пакет с адресом пришло подтверждение (ACK) от ведомого. Обмен продолжился. Информация передаётся также 9-битовыми посылками, но теперь 8 битов занимают данные и 1 бит – бит подтверждения получения ведомым каждого байта данных. Если в какой-то момент связь оборвётся и бит подтверждения не придёт, мастер прекратит передачу.

Временная диаграмма обмена по протоколу I2C

Калибровка pH электрода

Калибровка pH электрода играет существенную роль в нашем проекте. Для проведения калибровки нам будет нужна жидкость (вещество) с известным значением pH, будем называть эту жидкость контрольным раствором.

Предположим, что у нас есть жидкость, значение pH которой равно 7 (дистиллированная вода). К примеру, при погружении в эту жидкость мы получим на экране ЖК дисплея значение 6.5. В данном случае для осуществления калибровки нам будет необходимо просто добавить значение 7-6.5=0.5 к значению калибровочной переменной (“calibration_value”) в коде нашей программы, то есть получим ее значение равное 21.34 + 0.5=21.84. После внесения этих изменений в код программы ее необходимо заново загрузить в плату Arduino и снова проверить работу устройства путем погружения электрода в контрольный раствор (с известным значением pH). Теперь на экране ЖК дисплея мы должны увидеть уже точное значение pH равное 7. Если оно будет все равно немного отличаться от своего истинного значения, то снова корректируем калибровочное значение в коде программы и снова тестируем работу проекта.

Асинхронный опрос пачки датчиков

// пример компактного асинхронного опроса датчиков на программном таймере
// https://alexgyver.ru/lessons/time/

// количество датчиков для удобства
#define DS_SENSOR_AMOUNT 5

// создаём двухмерный массив с адресами
uint8_t addr[] = {
  {0x28, 0xFF, 0x78, 0x5B, 0x50, 0x17, 0x4, 0xCF},
  {0x28, 0xFF, 0x99, 0x80, 0x50, 0x17, 0x4, 0x4D},
  {0x28, 0xFF, 0x53, 0xE5, 0x50, 0x17, 0x4, 0xC3},
  {0x28, 0xFF, 0x42, 0x5A, 0x51, 0x17, 0x4, 0xD2},
  {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE},
};

#include <microDS18B20.h>
// указываем DS_ADDR_MODE для подключения блока адресации
// и создаём массив датчиков на пине D2
MicroDS18B20<2, DS_ADDR_MODE> sensor;

void setup() {
  Serial.begin(9600);
  // устанавливаем адреса
  for (int i = ; i < DS_SENSOR_AMOUNT; i++) {
    sensor.setAddress(addr);
  }
}

void loop() {
  // конструкция программного таймера на 1c
  static uint32_t tmr;
  if (millis() - tmr >= 1000) {
    tmr = millis();

    // выводим показания в порт
    for (int i = ; i < DS_SENSOR_AMOUNT; i++) {
      Serial.print(sensor.getTemp());
      Serial.print(',');
      //delay(5); // возможно понадобится дилей, у меня работает без него
    }
    Serial.println();

    // запрашиваем новые
    for (int i = ; i < DS_SENSOR_AMOUNT; i++) {
      sensor.requestTemp();
      //delay(5); // возможно понадобится дилей, у меня работает без него
    }
  }
}

Протокол 1-Wire

Протокол 1-Wire – это протокол, используемый для управления устройствами, которые производятся компанией Dallas Semiconductor (ныне Maxim). Хотя 1-Wire является приприетарным протоколом и торговой маркой Dallas, программисты, использующие драйверы 1-Wire, не обязаны делать за это никаких выплат.

Сеть 1-Wire, которую Dallas называет MicroLan (торговая марка), состоит из одного ведущего устройства, к которому при помощи единственной линии передачи данных подключено одно или несколько ведомых устройств. Эту линию, помимо прочего, можно использовать для электропитания ведомых устройств (ситуацию, когда устройства подпитываются через шину 1-Wire, называют «паразитным питанием»).

Среди прочих устройств, работающих через протокол 1-Wire, особенно популярны температурные датчики – они недороги, просты в использовании и позволяют напрямую считывать откалиброванные цифровые температурные данные. Кроме того, они терпимы к длинным проводам, которыми часто приходится пользоваться при создании цепи с Arduino. Один из примеров ниже демонстрирует, как работать с 1-Wire на примере цифрового термометра DS18S20. Многие чипы 1-Wire могут работать и через паразитное, и через нормальное питание.

Использование

void begin(void);            				// инициализация шины
void setClock(uint32_t clock);       		// ручная установка частоты шины 31-900 kHz (в герцах)
void beginTransmission(uint8_t address); 	// открыть соединение (для записи данных)
uint8_t endTransmission(bool stop);  		// закрыть соединение , произвести stop или restart (по умолчанию - stop)
uint8_t endTransmission(void);  			// закрыть соединение , произвести stop
void write(uint8_t data);                	// отправить в шину байт данных , отправка производится сразу , формат - byte "unsigned char"
void requestFrom(uint8_t address , uint8_t length , bool stop); //открыть соединение и запросить данные от устройства, отпустить или удержать шину
void requestFrom(uint8_t address , uint8_t length);  			//открыть соединение и запросить данные от устройства, отпустить шину
uint8_t read(void);                      	// прочитать байт , БУФЕРА НЕТ!!! , читайте сразу все запрошенные байты , stop или restart после чтения последнего байта, настраивается в requestFrom
uint8_t available(void);                 	// вернет количество оставшихся для чтения байт

Библиотека Wire

Библиотека Wire входит в состав Arduino и используется для работы с шиной I2C.

В скетче сначала необходимо активировать библиотеку, затем в setup() активировать шину.

Поскольку как правило плата Arduino действует как ведущее устройство, ей не нужно присваивать адрес. Если бы плата настраивалась на работу в режиме ведомого устройства, нам пришлось бы присвоить адрес в диапазоне от 0 до 127, передав его как параметр, чтобы уникально идентифицировать плату на шине I2C.

Передача данных по шине осуществляется по одному байту. Чтобы послать байт из платы Arduino в устройство на шине, необходимо вызвать три функции:

  • Первая функция инициализирует связь, как показано ниже (где аргумент address — это адрес ведомого устройства на шине в шестнадцатеричном виде, например 0x50):

  • Вторая функция посылает 1 байт данных из Arduino в устройство с адресом, указанным в предыдущем вызове функции. Здесь аргумент data — это переменная, содержащая 1 байт данных; вы можете послать несколько байтов, но для каждого байта придётся вызвать Wire.write():

  • По завершении передачи данных определённому устройству следует разорвать связь:

Чтобы запросить данные из устройства на шине I2C, инициализируйте связь вызовом Wire.beginTransmission(address) и отправьте запрос Wire.requestFrom(address, x), (где x — количество запрашиваемых байтов данных). Затем с помощью следующей функции нужно сохранить принятый байт в переменной:

По окончании приёма следует разорвать связь вызовом Wire.endTransmission().

Библиотеки для работы с датой и временем ардуино

Библиотека RTClib

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

Пример использования:

#include <RTClib.h>

RTC_DS1307 RTC; – выбор датчика (в данном случае DS1307).

rtc.adjust(DateTime( Date, Time)); – настройка времени и календаря.

dayOfTheWeek () – вывод дня недели. Аргумент от 0 до 6, 0 – воскресенье.

Библиотека Timelib

Позволяет Ардуино получать информацию о дате и времени в данный момент.

Пример использования:

#include <TimeLib.h>

Time(); – создание экземпляра.

setTime (t); – установка времени. Аргумент t – час, минута, секунда, день, месяц и год.

timeStatus(); – показывает, установлено ли время.

adjustTime(adjustment); – настройка времени.

Библиотека Ds1307

Библиотека для удобного взаимодействия часов DS1307 с Ардуино c использованием библиотеки Wire.

Пример использования:

#include <DS1307RTC.h>

class DS1307RTC – создание объекта DS1307.

SetTime() – установка времени.

get() – считывает RTC, возвращает полученную дату в формате POSIX.

Set(time_t t) – запись даты в RTC

Библиотека DS 3231

Предназначена для управления датой и временем в модуле ds3231.

#include “ds3231.h”

DS3231  Clock(SDA, SCL); – создание объекта DS3231, подключение к линии тактирования и линии данных.

getTime(); – считывание даты и времени с часов.

setDate(date, mon, year); – установка даты.