На днях я выкопал из земли свой самодельный датчик измерения глубины промерзания грунта, чтобы отпаять от него несколько сенсоров - они оказались лишними, хотя я ориентировался в целом при продумывании датчика на действующий ГОСТ (ГОСТ 24847— 2017) на подобные средства измерения. Почему так?
Чаще всего измерения проводят со строительными целями. В первую очередь для целей определения глубины заложения фундамента, во вторую - для понимания риска морозного пучения.
На практике, конечно же, никто ничего не измеряет - есть таблицы нормтивных показателей для разных климатических зон, ими и руководствуются. И этого действительно чаще всего достаточно, постоянный мониторинг излишен.
Совсем другое дело - это ситуация необходимости прогрева грунта. Например, греющим кабелем или электродами. Для этой задачи хотя бы примерно представлять реальную, а не нормативную глубину промерзания - дело благое, так как напрямую сказывается на расчете необходимой мощности. Но где узнать текущую глубину промерзания? Ответ - толком негде. А мне было надо для электродного прогрева.
Вторая причина возни - лыжи. В начале весны наступает период, который длится несколько недель, когда ночью слабый минус, ноль или слабый плюс, а днем жарит. Кататься в такие дни нормально можно только утром, причем только в том случае, если оставшийся снег достаточно прихвачен морозом. Который (мороз) идет в первую очередь от земли - не столь важна текущая температура, важнее сколько холода накапливает поверхностный слой земли, чтобы отдавать утром снегу. От этого прямо зависит продолжительность нормального катания. Если не угадать, то вполне можно километров через 10-15 на трассе в буквальном смысле сесть в лужу. Причем с очень малой зависимостью от температуры воздуха - что в плюс два, что в плюс восемь.
Третья причина - тепловая инерция толщи земли. Если верхний ей слой достаточно быстро реагирует на изменения погоды, оттаивая и замораживаясь, то более глубинные слои крайне резистентны - фактически температура верхних слоев доходит до них месяца через три-четыре. На чем, собственно, и основана идея погребов с залеганием ниже глубины промерзания - зимой тепло, летом прохладно, а в среднем по году одинаково. Если, конечно, не мешают грунтовые воды близкие, которые очень активно переносят тепло. Их я тоже искал, надеясь найти напорный выход через трещину в глинах - стратиграфия разреза вблизи позволяла на это надеяться.
Год собирался по этим причинам сделать собственный датчик глубины промерзания и в итоге все-таки сделал. Пробурил, сломав 2 бура, небольшую скважину в земле - на 2.2 метра, что ниже максимальной нормативной глубины промерзания для нашей местности, но вполне достаточно на практике, и стал думать над датчиками.
Вариантов измерения фактически всего два - мерзлотомером и гирляндой датчиков. Понятно, что по факту для постоянного мониторинга подходит только гирлянда.
Китайцы продают готовые, но дорого, и непонятно по точности, поэтому стал делать сам на основании идей из ГОСТ.

Конструкция в целом проста - в скважину вставил арматуру, к которой приделал гирлянду из 1-wire датчиков DS1820. Выход из земли оформил герметичными фитингами и отрезками полиэтиленовой водопроводной трубы. Заодно рядом закопал и резистивный датчик влажности.
Провод использовал КСПВ 0.8 мм, припаивая каждый датчик в парралель на зачищенные участки проводников. Герметизация - силикон, поверх клеевая термоусадка. Потом стяжками к арматуре и в скважину. Расстояние между датчиками выбрал в 15 сантиметров, что теоретически гарантирует точность измерения отметки промерзания в плюс-минус 3 сантиметра, чего мне вполне достаточно. Всего в гирлянду набрал 18 датчиков, причем один закрепил уже в трубке отвода под фитингом - для контроля.
Ключевой момент - юстировка и нумерация датчиков - нам же надо знать где какой на 1-wire шине.

