Температурный датчик NST1002 от компании Novosense

Датчик заявлен как высокоточный, +/- 0.1 градуса для 0…+85 град. С, в корпусе DFN-2L. Для всего диапазона температур -40… +150 градусов точность несколько хуже, до +/- 0.5 градуса. У датчика 15-ти битное АЦП, восемь разрядов на градусы и семь на дробную часть, что дает разрешающую способность 1/128 или 0.0078125 градуса. Время преобразования и считывания данных порядка 32-х миллисекунд. Подключается он по шине 1-Wire и имеет два варианта конструктивного исполнения: DFN-2L (1.6×0.8 мм) и TO-92S-2L (4.0×3.0 mm).

Типовая схема подключения показана на Рис. 1 и требует 2 ножки микроконтроллера. GPIO1 используется для управления обменом, GPIO2 для считывания данных. Рекомендуемое значение резистора 4.7 кОм @ 3.3 В.

0b5fa8941099e6a1fd59d2b68579b06f.PNG

Рис. 1 Схема подключения NST1002

 Обмен с микроконтроллером показан на Рис. 2. Его начало инициируется сбросом питания (GPIO1) в ноль на время 200 микросекунд. Этот импульс запускает в датчике процесс преобразования температуры. Он длится около 30 миллисекунд и по его окончании датчик выдает 17-ти микросекундный импульс (показан на рисунке пунктиром), который микроконтроллер считывает по линии GPIO2.

84e7ec260239b2ba90100cb052ad95de.PNG

Рис. 2 Обмен данными с микроконтроллером

Это означает, что процесс завершен корректно и датчик готов передавать данные. Передача данных происходит побитно, сбросом линии питания (GPIO1) в ноль на время порядка 1–2 микросекунды. При этом датчик удерживает нулевой потенциал примерно либо 7…10 микросекунд (что означает »1»), либо 18…21 микросекунду (что означает »0»). Интервал между импульсами сброса должен быть не менее 60-ти микросекунд, таким образом 24 бита данных передадутся минимально за 1440 микросекунд. Данные считываются соответственно по линии GPIO2, их формат показан на Рис. 3.

04befb0bf26e6a3a1a5b0c195310e3d0.PNG

Рис. 3 Формат принимаемых данных

Первые 16 бит это данные, из которых старший бит — это знак; следующие 8 бит — CRC код в формате Maxim/Dallas. Отрицательные значения температуры передаются в дополнительном коде. Пример вычисления CRC показан на Рис. 4 ниже. Не обязательно также считывать все 24 бита. Для получения температуры в целых градусах достаточно считать первые 9 бит.

Следует отметить, что процесс считывания данных должен начаться не позднее 5-ти миллисекунд после импульса готовности. Иначе датчик перейдет в дежурный режим (idle state), и будет выдавать все время одни и те же данные → 0×18 0×6E 0xE0.

73edfe5a20e9b2aa1b78278aff84c5c0.jpg

Рис. 4 Пример вычисления CRC

Импульс готовности, чтение 16 бит данных и затем стартовый импульс, снятые логическим анализатором, показаны на Рис. 5 ниже.

780d2c3c9685f5e51840c29c8b2038ea.png

Рис. 5 Данные с датчика NST1002-CDNR

 Чтение данных было организовано с помощью микроконтроллера STM32F103C8T6 c тактовой частотой 72 МГц. С помощью прерывания от таймера была получена временная сетка с шагом 5 микросекунд. Формирование сигналов и чтение данных организовано в обработчике прерывания. Для того чтобы минимизировать в нем количество проверок, был создан массив задержек от начала последовательности для фронтов arr[25]  (PB1 → »0»; PB1 → »1») и массив задержек для чтения данных brr[24]. С их помощью сначала формируется импульс 300 мкс для сброса датчика NST1002; затем примерно через 31 миллисекунду, когда датчик гарантировано выдает импульс окончания преобразования, формируются импульсы побитного считывания данных.

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

