diff --git a/README.md b/README.md
index b95fb00..9fbead9 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,18 @@
-[![Foo](https://img.shields.io/badge/Version-3.8-brightgreen.svg?style=flat-square)](#versions)
+[![Foo](https://img.shields.io/badge/Version-3.9-brightgreen.svg?style=flat-square)](#versions)
[![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/)
[![Foo](https://img.shields.io/badge/%E2%82%BD$%E2%82%AC%20%D0%9D%D0%B0%20%D0%BF%D0%B8%D0%B2%D0%BE-%D1%81%20%D1%80%D1%8B%D0%B1%D0%BA%D0%BE%D0%B9-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/)
# microDS18B20
-Легкая и простая библиотека для работы с 1-Wire (OneWire) термометрами Dallas DS18B20
+Легкая библиотека для работы с 1-Wire (OneWire) термометрами Dallas DS18B20
- Работа с несколькими датчиками на одном пине (режим адресации)
+- Хранение массива адресов в PROGMEM памяти
- Работа с одним датчиком на пине (без использования адресации)
- Расчет температуры в целых числах и с плавающей точкой
+- Чтение сырых данных для случаев сильной экономии памяти
- Проверка корректности полученной температуры
- Настраиваемое разрешение преобразования
-- Чтение сырых данных для случаев сильной экономии памяти
-- Проверка подлинности данных "на лету", с использованием CRC8 от Dallas
-- Расчет CRC8 (~6 мкс) или чтение из таблицы (<1 мкс + 256 байт flash)
+- Проверка подлинности данных
+- Проверка корректности работы датчика
### Совместимость
Совместима со всеми Arduino платформами (используются Arduino-функции)
@@ -42,9 +43,22 @@
## Инициализация
```cpp
-MicroDS18B20 ds; // один датчик на одном пине без адресации
-MicroDS18B20 ds; // несколько датчиков на одном пине с адресацией
-MicroDS18B20; // говорим, что датчик с адресацией, но не указываем адрес
+// один датчик на пине без адресации
+MicroDS18B20 ds;
+
+// несколько датчиков на пине с адресацией, указываем адрес (адрес - массив uint8_t)
+MicroDS18B20 ds;
+
+// указываем, что будем работать с адресацией. Сам адрес передадим позже (в setAddress())
+MicroDS18B20;
+
+// указываем, что будем работать с адресацией, и на линии будет несколько (amount) датчиков
+// см. пример async_read_many_bus
+MicroDS18B20;
+
+// указываем, что будем работать с адресацией, на линии будет несколько (amount) датчиков, а адреса будем хранить в PROGMEM
+// см. пример async_read_many_bus_pgm
+MicroDS18B20;
```
@@ -53,7 +67,7 @@ MicroDS18B20; // говорим, что дат
// ============= МЕТОДЫ КЛАССА =============
bool readAddress(uint8_t *addressArray); // Прочитать уникальный адрес термометра в массив. [true, если успешно]
void setAddress(uint8_t *addr); // установить (сменить) адрес
-void setResolution(uint8_t resolution); // Установить разрешение термометра 9-12 бит
+void setResolution(uint8_t resolution); // Установить разрешение 9-12 бит
bool online(); // проверить связь с датчиком (true - датчик онлайн). Шина должна быть подтянута
void requestTemp(); // Запросить новое преобразование температуры
@@ -63,6 +77,20 @@ float getTemp(); // получить значение
int16_t getTempInt(); // получить значение температуры в int
int16_t getRaw(); // получить "сырое" значение температуры (в 16 раз больше, чем реальная температура)
+// ======= МЕТОДЫ ДЛЯ ШИНЫ ДАТЧИКОВ =======
+// см. примеры async_read_many_bus и async_read_many_bus_pgm
+void setResolutionAll(uint8_t res); // Установить разрешение 9-12 бит у всех датчиков на линии
+void setResolution(uint8_t resolution, uint8_t idx); // Установить разрешение 9-12 бит (датчик под номером idx)
+bool online(uint8_t idx); // проверить связь (датчик под номером idx)
+
+void requestTempAll(); // запрос температуры у всех датчиков на линии
+void requestTemp(uint8_t idx); // Запросить новое преобразование температуры (датчик под номером idx)
+bool readTemp(uint8_t idx); // прочитать температуру с датчика (датчик под номером idx)
+
+float getTemp(uint8_t idx); // получить значение температуры в float (датчик под номером idx)
+int16_t getTempInt(uint8_t idx); // получить значение температуры в int (датчик под номером idx)
+int16_t getRaw(uint8_t idx); // получить "сырое" значение температуры (датчик под номером idx)
+
// =========== ФУНКЦИИ ВНЕ КЛАССА ===========
int DS_rawToInt(int data); // преобразовать raw данные в температуру int
float DS_rawToFloat(int data); // преобразовать raw данные в температуру float
@@ -124,6 +152,13 @@ if (sensor.readTemp()) value = sensor.getTemp();
где `readTemp()` запрашивает данные с датчика и возвращает `true`, если они прочитаны корректно. После этого можно забрать текущую температуру из `getTemp()`,
которая уже не запрашивает температуру с датчика, а отдаёт прочитанный в `readTemp()` результат.
+#### Подключаем много датчиков на один объект
+В версии библиотеки 3.9 появилась возможность подключить сколько угодно датчиков на один объект MicroDS18B20, не создавая массива объектов (как в старых версиях).
+Нужно создать двумерный массив адресов и передать его в библиотеку, также указав количество датчиков на линии (можно максимальное, если оно будет меняться в процессе работы программы).
+Это позволяет сэкономить немного памяти, но можно пойти дальше - засунуть массив адресов датчиков в PROGMEM, чтобы они не висели в оперативной памяти.
+Инициализация в этом случае выглядит так: `MicroDS18B20<пин, DS_ADDR_MODE, колич-во>;` или `MicroDS18B20<пин, DS_ADDR_MODE, колич-во, DS_PROGMEM>;` для PROGMEM режима.
+Адреса передаются в `setAddress()`, а для опроса просто передаём индекс датчика в те же функции что и раньше. Смотри примеры *async_read_many_bus*, *async_read_many_bus_pgm* и раздел документации *МЕТОДЫ ДЛЯ ШИНЫ ДАТЧИКОВ*.
+
## Подключение
![scheme](/doc/scheme.png)
@@ -316,6 +351,7 @@ void loop() {
- v3.6 - исправлена ошибка компиляции, добавлена поддержка GyverCore (спасибо ArtemiyKolobov)
- v3.7 - исправлена ошибка readTemp() при 0 градусов
- v3.8 - небольшая оптимизация. Совместимость с ESP32
+- v3.9 - добавил расширенный режим адресации и хранение адресов в PROGMEM
## Баги и обратная связь
diff --git a/examples/async_read_many_bus/async_read_many_bus.ino b/examples/async_read_many_bus/async_read_many_bus.ino
new file mode 100644
index 0000000..48fa3c7
--- /dev/null
+++ b/examples/async_read_many_bus/async_read_many_bus.ino
@@ -0,0 +1,42 @@
+// работа в режиме шины - несколько датчиков на линии, один объект
+// количество датчиков для удобства
+#define SENS_AMOUNT 5
+
+// создаём двухмерный массив с адресами
+uint8_t addr[][8] = {
+ {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 sensors;
+
+void setup() {
+ Serial.begin(9600);
+ // устанавливаем адреса
+ sensors.setAddress((uint8_t*)addr);
+
+ // Установить разрешение 9-12 бит у всех датчиков на линии
+ //sensors.setResolutionAll(10);
+}
+
+void loop() {
+ // конструкция программного таймера на 1c
+ static uint32_t tmr;
+ if (millis() - tmr >= 1000) {
+ tmr = millis();
+
+ // выводим показания в порт
+ for (int i = 0; i < SENS_AMOUNT; i++) {
+ Serial.print(sensors.getTemp(i));
+ Serial.print(',');
+ }
+ Serial.println();
+
+ // запрашиваем новые
+ sensors.requestTempAll();
+ }
+}
diff --git a/examples/async_read_many_bus_pgm/async_read_many_bus_pgm.ino b/examples/async_read_many_bus_pgm/async_read_many_bus_pgm.ino
new file mode 100644
index 0000000..52b641f
--- /dev/null
+++ b/examples/async_read_many_bus_pgm/async_read_many_bus_pgm.ino
@@ -0,0 +1,42 @@
+// работа в режиме шины - несколько датчиков на линии, один объект
+// количество датчиков для удобства
+#define SENS_AMOUNT 5
+
+// создаём двухмерный массив с адресами
+const uint8_t addr[][8] PROGMEM = {
+ {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 sensors;
+
+void setup() {
+ Serial.begin(9600);
+ // устанавливаем адреса
+ sensors.setAddress((uint8_t*)addr);
+
+ // Установить разрешение 9-12 бит у всех датчиков на линии
+ //sensors.setResolutionAll(10);
+}
+
+void loop() {
+ // конструкция программного таймера на 1c
+ static uint32_t tmr;
+ if (millis() - tmr >= 1000) {
+ tmr = millis();
+
+ // выводим показания в порт
+ for (int i = 0; i < SENS_AMOUNT; i++) {
+ Serial.print(sensors.getTemp(i));
+ Serial.print(',');
+ }
+ Serial.println();
+
+ // запрашиваем новые
+ sensors.requestTempAll();
+ }
+}
diff --git a/keywords.txt b/keywords.txt
index 2ff55f9..7cf5d75 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -20,6 +20,8 @@ getTemp KEYWORD2
getTempInt KEYWORD2
getRaw KEYWORD2
online KEYWORD2
+requestTempAll KEYWORD2
+setResolutionAll KEYWORD2
DS_rawToInt KEYWORD2
DS_rawToFloat KEYWORD2
@@ -29,4 +31,5 @@ DS_rawToFloat KEYWORD2
#######################################
DS_CHECK_CRC LITERAL1
DS_CRC_USE_TABLE LITERAL1
-DS_ADDR_MODE LITERAL1
\ No newline at end of file
+DS_ADDR_MODE LITERAL1
+DS_PROGMEM LITERAL1
\ No newline at end of file
diff --git a/library.properties b/library.properties
index f34e6c2..0cd5aa8 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=microDS18B20
-version=3.8
+version=3.9
author=AlexGyver
maintainer=AlexGyver
sentence=Light library for DS18b20 sensor
diff --git a/src/microDS18B20.h b/src/microDS18B20.h
index 5e7d1f0..d7e70df 100644
--- a/src/microDS18B20.h
+++ b/src/microDS18B20.h
@@ -1,16 +1,17 @@
/*
- Легкая и простая в обращении библиотека для работы с 1-Wire термометрами DS18B20
+ Легкая библиотека для работы с 1-Wire (OneWire) термометрами Dallas DS18B20
Документация:
GitHub: https://github.com/GyverLibs/microDS18B20
Возможности:
- Работа с несколькими датчиками на одном пине (режим адресации)
+ - Хранение массива адресов в PROGMEM памяти
- Работа с одним датчиком на пине (без использования адресации)
- Расчет температуры в целых числах и с плавающей точкой
+ - Чтение сырых данных для случаев сильной экономии памяти
- Проверка корректности полученной температуры
- Настраиваемое разрешение преобразования
- - Чтение сырых данных для случаев сильной экономии памяти
- - Проверка подлинности данных "на лету", с использованием CRC8 от Dallas
- - Расчет CRC8 (~6 мкс) или чтение из таблицы (<1 мкс + 256 байт flash)
+ - Проверка подлинности данных
+ - Проверка корректности работы датчика
Egor 'Nich1con' Zakharov & AlexGyver, alex@alexgyver.ru
https://alexgyver.ru/
@@ -27,6 +28,7 @@
v3.6 - исправлена ошибка компиляции, добавлена поддержка GyverCore (спасибо ArtemiyKolobov)
v3.7 - исправлена ошибка readTemp() при 0 градусов
v3.8 - небольшая оптимизация. Совместимость с ESP32
+ v3.9 - добавил расширенный режим адресации и хранение адресов в PROGMEM
*/
#ifndef _microDS18B20_h
@@ -35,6 +37,8 @@
#include "microOneWire.h"
#include "DS_raw.h"
+#define DS_PROGMEM 1
+
#ifndef DS_CHECK_CRC
#define DS_CHECK_CRC true // true/false - проверка контрольной суммы принятых данных - надежнее, но тратит немного больше flash
#endif
@@ -89,12 +93,12 @@ static const uint8_t PROGMEM _ds_crc8_table[] = {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
-static uint8_t _empDsAddr[1] = {1};
+uint8_t _empDsAddr[1] = {1};
#pragma GCC diagnostic pop
#define DS_ADDR_MODE _empDsAddr
// ====================== CLASS ======================
-template
+template
class MicroDS18B20 {
public:
MicroDS18B20() {
@@ -103,15 +107,20 @@ class MicroDS18B20 {
}
// Установить разрешение термометра 9-12 бит
- void setResolution(uint8_t res) {
+ void setResolution(uint8_t res, uint8_t idx = 0) {
if (!oneWire_reset(DS_PIN)) return; // Проверка присутствия
- addressRoutine(); // Процедура адресации
+ addressRoutine(idx); // Процедура адресации
oneWire_write(0x4E, DS_PIN); // Запись RAM
oneWire_write(0xFF, DS_PIN); // Максимум в верхний регистр тревоги
oneWire_write(0x00, DS_PIN); // Минимум в верхний регистр тревоги
oneWire_write(((constrain(res, 9, 12) - 9) << 5) | 0x1F, DS_PIN); // Запись конфигурации разрешения
}
+ // Установить разрешение термометра 9-12 бит у всех датчиков на линии
+ void setResolutionAll(uint8_t res) {
+ for (int i = 0; i < DS_AM; i++) setResolution(res, i);
+ }
+
// установить адрес
void setAddress(uint8_t *addr) {
_addr = addr;
@@ -134,36 +143,41 @@ class MicroDS18B20 {
}
// запрос температуры
- void requestTemp() {
- state = 0; // запрошена новая температура
+ void requestTemp(uint8_t idx = 0) {
+ state[idx] = 0; // запрошена новая температура
if (!oneWire_reset(DS_PIN)) return; // Проверка присутствия
- addressRoutine(); // Процедура адресации
+ addressRoutine(idx); // Процедура адресации
oneWire_write(0x44, DS_PIN); // Запросить преобразование
}
+ // запрос температуры у всех датчиков на линии
+ void requestTempAll() {
+ for (int i = 0; i < DS_AM; i++) requestTemp(i);
+ }
+
// получить температуру float
- float getTemp() {
- if (!state) readTemp();
- return (_buf / 16.0);
+ float getTemp(uint8_t idx = 0) {
+ if (!state[idx]) readTemp(idx);
+ return (_buf[idx] / 16.0);
}
// получить температуру int
- int16_t getTempInt() {
- if (!state) readTemp();
- return (_buf >> 4);
+ int16_t getTempInt(uint8_t idx = 0) {
+ if (!state[idx]) readTemp(idx);
+ return (_buf[idx] >> 4);
}
// получить "сырое" значение температуры
- int16_t getRaw() {
- if (!state) readTemp();
- return _buf;
+ int16_t getRaw(uint8_t idx = 0) {
+ if (!state[idx]) readTemp(idx);
+ return _buf[idx];
}
// прочитать температуру с датчика. true если успешно
- bool readTemp() {
- state = 1;
+ bool readTemp(uint8_t idx = 0) {
+ state[idx] = 1;
if (!oneWire_reset(DS_PIN)) return 0; // датчик оффлайн
- addressRoutine(); // Процедура адресации
+ addressRoutine(idx); // Процедура адресации
oneWire_write(0xBE, DS_PIN); // Запросить температуру
uint8_t crc = 0; // обнуляем crc
int16_t temp; // переменная для расчёта температуры
@@ -178,15 +192,15 @@ class MicroDS18B20 {
else if (i == 1) temp |= (data << 8);
}
if (sum == 0x8F7 || !sum || crc) return 0; // датчик оффлайн или данные повреждены
- if (temp != 0x0550) _buf = temp; // пропускаем первое чтение (85 градусов)
+ if (temp != 0x0550) _buf[idx] = temp; // пропускаем первое чтение (85 градусов)
return 1;
}
// проверить связь с датчиком (true - датчик на линии). ЛИНИЯ ДОЛЖНА БЫТЬ ПОДТЯНУТА
- bool online() {
- if (DS_ADDR) {
+ bool online(uint8_t idx = 0) {
+ if (DS_ADDR != nullptr) {
if (!oneWire_reset(DS_PIN)) return 0;
- addressRoutine();
+ addressRoutine(idx);
oneWire_write(0xBE, DS_PIN);
uint16_t sum = 0;
for (uint8_t i = 0; i < 5; i++) sum += oneWire_read(DS_PIN);
@@ -195,14 +209,17 @@ class MicroDS18B20 {
}
private:
- bool state = 0;
+ bool state[DS_AM];
+ int16_t _buf[DS_AM];
uint8_t *_addr = DS_ADDR;
- int16_t _buf = 0;
- void addressRoutine() { // Процедура адресации
- if (DS_ADDR) { // Адрес определен?
+ void addressRoutine(uint8_t idx) { // Процедура адресации
+ if (DS_ADDR != nullptr) { // Адрес определен?
oneWire_write(0x55, DS_PIN); // Говорим термометрам слушать адрес
- for (uint8_t i = 0; i < 8; i++) oneWire_write(_addr[i], DS_PIN); // Отправляем адрес
+ for (uint8_t i = 0; i < 8; i++) {
+ if (DS_PGM) oneWire_write(pgm_read_byte(&_addr[i + idx * 8]), DS_PIN);
+ else oneWire_write(_addr[i + idx * 8], DS_PIN);
+ }
} else oneWire_write(0xCC, DS_PIN); // Адреса нет - пропускаем адресацию на линии
}