Радиотракт брелков автомобильных сигнализаций.

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





В самых ранних простых моделях, использовалась схема сверхрегенеративного приемника. Несмотря на простоту, у них есть недостатки: небольшая чувствительность, низкая избирательность, паразитное излучение радиосигнала в антенну (без соответствующих схемных решений) и т.п.
Типовая схема такого приемника:



Типовая схема простейшего передатчика для него:



Способность сверхрегенеративного приемника, одновременно излучать и принимать сигнал в подобной схеме, но без предварительного каскада усиления, и переводимого в режим работы автодина, используется на пользу в микроволновых датчиках объемах различных охранных сигнализаций, которые являются дальнейшей эволюцией радиолокационных взрывателей снарядов и бомб периода второй мировой войны:
Схема из патента (не по ГОСТу):



Краткое описание работы (секретно):



Примерный монтаж:



Стоит продолжать,(военного блога то нет)? А они, наверное, в свою очередь, черпали идею от терменвокса.
Хорошее описание работы такого приемника можно почерпнуть тут:
nenuda.ru/сверхрегенеративные-приемники.html
Про микроволновый датчик объема можно много найти в литературе и интернете. radiokot.ru/circuit/analog/receiv_transmit/27/
Как и про радиолокационный взрыватель, если кому не повезло в жизни учится и служить в соответствующих заведениях: ru.wikipedia.org/wiki/Радиовзрыватель

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



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



Для примера, так выглядят плата трансивера с амплитудной модуляцией и одним преобразованием частоты:


Другая сторона:



А так с частотной, и двойным преобразованием частоты:



Другая сторона:



Так выглядит плата брелка, в котором есть только передатчик:



Другая сторона в заголовке.

Схема радиочастотной части трансивера примерно такая, как на картинке:



В верхней части разрисованы компоненты передатчика и приемника до смесителя, сигнализации с амплитудной модуляцией, или как принято у «них» — манипуляцией (ASK — amplitude shift keying), а на нижней – с частотной модуляцией (FSK — frequency shift keying). Далее в узле, отвечающей за прием, следует, как правило, специализированная микросхема, в типовой схеме её включения. Вариантов много, приведу пару:
Продолжения схемы приемника от верхней части:



Продолжения схемы приемника от нижней части:



Немного о назначении некоторых компонентов: В качестве частотозадающей схемы передатчика и гетеродина приемника, используются ПАВ резонаторы. ПАВ (SAW) резонаторы используют эффект поверхностных акустических волн и в отличие от кварцевых резонаторов, использующих пьезоэлектрический эффект, имеют большую рабочую частоту (диапазон частот от 100МГц до 1.1ГГц), но меньшую стабильность (от 20 до 200кГц (30-250ppm)). SAW резонаторы выпускаются в корпусах для поверхностного монтажа и для монтажа в отверстия. И раз SAW резонаторы и фильтра, имеют больший разброс характеристик по частоте резонанса, полосе пропускания и т.д., чем кварцевые, зачастую требуется корректировка частоты генератора передатчика и гетеродина приемника с помощью переменного конденсатора. Маркировка керамических резонаторов на плате не всегда информативна, на корпусе резонатора передатчика и гетеродина, может быть указана одна частота, а частота резонатора гетеродина отличается от частоты резонатора передатчика на величину промежуточной частоты (10,7МГц, 21,400МГц и т.д.). Их разницу может указывать буква или цифра, к примеру, Т-передатчик, R-приемник. Антенна, в зависимости от режима работы трансивера, с помощью pin-диодов (обведены красным), переключается то на выход передатчика, то на вход приемника. Напомню, Pin – диод, обладает способностью пропускать высокочастотный сигнал сквозь себя (или шунтировать), при наличии небольшого прямого тока через себя. А диод, обведенный зеленым, внизу слева – варикап. Его емкость изменяется в зависимости от обратного напряжения, приложенному к нему. Что позволяет в определенных пределах перестраивать частоту генератора передатчика, построенного на SAW резонаторе. На этот диод подается напряжение модуляции от микроконтроллера. После детектирования, сигнал с микросхемы приемника, подается в микроконтроллер для декодирования.
Схема брелка, без «обратной связи», оснащенного только передатчиком:



