1. Введение

  2. Как это работает и зачем это нужно

  3. О чипе

  4. Настройка драйвера

  5. Как должен выглядеть ультразвуковой сенсор температуры

  6. Проблемы, которые могут возникнуть в процессе проведения измерений

  7. Реализация алгоритма

  8. Уязвимость данного метода измерения температуры

1. Введение

До недавних пор для проведение подобных измерений требовалось использовать промышленные приемники/передатчики ультразвука. Только они могли дать приемлемую точность и дальность. Но они были слишком большие и дорогие. Использовать дешевые китайские модули, такие как HC-SR04/US-025, не выйдет. Точность, стабильность, повторяемость результата оставляет желать лучшего.

Ситуацию изменило появление нового чипа CH-201. Его основная проблема заключается в том, что он китайский. Я еще не видел китайский чип с хорошей документацией и хорошей службой поддержки.

На следующих изображениях продемонстрирован результат работы этого чипа.

Рис 1.  Графики температуры комнаты, потолка, пола, среднего между потолком и полом, ультразвука. По оси Х – показания, период 10 сек. По оси Y – температура, в градусах Фаренгейта (F).
Рис 1.  Графики температуры комнаты, потолка, пола, среднего между потолком и полом, ультразвука. По оси Х – показания, период 10 сек. По оси Y – температура, в градусах Фаренгейта (F).

Где,

  • Room – температура термистора, размещенного примерно по центру комнаты.

  • Ceiling – температура термистора, размещенного на потолке.

  • IR – температура поверхности пола, полученная от инфракрасного сенсора.

  • (IR+Ceiling)/2 – средняя температура между полом и потолком.

  • Ultrasound20 – температура полученная от ультразвукового сенсора. Где числа 10 и 20 — это сглаживание. Формула сглаживания Tsm = Tsm * (n-1)/n + T * 1/n.

Чуть дальше будет описание как получены данные, сейчас же просто демонстрация.

Рис 2. График температуры от ультразвукового сенсора.
Рис 2. График температуры от ультразвукового сенсора.

Я думаю, видя графики становится понятно, чем именно интересен этот способ отслеживания изменения температуры в комнате. Используя данную технологию, можно только отслеживать изменение температуры, а не проводить измерение температуры. Если добавить лазерный дальномер, с точностью хотя-бы +- 0.1 мм, то получится проводить измерение температуры. Также можно производить измерение температуры в комнате, если перед началом измерения точно измерить расстояние между сенсором и полом.

В первом прототипе я пробовал использовать дальномер VL53L3CX. Как оказалось, он работает не так как хотелось бы. Этот сенсор не дает точное расстояние, ошибка достигает 20 мм. Точность измерения зависит от цвета поверхности, освещенности комнаты. Лампочка, имитирующая солнечный свет, так и вовсе делает этот сенсор бесполезным. Данные от сенсора нужно ждать примерно от 5 до 15 минут.

2. Как это работает и зачем это нужно

Скорость звука зависит от температуры, влажности и давления. Скорость ветра можно не учитывать, в жилых помещениях нет сильного ветра. Соответственно отслеживая изменение скорости звука и зная текущую влажность, давление, можно вычислить насколько температура воздуха изменилась.

Ну тут возникает проблема. Дело в том, что ультразвуковой приемо-передатчик возвращает время за которое сигнал дошел до объекта, отразился и вернулся на приемник (ToF – Time of Flight). Время нельзя конвертировать в скорость не зная дистанцию. Это не проблема, если нужно отслеживать только изменение температуры. Для этого не нужно знать точную дистанцию.

Рис 3. Скриншот из документа “CH101 and CH201 SmartSonic Evaluation Kit User Guide”. Время прохождение ультразвукового сигнала к объекту и от объекта.
Рис 3. Скриншот из документа “CH101 and CH201 SmartSonic Evaluation Kit User Guide”. Время прохождение ультразвукового сигнала к объекту и от объекта.