Код формирования массивов приведен ниже. Они объявлены как const и располагаются во Flash памяти, возможно размещение их в ОЗУ позволит несколько убыстрить работу обработчика.

	uint32_t index_arr = 0, index_brr = 0, index_data = 0;
	uint32_t arr_data[90] = {0};
	const uint32_t arr[25*2] = {
		100/5, 400/5,
		(31500+(60* 0))/5, (31505+(60* 0))/5, 
		(31500+(60* 1))/5, (31505+(60* 1))/5,
		(31500+(60* 2))/5, (31505+(60* 2))/5,
		(31500+(60* 3))/5, (31505+(60* 3))/5,
		(31500+(60* 4))/5, (31505+(60* 4))/5,
		(31500+(60* 5))/5, (31505+(60* 5))/5,
		(31500+(60* 6))/5, (31505+(60* 6))/5,
		(31500+(60* 7))/5, (31505+(60* 7))/5,
		(31500+(60* 8))/5, (31505+(60* 8))/5,
		(31500+(60* 9))/5, (31505+(60* 9))/5,
		(31500+(60*10))/5, (31505+(60*10))/5,
		(31500+(60*11))/5, (31505+(60*11))/5,
		(31500+(60*12))/5, (31505+(60*12))/5,
		(31500+(60*13))/5, (31505+(60*13))/5,
		(31500+(60*14))/5, (31505+(60*14))/5,
		(31500+(60*15))/5, (31505+(60*15))/5,
		(31500+(60*16))/5, (31505+(60*16))/5,
		(31500+(60*17))/5, (31505+(60*17))/5,
		(31500+(60*18))/5, (31505+(60*18))/5,
		(31500+(60*19))/5, (31505+(60*19))/5,
		(31500+(60*20))/5, (31505+(60*20))/5,
		(31500+(60*21))/5, (31505+(60*21))/5,
		(31500+(60*22))/5, (31505+(60*22))/5,
		(31500+(60*23))/5, (31505+(60*23))/5
	};
	
	const uint32_t brr[24] = {
		(31515+(60* 0))/5, 
		(31515+(60* 1))/5,
		(31515+(60* 2))/5,
		(31515+(60* 3))/5,
		(31515+(60* 4))/5,
		(31515+(60* 5))/5,
		(31515+(60* 6))/5,
		(31515+(60* 7))/5,
		(31515+(60* 8))/5,
		(31515+(60* 9))/5,
		(31515+(60*10))/5,
		(31515+(60*11))/5,
		(31515+(60*12))/5,
		(31515+(60*13))/5,
		(31515+(60*14))/5,
		(31515+(60*15))/5,
		(31515+(60*16))/5,
		(31515+(60*17))/5,
		(31515+(60*18))/5,
		(31515+(60*19))/5,
		(31515+(60*20))/5,
		(31515+(60*21))/5,
		(31515+(60*22))/5,
		(31515+(60*23))/5
	};

Для этого каждые 60 мкс линия питания датчика опускается в »0» на 5 микросекунд, затем поднимается в »1» и так 24 раза подряд. Датчик NST1002 удерживает линию в »0» либо на время около 10 микросекунд (бит = »1»), либо на 20 микросекунд (бит = »0»).

Для чтения бита мы считываем PB2 в момент, отстоящий на 15us от падающего питания PB1 → »0». Считанный бит плюсуется к переменной, затем ее биты сдвигаются влево, и так 23 раза (кроме последнего). Код обработчика прерывания приведен ниже.

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){
		if(ccc == 1){
			//HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);
			aaa++;
				if(aaa == arr[index_arr]){
					if((index_arr & 0x01) == 0) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, 0);
					else HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, 1);
					
					index_arr ++;					
				}
				
				if(aaa == brr[index_brr]){
					if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)) dataBRR ++;
					if(index_brr != 23) dataBRR = dataBRR << (1);				
					index_brr ++;	
				}
				
				
				if(index_brr == 24){
					if(index_data < 90){
						arr_data[index_data] = dataBRR;
					}else{
						ccc = 0;
					}
				index_data ++;	
				dataBRR = 0;
				aaa = 0; 
				index_arr = 0;
				index_brr = 0;				
		}
		//HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);	
	}
}

С точки зрения использования аппаратных ресурсов микроконтроллера данное решение не является оптимальным, но вполне работоспособным. Время нахождения в обработчике примерно 1,2 микросекунды из 5-ти, что позволяет микроконтроллеру выполнять и другие задачи.

Экспериментальные данные температуры, полученные от NST1002-CDNR со скоростью чтения примерно 30 раз в секунду, представлены ниже на Рис. 6. Сам датчик находился при комнатной температуре в неподвижном воздухе и для достижения стабильных показаний был обернут фольгой.

a87a4345c796938b870a6cbd5228760a.PNG

Рис 6 Данные температуры с датчика NST1002

Заявленный Novosense температурный дрейф –> 0.4 градуса после 1000 часов наработки при +125 градусах С. Таким образом, NST1002 представляет вполне достойную альтернативу температурным датчикам американских и европейских производителей.

Выражаю отдельную благодарность компании MT-Systems за предоставленные образцы NST1002-CDNR.

High-precision Single-BUS Digital Temperature Sensor

© Habrahabr.ru