Схемы в лучшем качестве приложены в pdf -> zip.

Так выглядят сигналы, подаваемые на варикап, и полученные после детектирование на выходе приемников, на данной картинке, сигнал с приемника инвертирован относительно сигнала модуляции:



Схема подключения современного цифрового трансивера, где почти все на одном кристалле, как правило, не отличается от типовой, рекомендуемой производителем:



Да и плата с ним гораздо компактнее:



Современные автомобильные сигнализации, на цифровых трансиверах, за счет помехоустойчивого кодирования, более совершенного метода модуляции, возможности оперативно менять рабочую частоту, довольно толерантно относятся к помехам, которые создают при работе передатчики старых сигнализаций. Практически их не замечая. Чего, к сожалению, не скажешь не только о старых систем сигнализации, но и некоторых штатных пультах центрального замка с дистанционным управлением современных автомобилей. И вполне может быть, что радио тракт уличного холодильника по продаже напитков имеет более совершенную схему.
Приведу простой пример использования оставшихся не у дел блоков сигнализации. Куда в современном мире, без китайской люстры, с пультом дистанционного управления, работающего на той же частоте 433.920 МГц. В интернете это довольно обширная тема, и не обошла моих знакомых. Дальность действия передатчика в один момент резко упала. Приходилось вставать на табуретку и вплотную подносить пульт, что бы включить или выключить люстру. А затем, и даже в таком режиме люстра работала только несколько минут после подачи на неё напряжения питания. В результате экспериментов, причина такого отказа оказалась в микросхеме управления в люстре, которая стала почему-то греться и отказывать.
Плата в люстре (страшно такую вешать под потолок, особенно если он деревянный):



Да и приемник с передатчиком не внушал доверия, при попытке вместо штатной батарейки подключить внешний блок питания (с тем же напряжением) к пульту управления, сгорел транзистор передатчика, который был успешно заменен на КТ368А.



Но раз делать надо было хорошо, обойтись без каких либо покупных деталей, и заодно поэкспериментировать, решил вместо транзистора поставить передатчик от сигнализации, а в люстру – соответственно приемник (две одинаковые платы, только задействованы разные узлы, не задействованные удалены). Взамен неисправной микросхемы системы управления люстрой, принимать и декодировать радиосигнал, управлять люстрой поручил модулю на STM32. Удаляем с платы неисправные и ненужные компоненты (оставляем только реле и транзисторные ключи):



Устанавливаем блок питания с гальванической развязкой. Делаем соединения с модулем на STM32. Люстра работает по самому простому принципу, каждой кнопке соответствует свой код, который передается без какого либо шифрования и помехоустойчивой избыточности. Так выглядят осциллограммы этих 4 кодов:






Задача распознавания упрощается до примитивизма. Осталось организовать логику работы люстры по нажатиям соответствующих кнопок. Кнопки “A”, ”B”, ”C” – включают и выключают соответствующий ряд светильников. Кнопка ”D”- выключает все. По-моему, с таким примитивным подходом организации управления, даже детские игрушки делать нехорошо, владельца такой люстры легко довести до расстройства. Если же заменить микросхему и в пульте управления, то можно было бы реализовать кодирование с секретным блочным шифром, добавить исправление ошибок при приеме, перемежение бит. Но пока напишу, как был реализован простой вариант управления, так как микросхему, формирующую сигналы управления в пульте не меняли. Начинаем подключать и смотреть осциллограммы.
Проверяем как работает передатчик трансивера, сигнал модуляции на варикап подаем с тестового вывода осциллографа:


И смотрю, есть ли большая разница на выходе приемника с АМ и ЧМ:



Почти одно и тоже, но тогда проще и дешевле использовать приемник с АМ. Подаем сигнал на вход микроконтроллера с выхода приемника, а на другом выводе (с соответствующим кодом), проверим что получается.