Ультразвуковой сенсор обладает хорошей особенностью, это отсутствие инерции. Также с помощью ультразвука можно измерить температуру воздуха, а не температуру объекта. Ультразвуковой сенсор решает проблему самонагрева/нагрева сенсора. Например, когда сенсор разогрелся в процессе работы или сенсор нагрелся на солнечном свете, или вблизи лампы.

Напротив сенсора должна находится твердая плоская поверхность. С ковролином или линолеумом работать не будет. Также в радиусе 5 м не должно находится других CH-201 сенсоров или иных источников ультразвука.

Термисторы и инфракрасные сенсоры возвращают температуру объекта и температуру поверхности соответственно, а не температуру воздуха. Эти сенсоры легко использовать, и они дешёвые. Но почти всегда их нельзя расположить в помещении там где нужно.

Для простоты понимания зачем этим вообще нужно заниматься давайте поставим себе практическую задачу. Есть термостат и есть задача регулировать температуру в помещении. Помещение офисное с определенным дизайном.

Рис 4. Фото из интернета для примера офиса.
Рис 4. Фото из интернета для примера офиса.

Для решения этой задачи нужен сенсор температуры. Но возникает вопрос “Какой?”. Дизайн офиса, в большинстве случаев, никто не разрешит портить. Для каждого офиса разрабатывать сенсор с определенным дизайном не выйдет, это слишком дорого. Скорей всего разрешат поставить сенсор где-нибудь на кухне или возле бойлера с водой. Данные от такого сенсора будут так себе. А что делать если офис большой? Как тогда понять какая в нем температура?

Почти всегда и почти во всех случаях сенсор температуры можно ставить на потолок. Как правило, в таких случаях, сенсор можно устанавливать где хочется на потолке. Потолочные сенсоры не портят дизайн. Но потолочные сенсоры измеряют температуру под потолком, это проблема. Под потолком всегда теплее.

Есть разные пути решения проблемы измерения температуры под потолком. Самый очевидный способ, это использовать некоторое фиксированное смещение температуры вниз. Самое простое и самое не эффективное решение. Такой способ по разному работает в случае нагрева и в случае охлаждения помещения. В случае нагрева температура будет слишком быстро возрастать и слишком медленно падать. В случае охлаждения теплый воздух будет вытесняться под потолок, реакция будет с задержкой и температура будет падать слишком медленно.

Рис 5. Фиксированное смещение -2 F.
Рис 5. Фиксированное смещение -2 F.

Другой способ — это добавить инфракрасный сенсор температуры и вычислять среднее между потолком и полом. Этот способ работает лучше чем фиксированное смещение. Но у него есть большой недостаток в виде пола с огромной инерцией. Также под сенсором иногда ходят люди, они будут вносить искажения в результат измерения.

Рис 6. Среднее между потолком и полом.
Рис 6. Среднее между потолком и полом.
Рис 7. Среднее и фиксированное смещение. Только охлаждение.
Рис 7. Среднее и фиксированное смещение. Только охлаждение.

Других способов особо и нет. Можно экспериментировать с разными способами вычисления смещения, вычислением среднего и т.п. Но это не даст хороший результат. Ультразвук устраняет эту проблему. Но он не идеален, сложен в реализации и есть уязвимые моменты.

3. О чипе

Рис 8. Ультразвуковой сенсор TDK CH-201.
Рис 8. Ультразвуковой сенсор TDK CH-201.

Если бы этот сенсор разработала бы другая компания, например 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.

Рис 9. Акустическая камера с FoV 30 градусов.
Рис 9. Акустическая камера с FoV 30 градусов.
Рис 10. CH-201 с установленной акустической камерой.
Рис 10. CH-201 с установленной акустической камерой.

На выходе сенсор выдает массив, состоящий из пар комплексных чисел (I + jQ).

