├── .gitattributes
├── .github
└── workflows
│ └── tg-send.yml
├── LICENSE
├── README.md
├── README_EN.md
├── doc
└── scheme.png
├── examples
├── address_read
│ └── address_read.ino
├── async_read
│ └── async_read.ino
├── async_read_many
│ └── async_read_many.ino
├── async_read_many_bus
│ └── async_read_many_bus.ino
├── async_read_many_bus_pgm
│ └── async_read_many_bus_pgm.ino
├── flash_reduction
│ └── flash_reduction.ino
├── one_pin_many_sensors
│ └── one_pin_many_sensors.ino
├── one_pin_one_sensor
│ └── one_pin_one_sensor.ino
└── raw_and_calc
│ └── raw_and_calc.ino
├── keywords.txt
├── library.properties
└── src
├── DS_raw.cpp
├── DS_raw.h
├── microDS18B20.h
├── microOneWire.cpp
└── microOneWire.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/workflows/tg-send.yml:
--------------------------------------------------------------------------------
1 |
2 | name: Telegram Message
3 | on:
4 | release:
5 | types: [published]
6 | jobs:
7 | build:
8 | name: Send Message
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: send telegram message on push
12 | uses: appleboy/telegram-action@master
13 | with:
14 | to: ${{ secrets.TELEGRAM_TO }}
15 | token: ${{ secrets.TELEGRAM_TOKEN }}
16 | disable_web_page_preview: true
17 | message: |
18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }}
19 | ${{ github.event.release.body }}
20 | https://github.com/${{ github.repository }}
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Alex
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | |⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
**ВНИМАНИЕ, БИБЛИОТЕКА УСТАРЕЛА! ИСПОЛЬЗУЙ БИБЛИОТЕКУ [GyverDS18](https://github.com/GyverLibs/GyverDS18), ОНА ИМЕЕТ БОЛЬШЕ ВОЗМОЖНОСТЕЙ И РАБОТАЕТ НА ESP32**
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️|
2 | | --- |
3 |
4 | [](https://github.com/GyverLibs/microDS18B20/releases/latest/download/microDS18B20.zip)
5 | [](https://registry.platformio.org/libraries/gyverlibs/microDS18B20)
6 | [](https://www.ardu-badge.com/microDS18B20)
7 | [](https://alexgyver.ru/)
8 | [](https://alexgyver.ru/support_alex/)
9 | [](https://github-com.translate.goog/GyverLibs/microDS18B20?_x_tr_sl=ru&_x_tr_tl=en)
10 |
11 | [](https://t.me/GyverLibs)
12 |
13 | # microDS18B20
14 | Легкая библиотека для работы с 1-Wire (OneWire) термометрами Dallas DS18B20
15 | - Асинхронная работа (без ожидания конвертации)
16 | - Работа с несколькими датчиками на одном пине (режим адресации)
17 | - Хранение массива адресов в PROGMEM памяти
18 | - Работа с одним датчиком на пине (без использования адресации)
19 | - Расчет температуры в целых числах и с плавающей точкой
20 | - Чтение сырых данных для случаев сильной экономии памяти
21 | - Проверка корректности полученной температуры
22 | - Настраиваемое разрешение преобразования
23 | - Проверка подлинности данных
24 | - Проверка корректности работы датчика
25 |
26 | ### Совместимость
27 | Совместима со всеми Arduino платформами (используются Arduino-функции)
28 | - Не работает на свежих версиях sdk esp32
29 | - Не работает на Digispark, какой то конфликт с компилятором. Используй ядро [ATTInyCore Universal](https://github.com/SpenceKonde/ATTinyCore) с настройкой ATtiny85 + Micronucleous (Digispark) вместо стандартного Digi-ядра
30 |
31 | ## Содержание
32 | - [Установка](#install)
33 | - [Инициализация](#init)
34 | - [Использование](#usage)
35 | - [Подключение](#wiring)
36 | - [Примеры](#examples)
37 | - [Версии](#versions)
38 | - [Баги и обратная связь](#feedback)
39 |
40 |
41 | ## Установка
42 | - Библиотеку можно найти по названию **microDS18B20** и установить через менеджер библиотек в:
43 | - Arduino IDE
44 | - Arduino IDE v2
45 | - PlatformIO
46 | - [Скачать библиотеку](https://github.com/GyverLibs/microDS18B20/archive/refs/heads/main.zip) .zip архивом для ручной установки:
47 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64)
48 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32)
49 | - Распаковать и положить в *Документы/Arduino/libraries/*
50 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив
51 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA)
52 | ### Обновление
53 | - Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи
54 | - Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить"
55 | - Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!
56 |
57 |
58 |
59 | ## Инициализация
60 | ```cpp
61 | // один датчик на пине без адресации
62 | MicroDS18B20 ds;
63 |
64 | // несколько датчиков на пине с адресацией, указываем адрес (адрес - массив uint8_t)
65 | MicroDS18B20 ds;
66 |
67 | // указываем, что будем работать с адресацией. Сам адрес передадим позже (в setAddress())
68 | MicroDS18B20;
69 |
70 | // указываем, что будем работать с адресацией, и на линии будет несколько (amount) датчиков
71 | // см. пример async_read_many_bus
72 | MicroDS18B20;
73 |
74 | // указываем, что будем работать с адресацией, на линии будет несколько (amount) датчиков, а адреса будем хранить в PROGMEM
75 | // см. пример async_read_many_bus_pgm
76 | MicroDS18B20;
77 | ```
78 |
79 |
80 | ## Использование
81 | ```cpp
82 | // ============= МЕТОДЫ КЛАССА =============
83 | bool readAddress(uint8_t *addressArray); // Прочитать уникальный адрес термометра в массив. [true, если успешно]
84 | void setAddress(uint8_t *addr); // установить (сменить) адрес
85 | void setResolution(uint8_t resolution); // Установить разрешение 9-12 бит
86 | bool online(); // проверить связь с датчиком (true - датчик онлайн). Шина должна быть подтянута
87 |
88 | void requestTemp(); // Запросить новое преобразование температуры
89 | bool readTemp(); // прочитать температуру с датчика. [true если успешно]
90 |
91 | float getTemp(); // получить значение температуры в float
92 | int16_t getTempInt(); // получить значение температуры в int
93 | int16_t getRaw(); // получить "сырое" значение температуры (в 16 раз больше, чем реальная температура)
94 |
95 | // ======= МЕТОДЫ ДЛЯ ШИНЫ ДАТЧИКОВ =======
96 | // см. примеры async_read_many_bus и async_read_many_bus_pgm
97 | void setResolutionAll(uint8_t res); // Установить разрешение 9-12 бит у всех датчиков на линии
98 | void setResolution(uint8_t resolution, uint8_t idx); // Установить разрешение 9-12 бит (датчик под номером idx)
99 | bool online(uint8_t idx); // проверить связь (датчик под номером idx)
100 |
101 | void requestTempAll(); // запрос температуры у всех датчиков на линии
102 | void requestTemp(uint8_t idx); // Запросить новое преобразование температуры (датчик под номером idx)
103 | bool readTemp(uint8_t idx); // прочитать температуру с датчика (датчик под номером idx)
104 |
105 | float getTemp(uint8_t idx); // получить значение температуры в float (датчик под номером idx)
106 | int16_t getTempInt(uint8_t idx); // получить значение температуры в int (датчик под номером idx)
107 | int16_t getRaw(uint8_t idx); // получить "сырое" значение температуры (датчик под номером idx)
108 |
109 | // =========== ФУНКЦИИ ВНЕ КЛАССА ===========
110 | int DS_rawToInt(int data); // преобразовать raw данные в температуру int
111 | float DS_rawToFloat(int data); // преобразовать raw данные в температуру float
112 |
113 | // ============ ДЕФАЙНЫ НАСТРОЕК ============
114 | // прописывать перед подключением библиотеки
115 | #define DS_CHECK_CRC [true / false] // Проверка подлинности данных. При отключении будет выдавать некорректное значение при сбое передачи (умолч. true)
116 | #define DS_CRC_USE_TABLE [true / false] // Использовать таблицу для CRC. Быстрее, но +256 байт flash (<1мкс VS ~6мкс) (умолч. false)
117 |
118 | // ================== ИНФО ==================
119 | // Время преобразования от точности
120 | точность | время
121 | 12 бит | 750 мс
122 | 11 бит | 375 мс
123 | 10 бит | 187 мс
124 | 9 бит | 93 мс
125 | ```
126 |
127 | ### Работа с датчиком
128 | #### Без адресации
129 | В этом режиме на один пин МК подключается один датчик, для работы с ним не требуется предварительного чтения адреса и записи его в программу.
130 | Можно подключить несколько датчиков, каждому указать свой пин, см. пример *one_pin_one_sensor*.
131 | ```cpp
132 | MicroDS18B20<пин1> sensor1;
133 | MicroDS18B20<пин2> sensor2;
134 | // ... и так далее
135 | ```
136 |
137 | #### С адресацией
138 | В этом режиме можно подключить сколько угодно датчиков на один пин МК, но для работы с ними понадобится занести в программу уникальные адреса датчиков.
139 | В момент чтения адреса к пину должен быть подключен только один датчик! Пример - *address_read*.
140 | Для дальнейшей работы адреса хранятся в массивах на стороне программы и передаются датчикам при инициализации, пин указывается один и тот же:
141 | ```cpp
142 | uint8_t addr1[] = {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE};
143 | uint8_t addr2[] = {0x28, 0xFF, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};
144 |
145 | MicroDS18B20<пин, addr1> sensor1;
146 | MicroDS18B20<пин, addr2> sensor2;
147 | // ... и так далее
148 | ```
149 | Также адрес можно сменить во время работы программы, см. документацию выше.
150 |
151 | #### Чтение температуры
152 | Чтение температуры делится на два этапа - запрос и получение данных. Запрос делается функцией `requestTemp()`. После получения запроса
153 | датчик начинает измерение температуры, которое длится от 90 до 750 мс в зависимости от настроенной точности *(по умолчанию точность максимальная,
154 | преобразование длится 750 мс)*. Если прочитать температуру до окончания преобразования - датчик вернёт результат предыдущего измерения,
155 | поэтому в примерах используется задержка или опрос по таймеру на 1 секунду. Получить температуру можно при помощи `getTemp()` [float] или `getTempInt()` [int].
156 | Если принятые данные повреждены или датчик отсутствует на линии - функция вернёт предыдущее успешно прочитанное значение температуры.
157 | **Примечание:** при повторных вызовах `getTemp()` не запрашивает с датчика новую температуру (долгое выполнение функции),
158 | вместо этого она просто возвращает предыдущий результат до тех пор, пока не будет сделан новый запрос `requestTemp()`.
159 |
160 | В версии библиотеки 3.5 появилась возможность отдельно запросить температуру и определить корректность полученных данных, чтобы только после этого их прочитать
161 | и применить в программе - функция `readTemp()`. Также это позволяет определить состояние подключения и всё ли в порядке с датчиком.
162 | Для чтения температуры рекомендуется использовать конструкцию вида:
163 | ```cpp
164 | if (sensor.readTemp()) value = sensor.getTemp();
165 | // else отработка ошибки
166 | ```
167 | где `readTemp()` запрашивает данные с датчика и возвращает `true`, если они прочитаны корректно. После этого можно забрать текущую температуру из `getTemp()`,
168 | которая уже не запрашивает температуру с датчика, а отдаёт прочитанный в `readTemp()` результат.
169 |
170 | #### Подключаем много датчиков на один объект
171 | В версии библиотеки 3.9 появилась возможность подключить сколько угодно датчиков на один объект MicroDS18B20, не создавая массива объектов (как в старых версиях).
172 | Нужно создать двумерный массив адресов и передать его в библиотеку, также указав количество датчиков на линии (можно максимальное, если оно будет меняться в процессе работы программы).
173 | Это позволяет сэкономить немного памяти, но можно пойти дальше - засунуть массив адресов датчиков в PROGMEM, чтобы они не висели в оперативной памяти.
174 | Инициализация в этом случае выглядит так: `MicroDS18B20<пин, DS_ADDR_MODE, колич-во>;` или `MicroDS18B20<пин, DS_ADDR_MODE, колич-во, DS_PROGMEM>;` для PROGMEM режима.
175 | Адреса передаются в `setAddress()`, а для опроса просто передаём индекс датчика в те же функции что и раньше. Смотри примеры *async_read_many_bus*, *async_read_many_bus_pgm* и раздел документации *МЕТОДЫ ДЛЯ ШИНЫ ДАТЧИКОВ*.
176 |
177 |
178 | ## Подключение
179 | 
180 | P.S. Вместо резистора на 4.7к можно использовать параллельно два по 10к =)
181 |
182 |
183 | Остальные примеры смотри в **examples**!
184 | ## Один датчик без адресации
185 | ```cpp
186 | // один датчик лучше читать без адресации, это сильно экономит память
187 | #include
188 | MicroDS18B20<2> sensor;
189 |
190 | void setup() {
191 | Serial.begin(9600);
192 | }
193 |
194 | void loop() {
195 | // запрос температуры
196 | sensor.requestTemp();
197 |
198 | // вместо delay используй таймер на millis(), пример async_read
199 | delay(1000);
200 |
201 | // проверяем успешность чтения и выводим
202 | if (sensor.readTemp()) Serial.println(sensor.getTemp());
203 | else Serial.println("error");
204 | }
205 | ```
206 |
207 | ## Несколько датчиков без адресации
208 | ```cpp
209 | // 2 и более датчиков НЕВЫГОДНО использовать в таком режиме! Но можно
210 |
211 | #include
212 | // Датчики на D2 и D3
213 | MicroDS18B20<2> sensor1;
214 | MicroDS18B20<3> sensor2;
215 |
216 | void setup() {
217 | Serial.begin(9600);
218 | }
219 |
220 | void loop() {
221 | // запрос температуры
222 | sensor1.requestTemp();
223 | sensor2.requestTemp();
224 |
225 | // вместо delay используй таймер на millis(), пример async_read
226 | delay(1000);
227 |
228 | // ПЕРВЫЙ ДАТЧИК
229 | Serial.print("t1: ");
230 |
231 | // просто выводим температуру первого датчика
232 | Serial.print(sensor1.getTemp());
233 |
234 | // ВТОРОЙ ДАТЧИК
235 | Serial.print(", t2: ");
236 |
237 | // проверяем успешность чтения и выводим
238 | if (sensor2.readTemp()) Serial.println(sensor2.getTemp());
239 | else Serial.println("error");
240 | }
241 | ```
242 |
243 | ## Чтение адреса
244 | ```cpp
245 | #include
246 |
247 | // на пин подключен только один датчик!
248 | MicroDS18B20 <2> sensor; // Создаем термометр без адреса на пине D2
249 | uint8_t address[8]; // Создаем массив для адреса
250 |
251 | void setup() {
252 | Serial.begin(9600);
253 | }
254 |
255 | void loop() {
256 | // читаем адрес термометра в указанный массив
257 | if (sensor.readAddress(address)) { // если успешно, выводим
258 | Serial.print('{');
259 | for (uint8_t i = 0; i < 8; i++) {
260 | Serial.print("0x");
261 | Serial.print(address[i], HEX); // Выводим адрес
262 | if (i < 7) Serial.print(", ");
263 | }
264 | Serial.println('}');
265 |
266 | } else Serial.println("Not connected");
267 | delay(1000);
268 | }
269 | ```
270 |
271 | ## Несколько датчиков с адресацией
272 | ```cpp
273 | // 2 и более датчиков выгоднее использовать с адресацией на одном пине
274 | #include
275 | #define DS_PIN 2 // пин для термометров
276 |
277 | // Уникальные адреса датчиков - считать можно в примере address_read
278 | uint8_t s1_addr[] = {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE};
279 | uint8_t s2_addr[] = {0x28, 0xFF, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};
280 |
281 | MicroDS18B20 sensor1; // Создаем термометр с адресацией
282 | MicroDS18B20 sensor2; // Создаем термометр с адресацией
283 |
284 | void setup() {
285 | Serial.begin(9600);
286 | }
287 |
288 | void loop() {
289 | // асинхронное чтение нескольких датчиков смотри в примере async_read_many
290 | sensor1.requestTemp(); // Запрашиваем преобразование температуры
291 | sensor2.requestTemp();
292 |
293 | delay(1000); // ожидаем результат
294 |
295 | Serial.print("t1: ");
296 | if (sensor1.readTemp()) Serial.println(sensor1.getTemp());
297 | else Serial.println("error");
298 |
299 | Serial.print("t2: ");
300 | if (sensor2.readTemp()) Serial.println(sensor2.getTemp());
301 | else Serial.println("error");
302 | }
303 | ```
304 |
305 | ## Асинхронный опрос пачки датчиков
306 | ```cpp
307 | // пример компактного асинхронного опроса датчиков на программном таймере
308 | // https://alexgyver.ru/lessons/time/
309 |
310 | // количество датчиков для удобства
311 | #define DS_SENSOR_AMOUNT 5
312 |
313 | // создаём двухмерный массив с адресами
314 | uint8_t addr[][8] = {
315 | {0x28, 0xFF, 0x78, 0x5B, 0x50, 0x17, 0x4, 0xCF},
316 | {0x28, 0xFF, 0x99, 0x80, 0x50, 0x17, 0x4, 0x4D},
317 | {0x28, 0xFF, 0x53, 0xE5, 0x50, 0x17, 0x4, 0xC3},
318 | {0x28, 0xFF, 0x42, 0x5A, 0x51, 0x17, 0x4, 0xD2},
319 | {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE},
320 | };
321 |
322 | #include
323 | // указываем DS_ADDR_MODE для подключения блока адресации
324 | // и создаём массив датчиков на пине D2
325 | MicroDS18B20<2, DS_ADDR_MODE> sensor[DS_SENSOR_AMOUNT];
326 |
327 | void setup() {
328 | Serial.begin(9600);
329 | // устанавливаем адреса
330 | for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
331 | sensor[i].setAddress(addr[i]);
332 | }
333 | }
334 |
335 | void loop() {
336 | // конструкция программного таймера на 1c
337 | static uint32_t tmr;
338 | if (millis() - tmr >= 1000) {
339 | tmr = millis();
340 |
341 | // выводим показания в порт
342 | for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
343 | Serial.print(sensor[i].getTemp());
344 | Serial.print(',');
345 | }
346 | Serial.println();
347 |
348 | // запрашиваем новые
349 | for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
350 | sensor[i].requestTemp();
351 | }
352 | }
353 | }
354 | ```
355 |
356 |
357 | ## Версии
358 | - v3.0 - Библиотека переехала на шаблон! Старые примеры НЕСОВМЕСТИМЫ. Оптимизация, новые трюки.
359 | - v3.0.1 - добавлен пример
360 | - v3.1 - добавлена возможность смены адреса на лету
361 | - v3.1.1 - microOneWire разбит на .h и .cpp
362 | - v3.2 - исправлены отрицательные температуры
363 | - v3.3 - разбил на файлы
364 | - v3.4 - добавлена проверка онлайна датчика и буфер, при ошибке чтения возвращается последнее прочитанное значение
365 | - v3.5 - оптимизация, повышение стабильности, проверка правильности чтения, online() работает с адресацией, добавлен метод getTempInt() и readTemp(), упразднён DS_TEMP_TYPE
366 | - v3.6 - исправлена ошибка компиляции, добавлена поддержка GyverCore (спасибо ArtemiyKolobov)
367 | - v3.7 - исправлена ошибка readTemp() при 0 градусов
368 | - v3.8 - небольшая оптимизация. Совместимость с ESP32
369 | - v3.9 - добавил расширенный режим адресации и хранение адресов в PROGMEM
370 | - v3.10 - оптимизация, увеличена стабильность
371 |
372 |
373 | ## Баги и обратная связь
374 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru)
375 | Библиотека открыта для доработки и ваших **Pull Request**'ов!
376 |
377 |
378 | При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:
379 | - Версия библиотеки
380 | - Какой используется МК
381 | - Версия SDK (для ESP)
382 | - Версия Arduino IDE
383 | - Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
384 | - Какой код загружался, какая работа от него ожидалась и как он работает в реальности
385 | - В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код
386 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 | This is an automatic translation, may be incorrect in some places. See sources and examples!
2 |
3 | # Microds18b20
4 | Light library for working with 1-Wire (Onewire) thermometers Dallas DS18B20
5 | - asynchronous work (without expectation of conversion)
6 | - Work with several sensors on one pin (addressing mode)
7 | - storage of an array of addresses in ProGMEM memory
8 | - Work with one sensor on pin (without using addressing)
9 | - calculation of temperature in integers and with a floating point
10 | - reading raw data for cases of strong memory savings
11 | - checking the correctness of the resulting temperature
12 | - customized resolution of transformation
13 | - Data authenticity check
14 | - checking the correctness of the sensor
15 |
16 | ## compatibility
17 | Compatible with all arduino platforms (used arduino functions)
18 | - does not work on fresh versions of SDK ESP32
19 | - It does not work on Digispark, some kind of conflict with a compiler.Use the nucleus [Attinycore Universal] (https://github.com/spencekonde/atTinycore) with the setting of Attiny85 + Micronucleous (Digispark) instead
20 |
21 | ## Content
22 | - [installation] (# Install)
23 | - [initialization] (#init)
24 | - [use] (#usage)
25 | - [connection] (#wiring)
26 | - [Examples] (# ExamPles)
27 | - [versions] (#varsions)
28 | - [bugs and feedback] (#fedback)
29 |
30 |
31 | ## Installation
32 | - The library can be found by the name ** Microds18b20 ** and installed through the library manager in:
33 | - Arduino ide
34 | - Arduino ide v2
35 | - Platformio
36 | - [download the library] (https://github.com/gyverlibs/microds18b20/archive/refs/heads/main.zip). Zip archive for manual installation:
37 | - unpack and put in * C: \ Program Files (X86) \ Arduino \ Libraries * (Windows X64)
38 | - unpack and put in * C: \ Program Files \ Arduino \ Libraries * (Windows X32)
39 | - unpack and put in *documents/arduino/libraries/ *
40 | - (Arduino id) Automatic installation from. Zip: * sketch/connect the library/add .Zip library ... * and specify downloaded archive
41 | - Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA)
42 | ### Update
43 | - I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added
44 | - through the IDE library manager: find the library how to install and click "update"
45 | - Manually: ** remove the folder with the old version **, and then put a new one in its place.“Replacement” cannot be done: sometimes in new versions, files that remain when replacing are deleted and can lead to errors!
46 |
47 |
48 |
49 | ## initialization
50 | `` `CPP
51 | // One sensor on pin without addressing
52 | Microds18b20 ds;
53 |
54 | // Several sensors on the pin with addressing, indicate the address (address - array Uint8_T)
55 | Microds18b20 ds;
56 |
57 | // We indicate that we will work with addressing.We will transmit the address itself later (in Setaddress ())
58 | Microds18b20 ;
59 |
60 | // indicate that we will work with addressing, and there will be several (amount) sensors on the line
61 | // See example async_read_many_bus
62 | Microds18b20 ;
63 |
64 | // We indicate that we will work with addressing, there will be several sensors on the line, and we will store the addresses in Progmem
65 | // see pr.Imer async_read_many_bus_pgm
66 | Microds18b20 ;
67 | `` `
68 |
69 |
70 | ## Usage
71 | `` `CPP
72 | // ============= Methods of class ========================
73 | Bool Readaddress (Uint8_t *Addressarry);// Read the unique address of the thermometer in the array.[True, if successful]
74 | VOID Setaddress (Uint8_T *Addr);// Set (change) address
75 | VOID Setresolution (Uint8_T Resolution);// Set a resolution 9-12 bits
76 | Bool online ();// Check the connection with the sensor (True - online sensor).The tire should be fitted
77 |
78 | VOID RequestTemp ();// Request a new temperature transformation
79 | Bool Readtemp ();// Read the temperature from the sensor.[true if successfully]
80 |
81 | Float gettemp ();// get the temperature value in Float
82 | int16_t gettempint ();// get the temperature value in int
83 | Int16_T GETRAW ();// get a "raw" temperature value (16 times more than real temperature)
84 |
85 | // ======= Methods for the tire of sensors =========
86 | // See examples async_read_many_bus and async_read_many_bus_pgm
87 | VOID Setresolutionall (Uint8_T Res);// Set a resolution of 9-12 bits for all sensors on the line
88 | VOID Setresolution (Uint8_T Resolution, Uint8_T IDX);// Set a resolution 9-12 bits (sensor under the IDX number)
89 | Bool Online (Uint8_T IDX);// Check the connection (sensor under the IDX number)
90 |
91 | VOID RequestTempall ();// Temperature request for all sensors on the line
92 | VOID REQUESTEMP (Uint8_T IDX);// Request a new temperature conversion (sensor under the IDX number)
93 | Bool Readtemp (Uint8_T IDX);// Read the temperature from the sensor (sensor under the IDX number)
94 |
95 | Float Gettemp (Uint8_T IDX);// get the temperature value in Float (sensor under the IDX number)
96 | Int16_T Gettempint (Uint8_T IDX);// get the temperature value in int (sensor under the IDX number)
97 | Int16_T Getraw (Uint8_T IDX);// Get a "raw" temperature value (sensor under the IDX number)
98 |
99 | // =========== Functions outside the class ============
100 | int DS_RAWTOINT (inta);// Transform RAW data into temperature int
101 | Float DS_RAWTOFLOAT (Inta);// Transform RAW data to Float temperature
102 |
103 | // ========ward
104 | // write down before connecting the library
105 | #define ds_check_crc [True / False] // Checking of data authenticity.When disconnecting, it will give out incorrect value when gear failure (def. True)
106 | #define ds_crc_use_table [True / False] // Use a table for CRC.Faster, but +256 bytes Flash (<1mx vs ~ 6mx) (silence. False)
107 |
108 | // ====ward
109 | // Time of transformation from accuracy
110 | accuracy |time
111 | 12 bits |750 ms
112 | 11 bit |375 ms
113 | 10 bits |187 ms
114 | 9 bits |93 ms
115 | `` `
116 |
117 | ### Work with a sensor
118 | #### without addressing
119 | In this mode, one sensor is connected to one PIN MK, it does not require a preliminary reading of the address and write it to the program to work with it.
120 | You can connect several sensors, indicate each PIN, see example *One_pin_one_Sensor *.
121 | `` `CPP
122 | Microds18b20 Sensor1;
123 | Microds18b20 Sensor2;
124 | // ... and so on
125 | `` `
126 |
127 | ### with addressing
128 | In this mode, you can connect as many sensors to one PIN MK, but to work with them you will need to bring unique sensors addresses into the program.
129 | At the time of reading the address to Pin, only one sensor must be connected!Example - *Address_read *.
130 | For further work, the addresses are stored in arrays on the side of the program and transmitted to the sensors during initialization, the PIN is indicated the same:
131 | `` `CPP
132 | uint8_t addr1 [{0x28, 0xff, 0xcd, 0x59, 0x51, 0x17, 0x4, 0xfe};
133 | uint8_t addr2 [] = {0x28, 0xff, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};
134 |
135 | Microds18b20 Sensor1;
136 | Microds18b20 SensoR2;
137 | // ... and so on
138 | `` `
139 | Also, the address can be changed during the program, see the documentation above.
140 |
141 | #### Reading Temperature
142 | Reading the temperature is divided into two stages - a request and obtaining data.The request is made by the `REQUESTEMP ()` function.After receiving the request
143 | The sensor begins a temperature measurement, which lasts from 90 to 750 ms, depending on the configured accuracy *(by default, the accuracy is maximum,
144 | The transformation lasts 750 ms)*.If you read the temperature before the end of the transformation, the sensor will return the result of the previous measurement,
145 | Therefore, the examples use a delay or a survey by a timer for 1 second.You can get the temperature using `gettemp ()` [float] or `gettempint ()` [int].
146 | If the accepted data is damaged or the sensor is absent on the line, the function will return the previous successfully read temperature value.
147 | ** Note: ** During repeated calls, `gettemp ()` does not request a new temperature from the sensor (long execution of the function),
148 | Instead, she simply returns the previous result until a new request is made `RequestTemp ()`.
149 |
150 | In the version of Library 3.5, it became possible to separately request the temperature and determine the correctness of the data obtained, so that only after that read them
151 | And apply in the program - the function `Readtemp ()`.This also allows you to determine the condition of the connection and whether everything is in order with the sensor.
152 | To read temperature, it is recommended to use the design of the type:
153 | `` `CPP
154 | if (Sensor.Readtemp ()) value = sensor.gettemp ();
155 | // Else error development
156 | `` `
157 | Where `Readtemp ()` Causes the data from the sensor and returns `true` if they are read correctly.After that, you can pick up the current temperature from `gettemp ()`,
158 | Which no longer requests the temperature from the sensor, but gives the result read in `readtemp ()` result.
159 |
160 | ### We connect a lot of sensors to one object
161 | In the version of Library 3.9, it became possible to connect as many sensors to one object Microds18b20, without creating an array of objects (as in old versions).
162 | It is necessary to create a two -dimensional array of addresses and transfer it to the library, also indicating the number of sensors on the line (you can maximum if it changes in the process of the program).
163 | This allows you to save a little memory, but you can go further - put an array of sensors in the Progmem so that they do not hang in RAM.
164 | In this case, the initialization looks like this: `Microds18b20 ;` or `Microds18b20 ;` for Progmem mode.
165 | The addresses are transmitted to `setaddress ()`, and for the survey we simply transmit the sensor index to the same functions as before.See examples *async_read_many_bus *, *async_read_Many_bus_pgm *and documentation section *Methods for the sensors tire *.
166 |
167 |
168 | ## connection
169 | ! [Scheme] (/doc/scheme.png)
170 | P.S.Instead of a resistor at 4.7k, you can use two in parallel by 10k =)
171 |
172 |
202 | // sensors for d2 and d3
203 | Microds18b20 <2> Sensor1;
204 | Microds18b20 <3> Sensor2;
205 |
206 | VOID setup () {
207 | Serial.Begin (9600);
208 | }
209 |
210 | VOID loop () {
211 | // Temperature request
212 | Sensor1.requesttemp ();
213 | Sensor2.requesttemp ();
214 |
215 | // Instead of DELAY, use a timer on Millis (), an example async_read
216 | DELAY (1000);
217 |
218 | // The first sensor
219 | Serial.print ("t1:");
220 |
221 | // just display the temperature of the first sensor
222 | Serial.print (Sensor1.gettemp ());
223 |
224 | // Second sensationK.
225 | Serial.print (", t2:");
226 |
227 | // Check the success of reading and display
228 | if (Sensor2.Readtemp ()) serial.println (Sensor2.gettemp ());
229 | Else serial.println ("error");
230 | }
231 | `` `
232 |
233 | ## Reading the address
234 | `` `CPP
235 | #include
236 |
237 | // only one sensor is connected to the pin!
238 | Microds18b20 <2> Sensor;// Create a thermometer without address on pin D2
239 | uint8_t address [8];// Create an array for the address
240 |
241 | VOID setup () {
242 | Serial.Begin (9600);
243 | }
244 |
245 | VOID loop () {
246 | // read the thermometer address in the specified array
247 | if (Sensor.Readaddress (Address)) {// If successfully, we display
248 | Serial.print ('{');
249 | for (uint8_t i = 0; i <8; i ++) {
250 | Serial.print ("0x");
251 | Serial.print (address [i], hex);// display the address
252 | if (i <7) serial.print (",");
253 | }
254 | Serial.println ('}');
255 |
256 | } Else serial.println ("Not Connected");
257 | DELAY (1000);
258 | }
259 | `` `
260 |
261 | ## a few sensors with addressing
262 | `` `CPP
263 | // 2 or more sensors is more profitable to use with addressing on one pin
264 | #include
265 | #define ds_pin 2 // PIN for thermometers
266 |
267 | // Unique sensors - you can count in the example of Address_read
268 | uint8_t s1_addr [] = {0x28, 0xff, 0xcd, 0x59, 0x51, 0x17, 0x4, 0xfe};
269 | uint8_t s2_addr [] = {0x28, 0xff, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};
270 |
271 | Microds18b20 sensor1;// Create a thermometer with addressing
272 | Microds18b20 sensor2;// Create a thermometer with addressing
273 |
274 | VOID setup () {
275 | Serial.Begin (9600);
276 | }
277 |
278 | VOID loop () {
279 | // Asynchronous reading of several sensors see async_read_many
280 | Sensor1.requesttemp ();// Request temperature transformation
281 | Sensor2.requesttemp ();
282 |
283 | DELAY (1000);// We expect the result
284 |
285 | Serial.print ("t1:");
286 | if (Sensor1.Redtemp ()) serial.println (Sensor1.gettemp ());
287 | Else serial.println ("error");
288 |
289 | Serial.print ("t2:");
290 | if (Sensor2.Readtemp ()) serial.println (Sensor2.gettemp ());
291 | Else serial.println ("error");
292 | }
293 | `` `
294 |
295 | ## asynchronous survey packs of sensors
296 | `` `CPP
297 | // An example of a compact asynchronous survey of sensors on a software timer
298 | // https://alexgyver.ru/lessons/time/
299 |
300 | // number of sensors for convenience
301 | #define ds_sensor_amount 5
302 |
303 | // Create a two -dimensional array with addresses
304 | uint8_t addr [] [8] = {{
305 | {0x28, 0xff, 0x78, 0x5b, 0x50, 0x17, 0x4, 0xcf},
306 | {0x28, 0xff, 0x99, 0x80, 0x50, 0x17, 0x4, 0x4d},
307 | {0x28, 0xff, 0x53, 0xe5, 0x50, 0x17, 0x4, 0xc3},
308 | {0x28, 0xff, 0x42, 0x5a, 0x51, 0x17, 0x4, 0xd2},
309 | {0x28, 0xff, 0xcd, 0x59, 0x51, 0x17, 0x4, 0xfe},
310 | };
311 |
312 | #include
313 | // specify ds_addr_mode to connect an addressing unit
314 | // and create an array of sensors on pin D2
315 | Microds18b20 <2, ds_addr_mode> sensor [ds_sensor_amount];
316 |
317 | VOID setup () {
318 | Serial.Begin (9600);
319 | // Install the addresses
320 | for (int i = 0; i = 1000) {
329 | TMR = Millis ();
330 |
331 | // We display the readings to the port
332 | for (int i = 0; i
347 | ## versions
348 | - V3.0 - The library moved to the template!Old examples are incompatible.Optimization, new tricks.
349 | - v3.0.1 - Added example
350 | - v3.1 - added the possibility of changing the address on the fly
351 | - V3.1.1 - Microonewire is divided into .h and .cpp
352 | - v3.2 - negative temperatures are fixed
353 | - v3.3 - divided into files
354 | - v3.4 - added the sensor online and buffer, with an error of reading, the last value read is returned
355 | - V3.5 - optimization, increasing stability, checking the correctness of reading, online () works with addressing, added Gettempint () and Readtemp (), abolished ds_temp_type
356 | - V3.6 - Fixed compilation error, added support Gyvercore (thanks Artemiykolobov)
357 | - v3.7 - ReadTemp () error is fixed at 0 degrees
358 | - V3.8 - slight optimization.Compatibility with ESP32
359 | - v3.9 - added an extended addressing mode and storage of addresses in Progmem
360 | - v3.10 - optimization, stability increased
361 |
362 |
363 | ## bugs and feedback
364 | Create ** Issue ** when you find the bugs, and better immediately write to the mail [alex@alexgyver.ru] (mailto: alex@alexgyver.ru)
365 | The library is open for refinement and your ** pull Request ** 'ow!
366 |
367 |
368 | When reporting about bugs or incorrect work of the library, it is necessary to indicate:
369 | - The version of the library
370 | - What is MK used
371 | - SDK version (for ESP)
372 | - version of Arduino ide
373 | - whether the built -in examples work correctly, in which the functions and designs are used, leading to a bug in your code
374 | - what code has been loaded, what work was expected from it and how it works in reality
375 | - Ideally, attach the minimum code in which the bug is observed.Not a canvas of a thousand lines, but a minimum code
--------------------------------------------------------------------------------
/doc/scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GyverLibs/microDS18B20/db585e5843cfb4357d32bff863269813abe88a8e/doc/scheme.png
--------------------------------------------------------------------------------
/examples/address_read/address_read.ino:
--------------------------------------------------------------------------------
1 | /*
2 | Чтение уникального адреса термометра для последующего использования
3 | ВНИМАНИЕ! Устанавливать не более одного датчика на линию (пин)
4 | */
5 | #include
6 |
7 | MicroDS18B20 <2> sensor; // Создаем термометр без адреса на пине D2
8 | uint8_t address[8]; // Создаем массив для адреса
9 |
10 | void setup() {
11 | Serial.begin(9600);
12 | }
13 |
14 | void loop() {
15 | // читаем адрес термометра в указанный массив
16 | if (sensor.readAddress(address)) { // если успешно, выводим
17 | Serial.print('{');
18 | for (uint8_t i = 0; i < 8; i++) {
19 | Serial.print("0x");
20 | Serial.print(address[i], HEX); // Выводим адрес
21 | if (i < 7) Serial.print(", ");
22 | }
23 | Serial.println('}');
24 |
25 | } else Serial.println("Not connected");
26 | delay(1000);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/async_read/async_read.ino:
--------------------------------------------------------------------------------
1 | // пример асинхронного опроса датчика на программном таймере
2 | // https://alexgyver.ru/lessons/time/
3 | // один датчик - один пин
4 |
5 | #include
6 | MicroDS18B20<2> sensor; // датчик на D2
7 |
8 | void setup() {
9 | Serial.begin(9600);
10 | }
11 |
12 | void loop() {
13 | // конструкция программного таймера на 800 мс
14 | static uint32_t tmr;
15 | if (millis() - tmr >= 800) {
16 | tmr = millis();
17 |
18 | // читаем прошлое значение
19 | if (sensor.readTemp()) Serial.println(sensor.getTemp());
20 | else Serial.println("error");
21 |
22 | // запрашиваем новое измерение
23 | sensor.requestTemp();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/async_read_many/async_read_many.ino:
--------------------------------------------------------------------------------
1 | // пример компактного асинхронного опроса датчиков на программном таймере
2 | // https://alexgyver.ru/lessons/time/
3 |
4 | // количество датчиков для удобства
5 | #define DS_SENSOR_AMOUNT 5
6 |
7 | // создаём двухмерный массив с адресами
8 | uint8_t addr[][8] = {
9 | {0x28, 0xFF, 0x78, 0x5B, 0x50, 0x17, 0x4, 0xCF},
10 | {0x28, 0xFF, 0x99, 0x80, 0x50, 0x17, 0x4, 0x4D},
11 | {0x28, 0xFF, 0x53, 0xE5, 0x50, 0x17, 0x4, 0xC3},
12 | {0x28, 0xFF, 0x42, 0x5A, 0x51, 0x17, 0x4, 0xD2},
13 | {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE},
14 | };
15 |
16 | #include
17 | // указываем DS_ADDR_MODE для подключения блока адресации
18 | // и создаём массив датчиков на пине D2
19 | MicroDS18B20<2, DS_ADDR_MODE> sensor[DS_SENSOR_AMOUNT];
20 |
21 | void setup() {
22 | Serial.begin(9600);
23 | // устанавливаем адреса
24 | for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
25 | sensor[i].setAddress(addr[i]);
26 | }
27 | }
28 |
29 | void loop() {
30 | // конструкция программного таймера на 1c
31 | static uint32_t tmr;
32 | if (millis() - tmr >= 1000) {
33 | tmr = millis();
34 |
35 | // выводим показания в порт
36 | for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
37 | Serial.print(sensor[i].getTemp());
38 | Serial.print(',');
39 | }
40 | Serial.println();
41 |
42 | // запрашиваем новые
43 | for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
44 | sensor[i].requestTemp();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/examples/async_read_many_bus/async_read_many_bus.ino:
--------------------------------------------------------------------------------
1 | // работа в режиме шины - несколько датчиков на линии, один объект
2 | // количество датчиков для удобства
3 | #define SENS_AMOUNT 5
4 |
5 | // создаём двухмерный массив с адресами
6 | uint8_t addr[][8] = {
7 | {0x28, 0xFF, 0x78, 0x5B, 0x50, 0x17, 0x4, 0xCF},
8 | {0x28, 0xFF, 0x99, 0x80, 0x50, 0x17, 0x4, 0x4D},
9 | {0x28, 0xFF, 0x53, 0xE5, 0x50, 0x17, 0x4, 0xC3},
10 | {0x28, 0xFF, 0x42, 0x5A, 0x51, 0x17, 0x4, 0xD2},
11 | {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE},
12 | };
13 |
14 | #include
15 | MicroDS18B20 sensors;
16 |
17 | void setup() {
18 | Serial.begin(9600);
19 | // устанавливаем адреса
20 | sensors.setAddress((uint8_t*)addr);
21 |
22 | // Установить разрешение 9-12 бит у всех датчиков на линии
23 | //sensors.setResolutionAll(10);
24 | }
25 |
26 | void loop() {
27 | // конструкция программного таймера на 1c
28 | static uint32_t tmr;
29 | if (millis() - tmr >= 1000) {
30 | tmr = millis();
31 |
32 | // выводим показания в порт
33 | for (int i = 0; i < SENS_AMOUNT; i++) {
34 | Serial.print(sensors.getTemp(i));
35 | Serial.print(',');
36 | }
37 | Serial.println();
38 |
39 | // запрашиваем новые
40 | sensors.requestTempAll();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/examples/async_read_many_bus_pgm/async_read_many_bus_pgm.ino:
--------------------------------------------------------------------------------
1 | // работа в режиме шины - несколько датчиков на линии, один объект
2 | // количество датчиков для удобства
3 | #define SENS_AMOUNT 5
4 |
5 | // создаём двухмерный массив с адресами
6 | const uint8_t addr[][8] PROGMEM = {
7 | {0x28, 0xFF, 0x78, 0x5B, 0x50, 0x17, 0x4, 0xCF},
8 | {0x28, 0xFF, 0x99, 0x80, 0x50, 0x17, 0x4, 0x4D},
9 | {0x28, 0xFF, 0x53, 0xE5, 0x50, 0x17, 0x4, 0xC3},
10 | {0x28, 0xFF, 0x42, 0x5A, 0x51, 0x17, 0x4, 0xD2},
11 | {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE},
12 | };
13 |
14 | #include
15 | MicroDS18B20 sensors;
16 |
17 | void setup() {
18 | Serial.begin(9600);
19 | // устанавливаем адреса
20 | sensors.setAddress((uint8_t*)addr);
21 |
22 | // Установить разрешение 9-12 бит у всех датчиков на линии
23 | //sensors.setResolutionAll(10);
24 | }
25 |
26 | void loop() {
27 | // конструкция программного таймера на 1c
28 | static uint32_t tmr;
29 | if (millis() - tmr >= 1000) {
30 | tmr = millis();
31 |
32 | // выводим показания в порт
33 | for (int i = 0; i < SENS_AMOUNT; i++) {
34 | Serial.print(sensors.getTemp(i));
35 | Serial.print(',');
36 | }
37 | Serial.println();
38 |
39 | // запрашиваем новые
40 | sensors.requestTempAll();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/examples/flash_reduction/flash_reduction.ino:
--------------------------------------------------------------------------------
1 | /*
2 | Пример с максимальной экономией flash при использовании библиотеки
3 | Если датчик один - не используйте адресацию
4 | Если датчиков несколько - рекомендуется использование адресации и ОДНОЙ линии для экономии flash
5 | */
6 |
7 | #define DS_CHECK_CRC false // отключить проверку подлинности принятых данных (может привести к выдаче некорректных измерений)
8 | #include
9 |
10 | // Датчик один - не используем адресацию
11 | #define DS_PIN 2
12 | MicroDS18B20 sensor;
13 |
14 | void setup() {
15 | Serial.begin(9600);
16 | }
17 |
18 | void loop() {
19 | sensor.requestTemp();
20 | delay(1000);
21 | Serial.print("t: ");
22 | Serial.print(sensor.getTempInt());
23 | Serial.println(" *C");
24 | }
25 |
--------------------------------------------------------------------------------
/examples/one_pin_many_sensors/one_pin_many_sensors.ino:
--------------------------------------------------------------------------------
1 | /*
2 | Пример нескольких термометров на одном пине с использованием адресации
3 | Использование адресации для нескольких датчиков значительно экономит память
4 | */
5 |
6 | #include
7 | #define DS_PIN 2 // пин для термометров
8 |
9 | // Уникальные адреса датчиков - считать можно в примере address_read
10 | uint8_t s1_addr[] = {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE};
11 | uint8_t s2_addr[] = {0x28, 0xFF, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};
12 |
13 | MicroDS18B20 sensor1; // Создаем термометр с адресацией
14 | MicroDS18B20 sensor2; // Создаем термометр с адресацией
15 |
16 | void setup() {
17 | Serial.begin(9600);
18 | }
19 |
20 | void loop() {
21 | // асинхронное чтение нескольких датчиков смотри в примере async_read_many
22 | sensor1.requestTemp(); // Запрашиваем преобразование температуры
23 | sensor2.requestTemp();
24 |
25 | delay(1000); // ожидаем результат
26 |
27 | Serial.print("t1: ");
28 | if (sensor1.readTemp()) Serial.println(sensor1.getTemp());
29 | else Serial.println("error");
30 |
31 | Serial.print("t2: ");
32 | if (sensor2.readTemp()) Serial.println(sensor2.getTemp());
33 | else Serial.println("error");
34 | }
35 |
--------------------------------------------------------------------------------
/examples/one_pin_one_sensor/one_pin_one_sensor.ino:
--------------------------------------------------------------------------------
1 | // пример работы с двумя датчиками без адресации
2 | // один датчик - один пин
3 |
4 | #include
5 | // Датчики на D2 и D3
6 | MicroDS18B20<2> sensor1;
7 | MicroDS18B20<3> sensor2;
8 |
9 | void setup() {
10 | Serial.begin(9600);
11 | }
12 |
13 | void loop() {
14 | // запрос температуры
15 | sensor1.requestTemp();
16 | sensor2.requestTemp();
17 |
18 | // вместо delay используй таймер на millis(), пример async_read
19 | delay(1000);
20 |
21 | // ПЕРВЫЙ ДАТЧИК
22 | Serial.print("t1: ");
23 |
24 | // просто выводим температуру первого датчика
25 | Serial.print(sensor1.getTemp());
26 |
27 | // ВТОРОЙ ДАТЧИК
28 | Serial.print(", t2: ");
29 |
30 | // проверяем успешность чтения и выводим
31 | if (sensor2.readTemp()) Serial.println(sensor2.getTemp());
32 | else Serial.println("error");
33 | }
34 |
--------------------------------------------------------------------------------
/examples/raw_and_calc/raw_and_calc.ino:
--------------------------------------------------------------------------------
1 | // пример с чтением сырого 16 бит значения
2 | // и расшифровкой его в температуру
3 | // может быть использовано для чтения и передачи
4 |
5 | #include
6 | // Датчик на D2
7 | MicroDS18B20<2> sensor;
8 |
9 | void setup() {
10 | Serial.begin(9600);
11 | //sensor.setResolution(12); // разрешение [9-12] бит. По умолч. 12
12 | }
13 |
14 | void loop() {
15 | sensor.requestTemp();
16 | delay(1000);
17 | // прпочитали сырое значение
18 | uint16_t rawVal = sensor.getRaw();
19 | Serial.print(rawVal);
20 | Serial.print(" ");
21 |
22 | // преобразовали
23 | Serial.println(DS_rawToFloat(rawVal));
24 | }
25 |
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map For microDS18B20
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 | MicroDS18B20 KEYWORD1
9 | microDS18B20 KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 | setResolution KEYWORD2
15 | readAddress KEYWORD2
16 | setAddress KEYWORD2
17 | requestTemp KEYWORD2
18 | readTemp KEYWORD2
19 | getTemp KEYWORD2
20 | getTempInt KEYWORD2
21 | getRaw KEYWORD2
22 | online KEYWORD2
23 | requestTempAll KEYWORD2
24 | setResolutionAll KEYWORD2
25 |
26 | DS_rawToInt KEYWORD2
27 | DS_rawToFloat KEYWORD2
28 |
29 | #######################################
30 | # Constants (LITERAL1)
31 | #######################################
32 | DS_CHECK_CRC LITERAL1
33 | DS_CRC_USE_TABLE LITERAL1
34 | DS_ADDR_MODE LITERAL1
35 | DS_PROGMEM LITERAL1
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=microDS18B20
2 | version=3.10
3 | author=AlexGyver
4 | maintainer=AlexGyver
5 | sentence=Light library for DS18b20 sensor
6 | paragraph=Light library for DS18b20 sensor
7 | category=Sensors
8 | url=https://github.com/GyverLibs/microDS18B20
9 | architectures=*
--------------------------------------------------------------------------------
/src/DS_raw.cpp:
--------------------------------------------------------------------------------
1 | #include "DS_raw.h"
2 |
3 | int DS_rawToInt(int16_t data) {
4 | return (data / 16);
5 | }
6 | float DS_rawToFloat(int16_t data) {
7 | return (data / 16.0);
8 | }
--------------------------------------------------------------------------------
/src/DS_raw.h:
--------------------------------------------------------------------------------
1 | #ifndef _DS_raw_h
2 | #define _DS_raw_h
3 | #include
4 | int DS_rawToInt(int16_t data); // преобразовать raw данные в температуру int
5 | float DS_rawToFloat(int16_t data); // преобразовать raw данные в температуру float
6 |
7 | #endif
--------------------------------------------------------------------------------
/src/microDS18B20.h:
--------------------------------------------------------------------------------
1 | /*
2 | Легкая библиотека для работы с 1-Wire (OneWire) термометрами Dallas DS18B20
3 | Документация:
4 | GitHub: https://github.com/GyverLibs/microDS18B20
5 | Возможности:
6 | - Работа с несколькими датчиками на одном пине (режим адресации)
7 | - Хранение массива адресов в PROGMEM памяти
8 | - Работа с одним датчиком на пине (без использования адресации)
9 | - Расчет температуры в целых числах и с плавающей точкой
10 | - Чтение сырых данных для случаев сильной экономии памяти
11 | - Проверка корректности полученной температуры
12 | - Настраиваемое разрешение преобразования
13 | - Проверка подлинности данных
14 | - Проверка корректности работы датчика
15 |
16 | Egor 'Nich1con' Zakharov & AlexGyver, alex@alexgyver.ru
17 | https://alexgyver.ru/
18 | MIT License
19 |
20 | Версии:
21 | v3.0 - Библиотека переехала на шаблон! Старые примеры НЕСОВМЕСТИМЫ. Оптимизация, новые трюки.
22 | v3.1 - добавлена возможность смены адреса на лету
23 | v3.1.1 - microOneWire разбит на .h и .cpp
24 | v3.2 - исправлены отрицательные температуры
25 | v3.3 - разбил на файлы
26 | v3.4 - добавлена проверка онлайна датчика и буфер, при ошибке чтения возвращается последнее прочитанное значение
27 | v3.5 - оптимизация, повышение стабильности, проверка правильности чтения, online() работает с адресацией, добавлен метод getTempInt() и readTemp(), упразднён DS_TEMP_TYPE
28 | v3.6 - исправлена ошибка компиляции, добавлена поддержка GyverCore (спасибо ArtemiyKolobov)
29 | v3.7 - исправлена ошибка readTemp() при 0 градусов
30 | v3.8 - небольшая оптимизация. Совместимость с ESP32
31 | v3.9 - добавил расширенный режим адресации и хранение адресов в PROGMEM
32 | v3.10 - оптимизация, увеличена стабильность
33 | */
34 |
35 | #ifndef _microDS18B20_h
36 | #define _microDS18B20_h
37 | #include
38 | #include "microOneWire.h"
39 | #include "DS_raw.h"
40 |
41 | #define DS_PROGMEM 1
42 |
43 | #ifndef DS_CHECK_CRC
44 | #define DS_CHECK_CRC true // true/false - проверка контрольной суммы принятых данных - надежнее, но тратит немного больше flash
45 | #endif
46 |
47 | #ifndef DS_CRC_USE_TABLE
48 | #define DS_CRC_USE_TABLE false // true/false - использовать готовую таблицу контрольной суммы - значительно быстрее, +256 байт flash
49 | #endif
50 |
51 | /*
52 | Время исполнения функций для работы с датчиком (частота ядра - 16 МГц):
53 | _________________________________________________________________________________
54 | | Датчик без адресации (один на линии) | Датчик с адресацией (несколько на линии) |
55 | |______________________________________|__________________________________________|
56 | | .setResolution(...) ~ 3591.125 мкс | .setResolution(...) ~ 8276.0625 мкс |
57 | | .requestTemp() ~ 1839.9375 мкс | .requestTemp() ~ 6522.1875 мкс |
58 | |______________________________________|__________________________________________|
59 | | С использованием CRC8 |
60 | |_________________________________________________________________________________|
61 | | .readAddress(...) ~ 6467.3125 мкс | float .getTemp() ~ 12250.25 мкс |
62 | | float .getTemp() ~ 7620.25 мкс | int .getTemp() ~ 12250.2500 мкс |
63 | | int .getTemp() ~ 7574.0625 мкс | |
64 | |______________________________________|__________________________________________|
65 | | Без использования CRC8 |
66 | |_________________________________________________________________________________|
67 | | .readAddress(...) ~ 6394.3125 мкс | float .getTemp() ~ 7809.1250 мкс |
68 | | float .getTemp() ~ 3132.9375 мкс | int .getTemp() ~ 7809.1250 мкс |
69 | | int .getTemp() ~ 3132.9375 мкс | |
70 | |______________________________________|__________________________________________|
71 | */
72 |
73 | // ====================== CRC TABLE ======================
74 | #if (DS_CRC_USE_TABLE == true)
75 | static const uint8_t PROGMEM _ds_crc8_table[] = {
76 | 0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
77 | 0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,
78 | 0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
79 | 0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,
80 | 0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,
81 | 0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
82 | 0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,
83 | 0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
84 | 0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
85 | 0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,
86 | 0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,
87 | 0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1, 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
88 | 0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,
89 | 0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4, 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,
90 | 0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a, 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
91 | 0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35
92 | };
93 | #endif
94 |
95 | #pragma GCC diagnostic push
96 | #pragma GCC diagnostic ignored "-Wunused-variable"
97 | uint8_t _empDsAddr[1] = {1};
98 | #pragma GCC diagnostic pop
99 | #define DS_ADDR_MODE _empDsAddr
100 |
101 | // ====================== CLASS ======================
102 | template
103 | class MicroDS18B20 {
104 | public:
105 | MicroDS18B20() {
106 | pinMode(DS_PIN, INPUT);
107 | digitalWrite(DS_PIN, LOW);
108 | }
109 |
110 | // Установить разрешение термометра 9-12 бит
111 | void setResolution(uint8_t res, uint8_t idx = 0) {
112 | if (!oneWire_reset(DS_PIN)) return; // Проверка присутствия
113 | addressRoutine(idx); // Процедура адресации
114 | oneWire_write(0x4E, DS_PIN); // Запись RAM
115 | oneWire_write(0xFF, DS_PIN); // Максимум в верхний регистр тревоги
116 | oneWire_write(0x00, DS_PIN); // Минимум в верхний регистр тревоги
117 | oneWire_write(((constrain(res, 9, 12) - 9) << 5) | 0x1F, DS_PIN); // Запись конфигурации разрешения
118 | }
119 |
120 | // Установить разрешение термометра 9-12 бит у всех датчиков на линии
121 | void setResolutionAll(uint8_t res) {
122 | for (int i = 0; i < DS_AM; i++) setResolution(res, i);
123 | }
124 |
125 | // установить адрес
126 | void setAddress(uint8_t *addr) {
127 | _addr = addr;
128 | }
129 |
130 | // Прочитать уникальный адрес термометра в массив
131 | bool readAddress(uint8_t *addr) {
132 | if (!oneWire_reset(DS_PIN)) return 0; // Проверка присутствия
133 | oneWire_write(0x33, DS_PIN); // Запрос адреса
134 | uint16_t sum = 0; // контрольная сумма
135 | uint8_t crc = 0; // обнуляем crc
136 | for (uint8_t i = 0; i < 8; i++) { // Прочитать 8 байт адреса
137 | addr[i] = oneWire_read(DS_PIN); // Записать в массив
138 | sum += addr[i]; // контрольная сумма
139 | #if (DS_CHECK_CRC == true)
140 | _ds_crc8_upd(crc, addr[i]); // Обновить значение CRC8
141 | #endif
142 | }
143 | return !(sum == 0x8F7 || !sum || crc); // CRC не сошелся или адрес нулевой - ошибка
144 | }
145 |
146 | // запрос температуры
147 | void requestTemp(uint8_t idx = 0) {
148 | state[idx] = 0; // запрошена новая температура
149 | if (!oneWire_reset(DS_PIN)) return; // Проверка присутствия
150 | addressRoutine(idx); // Процедура адресации
151 | oneWire_write(0x44, DS_PIN); // Запросить преобразование
152 | }
153 |
154 | // запрос температуры у всех датчиков на линии
155 | void requestTempAll() {
156 | for (int i = 0; i < DS_AM; i++) requestTemp(i);
157 | }
158 |
159 | // получить температуру float
160 | float getTemp(uint8_t idx = 0) {
161 | if (!state[idx]) readTemp(idx);
162 | return (_buf[idx] / 16.0);
163 | }
164 |
165 | // получить температуру int
166 | int16_t getTempInt(uint8_t idx = 0) {
167 | if (!state[idx]) readTemp(idx);
168 | return (_buf[idx] >> 4);
169 | }
170 |
171 | // получить "сырое" значение температуры
172 | int16_t getRaw(uint8_t idx = 0) {
173 | if (!state[idx]) readTemp(idx);
174 | return _buf[idx];
175 | }
176 |
177 | // прочитать температуру с датчика. true если успешно
178 | bool readTemp(uint8_t idx = 0) {
179 | state[idx] = 1;
180 | if (!oneWire_reset(DS_PIN)) return 0; // датчик оффлайн
181 | addressRoutine(idx); // Процедура адресации
182 | oneWire_write(0xBE, DS_PIN); // Запросить температуру
183 | uint8_t crc = 0; // обнуляем crc
184 | int16_t temp; // переменная для расчёта температуры
185 | uint16_t sum = 0; // контрольная сумма
186 | for (uint8_t i = 0; i < 9; i++) { // Считать RAM
187 | uint8_t data = oneWire_read(DS_PIN); // Прочитать данные
188 | sum += data;
189 | #if (DS_CHECK_CRC == true)
190 | _ds_crc8_upd(crc, data); // Обновить значение CRC8
191 | #endif
192 | if (i == 0) temp = data;
193 | else if (i == 1) temp |= (data << 8);
194 | }
195 | if (sum == 0x8F7 || !sum || crc) return 0; // датчик оффлайн или данные повреждены
196 | if (temp != 0x0550) _buf[idx] = temp; // пропускаем первое чтение (85 градусов)
197 | return 1;
198 | }
199 |
200 | // проверить связь с датчиком (true - датчик на линии). ЛИНИЯ ДОЛЖНА БЫТЬ ПОДТЯНУТА
201 | bool online(uint8_t idx = 0) {
202 | if (DS_ADDR != nullptr) {
203 | if (!oneWire_reset(DS_PIN)) return 0;
204 | addressRoutine(idx);
205 | oneWire_write(0xBE, DS_PIN);
206 | uint16_t sum = 0;
207 | for (uint8_t i = 0; i < 5; i++) sum += oneWire_read(DS_PIN);
208 | return (sum != 0x4FB);
209 | } else return oneWire_reset(DS_PIN);
210 | }
211 |
212 | private:
213 | bool state[DS_AM];
214 | int16_t _buf[DS_AM];
215 | uint8_t *_addr = DS_ADDR;
216 |
217 | void addressRoutine(uint8_t idx) { // Процедура адресации
218 | if (DS_ADDR != nullptr) { // Адрес определен?
219 | oneWire_write(0x55, DS_PIN); // Говорим термометрам слушать адрес
220 | for (uint8_t i = 0; i < 8; i++) {
221 | if (DS_PGM) oneWire_write(pgm_read_byte(&_addr[i + idx * 8]), DS_PIN);
222 | else oneWire_write(_addr[i + idx * 8], DS_PIN);
223 | }
224 | } else oneWire_write(0xCC, DS_PIN); // Адреса нет - пропускаем адресацию на линии
225 | }
226 |
227 | void _ds_crc8_upd(uint8_t &crc, uint8_t data) {
228 | #if (DS_CRC_USE_TABLE == true) // Используем таблицу?
229 | crc = pgm_read_byte(&_ds_crc8_table[crc ^ data]); // Тогда берем готовое значение
230 | #else // считаем вручную
231 | #ifdef __AVR__
232 | // резкий алгоритм для AVR
233 | uint8_t counter;
234 | uint8_t buffer;
235 | asm volatile (
236 | "EOR %[crc_out], %[data_in] \n\t"
237 | "LDI %[counter], 8 \n\t"
238 | "LDI %[buffer], 0x8C \n\t"
239 | "_loop_start_%=: \n\t"
240 | "LSR %[crc_out] \n\t"
241 | "BRCC _loop_end_%= \n\t"
242 | "EOR %[crc_out], %[buffer] \n\t"
243 | "_loop_end_%=: \n\t"
244 | "DEC %[counter] \n\t"
245 | "BRNE _loop_start_%="
246 | : [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer)
247 | : [crc_in]"0" (crc), [data_in]"r" (data)
248 | );
249 | #else
250 | // обычный для всех остальных
251 | uint8_t i = 8;
252 | while (i--) {
253 | crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1);
254 | data >>= 1;
255 | }
256 | #endif
257 | #endif
258 | }
259 | };
260 | #endif
--------------------------------------------------------------------------------
/src/microOneWire.cpp:
--------------------------------------------------------------------------------
1 | #include "microOneWire.h"
2 | #ifdef __AVR__
3 | #define MOW_CLI() uint8_t oldSreg = SREG; cli();
4 | #define MOW_SEI() SREG = oldSreg
5 | #else
6 | #define MOW_CLI()
7 | #define MOW_SEI()
8 | #endif
9 |
10 | bool oneWire_reset(uint8_t pin) {
11 | pinMode(pin, OUTPUT);
12 | delayMicroseconds(600);
13 | pinMode(pin, INPUT);
14 | MOW_CLI();
15 | delayMicroseconds(60);
16 | bool pulse = digitalRead(pin);
17 | MOW_SEI();
18 | delayMicroseconds(600);
19 | return !pulse;
20 | }
21 |
22 | void oneWire_write(uint8_t data, uint8_t pin) {
23 | for (uint8_t i = 8; i; i--) {
24 | pinMode(pin, OUTPUT);
25 | MOW_CLI();
26 | if (data & 1) {
27 | delayMicroseconds(5);
28 | pinMode(pin, INPUT);
29 | delayMicroseconds(60);
30 | } else {
31 | delayMicroseconds(60);
32 | pinMode(pin, INPUT);
33 | delayMicroseconds(5);
34 | }
35 | MOW_SEI();
36 | data >>= 1;
37 | }
38 | }
39 |
40 | uint8_t oneWire_read(uint8_t pin) {
41 | uint8_t data = 0;
42 | for (uint8_t i = 8; i; i--) {
43 | data >>= 1;
44 | MOW_CLI();
45 | pinMode(pin, OUTPUT);
46 | delayMicroseconds(2);
47 | pinMode(pin, INPUT);
48 | delayMicroseconds(8);
49 | if (digitalRead(pin)) data |= (1 << 7);
50 | delayMicroseconds(60);
51 | MOW_SEI();
52 | }
53 | return data;
54 | }
--------------------------------------------------------------------------------
/src/microOneWire.h:
--------------------------------------------------------------------------------
1 | // v1.2 от 26.04.2020 - Повышена стабильность
2 | // v1.3 от 08.09.2021 - Разбил на .h и .cpp
3 | // v1.4 от 07.01.2022 - Чуть сократил код, поддержка GyverCore
4 | // v1.5 от 18.02.2022 - оптимизация, поддержка esp32
5 |
6 | #ifndef _microOneWire_h
7 | #define _microOneWire_h
8 | #include
9 |
10 | bool oneWire_reset(uint8_t pin);
11 | void oneWire_write(uint8_t data, uint8_t pin);
12 | uint8_t oneWire_read(uint8_t pin);
13 | #endif
--------------------------------------------------------------------------------