В журнале моего гаражного логгера однажды появилась лишняя колонка. Я не добавлял датчик — колонку писала сама DS3231: вызов getTemperature() стоил одну строку кода, и в файл рядом со временем пошла температура чипа. Первую неделю я ей не доверял: уличный DS18B20 показывал, скажем, плюс восемь, а чип — плюс одиннадцать. Разница в три градуса держалась стабильно, и я уже грешал на бракованный модуль, пока не понял: чип не врёт, он просто измеряет не воздух, а сам себя. Под питанием кремний греется, корпус чуть тёплый на ощупь — и термометр честно это показывает.
С тех пор эта колонка живёт в каждом моём журнале с часами. Бесплатный источник данных, за который не нужен ни второй провод, ни отдельная библиотека — значение отдаёт тот же объект, из которого мы берём время. Подумайте об этом как о смене приоритетов: отдельный термометр стоит денег, занимает пин и тянет за собой библиотеку, а этот уже сидит на шине и ждёт вызова. Но у бесплатного сыра понятные границы: точность плюс-минус три градуса, шаг в четверть градуса, самонагрев и фиктивный регистр у MEMS-версии. Ниже разберём, где чип выручит, где соврёт, и как за сутки откалибровать его до сносного комнатного термометра.
Столбец тот обнаружился, когда я принёс журнал с карты на ноутбук: колонка температуры росла и падала в такт солнцу на подоконнике — утром плавно вверх, к вечеру вниз, ночью плато. Корреляция с реальной погодой была, но со сдвигом вверх, будто ко всей кривой приложили константу. Это и есть типичный портрет датчика: динамику он показывает отлично, абсолютные значения — с поправкой на ваш экземпляр. Дальше в уроке: откуда берётся число, чем оно полезно в быту проекта и почему для вентилятора в щитке оно оказалось удобнее уличного датчика.
Датчик, который живёт для кварца
Термометр в DS3231 появился не для пользователей, а для самого чипа: раз в 64 секунды он меряет свою температуру и подстраивает кварц, чтобы ход часов не плыл от жары и мороза. Значит, и «свежесть» показания ограничена этим циклом: читать чаще, чем раз в минуту, бессмысленно — регистры между замерами не меняются, вы будете получать одно и то же число. В журнале это видно как ступеньки: при опросе раз в две секунды идут тридцать два подряд одинаковых значения, потом скачок на четверть градуса. Не путайте такие плато с зависанием — так выглядит честный темп обновления регистра. Механику компенсации и адреса регистров 0x11 и 0x12 я разбирал в уроке про точность DS3231 — там же про шаг 0,25 градуса, который библиотека переводит в дробную часть float. На уровне API всё просто: метод getTemperature() возвращает float, под капотом — два байта по шине, на 100 кГц это доли миллисекунды, описанные в уроке про I2C.
Точность по даташиту — плюс-минус три градуса, и это честно отражает назначение: датчик создан следить за температурой кристалла, а не за погодой. Для вывода «в щитке стало жарко» этого достаточно, для метеожурнала — нет. Отдельная ловушка — модули с маркировкой DS3231M: у них MEMS-ядро вместо кварца, регистр температуры читается, но числа в нём фиктивные; как отличить такие чипы на прилавке — в сравнении DS1307 и DS3231.
#include <Wire.h>#include <RTClib.h> RTC_DS3231 rtc;const int VENT = 12; // сюда — светодиод или модуль релеbool ventOn = false; void setup() { Serial.begin(9600); pinMode(VENT, OUTPUT); rtc.begin();} void loop() { float t = rtc.getTemperature(); Serial.print("t_rtc="); Serial.println(t); // гистерезис: включаем на 35, выключаем только на 33 if (!ventOn && t > 35.0) { ventOn = true; digitalWrite(VENT, HIGH); Serial.println("ventilator: vklyuchil"); } else if (ventOn && t < 33.0) { ventOn = false; digitalWrite(VENT, LOW); } delay(2000);}В скетче — гистерезис: порог включения 35 градусов, порог выключения 33. Разрыв в два градуса нужен, чтобы реле не защёлкало у границы: без него вентилятор включался бы и выключался каждые пару минут, а реле такого режима не прощает. Механику вилки я разбирал в уроке про термостат с гистерезисом — здесь та же схема, только датчик другой. Выходом может быть светодиод на пине 12 для макетки или модуль реле для настоящей вертушки — реле ставьте через транзисторный ключ или готовый модуль, катушку напрямую с пина не кормят. Проверка раз в две секунды избыточна для датчика с циклом 64 секунды, но почти бесплатна и даёт живой поток в Serial для отладки.
Три практических применения, проверенных на своих устройствах. Первое — колонка в журнале из урока про логгер со штампами: график температуры чипа рядом с графиком хода часов мгновенно показывает, насколько вашему модулю страшна жара. Второе — охрана корпуса: логгер в герметичном щитке на солнце нагревается незаметно, и вентилятор по порогу дешевле сгоревшей платы. Третье — калибровка самого датчика: снимите сутки показаний чипа и параллельного DHT22, посчитайте среднее разницы — это и есть смещение вашего экземпляра, которое можно вычитать в скетче. Один замер для этого не годится: шум и шаг 0,25 градуса требуют усреднения.
Калибровка — протоколом, а не на глазок. Рядом ставится эталон: DHT22 на своём пине данных или DS18B20 на проводе 1-Wire — и пары значений снимаются весь день: утро, полдень, вечер, ночь. Не меньше двадцати пар, иначе один шумный замер перекосит среднее. Среднее разницы — смещение экземпляра; после вычитания одной строкой в скетче чип выдаёт сносную комнатную температуру с погрешностью порядка градуса — остаток от заявленных плюс-минус трёх. Если разница в течение дня гуляет — утром плюс один, вечером плюс три, — это признак сквозняка или соседства с греющейся платой, и тоже диагностический сигнал. А если встал вопрос, какой термометр вообще брать в проект, — расклад NTC, DHT и DS18B20 по точности и возне с калибровкой сделан в отдельном сравнении термометров.
Про обработку пар: среднее чувствительно к выбросам, поэтому надёжнее медиана двадцати значений — она не поедет от одного странного замера во время возни с проводами. Смещение оформите именованной константой рядом с объектом часов и вычитайте одной строкой — без магии по всему скетчу. Проверка после калибровки простая: оба датчика рядом на сутки, и разница должна гулять в пределах полградуса-градуса, а не дрейфовать в сторону. Ушло в сторону — значит, менялись условия, а не датчик: посмотрите, что рядом стояло.
| Термометр | Точность | Шаг | Где живёт |
|---|---|---|---|
| DS3231 встроенный | ±3 °C, теплее воздуха на 1–3 °C | 0,25 °C | внутри часов, чтение по I2C бесплатно |
| DHT22 | ±0,5 °C | 0,1 °C | отдельный сенсор, один пин данных, пауза 2 с |
| DS18B20 | ±0,5 °C | 0,0625 °C | OneWire, один пин, защита от помех лучше |
| NTC-термистор | ±1–2 °C после калибровки | ограничен 10-битным АЦП | аналоговый вход и делитель из двух резисторов |
Симулятор: чип прибит к 23,5
Здесь нужна полная честность: движок симулятора всегда отвечает на getTemperature() числом 23,5 — он не греет и не охлаждает виртуальный чип. Зато рядом подключён живой DHT22 на пине 2: ползунок температуры под вашим контролем, и скетч печатает обе величины и разницу. На настоящей плате оба числа живые, а разница между ними — то самое смещение вашего экземпляра: один-три градуса самонагрева, зависящие от корпуса и потока воздуха. В симе разница отражает только ваши движения ползунка — но сам формат наблюдения «два термометра рядом» отрабатывается именно так.
Ещё одна деталь, которую в симе не увидеть, — ступеньки 0,25 градуса и знак. Значение t_rtc здесь стоит на месте, а на плате за полчаса вы поймаете два-три скачка на четверть — это нормальный темп обновления регистра, а не заикание. Минусовые значения getTemperature() отдаёт честно: зимой в гараже я снял минус двенадцать против минус четырнадцати у уличного DS18B20 — и оба были правы, каждый про своё место. Если хочется увидеть срабатывание охраны прямо в симуляторе, опустите порог в строке if (trtc > 35.0) до двадцати: светодиод загорится, и вся логика гистерезиса пройдёт на ваших глазах.
- Подвиньте ползунок DHT22 к реальной комнатной температуре — разница delta покажет, насколько чип «теплее» симуляционного воздуха
- Опустите порог в строке if (trtc > 35.0) до 20: светодиод загорится — механика гистерезиса работает, просто 23,5 ниже заводского порога
- Снимите с плате десять пар t_rtc и t_dht за сутки и посчитайте среднее разницы — так калибруют смещение экземпляра
- Добавьте t_rtc колонкой в логгер из соседнего урока: два месяца журнала дадут настоящую корреляцию хода часов и жары
- Термометр DS3231 существует ради компенсации кварца: замер раз в 64 секунды, читать чаще — то же число
- getTemperature() возвращает float с шагом 0,25 °C; точность ±3 °C — годится для «жарко или холодно», не для метеожурнала
- Чип теплее воздуха на 1–3 °C от самонагрева: суточное среднее разницы с DHT22 даёт смещение, которое можно вычитать
- Порог вентилятора ставь от температуры корпуса и с гистерезисом в 2 °C — иначе реле защёлкает у границы
- Колонка температуры чипа в журнале логгера — бесплатная ось для корреляции хода часов с жарой
- 1. Зачем в DS3231 вообще есть термометр?
- 2. С каким шагом меняется показание getTemperature()?
- 3. Почему чип показывает на пару градусов теплее воздуха?
- 4. Что вернёт getTemperature() у модуля DS3231M?
- 5. Как выжать из DS3231 более честную комнатную температуру?
Частые вопросы по теме урока
- Зачем в DS3231 вообще есть термометр?
- Датчик обслуживает схему термокомпенсации: чип меряет свою температуру и подстраивает кварц. Побочный бонус — вы можете читать регистры температуры сами через getTemperature(). Чтобы компенсировать ход кварца замером каждые 64 секунды
- С каким шагом меняется показание getTemperature()?
- Старший регистр хранит целые градусы, два бита младшего — четверти: показания идут ступеньками по 0,25 °C. 0,25 °C
- Почему чип показывает на пару градусов теплее воздуха?
- Термометр меряет температуру кристалла, а кремний под током греется. Показание честно описывает чип, а не комнату — смещение компенсируется калибровкой. Он сам нагревается под питанием
- Что вернёт getTemperature() у модуля DS3231M?
- У DS3231M с MEMS-ядром регистр температуры присутствует, но его содержимое не отражает реальный нагрев. На M-модулях пороги от этого регистра не строят. Фиктивное число: регистр есть, реального датчика нет
- Как выжать из DS3231 более честную комнатную температуру?
- Смещение экземпляра стабильно в пределах градуса-двух. Суточное усреднение разницы с реальным термометром убирает шум, и после вычитания чип превращается в сносный комнатный датчик. Снять суточное среднее разницы с DHT22 и вычесть это смещение