Метод кодирования данных в пульте управления прост, это длительность положительного уровня сигнала на одном битовом интервале, при «1» — длительность равна примерно 0,76 миллисекунды, при «0» — 0.25 миллисекунды. Длительность одного битового (бодового) интервала 1 миллисекунда. Количество бит в сообщении — 25. При удержании нажатой кнопки на пульте, сообщения идут с периодичностью примерно 32 миллисекунды.
Основная идея программы для микроконтроллера такая: организуем в программе таймер, который будет периодически опрашивать сигнал от приемника, с частотой, большей, чем поступающие биты данных. К примеру, чтобы на один битовый интервал, могли брать 36 отсчетов таймера.
Стробы (прерывания) таймера на фоне поступающих данных:



Тогда определять, приняли мы «1» или «0» будем по количеству отсчетов, при положительном сигнале на выходе приемника. Если примерно 28 таких отсчетов — то решаем что это «1», а если 11, то это «0». Но и проверяем, что весь битовый интервал уложился в требуемое количество отсчетов таймера. Иначе решаем что это помеха. Все подсчеты начинаем вести по одному из фронтов, в зависимости от типа приемника. Если принимаемый бит, соответствуют требуемым параметрам, кладем его в сдвиговый регистр, сдвигаем влево на один разряд для приема следующего. Считаем количество принятых правильных бит в счетчике (если приняли неправильный — все сбрасываем). Если приняли все 25, то сверяем полученное число в регистре с заданным заранее значением кода кнопки, у меня такие значения были определены:

//для конкретной люстры
//количество бит в сообщении : 25
//длительность сообщения : 24,5mS
//длительность h	: 0.76 mS
//длительность l	: 0.25 mS
//бодовый интервал: 1 mS
//код кнопки "A"
//1101 0000 0101 0011 1100 0000 0
//код кнопки "B"
//1101 0000 0101 0011 0011 0000 0
//код кнопки "C"
//1101 0000 0101 0011 0000 1100 0
//код кнопки "D"
//1101 0000 0101 0011 0000 0011 0
//
//подсчеты по тактам и бодам:
//1:
//__/^^^^^^^^^\___/
//            28  7    36
//
//0:
//__/^^^\_________/
//      11	 27    36
//


Процедура определения бит:

//по каждому прерыванию от таймера 2, читаем выход приемника определяем байты
void	detectorbit(void)
{
		oldrxpin=rxpin;
		rxpin=HAL_GPIO_ReadPin(RFIN_GPIO_PORT, RFIN_GPIO_PIN);
		//проверим наше прерывание от таймера синим светодиодом
		rfOut(rxpin);
		//если определили передний фронт сигнала, проверим интервалы, и сбрасываем счетчики
		//учтем, что после переднего положительного фронта всегда считается - cnth,
		//а после изменения уровня на низкий - cntl
		if((rxpin==1)&&(oldrxpin==0))
			{
				testlen();  //проверим интервалы, сколько насчитали cnth и cntl
				cnth=0;	    //сброс счетчиков
				cntl=0;
			}
		
		//читаем состояние и считаем сколько тактов оно удерживается
		if(rxpin==1)
			{
			    cnth++;
			    //rfOut(1);
			    if(cnth>bodcnt) {cnth=bodcnt;rxok=0;cntrxdata=0;}	//предохранимся от переполнения	и отсутствия фронтов
			}
			else
			{
			    cntl++;
			    //rfOut(0);
			if(cntl>bodcnt)	{cntl=bodcnt;rxok=0;cntrxdata=0;}	//предохранимся от переполнения	и отсутствия фронтов
			}
			
		//так как это процедура, вызывается 36000 раз в секунду
		//будем заодно тут определять в процедуре состояние кнопок
		//увеличивая таймер каждой, если не нажата кнопка
		//кнопка "A"	
		key1off++;
		    if(key1off>=KEYTIME)	//не нажата больше требуемой доли секунды 
			{
			    key1=0;	        //считаем что кнопку отпустили
			    key1off=KEYTIME;	//предохранимся от переполнения
			}	
		//кнопка "B"	
		key2off++;
		    if(key2off>=KEYTIME)	//не нажата больше требуемой доли секунды 
			{
			    key2=0;		//считаем что кнопку отпустили
			    key2off=KEYTIME;	//предохранимся от переполнения
			}	
		//кнопка "C"	
		key3off++;
		    if(key3off>=KEYTIME)	//не нажата больше требуемой доли секунды 
			{
			    key3=0;	        //считаем что кнопку отпустили
			    key3off=KEYTIME;	//предохранимся от переполнения
			}	
		//кнопка "D"	
		key4off++;
		    if(key4off>=KEYTIME)	//не нажата больше требуемой доли секунды 
			{
			    key4=0;		//считаем что кнопку отпустили
			    key4off=KEYTIME;	//предохранимся от переполнения
			}	
}


