1. Введение
До недавних пор для проведение подобных измерений требовалось использовать промышленные приемники/передатчики ультразвука. Только они могли дать приемлемую точность и дальность. Но они были слишком большие и дорогие. Использовать дешевые китайские модули, такие как HC-SR04/US-025, не выйдет. Точность, стабильность, повторяемость результата оставляет желать лучшего.
Ситуацию изменило появление нового чипа CH-201. Его основная проблема заключается в том, что он китайский. Я еще не видел китайский чип с хорошей документацией и хорошей службой поддержки.
На следующих изображениях продемонстрирован результат работы этого чипа.
Где,
Room – температура термистора, размещенного примерно по центру комнаты.
Ceiling – температура термистора, размещенного на потолке.
IR – температура поверхности пола, полученная от инфракрасного сенсора.
(IR+Ceiling)/2 – средняя температура между полом и потолком.
Ultrasound20 – температура полученная от ультразвукового сенсора. Где числа 10 и 20 — это сглаживание. Формула сглаживания Tsm = Tsm * (n-1)/n + T * 1/n.
Чуть дальше будет описание как получены данные, сейчас же просто демонстрация.
Я думаю, видя графики становится понятно, чем именно интересен этот способ отслеживания изменения температуры в комнате. Используя данную технологию, можно только отслеживать изменение температуры, а не проводить измерение температуры. Если добавить лазерный дальномер, с точностью хотя-бы +- 0.1 мм, то получится проводить измерение температуры. Также можно производить измерение температуры в комнате, если перед началом измерения точно измерить расстояние между сенсором и полом.
В первом прототипе я пробовал использовать дальномер VL53L3CX. Как оказалось, он работает не так как хотелось бы. Этот сенсор не дает точное расстояние, ошибка достигает 20 мм. Точность измерения зависит от цвета поверхности, освещенности комнаты. Лампочка, имитирующая солнечный свет, так и вовсе делает этот сенсор бесполезным. Данные от сенсора нужно ждать примерно от 5 до 15 минут.
2. Как это работает и зачем это нужно
Скорость звука зависит от температуры, влажности и давления. Скорость ветра можно не учитывать, в жилых помещениях нет сильного ветра. Соответственно отслеживая изменение скорости звука и зная текущую влажность, давление, можно вычислить насколько температура воздуха изменилась.
Ну тут возникает проблема. Дело в том, что ультразвуковой приемо-передатчик возвращает время за которое сигнал дошел до объекта, отразился и вернулся на приемник (ToF – Time of Flight). Время нельзя конвертировать в скорость не зная дистанцию. Это не проблема, если нужно отслеживать только изменение температуры. Для этого не нужно знать точную дистанцию.
Ультразвуковой сенсор обладает хорошей особенностью, это отсутствие инерции. Также с помощью ультразвука можно измерить температуру воздуха, а не температуру объекта. Ультразвуковой сенсор решает проблему самонагрева/нагрева сенсора. Например, когда сенсор разогрелся в процессе работы или сенсор нагрелся на солнечном свете, или вблизи лампы.
Напротив сенсора должна находится твердая плоская поверхность. С ковролином или линолеумом работать не будет. Также в радиусе 5 м не должно находится других CH-201 сенсоров или иных источников ультразвука.
Термисторы и инфракрасные сенсоры возвращают температуру объекта и температуру поверхности соответственно, а не температуру воздуха. Эти сенсоры легко использовать, и они дешёвые. Но почти всегда их нельзя расположить в помещении там где нужно.
Для простоты понимания зачем этим вообще нужно заниматься давайте поставим себе практическую задачу. Есть термостат и есть задача регулировать температуру в помещении. Помещение офисное с определенным дизайном.
Для решения этой задачи нужен сенсор температуры. Но возникает вопрос “Какой?”. Дизайн офиса, в большинстве случаев, никто не разрешит портить. Для каждого офиса разрабатывать сенсор с определенным дизайном не выйдет, это слишком дорого. Скорей всего разрешат поставить сенсор где-нибудь на кухне или возле бойлера с водой. Данные от такого сенсора будут так себе. А что делать если офис большой? Как тогда понять какая в нем температура?
Почти всегда и почти во всех случаях сенсор температуры можно ставить на потолок. Как правило, в таких случаях, сенсор можно устанавливать где хочется на потолке. Потолочные сенсоры не портят дизайн. Но потолочные сенсоры измеряют температуру под потолком, это проблема. Под потолком всегда теплее.
Есть разные пути решения проблемы измерения температуры под потолком. Самый очевидный способ, это использовать некоторое фиксированное смещение температуры вниз. Самое простое и самое не эффективное решение. Такой способ по разному работает в случае нагрева и в случае охлаждения помещения. В случае нагрева температура будет слишком быстро возрастать и слишком медленно падать. В случае охлаждения теплый воздух будет вытесняться под потолок, реакция будет с задержкой и температура будет падать слишком медленно.
Другой способ — это добавить инфракрасный сенсор температуры и вычислять среднее между потолком и полом. Этот способ работает лучше чем фиксированное смещение. Но у него есть большой недостаток в виде пола с огромной инерцией. Также под сенсором иногда ходят люди, они будут вносить искажения в результат измерения.
Других способов особо и нет. Можно экспериментировать с разными способами вычисления смещения, вычислением среднего и т.п. Но это не даст хороший результат. Ультразвук устраняет эту проблему. Но он не идеален, сложен в реализации и есть уязвимые моменты.
3. О чипе
Если бы этот сенсор разработала бы другая компания, например Ti или ST, то цены бы ему не было. Но имеем, что имеем. Документация отвратительная. Имеется почти два десятка PDF файлов/брошюрок и примеры кода. При этом толком не объясняется, что и как работает, что означают некоторые переменные. Не описаны многие параметры чипа.
Основные характеристики:
Дальность действия от 20 см до 5 м;
Регулируемое поле зрения (FoV) до 180°, используется внешняя акустическая камера;
Обнаружение нескольких объектов;
Один датчик для приема и передачи;
Рабочее напряжение 1.8V, нет толерантности к 3.3V;
I2C 400 kHz;
3,5 x 3,5 x 1,26 мм, 8-контактный корпус LGA;
Low-power SoC, проприетарная прошивка устанавливается в RAM перед стартом;
Рабочая температура -40°C до 85°C;
Низкое энергопотребление
• 1 sample/s:
· 7.5 µA (1 m max range) ;
· 13.5 µA (5 m max range);
• 25 samples/s:
· 63 µA (1 m max range) ;
· 247 µA (5 m max range), частоту нужно понизить до 24 samples/s;
Частота ультразвука 82…85 kHz;
Встроенная RC цепочка тактирования;
I2C адрес для программирования фиксированный, I2C рабочий адрес программируемый.
Если скачать старые версии кода, то там упоминается компания Atmel. По всей видимости внутри ATtiny. Код прошивки не предоставляется. Тактируется этот чип от RC цепочки, это просто “гениальное” решение. Т.к. частота ультразвука плывет вслед за температурой чипа. Нигде в документации не сказано, что частота плавает. А это очень сильно влияет на точность. Это не большая проблема, легко фиксится софтварно. Чип ловит наводки, например от светодиодного освещения. Размер посылки от чипа может достигать примерно 1600 байт. TDK не предоставляет информацию о том какая погрешность измерения, но она явно меньше 1 мм.
Сам по себе сенсор не работает, нужна акустическая камера. Как должна выглядеть акустическая камера можно почитать в документе AN-000337 “CH201 and ICU-20201 Acoustic Housing Reference Designs ”. О том как устанавливать камеру в документах AN-000221 “CH201 and ICU-20201 Mechanical Integration Guide” и AN-000223 “Acoustic Interface Gluing Procedure for Chirp Ultrasonic Sensing Modules”. Прямые ссылки на документы не даю. Нужно переходить на сайт TDK и искать по названию. Т.к. после обновления документа ссылка у них меняется и иногда они вовсе размещают битые ссылки. Тогда приходится с неделю ждать ответа от службы поддержки.
Ультразвук хорошо фокусируется. В тестах я перепробовал много вариантов акустических камер. Самый лучший результат дают камеры с низким FoV. TDK не приводит формул для расчета акустической камеры. Как их проектировать правильно я не знаю. Но опытным путем было выяснено, что чем выше камера тем ниже FoV.
На выходе сенсор выдает массив, состоящий из пар комплексных чисел (I + jQ).
Которые можно конвертировать в амплитуду . В своем коде я работаю только с амплитудой, что можно выжать из комплексных чисел, я не знаю.
Для получения ToF используется формула где,
n – номер сэмпла;
– актуальная частота ультразвука.
ToF нужно разделить на 2. Для визуализации сигнала я умножаю на скорость 343 м/c.
Имея ToF и амплитуду получаем что-то вроде аудиофайла. Обработав который, мы можем понять сколько объектов находится в FoV и на каком расстояние они находятся.
На высоту амплитуды влияет продолжительность сигнала, отражающая способность материала и форма объекта. Продолжительность сигнала можно регулировать. Чем больше продолжительность, тем больше шума и больше вероятность словить эхо. Например расстояние между сенсором и полом 2 м, но в выборке четко виден объект на дистанции 3 м. Это сигнал который сначала отразился от пола в стену а потом в сенсор. Также чем больше продолжительность, тем ниже четкость сигнала. Например в поле зрения сенсора на поле лежит книга, при короткой продолжительности сигнала будет четко видно два пика. А при большой продолжительности сигнала будет виден один широкий пик. Именно поэтому нельзя использовать высокую мощность сигнала, можно пропустить момент когда на пол или стол что-то положили.
Сенсор реагирует на кашель при бронхите или пневмонии. Когда болел заметил эту особенность. Используя этот сенсор можно сделать детектор кашля.
TDK в своем Users Guide пишет:
However, there is a good reason not to increase the TX length too much. The mechanism that creates a lot of false positives is interference between stationary echoes that exist in the environment. In order for the echoes to interfere, they must overlap in time/range, meaning if e.g. you have static object A at 1m and static object B at 1.1m range from the sensor, and the pulse is e.g. 100 cycles/200mm in duration (1 cycle = 2mm in range), then the echoes from objects A and B will overlap, and have an interference pattern which is a function of the range to the two targets. Small changes in the propagation time to object A which doesn’t affect the propagation time to B in exactly the same way will cause the phase of the echo returning from A to change relative to that of B, for example, when the air around the sensor is turbulent or changing temperature, the interference pattern will start changing rapidly (especially when the echoes are about the same amplitude) and the STR algorithm is unfortunately sensitive to that.
Также высота амплитуды зависит от дистанции и от формы объекта. Чем сложнее форма объекта тем слабее амплитуда. TDK приводит следующую зависимость:
For large, flat surfaces, (e.g. walls, the ground, etc.), the amplitude scales as 1/R, where R is the distance between the CH201 and the target. For most other targets, the amplitude scales as 1/R².
Впрочем, для измерения температуры эта информация не слишком важна. Я использую слабую мощность сигнала, от сложных объектов такой сигнал почти не отражается.
4. Настройка драйвера
Драйвер для чипа можно найти в любом примере кода. Код можно скачать с сайта TDK. Вообще перед началом работы лучше купить отладочную плату CH201 Development Kit. Плата довольно удобная и на ней можно протестировать все интересующие моменты. Документация довольно скудная и без нее будет довольно сложно работать с чипом.
В файле настроек app_config.h нужно выбрать следующие настройки
#define CHIRP_SENSOR_FW_INIT_FUNC ch201_gprstr_init /* standard STR firmware */
Важно выбрать режим FREERUN. В этом режиме чип CH-201 использует внутренний источник тактирования для инициации цикла замера. Измерив задержку между циклами, можно определить, насколько частота RC цепочки ушла от стартовой.
#define CHIRP_SENSOR_MODE CH_MODE_FREERUN
Отключаем фильтр, каждый цикл должен вызывать прерывание.
#define CHIRP_SENSOR_TARGET_INT CH_TGT_INT_FILTER_OFF
Выставляем максимальную дистанцию. Чем больше дистанция, тем больше размер посылки. Если нужна максимальная частота опроса, то дистанцию нужно ограничить до 3 м. Иначе у I2C не хватит пропускной способности.
#define CHIRP_SENSOR_MAX_RANGE_MM 5000 /* maximum range, in mm */
Включаем усиление. Число означает с какого сэмла начинает действовать усилитель. Этот параметр важен для измерения температуры. Кстати, если есть задача определять форму объекта, то ее можно решить следующим способом. Выставив продолжительность передачи 30, провести первое измерение с включенным усилителем (значение 1), второе с выключенным усилением (значение >= 350). Если разность между пиками в двух выборках будет большой, то это объект с сложной формой. Если почти не изменится, то это плоский твердый объект.
#define CHIRP_SENSOR_RX_LOW_GAIN 1
Продолжительность передачи. Не ставить большие значение. На дистанциях меньше 2 м, хороший результат дает продолжительность 1.
#define CHIRP_SENSOR_TX_LENGTH 2
#define CHIRP_SENSOR_STR_RANGE 0
Задержка между циклами. Чем выше задержка тем точнее рассчитывается коэффициент коррекции частоты. Дело в том, что CH201 подключается к микроконтроллеру через преобразователь уровней. Преобразователь добавляет небольшую ошибку. На фоне большой задержки, этой ошибкой можно пренебречь. Также CH201 добавляет некую фиксированную задержку в 250 uS. Служба поддержки TDK мне так и не ответила, что это за задержка. В случае точного измерения дистанции эту задержку нужно учитывать в расчетах. Если требуется отслеживать только отклонение температуры, то эту задержку можно не учитывать.
#define MEASUREMENT_INTERVAL_MS 100
#define IQ_DATA_MAX_NUM_SAMPLES CH201_GPRSTR_MAX_SAMPLES // use max for ch201_gprstr
В файл, в котором у вас будет хранится sensor_int_callback нужно добавить две глобальные переменные
uint64_t t=0;
static int period=0;
В функцию калбэка добавить следующий код
static void sensor_int_callback(ch_group_t *grp_ptr, uint8_t dev_num,ch_interrupt_type_t __attribute__((unused)) int_type)
{
……
if (ch_get_mode(dev_ptr) == CH_MODE_FREERUN)
{
if(t==0)
{
t=time_hal_get_in_us();
period=MEASUREMENT_INTERVAL_MS*1000;
}
else
{
uint64_t buf = time_hal_get_in_us();
period=buf-t;
t=buf;
}
……
}
Функция коррекции частоты будет выглядеть следующим образом.
void UpdateFrequency()
{
usFrequencyCorrection = CH201_PERIOD/(((double)period)/(1000.0*1000.0));
usFrequency = Frequency * usFrequencyCorrection * usFrequencyCorrection;
}
Где,
double CH201_PERIOD = 1.0 / SAMPLE_PER_SEC;
Frequency – стартовая частота, получить можно вызвав функцию uint32_t ch_get_frequency(ch_dev_t *dev_ptr).
Демонстрацию работы функции коррекции частоты можно посмотреть в этом видео.
В качестве нагревателя используется лампа инфракрасного света.
В принципе с драйвером на этом все. Дальше нужно просто обрабатывать данные. Портировать драйвер в свой проект не сложно. По большому счету нужно только заменить функции i2c и добавить в свой обработчик прерывания вызов sensor_int_callback.
Данные от сенсора будут возвращается в uint8_t handle_data_ready(ch_group_t *grp_ptr).
…
ch_iq_sample_t *iq_ptr; // pointer to individual I/Q pair
/* Read I/Q data in normal, blocking mode */
error = ch_get_iq_data(dev_ptr, chirp_data[dev_num].iq_data,
start_sample, num_samples, CH_IO_MODE_BLOCK);
iq_ptr = &(chirp_data[dev_num].iq_data[0]);
…
На этом этапе все необходимое для работы уже есть. Это количество сэмплов в выборке, стартовая частота ультразвука, период, пара I и Q.
5. Как должен выглядеть ультразвуковой сенсор температуры
Теперь нужно определится как же будет выглядеть устройство. Готовые сенсоры у меня уже конечно же есть. Но на момент проектирования, функция ультразвука была тестовой и не было понимания как она будет работать, и будет ли эта технология вообще работать. Поэтому готовые доски пришлось дорабатывать вручную.
Большой вырез в корпусе это термобарьер. В процессе тестирования было выявлено, что АБС пластик отлично проводит тепло. Да и чем больше корпус, тем больше инерция у сенсора температуры. Такое решение позволило уменьшить теплоемкость кармана с сенсором температуры и устранило проблему с теплопередачей тепла от корпуса к сенсору температуры. Есть еще черный вариант корпуса. За счет цвета удалось еще немного снизить инерцию.
Воздушная прослойка между потолочной пластиной и сенсором добавлена специально. Это термобарьер. У потолка большая инерция. Температура поверхности потолка оказывает влияние на температуру сенсора. Для решения этой проблемы добавлена воздушная прослойка.
Площадь контакта основного корпуса и потолочной пластины сведены к минимуму.
Для отслеживания изменения температуры на плате должны присутствовать:
Сенсор температуры;
Инфракрасный сенсор температуры;
Сенсор влажности;
Сенсор атмосферного давления;
Акселерометр;
Ультразвуковой сенсор;
Микроконтроллер.
Выяснилось, что CH201 весьма прожорлив к RAM. Для драйвера и алгоритма обработки ультразвука нужно выделить примерно 10 кБайт памяти. Также для ультразвука нужно выделить свой отдельный I2C. Ультразвук съедает львиную долю пропускной способности I2C. На протяжении дня влажность и атмосферное давление меняются. Если не учитывать эти параметры в расчетах скорости звука, то температура поплывет и будет давать большую ошибку. С помощью акселерометра можно убедится, что сенсор установлен правильно, не под углом и смотрит прямо вниз на пол. Также акселерометр работает как сенсор движения устройства. В процессе проведения измерений устройство не должно перемещаться. Инфракрасный сенсор температуры нужен для точного определения точки начала отсчета.
Для проведения опытов сенсор был размещен под потолком, по центру комнаты подвешен термистор.
6. Проблемы, которые могут возникнуть в процессе проведения измерений
CH201 на прием работает как микрофон. Ограничения по частоте принимаемого ультразвукового сигнала выставить нельзя. Я проверял как сенсор реагирует на ультразвук с частотой 30 кГц и чип его принимал, не отфильтровывал. Нужно учитывать, что могут и будут появляться различные ложные ультразвуковые сигналы.
Наклонные поверхности могут отразить сигнал. Такой сигнал не годится для расчета температуры. Мне так и не удалось полностью решить это проблему. Вероятность появления такой ситуации можно сильно уменьшить если сделать продолжительность ультразвукового сигнала как можно меньше.
В поле зрения сенсора могут появляться и исчезать объекты. Особенно часто это будет происходить если сенсор будет установлен над столом. Эту ситуацию довольно легко обработать. В выборке появится дополнительный пик либо ToF резко скакнёт.
Объект под сенсором могут немного передвинуть, из-за чего дистанция может изменится немного. Либо на стол могу облокотится или что-то положить, из-за чего он немного просядет. Эта ситуация довольно сложная в обнаружении.
Ламинат/паркет немного проседает, когда проходят или стоят люди. Решения так и не нашел.
7. Реализация алгоритма
Пытаться разработать прошивку сразу в лоб довольно плохая затея. Нужно обрабатывать большие массивы данных и без визуального представления это будет непосильная задача. Поэтому быстро было принято решение сбрасывать все данные на ПК и библиотеку писать на нем, с последующим портирование на микроконтроллер.
Описание программы для визуализации данных.
Сперва проверяем есть ли кто-то в комнате, можно и не делать. Но в пустой комнате IR сенсор дает более точное значение. Проверяем данные акселерометра. Нужно убедится, что устройство установлено правильно и его никто не переместил. Обновляем порог для поиска новых объектов и заодно проверяем выборку на наличие шума. Далее если температура не менялась в течении определенного времени и не работает обогреватель/охладитель, проверяем выборку на наличие новых объектов. О том работает ли нагрев/охлаждение сообщает термостат установленный в помещении. Если не делать проверку, на стабильность температуры в помещении, то появится риск того, что точка старта будет выбрана не верно. После обрабатываем выборку, получаем смещение температуры и обновляем таймеры.
private void UltrasoundMain()
{
//========== UPDATE PIR STATE
UltrasonicPirStateUpdate();
//========== UPDATE POSITION STATE
UltrasonicUpdatePositionState();
//========== UPDATE THRESHOLD
UltrasonicUpdateThreshold();
//========== NEW OBJECT SEARCH
if(temp_ceiling_stable)
UltrasonicNewObjectSearch();
//========== UPDATE OBJECT STATE
UltrasonicUpdateObjectState();
//========== SAMPLE TICK
UltrasonicSampleTick();
}
Как понять, что в выборке есть шум? На Рис 23. и Рис 24. можно посмотреть чем нормальная выборка отличается от зашумленной. В нормальной ситуации не может внезапно возникнуть множество пиков.
Теперь обрабатываем выборку. Проходим по всему массиву найденных объектов.
…
for (int i = 0; i < ULTRASONIC_OBJECT_NUM; i++)
{
if((ultrasonic_dist_obj[i].state&ULTRASONIC_OBJECT_OCCUPIED)== ULTRASONIC_OBJECT_OCCUPIED)
{
…
Если найден добавленный объект, то сначала вычисляем максимум на отрезке где он находится. Максимум пика нужен для того, чтобы правильно вычислить порог и соответственно узнать координаты пересечения порога и амплитуды.
…
us_PeakFound = 0;
found = false;
for (int iqCount = ultrasonic_dist_obj[i].index_start; iqCount < Samples; iqCount++)
{
us_AmplitudePrev = Amp[iqCount - 1];
us_Amplitude = Amp[iqCount];
if (us_PeakFound == 0)
{
if (iqCount >= ultrasonic_dist_obj[i].index_end)
break;
C_x = (iqCount - 1); C_y = us_AmplitudePrev;
D_x = iqCount; D_y = us_Amplitude;
if (IsIntersection(A_y, B_y, C_y, D_y) == 1)
{
us_PeakFound = 1;
us_AmplitudeMax = us_Amplitude;
}
}
else if (us_Amplitude <= us_AmplitudePrev)
{
us_PeakFound = 0;
found = true;
iqCount = Samples;
}
else if (us_Amplitude > us_AmplitudeMax)
us_AmplitudeMax = us_Amplitude;
…
Проходимся по отрезку и находим точку пересечения. В переменной E_x будет ToF.
…
if (found == true)
{
us_PeakFound = 0;
for (int iqCount = ultrasonic_dist_obj[i].index_start; iqCount < Samples; iqCount++)
{
us_AmplitudePrev = Amp[iqCount - 1];
us_Amplitude = Amp[iqCount];
if (iqCount >= ultrasonic_dist_obj[i].index_end)
break;
C_x = (iqCount - 1); C_y = us_AmplitudePrev;
D_x = iqCount; D_y = us_Amplitude;
if (SegmentSegment((int)A_x, (int)A_y, (int)B_x, (int)B_y, (int)C_x, (int)C_y, (int)D_x, (int)D_y, out E_x, out E_y) == 0)
…
Теперь данные нужно отфильтровать. Сглаживающий фильтр для этого использовать нельзя. На Рис 25. показано почему. Сглаживающий фильтр исказит данные и добавит инерцию. Это негативно скажется на работе алгоритма. Также есть проблема наводок от светодиодного освещения. Из-за наводок на графике появляется мелкая пульсация, напоминающая кардиограмму. Медианный фильтр не устраняет эти пульсации. Но если сделать решетку из чисел Фибоначчи, то проблема решается. Можно использовать псевдо случайные числа, если хочется.
…
n = E_x;
UInt32 n_in = (UInt32)(n * 1000000);
ultrasonic_dist_obj[i].yes = false;
ultrasonic_dist_obj[i].fib_c++;
if (ultrasonic_dist_obj[i].fib_c == ultrasonic_dist_obj[i].fib_n2)
{
ultrasonic_dist_obj[i].fib_c = 0;
ultrasonic_dist_obj[i].yes = true;
MedianFilterAdd(i, n_in);
int b = ultrasonic_dist_obj[i].fib_n1 + ultrasonic_dist_obj[i].fib_n2;
ultrasonic_dist_obj[i].fib_n1 = ultrasonic_dist_obj[i].fib_n2;
ultrasonic_dist_obj[i].fib_n2 = b;
if (ultrasonic_dist_obj[i].fib_n2 > 10)
{
ultrasonic_dist_obj[i].fib_n1 = 1;
ultrasonic_dist_obj[i].fib_n2 = 1;
}
}
…
При первом проходе нужно выбрать точку старта. Относительно этой точки будет рассчитывается смещение температуры. Среднее между полом и потолком принимаем за температуру комнаты. Температуру комнаты, давление и влажность конвертируем в скорость звука. Дальше умножаем ToF на скорость и получаем стартовую дистанцию.
…
if ((ultrasonic_dist_obj[i].state & ULTRASONIC_OBJECT_USE) == ULTRASONIC_OBJECT_USE)
{
UInt32 n_out = MedianFilterGet(0, ultrasonic_dist_obj[i].head, i);
n_median = (double)n_out / 1000000.0;
…
else if ((ultrasonic_dist_obj[i].state & ULTRASONIC_OBJECT_DIST_INIT) == ULTRASONIC_OBJECT_DIST_INIT)
{
ultrasonic_dist_obj[i].state &= ~ULTRASONIC_OBJECT_DIST_INIT;
ultrasonic_dist_obj[i].distance_start = DistCalc(temp_IrCeiling, pressure, temp_hum, n_median);
…
Тут возникает вопрос. А как конвертировать температуру, давление и влажность в скорость звука? И самое главное, как произвести обратное преобразование. Формулу можно забрать тут. Вывести обратную формулу я не смог. Поэтому задачу решил обычным подбором.
private double DistCalc(double Temp, double Pressure, double Hum, double n)
{
double V_cur = Calculate_SpeedOfSound(Temp, Pressure, Hum); //текущая скорость
double S;
double ToF;
ToF = 4 * n / usFrequency;
S = ToF * V_cur;
return S;
}
private double DistToTemp(double TempLast, double Pressure, double Hum, double n, double DistStart)
{
double T = 0;
double temp_step = 0.5;
double V_cur;
double V;
double ToF;
ToF = 4 * n / usFrequency;
V_cur = DistStart / ToF;
T = TempLast;
V = Calculate_SpeedOfSound(T, Pressure, Hum);
//поиск текущей температуры
for (int i = 0; i < 3; i++)
{
if (V > V_cur)
{
do
{
T -= temp_step;
V = Calculate_SpeedOfSound(T, Pressure, Hum);
} while (V > V_cur);
}
else
{
do
{
T += temp_step;
V = Calculate_SpeedOfSound(T, Pressure, Hum);
} while (V < V_cur);
}
temp_step /= 2;
}
return T;
}
//Range of validity: the calculator is only valid over the temperature range 0 to 30 ° C (273.15 - 303.15 K) and for the pressure range 75 - 102 kPa
private double Calculate_SpeedOfSound(double temp, double pressure, double hum)
{
// main body of program to calculate speed of sound in humid air
double T; // temperature degC
double P; // pressure
double Rh; // relative humidity
double C; // speed
double Xc, Xw; // Mole fraction of carbon dioxide and water vapour respectively
double H; // molecular concentration of water vapour
double C1; // Intermediate calculations
double C2;
double C3;
double ENH;
double PSV;
double PSV1;
double PSV2;
double T_kel; // ambient temperature (Kelvin)
double Kelvin = 273.15; //For converting to Kelvin
double e = 2.71828182845904523536;
// Get variables from form
T = (temp - 32) * 5 / 9;
P = pressure * 1000.0;
Rh = hum;
T_kel = Kelvin + T; //Measured ambient temp
//Molecular concentration of water vapour calculated from Rh
//using Giacomos method by Davis (1991) as implemented in DTU report 11b-1997
ENH = 3.14 * Math.Pow(10, -8) * P + 1.00062 + Math.Pow(T, 2) * 5.6 * Math.Pow(10, -7);
PSV1 = Math.Pow(T_kel, 2) * 1.2378847 * Math.Pow(10, -5) - 1.9121316 * Math.Pow(10, -2) * T_kel;
PSV2 = 33.93711047 - 6.3431645 * Math.Pow(10, 3) / T_kel;
PSV = Math.Pow(e, PSV1) * Math.Pow(e, PSV2);
H = Rh * ENH * PSV / P;
Xw = H / 100.0;
Xc = 400.0 * Math.Pow(10, -6);
//Speed calculated using the method of Cramer from
//JASA vol 93 pg 2510
C1 = 0.603055 * T + 331.5024 - Math.Pow(T, 2) * 5.28 * Math.Pow(10, -4) + (0.1495874 * T + 51.471935 - Math.Pow(T, 2) * 7.82 * Math.Pow(10, -4)) * Xw;
C2 = (-1.82 * Math.Pow(10, -7) + 3.73 * Math.Pow(10, -8) * T - Math.Pow(T, 2) * 2.93 * Math.Pow(10, -10)) * P + (-85.20931 - 0.228525 * T + Math.Pow(T, 2) * 5.91 * Math.Pow(10, -5)) * Xc;
C3 = Math.Pow(Xw, 2) * 2.835149 + Math.Pow(P, 2) * 2.15 * Math.Pow(10, -13) - Math.Pow(Xc, 2) * 29.179762 - 4.86 * Math.Pow(10, -4) * Xw * P * Xc;
C = C1 + C2 - C3;
return C;
}
Теперь можно рассчитать температуру и переменные для проверки на возможное появление новых объектов. При нормальной ситуации, дистанция не может резко изменится. Для обнаружения подобных ситуаций я проверяю разность температур между первой половиной медианного фильтра и второй половиной медианного фильтра. А также разность значений медианного фильтра и второй половины медианного фильтра. Данные не прошедшие медианный фильтр сравнивать нельзя, слишком много шума. В данном видео можно пронаблюдать как это работает.
UInt32 n_half1_out = MedianFilterGet(0, ultrasonic_dist_obj[i].head / 2, i);
n_half1_median = (double)n_half1_out / 1000000.0;
UInt32 n_half2_out = MedianFilterGet(ultrasonic_dist_obj[i].head / 2, ultrasonic_dist_obj[i].head, i);
n_half2_median = (double)n_half2_out / 1000000.0;
//============================= T calculation ================================
double T_half1_median = 0, T_half2_median = 0;
double T_median = 0;
double temp_up, temp_down;
T_half1_median = DistToTemp(ultrasonic_dist_obj[i].temperature,
pressure,
temp_hum,
n_half1_median,
ultrasonic_dist_obj[i].distance_start);
T_half2_median = DistToTemp(ultrasonic_dist_obj[i].temperature,
pressure,
temp_hum,
n_half2_median,
ultrasonic_dist_obj[i].distance_start);
T_median = DistToTemp(ultrasonic_dist_obj[i].temperature,
pressure,
temp_hum,
n_median,
ultrasonic_dist_obj[i].distance_start);
…
if (Math.Abs(T_half1_median - T_half2_median) > ULTRASONIC_TEMP_MAX_JUMP && Math.Abs(T_median - T_half2_median) > ULTRASONIC_TEMP_MAX_JUMP)
{
…
}
else if (T_median > (temp_down - ULTRASONIC_TEMP_RANGE_DOWN) && T_median < (temp_up + ULTRASONIC_TEMP_RANGE_UP))
{
ultrasonic_dist_obj[i].temperature = ultrasonic_dist_obj[i].temperature * 0.99 + T_median * 0.01;
ultrasonic_dist_obj[i].timer = ULTRASONIC_OBJECT_DIST_TIMEOUT;
}
На следующих графиках продемонстрированы данные от сенсора за пять дней непрерывной работы. Серая линия — это модуль разности между сравниваемой температурой и температурой термистора.
Проверка сенсора на то, как он будет работать в разных ситуациях.
8. Уязвимость данного метода измерения температуры
Ультразвуковой сенсор можно обмануть, при этом не будет ясно работает он правильно или нет.
Этого можно достичь если медленно перемещать в поле зрения CH201 твердый плоский объект. Например доску, лист гипсокартонна или планшет. При медленном перемещении происходит плавное изменение дистанции. Для устранения этой проблемы нужно использовать какой-то другой сенсор.
Если сенсор размещен над столом, то есть риск того, что не будет обнаружено событие когда, кто-то сдвинет стол. Расстояние изменится на десятые доли миллиметра, этого хватит, чтобы вызвать отклонение на 2-3 градуса Фаренгейта.
Эту проблему скорей всего можно устранить, если использовать видеокамеру с хорошим разрешением и отслеживать перемещение объектов в поле зрения. Но тогда понадобится использовать одноплатный компьютер и энергопотребление возрастет на порядки.
Пока что не совсем ясно, существенны эти проблемы или нет. Т.к. сенсор в связке с термостатом должен работать не так как в демонстрационной программе. К примеру, термостат работает на охлаждение. Перед тем как включить охлаждение, включается отслеживание изменения температуры с помощью ультразвука. После включается охлаждение. Когда температура упадет, к примеру на 4 градуса Фаренгейта, ультразвуковой сенсор перезапускается. Ожидается событие, когда температура поднимется на 4 градуса F. И цикл перезапускается. Для термостата не сильно нужна текущая температура. Важно знать на сколько температура изменилась. В любом случае работа сенсора в связке с термостатом еще не протестирована и до этого события еще далеко.
Комментарии (16)
s1967
05.09.2023 11:13А почему бы не ипользовать лазерный дальномер. В этом случае расстояние будет известно, а с помощью алгоритмов фильтрации можно исключить мелькания объектов на пути луча сенсора и исключить многолучевые отражения.
Так же интересной конфигурацией будет создание горизонтальной сетки из таких сенсоров и постоение карты температуры помещения и соответственно включения нужных "локальных" охладителей/нагревателей
shadrap
05.09.2023 11:13Очень интересно и детально, спасибо. Однако практическая сторона как то туманна. Во-первых если это офис, то получить очень точную температуру в точке не равно поддержать нормальную температуру внутри сложного помещения с людьми. Если это кондиционер он будет дуть на кого-то и этот кто-то будет крутить настройки. Во-вторых объекты и люди будут давать искажения на точку.
Я не специалист, но в своей автоматизации я сделал несколько беспроводных термометров с фиксированным алгоритмом распределения температуры по ним..
Apoheliy
05.09.2023 11:13давайте поставим себе практическую задачу
Можно по-подробнее про реальную задачу. Пока (по статье) это всё выглядит как "хотел сделать - сделал; получилось дорого, нестабильно, куча настроек - но сделал".
Извините, но задача про офис (по-моему) вообще таких решений не требует (работники ставят условную температуру на кондиционере и далее её поднимают/опускают по ощущению комфорта).
Такое решение больше подойдёт там, где требуется отслеживание изменения температуры самого воздуха (без учёта нагретых стен). И где это нужно?
a9d Автор
05.09.2023 11:13-1в чем собственно заключается нестабильность? Работает стабильно. Проблема в надежности. Т.к. есть ситуации когда сенсор можно обмануть. Предоставлены графики работы сенсора за рабочую неделю. На них видно насколько сенсор стабильно работает.
Это задача реальная. И продукт реальный.
Это используется в офисах. Для управления VAV Box-ом и заслонками. Другое дело, что ультразвук это функция которая еще тестируется.
Да и не дорого это.
sav13
05.09.2023 11:13Подскажите, на алишке такте сенсоры еще не продаются?
Где вообще его можно купить в наше время?
(Кроме как в ЧиД за 50к рублей)
a9d Автор
05.09.2023 11:13Это ж Китай. Попробуй через Китайские площадки брать https://www.lcsc.com/product-detail/Ultrasonic-Receivers-Transmitters_TDK-InvenSense-CH201-00ABR_C1513114.html
Хотя они в РФ не отправляют наверное
"Dear Valued Customer,Thank you for your partnership, we appreciate your business.
We are closely monitoring the situation of the Ukraine conflict and currently do not anticipate any risk of supply chain disruptions.
In light of the sanctions imposed upon Russia by governments and organizations around the world and the restrictions from our supplier sides, LCSC has stopped receiving orders from conflict zones and suspended shipping all product categories to all customers and end-users in Russia, the Donetsk and Luhansk regions of Ukraine, and Belarus.
As the situation remains dynamic, circumstances may change due to factors beyond our control. We will continue to follow the situation and keep you informed of any changes.
Yours Sincerely,
LCSC Team
Last Updated: March 17, 2022"
Jury_78
На мой взгляд это какая то средняя температура по лучу получается. Непонятно как будут влиять локальные области с различными температурой/влажность. Например, человек, горшок с цветами, вентилятор, солнце в окно и т.п.
a9d Автор
Вентилятор почти никак не влияет. Слишком слабые вентиляторы используются в офисах. Это все проверялось. Солнце никак не влияет на скорость звука.
Да это среднее отклонение температуры. По другому нельзя ведь. Если бы у пола была маленькая инерция, то такими бы вещами не заморачивались и мы бы просто брали среднее между потолком и полом.
Jury_78
Имел ввиду не само солнце, а нагретые им предметы.
a9d Автор
Не совсем понимаю о чем речь. Да солнце может нагреть помещение и поверхность. Но это ж никак не влияет на изменение температуры при нагреве и охлаждении. Данный способ не работает на измерение температуры, измеряется только отклонение температуры. Софт делался для отладки и тестирования, поэтому создается впечатление, что температура измеряется.
Jury_78
Допустим солнце нагрело пол, теплый воздух поднялся вверх, а звук прошел через эту область. Может это малая часть, а может нет.
a9d Автор
Ну да. Солнце нагрело пол, температура в комнате повысилась. Пол же будет разогревать воздух. Все такие моменты проверены. Разогретый пол представляет проблему только для IR сенсоров.
Jury_78
Обычно температура тянет за собой влажность. Что там по формуле, чье влияние сильнее я не знаю, боюсь, что пары воды окажутся силнее.