Которые можно конвертировать в амплитуду A = sqrt(I^2+Q^2) . В своем коде я работаю только с амплитудой, что можно выжать из комплексных чисел, я не знаю.

Рис 11. Зависимость между значениями I и Q , амплитудой, и фазой.
Рис 11. Зависимость между значениями I и Q , амплитудой, и фазой.

Для получения ToF используется формула ToF = n*8/f_oгде,

  • n – номер сэмпла;

  • f_o– актуальная частота ультразвука.

ToF нужно разделить на 2. Для визуализации сигнала я умножаю ToF/2на скорость 343 м/c.

Имея ToF и амплитуду получаем что-то вроде аудиофайла. Обработав который, мы можем понять сколько объектов находится в FoV и на каком расстояние они находятся.

Рис 12. Визуализация выборки. По оси X – дистанция (м) , по оси Y – амплитуда.
Рис 12. Визуализация выборки. По оси X – дистанция (м) , по оси Y – амплитуда.

На высоту амплитуды влияет продолжительность сигнала, отражающая способность материала и форма объекта. Продолжительность сигнала можно регулировать. Чем больше продолжительность, тем больше шума и больше вероятность словить эхо. Например расстояние между сенсором и полом 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. Плата довольно удобная и на ней можно протестировать все интересующие моменты. Документация довольно скудная и без нее будет довольно сложно работать с чипом.

Рис 13. Отладочная плата DK-CH201.
Рис 13. Отладочная плата DK-CH201.

В файле настроек 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).

Демонстрацию работы функции коррекции частоты можно посмотреть в этом видео.

В качестве нагревателя используется лампа инфракрасного света.

Рис 14. Испытание функции коррекции частоты.
Рис 14. Испытание функции коррекции частоты.

В принципе с драйвером на этом все. Дальше нужно просто обрабатывать данные. Портировать драйвер в свой проект не сложно. По большому счету нужно только заменить функции 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. Как должен выглядеть ультразвуковой сенсор температуры

Теперь нужно определится как же будет выглядеть устройство. Готовые сенсоры у меня уже конечно же есть. Но на момент проектирования, функция ультразвука была тестовой и не было понимания как она будет работать, и будет ли эта технология вообще работать. Поэтому готовые доски пришлось дорабатывать вручную.

Рис 15. Примерный вид сенсора сверху.
Рис 15. Примерный вид сенсора сверху.

Большой вырез в корпусе это термобарьер. В процессе тестирования было выявлено, что АБС пластик отлично проводит тепло. Да и чем больше корпус, тем больше инерция у сенсора температуры. Такое решение позволило уменьшить теплоемкость кармана с сенсором температуры и устранило проблему с теплопередачей тепла от корпуса к сенсору температуры. Есть еще черный вариант корпуса. За счет цвета удалось еще немного снизить инерцию.

Рис 16. Примерный вид сенсора снизу.
Рис 16. Примерный вид сенсора снизу.
Рис 17. Примерный вид сенсора с боку.
Рис 17. Примерный вид сенсора с боку.

Воздушная прослойка между потолочной пластиной и сенсором добавлена специально. Это термобарьер. У потолка большая инерция. Температура поверхности потолка оказывает влияние на температуру сенсора. Для решения этой проблемы добавлена воздушная прослойка.

Рис 18. Примерный вид сенсора снизу, без потолочной пластины.
Рис 18. Примерный вид сенсора снизу, без потолочной пластины.

Площадь контакта основного корпуса и потолочной пластины сведены к минимуму.

Рис 19. Примерный вид печатной платы.
Рис 19. Примерный вид печатной платы.
Рис 20. Плата после доработки и размещение под потолком.
Рис 20. Плата после доработки и размещение под потолком.

Для отслеживания изменения температуры на плате должны присутствовать:

  • Сенсор температуры;

  • Инфракрасный сенсор температуры;

  • Сенсор влажности;

  • Сенсор атмосферного давления;

  • Акселерометр;

  • Ультразвуковой сенсор;

  • Микроконтроллер.

