Почему я решил сделать сам?
У меня есть две любимые сестры, которые очень хотели бы иметь дома сенсор CO2, а также температуры и влажности воздуха. Представленные на рынке готовые решения меня не сильно устраивали, а как говорится: хочешь сделать хорошо – сделай это сам. К тому же, у меня была давняя мечта сделать свою собственную плату.
Выбор компонентов
Я сам пользовался сенсорами углекислого газа MH-Z19 и SHT31-D для температуры и влажности воздуха, которые навесным монтажом были приделаны к ESP32.
Я искал сенсор, который бы по возможности имел бы более удачный форм-фактор и по возможности бы сочетал в мог бы измерять все три характеристики. В списке поддерживаемых сенсоров на сайте ESPHome я обнаружил SCD30 от фирмы Senserion.
Помимо компактных размеров и позитивных отзывов на форумах, также приятно порадовала цена в районе $15 за штуку.
В качестве контроллера решил использовать ESP8266 за отсутствием потребности в Bluetooth и использовании одного единственного I2C устройства.
Исходя из того, что устройством будут пользоваться люди далекие от мира микроконтроллеров и электроники, было решено использовать USB-C для устройства и снабдить каждую плату встроенным USB-UART конвертером для загрузки прошивки. Здесь бы я снова хотел обратить внимание на экосистему ESPHome, в которой прошивка конфигурируется yaml файлом, компилируется и загружается программой на Python в автоматическом режиме. Помимо всего прочего работает как под Widnows, так и под MacOS, и под Linux без каких либо проблем.
Разработка платы
Так как изначально планировалось заказывать платы на JLPCB, то я решил воспользоваться их средой EasyEDA Pro (которая бесплатна ровно так же как и стандартная версия).
Для схемы подключения UART конвертера были взяты референсы из официальной документации ESP. Использование RTS и DTR пинов с двумя транзисторами позволяют загрузчику прошивки перезагружать плату в режим прошивки без активного участия пользователя.
Затем перепробовал порядка 5 вариантов расположения элементов и остановился на следующем:
Основной мотивацией для такого расположения элементов были две причины:
Максимальное удаление температурного сенсора SCD30 от ESP8266, расположенного на нижней стороне платы сенсора, на месте зеленого кружочка
Нахождение сенсора ниже контроллера, при вертикальной ориентации устройства (при этом USB-C на нижней части устройства) для избежания искажения температуры от теплого потока конвекции с ESP8266
Интересно было также, будет ли эффект конвекции играть хоть какую-то значительную роль для циркуляции воздуха. Для этого я провёл симуляцию в Autodesk Fusion для горизонтального и вертикального расположения схемы в корпусе с отверстиями.
Симуляции воздушных потоков
Температурный эффект от нагрева не отличался от ориентации платы, а скорость потока воздуха отличается несущественно (в принципе, как и ожидалось). Не уверен, правда, можно ли считать симуляцию правдоподобной для таких слабых скоростей потока и мощности нагреваемого элемента.
Заказ и изготовление платы
Для большей экономической целесообразности решил заказать сразу 10 плат, тем более что есть ещё знакомые, коллеги и родственники, которые были заинтересованы в таком продукте.
Так как ни опыта пайки SMD компонентов, ни самих SMD компонентов у меня в наличии не было, а ассортимент и стоимость последних на digikey и mouser меня категорически расстроили, решил воспользоваться сервисом PCB Assembly на том же JLPCB. Там же можно было бы заказать и распайку ESP8266, но тогда надо было бы выбирать более дорогой пакет обслуживания и довольно дорого платить за сам контроллер, так что их я заказал отдельно на AliExpresse (см. ссылки внизу статьи)
Итого за 10 плат, доставкой FedEx в Германию и купоном на скидку в $10 (на первую покупку) у меня вышел заказ на $76.77. Заказал я платы 2го января, а 9го января в 7:38 утра курьер вручил мне коробку с готовыми платами.
Затем моими не очень прямыми руками были припаяны сенсор и плата ESP8266.
Прошивка
При использовании Home Assistant (HASS) никаких особых нюансов нет. Сенсор в один клик интегрируется в умный дом.
Изначальная цель была разработать устройство, которое могло бы работать самодостаточно. Я не считаю целесообразным настройку HASS ради одного единственного устройства. Также не хотелось бы изобретать велосипед, а использовать ESPhome как основу.
Среди готовых компонентов для ESPhome есть web_server, который поднимает на самом контроллере простенький веб интерфейс с датчиками и возможностью обновления прошивки.
В процессе конфигурации прошивки, однако, выяснилось, что последние значения сенсоров хранятся на клиентской стороне и после обновления страницы, соотвестенно теряются и график строится с нуля.
Для этого пришлось написать свой небольшой компонент history_container
, который подписывается на обновления сенсора и запоминает N
последних значений и разницу во времени между измерениями.
Также был чуть-чуть доработан фронтенд, для поддержки контейнера и между делом исправлен селектор CSS, который не работал в Safari и Firefox.
Приятно порадовала возможность хранить все необходимые ресурсы для сайта непосредственно на ESP, так что сенсор становится полностью самодостаточным устройством.
Калибровка контроллера
В процессе тестирования устройств заметил, что температура SCD30 разительно отличается от моего старого сенсора SHT31-D в большую сторону, а значит нужно провести калибровку.
В пользу достоверности значений старого сенсора также говорил встроенный температурный сенсор в MH-Z19, показывающий похожие значения, и здравый смысл.
Для этого оставил оба сенсора подключенными к HASS на несколько часов с закрытым окном. Затем выгрузил оба ряда значений и нехитрым образом высчитал константу, которая минимизирует среднеквадратичное отклонение между двумя рядами.
Код для калибровки
import pandas as pd
import numpy as np
# csv файл экспортированный из Home Assistant
df = pd.read_csv("history-0010.csv")
# выбор референсного и сенсора для калибровки
true_values = df.loc[(df['entity_id'] == 'sensor.bedroom_sensor_bedroom_temperature')].drop(columns=['entity_id'])
to_calibrate = df.loc[(df['entity_id'] == 'sensor.scd30_0010_scd30_temperature')].drop(columns=['entity_id'])
# почему-то значения не распарсились как числа
true_values['state'] = true_values['state'].astype(float)
to_calibrate['state'] = to_calibrate['state'].astype(float)
# конвертируем строки в дату
true_values['last_changed'] = pd.to_datetime(true_values['last_changed'])
to_calibrate['last_changed'] = pd.to_datetime(to_calibrate['last_changed'])
# присваиваем дату как индекс
true_values = true_values.set_index('last_changed')
to_calibrate = to_calibrate.set_index('last_changed')
# сортируем оба ряда
true_values = true_values.sort_values('last_changed')
to_calibrate = to_calibrate.sort_values('last_changed')
# приводим оба ряда к общей временной шкале
df_merged = pd.merge_asof(true_values, to_calibrate, on='last_changed', direction='nearest', suffixes=('_true', '_calib'))
# считаем среднее квадратичное отклонение
def calculate_rmse(offset):
diff = (df_merged['state_true'] - (df_merged['state_calib'] + offset)) ** 2
rmse = np.sqrt(diff.mean())
return rmse
# диапазон для поиска оффсета
offset_range = np.linspace(-10, 0, 1000)
rmse_values = [calculate_rmse(offset) for offset in offset_range]
best_offset = offset_range[np.argmin(rmse_values)]
print(f"The optimal offset that minimizes RMSE is: {best_offset:.2f}")
Получаем следующий график для референсного сенсора и нового сенсора до и после калибровки
Сам сенсор поддерживает установку температурного оффсета, который учитывается и для расчёта относительной влажности. Меня сильно удивило то, что значение оффсета применяется с задержкой во времени, даже если устройство выключить и включить.
Я бы мог понять, если бы после изменения оффсета непосредственно во время работы устройства сопровождалось временной задержкой. Это означало бы наличие буфера последних значений температуры для уменьшения шума. Задержка бы обуславливалась замещением значений в буфере новыми значениями с оффсетом (да и то, можно было бы применять коррекцию после высчитывания среднего значения буфера).
Если задержка присутствует и отключения питания, это наводит на мысль, что буфер последних значений находится в энергонезависимой памяти. Может быть этим разработчики хотели уменьшить шум для первых измерений температуры после включения, предполагая, что температура до и после включения не изменилась так сильно.
Заключение
Окончательным результатом я более чем доволен. Точность измерения и возможность кастомизации, полная открытость проекта и удобство пользования программным обеспечением (EasyEDA и Autodesk Fusion) приятно удивили.
Суммарная стоимость одной единицы составила $24, расчёт: $76.77 / 10 (платы с компонентами) + $1.43 (ESP8266) + $14.89 (SCD30) и является полностью кастомизируемым и простым в использовании устройством.
Ссылки
SCD30 на AliExpress (https://de.aliexpress.com/item/1005007654300194.html)
ESP8266 на AliExpress (https://de.aliexpress.com/item/1005007014587323.html)
Ссылка на репозиторий GitHub со всеми файлами и описанием проекта https://github.com/lrlunin/scd30-esphome
Ссылка на проект EasyEDA https://oshwlab.com/lunin.leonid/scd_with_pins_uart
Комментарии (31)
AllexIn
16.01.2025 18:04Для бытового использования обывателем на такие датчики нужен экран. Удивлен что вы не стали его лепить.
kenomimi
16.01.2025 18:04Если экран - то только еинк или самый простой жк (как в калькуляторе) с отключаемой подсветкой. Девайс часто применяется в спальнях, и горящий экранчик будет мешать...
JBFW
16.01.2025 18:04Вот кстати, вам реально мешают спать всякие экранчики?
Удивлен, потому что у нас никогда в доме не бывает полной темноты, всегда что-то светится, лишь бы не моргало.
victor_1212
16.01.2025 18:04интересно чем Вас не устроил к примеру S8, как в HT-501?
в доме работает вполне нормально 2 штуки, авто калибруется до точности порядка 20 ppm
xSVPx
16.01.2025 18:04Как в доме можно автокалибровкой пользоваться? Онаж требует чистого забортного воздуха с 420ppm хотя бы некоторое время в течении временного окна (дни-недели)
Yuri0128
16.01.2025 18:04Раз в неделю проветривайте дольше обычного и без людей, потрящих воздух.
xSVPx
16.01.2025 18:04Ээээ...серьезно :)?
Мне нужна техника, чтобы уменьшать гемморой, а не добавлять необходимые ручные действия еще и еженедельные. При этом если ты разок забудешь, то он будет ерунду показывать... Нет - это не дело, свой scd30 я планирую раз в год принудительно калибровать, по ощущениям за полгода особого дрейфа нету. Народ пишет, что годами работает без рекалибровки вполне нормально...
PS. Я кажется, понимаю откуда у адептов измерения СО2 берется 400ppm в рабочем помещении... Помнится кто-то жаловался, что после отпуска сенсор глючит и показывает страшные тыщи, но за недельку приходит в себя и опять 400+-
Yuri0128
16.01.2025 18:04Ну, тогда возьмите сенсор подороже и отрубите в нем автокалибровку. Калибруйте вручную раз в год. Или автоматику на проветривание поставьте.
victor_1212
16.01.2025 18:04по опыту 30-40 мин проветривания для комнаты среднего размера, при условии вне города типа на природе, side effect поняли как именно эффективно проветривать, иначе какой смысл в хорошем датчике, если не проветривать, цикл автокалибровки s8 порядка трех недель
kvazimoda24
16.01.2025 18:04Мне хватает того, что я не прикован дома к батарее, и иногда ухожу куда-нибудь на полдня-день, приточная вентиляция при этом продолжает работать в самом слабом режиме, что понижает уровень CO₂ до уличных значений. В целом, за несколько лет я не заметил каких-то сильных отклонений в показаниях. Значения вполне неплохо коррелируют с тем, есть ли кто дома, сколько дома человек, в какой они комнате и на сколько активны.
fixed77
16.01.2025 18:04Я дома собрал на wemos d1 mini и этот же датчик. Больше никаких плат и компонентов не надо. На wemos все есть. Обновлять можно по воздуху.
xSVPx
16.01.2025 18:04Собрал такой с полгода, но вместо вебсерверов и прочей фигни вывожу данные на обычный 8числовой семисегментный показометр. И дублируется это rgb светодиодом. Так по опыту эксплуатации светодиод гораздо удобнее. Если начал краснеть, пора проветрить итп...
Калибровал вручную один раз выйдя на улицу.
G-rave
16.01.2025 18:04С точки зрения DIYного творчества, отличная работа, но если эти датчики не предназначаются для подключения к чему либо (я про home assistant), мне кажется, не помешает бы экран
Кто видел веб-морду esphome, второй раз туда смотреть не захочет. К тому же, открывать страницу, чтоб посмотреть данные, такое себе
xSVPx
16.01.2025 18:04В HA его засунуть - дело пятнадцати минут. (на днях игрался, и у меня самопис не esphome, даже с ним это заняло четверть часа времени) Но лучше, конечно на коробку индикацию сделать...
everis
16.01.2025 18:04В качестве устройства индикации рекомендую ознакомиться с дисплеями DWIN
Крайне удобные, качественные и простые в разработке устройства. Собственный контроллер на борту - обеспечивающий всю графику, управлять можно с любого супер мелкого контроллера/компа по UART(RS232/TTL).
Размеры/разрешение на любую потребность, цена доступна для DIY.
defecator
16.01.2025 18:04DWIN - это разве не очередной клон клонов, типа Nextion ?
everis
16.01.2025 18:04Не клон, аналог.
Мне DWINы понравились больше. Уже несколько моделей пользовал для разных проектов.
jar_ohty
16.01.2025 18:04Клоном там не пахнет совсем. Принципы совсем другие.
Nextion тем хорош, что он достаточно "дружелюбный". Скачал программу, натыкал мышкой интерфейс, подключил контроллер, разобрался, что как отправлять в дисплей -- все работает. С DWINом так не получится. Вам придется сломать весь мозг, продираясь через совершенно жуткую документацию и крайне некачественную программу, сто раз пожалев о потраченных на дисплей деньгах. Все крайне неочевидно. Вот представьте, что вам пришлось бы программировать STM32 прямо в кодах -- вот такой DWIN. Зато отличные IPS матрицы (у некстиона недавно тоже появились модели с IPS, но цены такие, что проще планшет с андроидом прикрутить), очень быстрая работа, емкостный сенсор и второе ядро, на котором можно запустить пользовательский софт (правда, еще надо разобраться, как и на чем его писать). Из глобальных недостатков -- долгое время запуска с момента подачи питания (как минимум, полторы секунды против некстионовских 200-300 мс) и относительно высокое потребление тока (180 мА для 3,5")
DarkTiger
16.01.2025 18:04Так как ни опыта пайки SMD компонентов, ни самих SMD компонентов у меня в наличии не было, а ассортимент и стоимость последних на digikey и mouser меня категорически расстроили, решил воспользоваться сервисом PCB Assembly на том же JLPCB.
Полагаю, в статье стоило бы также раскрыть причину, зачем Вы свою плату с ESP стали делать, а не взяли копеечную готовую, WROOM32 за 3-5$ от Espressif, например. При отсутствии опыта в пайке такое решение прямо-таки напрашивается.
Devastor87
16.01.2025 18:04Чем это решение лучше MH-Z19B в итоге непонятно... По стоимости даже больше вышло, а у MH-Z19B два варианта измерения (uart и pwm), что очень удобно.
NutsUnderline
16.01.2025 18:04я вообще не нашел никаких готовых приборов сделанных именно на SCD30, подскажите какие есть?
shadrap
16.01.2025 18:04как многолетний обладатель достаточно точного AZ RH7722 ,внутри инфракрасный SenseAir K22 , старый но довольно точный и калиброван был в лаборатории, могу сказать что средний показатель ррм в воздухе , в мегаполисе на высоте около 45м ,480 -560,в проветренной приточкой 18м2 комнате, за 7-8 часов сна один человек , при закрытых дверях поднимает уровень до 1200. Так что про 400 и раз в неделю проветривать это сказки.
almirus
Я использовал такой датчик https://esphome.io/components/sensor/scd4x.html достаточно точный, дешевый, не нужна калибровка, маленький, есть датчик температуры (нужен поправочный коэффициент) и влажности.
Tirarex
Поделитесь ссылкой на его покупку? На али его продают по 40-50$, датчик из статьи по 20-25, возможно не там ищу.
JBFW
Али теперь разный