Сделал так. В термос налил холодной воды, насыпал в него льда и по очереди погружал в него каждый датчик с гирлянды, фиксируя его uid и погрешность просто в csv файле. Дело оказалось благим.
Согласно ГОСТ, погрешность датчика не должна превышать 0.3 градуса. Очевидно, что нас при этом интересует минимизация погрешности именно в районе точки замерзания воды. И тут с китайскими (естественно, покупал самые дешевые) клонами DS есть проблемы, которых может быть нет у оригинальных Dallas - не знаю.
Sensor 28:61:64:34:83:6C:93:C0: 110000 °C
Sensor 28:61:64:34:80:10:F4:39: 111875 °C
Sensor 28:61:64:35:18:33:26:C4: 111875 °C
Sensor 28:61:64:35:18:29:97:A3: 115625 °C
Sensor 28:61:64:35:18:3F:B5:7A: 112500 °C
Sensor 28:61:64:35:18:0E:2B:9D: 111875 °C
Sensor 28:61:64:35:18:1E:74:EB: 111875 °C
Sensor 28:61:64:35:1B:4E:39:C3: 113750 °C
Sensor 28:61:64:35:18:39:23:1C: 110625 °C
Начал с измерений при плюсовой температуре. Просто сложил датчики кучей и померил - сначала при комнатной температуре, потом нагревая феном. Три датчика достаточно сильно врали, причем чем ближе к нулю градусов, тем больше - окунув всю гирлянду в термос, получил разброс уже в 1.7 градуса - это очень много. Поэтому внес поправки, окуная их в лед уже по одному - это позволило и разметить их адреса на гирлянде заодно.
Для юстировки и сбора данных использовал ESP8266 и Lua. Рассказывать тут не о чем - есть готовая библиотека (https://nodemcu.readthedocs.io/en/dev/lua-modules/ds18b20/), в доке к которой есть вполне рабочий пример. Достаточно дополнить его вызовом по таймеру и убрать освобождение библиотеки после вызова и все.
local t = require("DS1820")
local pin = 1
local function readout(temp)
if t.sens then
print("Total number of DS18B20 sensors: ".. #t.sens)
for i, s in ipairs(t.sens) do
print(string.format(" sensor #%d address: %s%s", i, ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(s:byte(1,8)), s:byte(9) == 1 and " (parasite)" or ""))
end
end
for addr, temp in pairs(temp) do
if tonumber(temp) < 20000 then
print(string.format("Sensor %s: %s °C", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(addr:byte(1,8)), temp))
end
end
end
local function read()
t:read_temp(readout, pin, t.C)
end
timer = tmr.create()
timer:register(7000, tmr.ALARM_AUTO,read)
timer:start()
После юстировки тот же код использовал для передачи данных на сервер по TCP сокету. Из кода для простоты выкинул часть, связанную с опросом аналогового входа (там у меня еще был датчик влажности почвы).
local results = {} -- DS1822 results
local function readout(temp)
for addr, temp in pairs(temp) do
local uid = string.format('%s',('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(addr:byte(1,8)))
results[uid] = temp
end
end
local function read_sensors()
t:read_temp(readout, ds_pin, t.C)
end
function data_out()
read_sensors()
local pack = {}
pack['sensors'] = results
return encoder.toBase64(sjson.encode(pack))
end
local function send()
srv:connect(8888,"server.com")
srv:on("connection", function(sck, c)
print('connection')
sck:send(data_out().."\r\n")
end)
srv:on("disconnection", function(sck,c)
print('disconnection')
end)
end
tcptimer = tmr.create()
tcptimer:register(timing, tmr.ALARM_AUTO,send)
Расшифровку показаний и расчет глубины промерзания делал уже на сервере.
По факту оказалось, что для всех моих целей размер гирлянды избыточен. На практике достаточно знать градиент распределения температуры в 50-70 сантиметровом верхнем слое грунта. В наших условиях именно на этом уровне начинается плотная глина, по стратиграфии слоем в несколько метров, в которой распределение температуры и ее падение практически линейны, поэтому смысла заглубляться так глубоко не было. Поэтому вынул и сократил гирлянду до пяти датчиков - этого по факту оказалось более, чем достаточно.