Тестовый фронт по окончанию проверки приема правильного бита:


Проверяем на допустимые интервалы бит:


//проверим, допустимая ли длительность высокого или низкого уровня
void	testlen(void)
{
	//сбросим признак что пришел правильный 0 или 1, перед разбором
	rxok=0;
        //по переднему положительному фронту, проверим интервал cnth и cntl
	//если интервал не выдержан, то все сбрасываем
	//при "1"
	//cnth принимает значения 28 +/-, cntl принимает значения 7 +/-
	//
	//при "0"
	//cnth принимает значения 11 +/-, cntl принимает значения 27 +/-
	//проверка на 1
	if(
	    //проверим на допустимые пределы значений
	    (cnth>(bodh - deltabod))&&
	    (cnth<(bodh + deltabod))&&	
	    (cntl>(bodl - deltabod))&&
	    (cntl<(bodl + deltabod))
	    )
	        {
		//надо записать как 1
		rxdata=rxdata<<1;	        //сдвинем влево
		rxdata=rxdata | 0x00000001;	//установим младший бит
		cntrxdata++;			//увеличим счетчик принятых бит
		rxok=1;				//признак что приняли верный бит
		}
		
	//проверка на 0
	if(
	    //проверим на допустимые пределы значений
	    (cnth>(bodl - deltabod))&&
	    (cnth<(bodl + deltabod))&&	
	    (cntl>(bodh - deltabod))&&
	    (cntl<(bodh + deltabod))
	    )
	        {
	        //надо записать как 0
	        rxdata=rxdata<<1;	        //сдвинем влево
		rxdata=rxdata & 0xfffffffe;	//обнулим младший бит
		cntrxdata++;	    	        //увеличим счетчик принятых бит
		rxok=1;				//признак что приняли верный бит
		}
				
		//проверим, сколько бит приняли, и занесем если все
		//пришли правильно	
		if(cntrxdata>=rxdatalen)
		{
		    //rfOut(1);
		    rxdataout=rxdata;	//запомним
		    cntrxdata=0;	//сбросим
		    rxfull=1;		//выставляем признак что приняли
		    lampon();           //управляем люстрой 
		    //rfOut(0);
		}

		//если  не приняли ни 0, ни 1
		if(rxok==0)
		    {
			rxdata=0;			//все сбрасываем
			cntrxdata=0;
			rxfull=0;
		    }
}



Тестовый фронт завершения принятия всех 25 бит:



И сама логика принятия решения в зависимости от принятой команды с пульта:

void	lampon(void)
{
        if(rxfull==1)	//если приняли весь пакет
	{
    	    switch(rxdataout)	//сравним и определимся что предпринять
		{
		    case acode:		//0xD053C0:
			key1off=0;	//сбросим таймер кнопки
			if(key1==0)	//если кнопка была до этого не нажата, и мы попали сюда
			    {
				key1=1;			//кнопка нажата
				if(rly1==0)	//если реле не включено, то
				{
				 rly1=1;	//включим его
				 LedR(1);
				}
				else
				{
				 rly1=0;	//а если иначе, выключим его
				 LedR(0);
				}
			    }					
			break ;
							
			case bcode:	//0xD05330:
			key2off=0;	//сбросим таймер кнопки
			if(key2==0)	//если кнопка была до этого не нажата, и мы попали сюда
			    {
				key2=1;			//кнопка нажата
				if(rly2==0)	//если реле не включено, то
			    	    {
					rly2=1;	//включим его
					LedG(1);
				    }
				    else
				    {
				        rly2=0;	//а если иначе, выключим его
					LedG(0);
				    }
			    }					
			break ;

			case ccode:	//0xD0530C:
			key3off=0;	//сбросим таймер кнопки
			if(key3==0)	//если кнопка была до этого не нажата, и мы попали сюда
    			    {
				key3=1;			//кнопка нажата
				if(rly3==0)	//если реле не включено, то
			            {
					rly3=1;	//включим его
					LedB(1);
				    }
				    else
				    {
					rly3=0;	//а если иначе, выключим его
					LedB(0);
				    }
				}					
			break ;
							
			case dcode:	//0xD05303:
			key4off=0;	//сбросим таймер кнопки
			if(key4==0)	//если кнопка была до этого не нажата, и мы попали сюда
			    {
				key4=1;			//кнопка нажата
				rly1=0;			//все выключаем
				rly2=0;
				rly3=0;
				LedR(0);
				LedG(0);
				LedB(0);
			    }					
		break ;
		
		default:
		    LedR(0);
		    LedG(0);
		    LedB(0);
		break ;
	    }
	//сбросим, раз все обработали	
	rxfull=0;
	}
}