Выяснилось, что CH201 весьма прожорлив к RAM. Для драйвера и алгоритма обработки ультразвука нужно выделить примерно 10 кБайт памяти. Также для ультразвука нужно выделить свой отдельный I2C. Ультразвук съедает львиную долю пропускной способности I2C. На протяжении дня влажность и атмосферное давление меняются. Если не учитывать эти параметры в расчетах скорости звука, то температура поплывет и будет давать большую ошибку. С помощью акселерометра можно убедится, что сенсор установлен правильно, не под углом и смотрит прямо вниз на пол. Также акселерометр работает как сенсор движения устройства. В процессе проведения измерений устройство не должно перемещаться. Инфракрасный сенсор температуры нужен для точного определения точки начала отсчета.

Для проведения опытов сенсор был размещен под потолком, по центру комнаты подвешен термистор.

Рис 21. Размещение сенсора под потолком.
Рис 21. Размещение сенсора под потолком.
Рис 22. Термистор.
Рис 22. Термистор.

6. Проблемы, которые могут возникнуть в процессе проведения измерений

CH201 на прием работает как микрофон. Ограничения по частоте принимаемого ультразвукового сигнала выставить нельзя.  Я проверял как сенсор реагирует на ультразвук с частотой 30 кГц и чип его принимал, не отфильтровывал. Нужно учитывать, что могут и будут появляться различные ложные ультразвуковые сигналы.

Рис 23. CH201 может принимать ультразвуковой сигнал от посторонних источников.
Рис 23. CH201 может принимать ультразвуковой сигнал от посторонних источников.

Наклонные поверхности могут отразить сигнал. Такой сигнал не годится для расчета температуры. Мне так и не удалось полностью решить это проблему. Вероятность появления такой ситуации можно сильно уменьшить если сделать продолжительность ультразвукового сигнала как можно меньше.

Рис 24. Отраженный сигнал от наклонных поверхностей.
Рис 24. Отраженный сигнал от наклонных поверхностей.

В поле зрения сенсора могут появляться и исчезать объекты. Особенно часто это будет происходить если сенсор будет установлен над столом. Эту ситуацию довольно легко обработать. В выборке появится дополнительный пик либо ToF резко скакнёт.

Объект под сенсором могут немного передвинуть, из-за чего дистанция может изменится немного. Либо на стол могу облокотится или что-то положить, из-за чего он немного просядет. Эта ситуация довольно сложная в обнаружении.

Ламинат/паркет немного проседает, когда проходят или стоят люди. Решения так и не нашел.  

7. Реализация алгоритма

Пытаться разработать прошивку сразу в лоб довольно плохая затея. Нужно обрабатывать большие массивы данных и без визуального представления это будет непосильная задача. Поэтому быстро было принято решение сбрасывать все данные на ПК и библиотеку писать на нем, с последующим портирование на микроконтроллер.

Рис 25. Программа для визуализации данных от ультразвукового сенсора.
Рис 25. Программа для визуализации данных от ультразвукового сенсора.

Описание программы для визуализации данных.

Сперва проверяем есть ли кто-то в комнате, можно и не делать. Но в пустой комнате 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. можно посмотреть чем нормальная выборка отличается от зашумленной.  В нормальной ситуации не может внезапно возникнуть множество пиков.

Рис 26. Выборка без шума.
Рис 26. Выборка без шума.
Рис 27. Выборка с шумом.
Рис 27. Выборка с шумом.

Теперь обрабатываем выборку. Проходим по всему массиву найденных объектов.

…
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;
  }
}
…
Рис 28. Изображение из интернета демонстрирующие работу медианного фильтра. На первом графике входные данные, на втором работа сглаживающего фильтра, на третьем работа медианного фильтра.
Рис 28. Изображение из интернета демонстрирующие работу медианного фильтра. На первом графике входные данные, на втором работа сглаживающего фильтра, на третьем работа медианного фильтра.

