
Почему я решил сделать сам?
У меня есть две любимые сестры, которые очень хотели бы иметь дома сенсор 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
Комментарии (60)
AllexIn
16.01.2025 18:04Для бытового использования обывателем на такие датчики нужен экран. Удивлен что вы не стали его лепить.
kenomimi
16.01.2025 18:04Если экран - то только еинк или самый простой жк (как в калькуляторе) с отключаемой подсветкой. Девайс часто применяется в спальнях, и горящий экранчик будет мешать...
JBFW
16.01.2025 18:04Вот кстати, вам реально мешают спать всякие экранчики?
Удивлен, потому что у нас никогда в доме не бывает полной темноты, всегда что-то светится, лишь бы не моргало.
vanyas
16.01.2025 18:04А зачем экран? Это же девайс для home assistant, все в приложеньке на телефоне
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Ну, тогда возьмите сенсор подороже и отрубите в нем автокалибровку. Калибруйте вручную раз в год. Или автоматику на проветривание поставьте.
NutsUnderline
16.01.2025 18:04интересно какой
Yuri0128
16.01.2025 18:04Не знаю, человеку надо - пускай ищет.
NutsUnderline
16.01.2025 18:04мне надо. искал. не нашел.
Yuri0128
16.01.2025 18:04Искать с встроенным образцом для калибровки. Им не надо провертивание регулярное.
xSVPx
16.01.2025 18:04Тот про который речь в этой статье чем вам плох ?
Yuri0128
16.01.2025 18:04Ну - сильным влиянием нагрева камеры на термодатчик и включенным " ASC field-calibration algorithm" (ну или FRC - нужно раз в году хотя-бы калибровать), - то есть отстутствием встроенного образца, о чем, собственно, я и написал.
xSVPx
16.01.2025 18:04Ну так он ведь и не для измерения температуры, зачем там термодатчик вообще не очень понятно(вероятно нужна температура для каких-то поправок). Температуру с него нужно не брать, а брать с нормального точного датчика, они недорогие.
Калибровка раз в год - это совершенно не проблема, тут люди пишут, что раз в неделю условия для калибровки обеспечивают :).
А вообще без калибровки боюсь получится только за совершенно неприличные деньги.
Кстати посмотрел... Scd30 подешевели за год кабы не вдвое, что странно.
Yuri0128
16.01.2025 18:04Термодатчик там для учета температуры воздуха, - она оказывает влияние на результат фактического измерения (точнее не скажу - очень давно читал о применении подобных датчиков) и по ней делается какая-то коррекция. Походу и датчик влажности для того-же. Там и стоит вроде SHT30, не, глянул, - SHT31.
А вообще без калибровки боюсь получится только за совершенно неприличные деньги.
Да, к сожалению. Себе такой хотел. Пока хочу дальше.
Scd30 подешевели за год кабы не вдвое, что странно.
Может наладили производство, выпустили много а спрос упал.
victor_1212
16.01.2025 18:04по опыту 30-40 мин проветривания для комнаты среднего размера, при условии вне города типа на природе, side effect поняли как именно эффективно проветривать, иначе какой смысл в хорошем датчике, если не проветривать, цикл автокалибровки s8 порядка трех недель
kvazimoda24
16.01.2025 18:04Мне хватает того, что я не прикован дома к батарее, и иногда ухожу куда-нибудь на полдня-день, приточная вентиляция при этом продолжает работать в самом слабом режиме, что понижает уровень CO₂ до уличных значений. В целом, за несколько лет я не заметил каких-то сильных отклонений в показаниях. Значения вполне неплохо коррелируют с тем, есть ли кто дома, сколько дома человек, в какой они комнате и на сколько активны.
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, даже с ним это заняло четверть часа времени) Но лучше, конечно на коробку индикацию сделать...
lrlunin Автор
16.01.2025 18:04Прошу прощения за запоздалый ответ, был в отъезде. Я скорее представлял, что этот сенсор будет лежать где-то на шкафу или на полочку. С экраном тоже много мороки, если он светит - это может не нравится владельцу. Ну и как-то я так прикинул, всё равно телефон всегда под рукой - открыл ссылочку и тут тебе история. Ну и да, если что в Home Assistant добавил, там тоже очень удобно и клёво работает.
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, например. При отсутствии опыта в пайке такое решение прямо-таки напрашивается.
lrlunin Автор
16.01.2025 18:04Спасибо за комментарий, вы имеете в виду Dev Board? Не хотелось висячих проводков, а цельную печатную плату.
В целом опыт пайки у меня присутствует, просто не работал с SMD. И на самом деле хотелось попробовать попаять SMD компоненты, но делать 10 плат со всей рассыпухой для начала показалось слишком круто. Плюс, как я уже упомянул, вышло бы дороже заказывать все эти компоненты из Китая отдельно, чтобы потом припаять. А вот как раз ESP получилось урвать сильно дешевле.
Devastor87
16.01.2025 18:04Чем это решение лучше MH-Z19B в итоге непонятно... По стоимости даже больше вышло, а у MH-Z19B два варианта измерения (uart и pwm), что очень удобно.
NutsUnderline
16.01.2025 18:04тут co2 автокалибруется по встроенному образцу
xSVPx
16.01.2025 18:04Где "тут"? Насколько я понимаю в sdc30 нет образца, калибруется он совершенно точно по воздуху забортному.
Второй тракт используется для рекалибровки источника излучения вроде бы.
Devastor87
16.01.2025 18:04А MH-Z19B продаются уже откалиброванные, причем, очень точно. Ответа на вопрос чем решение в статье лучше этого датчика так и не получен)
xSVPx
16.01.2025 18:04Тем, что имеют два тракта и в состоянии рекалибровать себя в процессе эксплуатации по мере деградации источника излучения.
Эти тоже уже откалиброванными продаются, но их рекомендуют всё таки калибровать после перевозки итд.
Yuri0128
16.01.2025 18:04Через некоторое время все сенсоре требуют рекалибровки. Если внимательно паспорт почитать, то там это прямым текстом указано.
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 и раз в неделю проветривать это сказки.
victor_1212
16.01.2025 18:04однако, 1200 будет многовато для спальни, у нас обычно не выше 550-600 при закрытых окнах, 1200 скорее уровень в кухне при включенной плите и то не сразу, вентиляция обычная, сама система в подвале, в жилых комнатах 2-3 входных + 2-3 выходных жалюзи, правда далеко не в мегаполисе, возможно поэтому воздух лучше
shadrap
16.01.2025 18:04Ну опять же - чем измерять . По умолчанию 450ррм - это "референсный" уровень чистого воздуха города у нас, следовательно , ну никак без вентиляции , два человека не могут надышать в 20м2 меньше 500ррм , это я называл цифры без включенной приточки (она все ж шумит слегка)
victor_1212
16.01.2025 18:04примерно так, + от объема также зависит, циркуляция работает 24/7, и площадь дома в разы больше квартиры, насколько знаю датчики на основе IR бытового уровня сравнимую точность имеют, imho абсолютные значения по жизни не так важны как относительные, ну и конечно внешний воздух тоже разный, но таки учитывая все 1200 для спальни много будет, хотя конечно Вам виднее
shadrap
16.01.2025 18:041200 это просто для примера, за какое время воздух в помещении становится , " практически не пригодным" , а тот тут товарищи говорили о "проветривании раз в неделю", конечно я стараюсь либо открывать на ночь окно , либо включать приточку , в целом AZ RH7722 настроен на начало алерта на 900ррм и тревогу на 1200ррм
alaltitov
16.01.2025 18:04Разводка платы автотрассировкой делалась?
По логической схеме, так небольшая придирка, земля снизу…
lrlunin Автор
16.01.2025 18:04Не, сам разводил ручками. Я там сильно трогательно отнёсся к длинам дифференциальных пар, возможно оно и не требовало такого совпадения.
Я очень пытался развести VCC и GND в один уровень, но не смог. Я рассчитывал, что ESP потребляет немного и одного переходного отверстия хватит.
Буду очень признателен, если подскажете что можно было бы сделать лучше!
Yuri0128
16.01.2025 18:04Я там сильно трогательно отнёсся к длинам дифференциальных пар
Так у вас тама только одна диф.пара (USB D+/USB D-). И, навскидку, там не выдержан нужный импеданс (но пофиг для 10-ки). USART/i2c - не дифпары - там как вам удобно, но не забывая про помехи/наводки.
lrlunin Автор
16.01.2025 18:04Так у вас тама только одна диф.пара (USB D+/USB D-).
Да, неправильно выразился. В голове было про две дорожки (множественное), что составляет одну диф. пару, конечно.
И, навскидку, там не выдержан нужный импеданс
Спасибо, в следующий раз буду внимательнее.
comerc
16.01.2025 18:04А какой сенсор внутри QINGPING CGP22C? Ручная калибровка не помогает - показывают разные значения, зараза!
Stepyon
16.01.2025 18:04А вот как я сделал датчик СО2 для умного дома, давайте сравним у кого лучше ;)
https://diycraic.com/2024/12/09/diy-high-quality-advanced-co2-sensor-for-home-assistant/
almirus
Я использовал такой датчик https://esphome.io/components/sensor/scd4x.html достаточно точный, дешевый, не нужна калибровка, маленький, есть датчик температуры (нужен поправочный коэффициент) и влажности.
Tirarex
Поделитесь ссылкой на его покупку? На али его продают по 40-50$, датчик из статьи по 20-25, возможно не там ищу.
JBFW
Али теперь разный