Общие сведения
WEMOS DS18b20 Shield — это модуль с цифровым датчиком температуры DS18B20, предназначенный для установки на платы WeMos: WEMOS D1 mini / WEMOS D1 mini Pro. Модуль позволяет измерять температуру окружающей среды и объектов от -55 до 125°C.
Характеристики
- Используемые выводы: D2, 5V, GND.
- Шина передачи данных: 1-wire.
- Диапазон измеряемых температур: -55 ... 125 °C.
- Разрешение: настраивается от 9 бит (0,5 °C) до 12 бит (0,0625 °C).
- Точность: ±0,5 °C.
- Габариты: 27,6x25,6 мм.
Подключение
- Перед установкой Shield, к его выводам нужно припаять разъемы идущие с ним в комплекте.
- Все Shield WeMos устанавливаются на плату WEMOS D1 mini или WEMOS D1 mini Pro без использования проводов.
- На всех платах WeMos имеется вырез возле вывода 3V3. При установке Shield вырезы всех плат должны находиться с одной и той же стороны (друг над другом).
Подробнее о модуле
На плате WeMos DS18b20 Shield установлен цифровой датчик температуры DS18B20 подключённый к выводу «D2». Чтение данных с датчика осуществляется по шине 1-Wire. Датчик способен измерять температуру от -55 до 125°C с настраиваемым разрешением от 9 бит (0,5 °C) до 12 бит (0,0625 °C).
Примеры
Вывод температуры в монитор последовательного порта.
#include <OneWire.h> // Подключаем библиотеку OneWire для работы с шиной 1-wire. OneWire ds(D2); // Объявляем объект ds для работы с функциями и методами библиотеки OneWire, указывая номер вывода используемого в качестве шины 1-wire. byte addr[8]; // Объявляем массив для хранения адреса найденного устройства. Адрес устройства состоит из 64 бит = 8 байт, где последний байт является CRC8 для первых 7 byte data[9]; // Объявляем массив для хранения данных полученных от устройства. Датчики семейства DS18x20 отправляют 9 байт данных, где последний байт является CRC8 для первых 8 // void setup(void){ // Serial.begin(74880); // Инициируем передачу данных в монитор последовательного порта на скорости 74880 бод. } // // void loop(void){ // // Ищем очередное устройство: // if(!ds.search(addr)){ // Ищем очередное устройство на шине 1-wire, получая его адрес в массив addr. Если устройство найдено, то код в теле оператора if будет пропущен, а если устройство не найдено, то ... ds.reset_search(); // Завершаем текущий цикл поиска устройств, следующий вызов функции search() найдёт адрес певого, а не следующего, устройства на шине 1-wire. Serial.println("==================\r\n"); // Выводим в монитор черту "==================" отделяя найденные устройства в данном цикле поиска от устройств которые будут найдены в следующем цикле. delay(1000); return; // Ждём 1 секунду и выходим из текущего прохода цикла loop(). Меняя время ожидания, Вы будете чаще или реже получать показания в мониторе. } // // Выводим адрес найденного устройства: // Serial.print("ADDRES = "); // Выводим в монитор надпись "ADDRES:". for(byte i=0; i<8; i++){ // Проходим по всем 8 байтам найденного адреса (он хранится в массиве addr). if(addr[i]<0x10){Serial.print("0");} // Если значение очередного байта адреса addr[i] меньше чем 0x10, то сначала выводим "0". Тогда каждый байт адреса будет выводиться в 2 разрядах (например: 01, а не 1). Serial.print(addr[i], HEX); // Выводим очередной байт найденного адреса в шеснадцатиричном формате. } // // Проверяем целостность найденного адреса: // Последний байт адреса является байтом циклически избыточного кода CRC8 для первых 7 байт принятого адреса. if(OneWire::crc8(addr, 7) != addr[7]){ // Если рассчитанный CRC8 для первых 7 байт адреса не совпадает с последним байтом, значит адрес принят с ошибкой, тогда ... Serial.println(" - CRC is not valid!"); return; // Выводим надпись " - CRC is not valid!" (CRC не корректный) и выходим из текущего прохода цикла loop(). } Serial.println(); // // Определяем тип чипа по его адресу: // Тип чипов DS18x20 определяется по старшему байту их адреса. switch(addr[0]){ // case 0x10: Serial.println(" Chip = DS18S20"); break; // Найденное устройство принадлежит семейству DS18S20 или является чипом более ранней версии. case 0x28: Serial.println(" Chip = DS18B20"); break; // Найденное устройство принадлежит семейству DS18B20. case 0x22: Serial.println(" Chip = DS1822" ); break; // Найденное устройство принадлежит семейству DS1822. default: Serial.println("Device is not a DS18x20."); return; // Выводим надпись "Device is not a DS18x20." - устройство не является DS18x20 и выходим из текущего прохода цикла loop(). } // // Отправляем чипу команду 0x44 - выполнить температурную конверсию: // if(!ds.reset()){Serial.println("break connection"); return;} // Отправляем сигнал RESET. Устройства должны ответить сигналом PRESENCE и ждать начало обмена данными. Если сигнал PRESENCE не поступил, то выполняем выход из текущего прохода цикла loop(). ds.select(addr); // Выбираем устройство с адресом addr. ds.write(0x44); // Отправляем выбранному устройству команду 0x44. Если используется паразитное питание (2 провода), то нужно указать 1 в качестве второго аргумента: ds.write(0x44,1); delay(750); // Ждём 750мс, это максимальное время требуемое для выполнения температурной конверсии для модуля DS18B20. // Отправляем чипу команду 0xBE - прочитать данные из ОЗУ: // if(!ds.reset()){Serial.println("break connection"); return;} // Отправляем сигнал RESET. Устройства должны ответить сигналом PRESENCE и ждать начало обмена данными. Если сигнал PRESENCE не поступил, то выполняем выход из текущего прохода цикла loop(). ds.select(addr); // Выбираем устройство с адресом addr. ds.write(0xBE); // Отправляем выбранному устройству команду 0xBE. Если используется паразитное питание (2 провода), то нужно указать 1 в качестве второго аргумента: ds.write(0xBE,1); // Получаем ответ от чипа: // for(byte i=0; i<9; i++){data[i]=ds.read();} // Чип должен вернуть 9 байт данных, поочерёдно записываем их в массив data. // Выводим полученные данные: // Serial.print(" Data = "); // Выводим надпись "Data =". for(byte i=0; i<8; i++){ // Проходим по первым 8 байтам принятых данных (последний 9 байт является байтом CRC, а не байтом данных). if(data[i]<0x10){Serial.print("0");} // Если значение очередного байта данных data[i] меньше чем 0x10, то сначала выводим "0". Тогда каждый байт данных будет выводиться в 2 разрядах (например: 01, а не 1). Serial.print(data[i], HEX); // Выводим очередной байт полученных данных в шеснадцатиричном формате. } // // Проверяем целостность принятых данных: // Последний байт данных является байтом циклически избыточного кода CRC8 для первых 8 байт принятых данных. if(OneWire::crc8(data, 8) != data[8]){ // Если рассчитанный CRC8 для первых 8 байт данных не совпадает с последним принятым байтом, значит данные приняты с ошибкой, тогда ... Serial.println(" - CRC is not valid!"); return; // Выводим надпись " - CRC is not valid!" (CRC не корректный) и выходим из текущего прохода цикла loop(). } Serial.println(); // // Выравниваем полученные данные температуры до 12 бит: // int16_t raw = (data[1] << 8) + data[0]; // Значение температуры содержится в первых двух байтах: data[1] - старший байт значения температуры, data[0] - младший байт значения температуры. if(addr[0]==0x10){ // Если чип принадлежит семейству DS18S20 или более ранней версии, то ... raw <<= 3; // Значение температуры состоит из 9 младших бит с разрешением 0.5°C, приводим значение температуры к 12 битному формату, сдвигая все биты на 3 разряда вверх. if(data[7]==0x10){raw = (raw & 0xFFF0) + 12 - data[6];} // Если регистр COUNT_PER_C (data[7]) позволяет пересчитать температуру к более высокому разрешению, то разумеется делаем это. }else{ // Иначе (если чип принадлежит семейству DS18B20 или DS1822), то ... if(data[4]&0x60 == 0x00){raw &= 0xFFF8;}else // Если биты 6 и 5 статусного регистра data[4] равны 00, значит температура состоит из 9 бит с разрешением 0.5 °C, младшие 3 бита не участвуют, мы их сбрасываем в 0 (raw &= 0xFFF8). if(data[4]&0x60 == 0x20){raw &= 0xFFFC;}else // Если биты 6 и 5 статусного регистра data[4] равны 01, значит температура состоит из 10 бит с разрешением 0.25 °C, младшие 2 бита не участвуют, мы их сбрасываем в 0 (raw &= 0xFFFС). if(data[4]&0x60 == 0x40){raw &= 0xFFFE;} // Если биты 6 и 5 статусного регистра data[4] равны 10, значит температура состоит из 11 бит с разрешением 0.125 °C, младший 1 бит не участвует, мы его сбрасываем в 0 (raw &= 0xFFFE). } // Если биты 6 и 5 статусного регистра data[4] равны 11, значит температура состоит из 12 бит с разрешением 0.0625°C, все биты участвуют, сбрасывать ничего не надо. // Преобразуем 12 бит данных к температуре в °C и выводим в монитор: // float result = (float) raw / 16.0; // Температура состоит из 12 бит, старшие 8 бит являются целым числом, а младшие 4 дадут дробную часть при умножении на разрешение. То же произойдёт при делении всего числа на 16. Serial.println((String) " Temp = " + result + "*C"); // Выводим результат в монитор. } //
Данный скетч использует библиотеку OneWire для работы с устройствами по шине 1-Wire.
Чтение показаний датчика состоит из 5 частей:
- Обнаружение датчика на шине 1-wire с получением и проверкой целостности его адреса.
- Определение типа датчика.
- Отправка команд датчику на выполнение конверсии температуры и выгрузки данных из ОЗУ.
- Получение данных от датчика с проверкой их целостности.
- Преобразование данных к температуре в °C и её вывод.
Единственная строка кода setup() инициирует передачу данных в монитор последовательного порта на скорости 74880 бод. Данная скорость выбрана не случайно, именно на этой скорости микроконтроллер ESP8266 отправляет в UART отладочную информацию при старте.
Комплектация
- 1x WeMos DS18b20 Shield;
- 2x Соединитель типа "ПАПА-ПАПА";