При первом проходе нужно выбрать точку старта. Относительно этой точки будет рассчитывается смещение температуры. Среднее между полом и потолком принимаем за температуру комнаты. Температуру комнаты, давление и влажность конвертируем в скорость звука. Дальше умножаем 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;
}
Рис 29. Получение переменных для проверки на появление новых объектов.
Рис 29. Получение переменных для проверки на появление новых объектов.
Рис 30. Появление нового объекта в поле зрения ультразвукового сенсора.
Рис 30. Появление нового объекта в поле зрения ультразвукового сенсора.

На следующих графиках продемонстрированы данные от сенсора за пять дней непрерывной работы. Серая линия — это модуль разности между сравниваемой температурой и температурой термистора.

Рис 31. Сравнение средней температуры с температурой термистора.
Рис 31. Сравнение средней температуры с температурой термистора.
Рис 32. Сравнение температуры с фиксированным смещением с температурой термистора.
Рис 32. Сравнение температуры с фиксированным смещением с температурой термистора.
Рис 33. Сравнение температуры ультразвукового сенсора с температурой термистора.
Рис 33. Сравнение температуры ультразвукового сенсора с температурой термистора.

Проверка сенсора на то, как он будет работать в разных ситуациях.

8. Уязвимость данного метода измерения температуры

Ультразвуковой сенсор можно обмануть, при этом не будет ясно работает он правильно или нет.

Этого можно достичь если медленно перемещать в поле зрения CH201 твердый плоский объект. Например доску, лист гипсокартонна или планшет. При медленном перемещении происходит плавное изменение дистанции. Для устранения этой проблемы нужно использовать какой-то другой сенсор.

Если сенсор размещен над столом, то есть риск того, что не будет обнаружено событие когда, кто-то сдвинет стол. Расстояние изменится на десятые доли миллиметра, этого хватит, чтобы вызвать отклонение на 2-3 градуса Фаренгейта.

Эту проблему скорей всего можно устранить, если использовать видеокамеру с хорошим разрешением и отслеживать перемещение объектов в поле зрения. Но тогда понадобится использовать одноплатный компьютер и энергопотребление возрастет на порядки.

Пока что не совсем ясно, существенны эти проблемы или нет. Т.к. сенсор в связке с термостатом должен работать не так как в демонстрационной программе. К примеру, термостат работает на охлаждение. Перед тем как включить охлаждение, включается отслеживание изменения температуры с помощью ультразвука. После включается охлаждение. Когда температура упадет, к примеру на 4 градуса Фаренгейта, ультразвуковой сенсор перезапускается. Ожидается событие, когда температура поднимется на 4 градуса F. И цикл перезапускается. Для термостата не сильно нужна текущая температура. Важно знать на сколько температура изменилась. В любом случае работа сенсора в связке с термостатом еще не протестирована и до этого события еще далеко.  

Рис 34. Пример алгоритма работы ультразвукового сенсора в связке с термостатом.
Рис 34. Пример алгоритма работы ультразвукового сенсора в связке с термостатом.