Такие переменные были определены заранее:


uint32_t	rxdata	=0;		//приемный регистр для данных
uint32_t	rxdataout	=0;	//приемный регистр для данных
uint8_t		cntrxdata	=0;	//счетчик принятых бит
uint8_t		rxdatalen	=25-1;	//количество бит в сообщении	(последний фронт похоже контрольный)
uint8_t		rxok		=0;	//==1 если приняли бит
uint8_t		rxfull		=0;	//==1 если приняли всю последовательность
uint8_t		bodcnt		=36;	//количество отсчетов в бодовом интервале (36/4=9)
uint8_t		bodh		=27;	//количество отсчетов в длинном промежутке
uint8_t		bodl		=9;	//количество отсчетов в коротком промежутке
uint8_t		deltabod	=4;	//допустимая погрешность в длительности интервалов
uint8_t		cnth;			//переменная подсчета удержания сигнала в состоянии 1
uint8_t		cntl;			//переменная подсчета удержания сигнала в состоянии 0
uint8_t		rxpin;			//переменная состояния выхода приемника
uint8_t		oldrxpin;		//переменная предыдущего состояния выхода приемника

uint8_t		rly1=0;			//состояние реле 1
uint8_t		rly2=0;			//состояние реле 2
uint8_t		rly3=0;			//состояние реле 3

uint8_t		key1=0;			//состояние кнопки 1
uint8_t		key2=0;			//состояние кнопки 2
uint8_t		key3=0;			//состояние кнопки 3
uint8_t		key4=0;			//состояние кнопки 4

uint32_t	key1off=0;		//счетчик, =0 если кнопка нажата, и увеличивающийся если кнопка отпущена
uint32_t	key2off=0;		//счетчик, =0 если кнопка нажата, и увеличивающийся если кнопка отпущена
uint32_t	key3off=0;		//счетчик, =0 если кнопка нажата, и увеличивающийся если кнопка отпущена
uint32_t	key4off=0;		//счетчик, =0 если кнопка нажата, и увеличивающийся если кнопка отпущена

//коды кнопок для сравнения
#define	acode	0xD053C0
#define	bcode	0xD05330
#define	ccode	0xD0530C
#define	dcode	0xD05303
//количество циклов прерывания,
//за которое считается что кнопка отпущена
#define	KEYTIME	18000


Проверяем, упаковываем и сдаем заказчику:



Извиняюсь за качество картинок, немного провокационно, чуть лишнего, но это для общего развития. Если что надо поправить или изменить — пишите.
Файлы в топике: DipTrace Schematic - 433rxtx.zip

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

RSS свернуть / развернуть
Перенес в Радио.
0
На будущее: Вы бы смотрели список блогов, да выбирали более тематичный. То что это из автосигнализаций не делает пост о автоэлектрике, т.к. речь про передающие тракты, а они могут быть где угодно. Так что в Радио.
0
Согласен :)
0
Схемы слишком мелкие. Сделай их кликабельными. Полноразмерные можно положить в аттачи (до трех файлов, ЕМНИП, так что выбирай представляющие наибольший интерес).
0
  • avatar
  • Vga
  • 03 марта 2016, 08:49
А если не секрет, что за книжка по радиовзрывателям? =)
0
Руководство службы Радиовзрыватель АР-30 (1962)
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.