Комментарии (16)


  1. Jury_78
    05.09.2023 11:13

    На мой взгляд это какая то средняя температура по лучу получается. Непонятно как будут влиять локальные области с различными температурой/влажность. Например, человек, горшок с цветами, вентилятор, солнце в окно и т.п.


    1. a9d Автор
      05.09.2023 11:13

      Вентилятор почти никак не влияет. Слишком слабые вентиляторы используются в офисах. Это все проверялось. Солнце никак не влияет на скорость звука.
      Да это среднее отклонение температуры. По другому нельзя ведь. Если бы у пола была маленькая инерция, то такими бы вещами не заморачивались и мы бы просто брали среднее между потолком и полом.


      1. Jury_78
        05.09.2023 11:13

        Солнце никак не влияет на скорость звука.

        Имел ввиду не само солнце, а нагретые им предметы.


        1. a9d Автор
          05.09.2023 11:13
          +1

          Не совсем понимаю о чем речь. Да солнце может нагреть помещение и поверхность. Но это ж никак не влияет на изменение температуры при нагреве и охлаждении. Данный способ не работает на измерение температуры, измеряется только отклонение температуры. Софт делался для отладки и тестирования, поэтому создается впечатление, что температура измеряется.


          1. Jury_78
            05.09.2023 11:13

            Допустим солнце нагрело пол, теплый воздух поднялся вверх, а звук прошел через эту область. Может это малая часть, а может нет.


            1. a9d Автор
              05.09.2023 11:13

              Ну да. Солнце нагрело пол, температура в комнате повысилась. Пол же будет разогревать воздух. Все такие моменты проверены. Разогретый пол представляет проблему только для IR сенсоров.


              1. Jury_78
                05.09.2023 11:13

                Обычно температура тянет за собой влажность. Что там по формуле, чье влияние сильнее я не знаю, боюсь, что пары воды окажутся силнее.


  1. s1967
    05.09.2023 11:13

    А почему бы не ипользовать лазерный дальномер. В этом случае расстояние будет известно, а с помощью алгоритмов фильтрации можно исключить мелькания объектов на пути луча сенсора и исключить многолучевые отражения.

    Так же интересной конфигурацией будет создание горизонтальной сетки из таких сенсоров и постоение карты температуры помещения и соответственно включения нужных "локальных" охладителей/нагревателей


    1. a9d Автор
      05.09.2023 11:13

      Цена. Лазерный дальномер с необходимой точностью стоит ~3500$


      1. sim2q
        05.09.2023 11:13

        наверное имелось в виду VL53L0X, тут по нему много было


        1. a9d Автор
          05.09.2023 11:13

          В статье я упоминаю оптический дальномер от ST. Там погрешность большая. Они не годятся


  1. shadrap
    05.09.2023 11:13

    Очень интересно и детально, спасибо. Однако практическая сторона как то туманна. Во-первых если это офис, то получить очень точную температуру в точке не равно поддержать нормальную температуру внутри сложного помещения с людьми. Если это кондиционер он будет дуть на кого-то и этот кто-то будет крутить настройки. Во-вторых объекты и люди будут давать искажения на точку.

    Я не специалист, но в своей автоматизации я сделал несколько беспроводных термометров с фиксированным алгоритмом распределения температуры по ним..


  1. Apoheliy
    05.09.2023 11:13

    давайте поставим себе практическую задачу

    Можно по-подробнее про реальную задачу. Пока (по статье) это всё выглядит как "хотел сделать - сделал; получилось дорого, нестабильно, куча настроек - но сделал".

    Извините, но задача про офис (по-моему) вообще таких решений не требует (работники ставят условную температуру на кондиционере и далее её поднимают/опускают по ощущению комфорта).

    Такое решение больше подойдёт там, где требуется отслеживание изменения температуры самого воздуха (без учёта нагретых стен). И где это нужно?


    1. a9d Автор
      05.09.2023 11:13
      -1

      в чем собственно заключается нестабильность? Работает стабильно. Проблема в надежности. Т.к. есть ситуации когда сенсор можно обмануть. Предоставлены графики работы сенсора за рабочую неделю. На них видно насколько сенсор стабильно работает.
      Это задача реальная. И продукт реальный.
      Это используется в офисах. Для управления VAV Box-ом и заслонками. Другое дело, что ультразвук это функция которая еще тестируется.
      Да и не дорого это.


  1. sav13
    05.09.2023 11:13

    Подскажите, на алишке такте сенсоры еще не продаются?

    Где вообще его можно купить в наше время?

    (Кроме как в ЧиД за 50к рублей)


    1. 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"