Автосигнализация постоянно срабатывает от помех

Обсуждаем приемники, передатчики, радиомикрофоны, жучки, генераторы, ВЧ-усилители, антенны и прочее радиохозяйство
Аватара пользователя
Nerevarine1810
Родился
Сообщения: 14
Зарегистрирован: Пн апр 20, 2015 20:22:26
Откуда: Великий Новгород

Re: Автосигнализация постоянно срабатывает от помех

Сообщение Nerevarine1810 »

Перевел код брелка в двоичный вид (100 бит). На досуге накидал что мог. Естественно, в отладчике работает отлично. В железе пока что тоже нет особых претензий, за 5 минут теста такая картина: сигналка рядом "буянит" релюшками, а светодиод не горит, значит не будет пропускать к декодеру. Нажимаю на пульт - загорается светодиод. Все как и планировалось. Пока МК подсоединил параллельно к DATA. Надо будет потестить и поиграть со значениями в первом FOR (где несколько проверок на ноль), чтобы пульт срабатывал стабильно (сейчас то с первого раза, то с пятого). Опять же, наверняка есть более эффективный способ, но и так работает. Код сырой, надо немного улучшить + добавить коды брелков. Тут даже не придется сравнивать 2-3 раза, вместо этого длинная проверка нулевого уровня в начале.
Спойлер

Код: Выделить всё

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

unsigned char massiv[101];		// Принимаемый массив кода брелка
unsigned char i_massiv = 0;		// Его индекс

int main(void) {
/*	Задействую порт B, прием сигнала на вывод 7
	Индикация окончания приема вывод 0
	(на нем будет светодиод через резистор).
	Остальные порты на вход + подтягивающий резистор
	против наводок
*/
	DDRB &= 0;
	DDRB |= (1<<0);
	PORTB |= 0b11111111;
	PORTB &= ~(1<<7);
	PORTB &= ~(1<<0);

	for (int i = 0; i < 101; i++) {					// Запись массива левыми числами
	massiv[i_massiv] = i_massiv;
	i_massiv++;
	}

	i_massiv = 0;

    while (1) {
		if (PINB == 0b01111110) {					// Проверка нуля на 7 ножке
			for (int i = 0; i < 9; i++) {			// Проверяем 9 раз по 800мкс = 720мкс (10мс разрыв между кодами)
				if (PINB == 0b11111110) break;		// Если '1', то прервать проверку
				_delay_us(800);
				if (i == 8) i_massiv = 1;			// Если успешно, условный переход на запись данных в массив
			}
			
			if (i_massiv == 1) {					// Сам условный переход
				i_massiv = 0;
				while (PINB != 0b01111110);			// Ждем первой '1' (оставшаяся время до кода)
				_delay_us(170);						// Задержка в пол импульса
				for (int i = 0; i < 101; i++) {		// Запись данных в массив
					massiv[i] = PINB>>7;
					_delay_us(340);
				}
			}
		}
		if (massiv[97] == 1) PORTB |= (1<<0);		// Собственно, записался ли код ('1' точно должна быть на 97 месте моего кода)
		//if (massiv[97] == 0) PORTB |= (1<<0);		// Проверка общая, вообще ли записывает что то в массив (0 или 1)
    }
	return 0;
}
И да, "unsigned char i_massiv" выкину вообще, он не нужен, тот переход условный во внутрь цикла проверки нуля помещу. Так же избавлюсь от проверок PIN всех ненужных портов. Ну это все ближе к воскресению))
Ну в простейшем случае - подаём на вывод INT
Хотел сначала, но будет куча прерываний ложных + еще счетчик задействовать. И как эти "кривые" импульсы определить? Думаю, сложнее получилось бы)) А тут простая логика, проще. А что проще - то надежнее :) А UART - насколько помню нужна скорость для него. 1/длит импульса = 2900 бит/с. Ближайшая стандартная 2400 бод. А хотя же там можно регистрами любую выставить. Да, как вариант. Но тут как - сначала надо полностью принять байт, сравнить его и только потом вынести вердикт, записывать все дальше или заново проверять первый байт.

Пока дописывал сообщение, обнаружил баг у себя (светодиодик загорелся). Оказывается, к ночи эфир очищается и уровень 0 стоит достаточно долго. Вот и срабатывает. Получается, что проверка на 0 проходит и идет запись в массив. Надо добавить дальше одну проверку на первые импульсы. Да и хотя, когда добавлю код брелка, он не совпадет с записанным массивом, поэтому не особо и баг получается) Но чтобы лишний раз массив не записывался добавлю проверку.

И да, поле деятельности (пока что камень Atmega8A). То, что конденсатор мятый - знаю. Китайцы таким прислали :))
СпойлерИзображение
...the best or nothing...
Реклама
roman.com
Друг Кота
Сообщения: 9149
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Автосигнализация постоянно срабатывает от помех

Сообщение roman.com »

Ну в целом всё верно)) Один момент - на МК надо поставить кварц. Иначе при изменении температуры (зимой-летом) частота выборок (семплов) будет не совпадать с частотой импульсов пульта.. Уже проходили..))

В простом UART есть логика обнаружения ложного старт-бита. В даташите так и написано:
1- в исходном состоянии - на входе UART высокий уровень.
2- при появлении низкого уровня включается логика обнаружения старт-бита. МК проверяет (по семплам) действительно ли это старт-бит (или просто помеха).
3- если старт-бит не обнаружен (т.е. помеха), возвращаемся к пункту 1.
4- после обнаружения действительного старт-бита включается логика обнаружения последующих битов и записи последующих битов в буфер приёмника (в нашем случае запись в массив).
...
Но определение по одному биту - это малоэффективно.

Поэтому обычно для синхронизации используют не один бит, а синхро байт. МК начинает запись в буфер приёмника (в нашем случае запись в массив), после того как найдёт синхробайт... или несколько синхробайт. По этому принципу работают практически все радиомодули. При этом ошибок меньше)) Как пишут в даташитах: буфер приёмника (в нашем случае запись в массив) не заполняется шумом.

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

Жаль что код - не манчестер)) Я обычно использую манчестер... тоже по семплам, только я семплы считаю иначе (манчестер это позволяет). У меня МК работает с шумами))
3.jpg
(193.23 КБ) 597 скачиваний
Короче.. всё ясно. Осталось дописать и оптимизировать код. ))
:tea:
Реклама
Аватара пользователя
Nerevarine1810
Родился
Сообщения: 14
Зарегистрирован: Пн апр 20, 2015 20:22:26
Откуда: Великий Новгород

Re: Автосигнализация постоянно срабатывает от помех

Сообщение Nerevarine1810 »

Оптимизировал я, конечно, по полной :)))
А кстати... пульт у нас с кварцем?
Да, с кварцем) Сегодня убил немало времени на связь пульта с МК - черт пойми что происходит. Видимо косяк с алгоритмом. Это на чем застрял. Код был похож принимаемый на теоретический, но всегда где-то появлялась помеха и битики пропадали нужные. Код для интереса, отладочный типа. Запись в EPPROM для анализа. Синхронизация такова - ищем длительность 10мс низкого уровня, потом ждем переход из 0 в 1. Сразу же задержка в пол импульса и считывание всех импульсов через их длительность.
Спойлер

Код: Выделить всё

volatile unsigned long long massiv_L = 0;		// Принимаемый массив кода брелка
volatile unsigned long long massiv_H = 0;

volatile unsigned long long OFF_L = 0xEEE88888EEE88E88; // EE E8 88 88 EE E8 8E 88
volatile unsigned long long OFF_H = 0x0000000EEEE8EE8E; // 00 00 00 0E EE E8 EE 8E


while (1) {
	if (!(PINB & (1<<7))) {							// Проверка нуля на 7 ножке
		for (i = 0; i < 78; i++) {					// Проверяем 9 раз по 800мкс = 720мкс (10мс разрыв между кодами)
			if (PINB & (1<<7)) break;				// Если '1', то прервать проверку
			_delay_us(125);
			if (i == 77) {							// Если успешно, условный переход на запись данных в массив
				while (!(PINB & (1<<7)));			// Ждем первой '1' (оставшаяся время до кода)
				_delay_us(177);						// Задержка в половину импульса
				for (i = 0; i < 101; i++) {			// Запись данных в массив
					if (i > 35) {
						massiv_L = massiv_L << 1;
						massiv_L |= (PINB>>7)<<0;
						_delay_us(355);
					}
					else {
						massiv_H = massiv_H << 1;
						massiv_H |= (PINB>>7)<<0;
						_delay_us(355);
					}
				}
				i = 8;
				
				eeprom_write_dword(&DATA1, (massiv_L>>32));
				eeprom_write_dword(&DATA2, massiv_L>>16);
				
				
				//if ((massiv_H == OFF_H) || (massiv_L == OFF_L)) PORTB |= (1<<0);
				
				//eeprom_write_dword(&DATA2_L, massiv_H>>4);
				//eeprom_write_dword(&DATA2_H, massiv_H<<4);
				
				PORTB |= (1<<0);
				//massiv_H = OFF_H; massiv_L = OFF_H;
				//if ((massiv_H == OFF_H) && (massiv_L == OFF_L)) eeprom_write_dword(&DATA_L, massiv_H);
				_delay_ms(500);
				PORTB &= ~(1<<0);
			}
		}
	}
}
*/
После долгих размышлений пришла мысль все в край упростить - проблема же с шумами? Так и надо чтобы их не было и все. Реализация на транзисторном ключе, управляемым МК (опять же четко отслеживаем интервал 10мс между последовательностями импульсов, и если этот интервал соблюдается - открыть транзистор). Через транзистор данные из DATA попадут на штатный МК, в момент передачи помех нет. А при помехах он будет закрыт (тестил день - не было срабатываний). А если эфир будет чист, то и транзистор будет всегда включен. Вот что получилось, для ATtiny13A:
Спойлер

Код: Выделить всё

#define F_CPU 1000000

#include <avr/io.h>
#include <util/delay.h>

int main (void) {
	DDRB |= (1<<0);					// Задействую порт B, прием сигнала на вывод 7
	PORTB &= ~((1<<5) | (1<<0));	// Вывод 0 на транзисторный ключ

    while (1) {
		if (!(PINB & (1<<5))) {				// Проверка нуля на 7 ножке
			for (char i = 0; i < 80; i++) {	// Проверяем 78 раз по 125мкс = 9,75мс (10мс разрыв между кодами)
				if (PINB & (1<<7)) break;	// Если '1', то прервать проверку
				_delay_us(125);
				if (i == 79) {				// Если успешно, условный переход на запись данных в массив
					PORTB |= (1<<0);		// Открыть транзистор
					_delay_ms(300);			// Время нескольких кодов брелка
					PORTB &= ~(1<<0);		// Закрыть транзистор
				}
			}
		}
	}
	return 0;
}
Наверно до этого дошел из-за усталости. В этом решении даже кварц не нужен.

А Ваши идеи хороши, для серьезных проектов такие и следует использовать. Буду иметь ввиду. Завтра куплю МК и в пт наверно все соберу. Выходные потестить надо будет и к пн поставлю обратно на авто. Пока такие планы :)
...the best or nothing...
roman.com
Друг Кота
Сообщения: 9149
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Автосигнализация постоянно срабатывает от помех

Сообщение roman.com »

Идею проверять каждый импульс только один раз можно использовать в самодельном ИК пульте или когда сигнал идёт по проводам, да ещё в экранированном кабеле и только на небольшое расстояние)). При передачи кодов с помощью ИК пультов шумов нет. На выходе фотоприёмника (TSOP) никаких шумов нет.
С радио каналом этот номер не прокатит)) Потому, что у нормального радиприёмника всегда на выходе есть шумы. Поэтому проверять только один раз каждый импульс - не эффективно. На эти "грабли" многие уже наступали, когда пытались использовать простые алгоритмы при передачи по радиоканалу)) Вот почему все современные радио модули проверяют много раз каждый импульс. Тогда всё работает чётко)). :tea:
Nerevarine1810 писал(а):Синхронизация такова - ищем длительность 10мс низкого уровня, потом ждем переход из 0 в 1. Сразу же задержка в пол импульса и считывание всех импульсов через их длительность.
для интерса сделал то же самое в протеусе))
Синхронизация такова - ищем длительность 4мс высокого уровня, потом ждем переход из 1 в 0 - старт бит. После этого считывание всех семплов в массив, с задержками через таймер (таймер тактируется от кварца, поэтому все задержки получаем с кварцевой точностью). Всё работает))
2.jpg
(59.02 КБ) 378 скачиваний
Причём сами импульсы могут быть "ломанные" и даже с шумами (в разумных пределах конечно)... Всё равно МК находит синхро...))
Всё работает))
3.jpg
(58.4 КБ) 594 скачивания
Nerevarine1810 писал(а):Реализация на транзисторном ключе
Ну можно и так... Теоретически можно и без ключа)). Сигнал с приёмника (DATA) МК пропускает через себя...

Примерно так:
1- МК ищет синхро. При этом выход МК отключен. PORTB.0=0;
2- МК находит синхро. При этом выход МК отключен. PORTB.0=0;
3- МК ждёт старт-бит (1). while(PORTB.7==0); При этом выход МК отключен. PORTB.0=0;
4- МК находит страрт-бит (1). МК переходит в режим повторителя. PORTB.0=PORTB.7; Сигнал с приёмника (DATA) проходит на штатный декодер.

А вообще... я бы наверное просто разбил весь код на семплы и записал в массив семплы. Всего кодов в пульте не много.. массив будет маленький))
Т.е. по сути я бы просто "оцифровал" весь код пульта и хранил бы "цифровую копию" в EPPROM для анализа. В этом случае ни одна помеха мимо нас не проскочит! )) :))) Например вот так:
1.jpg
(105.68 КБ) 204 скачивания
:tea:
У нас код 40 мс. Разбиваем заждый импульс например на 8 семплов (или больше). Получаем 320 семплов.

Далее... супер мощный алгоритм))) :)))

Кратко:
1- ждём первый импульс (например переход от 0 к 1). while(PORTB.7==0);
2- задежка по таймеру... сравниваем семпл №0 с массивом №0. Если не совпадает, то переходим к пункту 1.
if (PORTB.7 != x[0]; ) {goto mesto_1;};
3- задежка по таймеру... сравниваем семпл №1 с массивом №1. Если не совпадает, то переходим к пункту 1.
if (PORTB.7 != x[1]; ) {goto mesto_1;};
...
...
...
320- задежка по таймеру... сравниваем семпл №320 с массивом №320. Если не совпадает, то переходим к пункту 1.
if (PORTB.7 != x[320]; ) {goto mesto_1;};

Если все принятые сепмлы совпали, то МК выдаёт на выводе PORTB.0 копию принятого кода.

Если в ходе проверки хоть один семпл не совпал... то начинаем всё сначала))
код ошибка.png
(34.57 КБ) 380 скачиваний
Короче... никаких синхронизаций не нужно.)) Оцифровываем и проверяем все импульсы "на ходу" ...))
Ну прям сигнальный процессор получается )) :)))

Это простой линейный алгоритм. Если кодов несколько, то получим ветвящийся алгоритм. Для оптимизации алгоритма можно использовать FOR и всякие подпрограммы... ))

Один недостаток... этот алгоритм работает только при хорошем сигнале (без шумов). Это ограничивает максимальный радиус действия пульта, но зато всё супер надёжно))
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Nerevarine1810
Родился
Сообщения: 14
Зарегистрирован: Пн апр 20, 2015 20:22:26
Откуда: Великий Новгород

Re: Автосигнализация постоянно срабатывает от помех

Сообщение Nerevarine1810 »

Сигнал с приёмника (DATA) МК пропускает через себя...
Точно, вот вообще все упростили, остался МК и малюсенький нехитрый код)
для интереса сделал то же самое в протеусе)) ... Всё работает))
Так вот, теоретически да. Видать, временные издержки не совпали, использовал библиотечную функцию, может надо было счетчик...
по сути я бы просто "оцифровал" весь код пульта и хранил бы "цифровую копию"
А вот это уже хорошая идея) Только я вот решил избавится от массива, так как один символ (0 или 1) занимает минимум байт памяти МК. В моем алгоритме ушло бы пол килобайта на 4 кода брелка :shock: . Расточительство) Поэтому поступил так: задал переменную long long, это и получился массив из 64 бит (теперь одно значение занимает один бит, у нас то двоичный код). Возможно, где то косяк из-за этого, с битовыми сдвигами или масками... Не знаю в общем.
Ну прям сигнальный процессор получается ))
Да да)) Есть второй блок, первый пока по простому сделаю, чтобы работал, а не дома валялся. А со вторым можно будет поэкспериментировать позже, в любое свободное время)
...the best or nothing...
Реклама
roman.com
Друг Кота
Сообщения: 9149
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Автосигнализация постоянно срабатывает от помех

Сообщение roman.com »

Nerevarine1810 писал(а):со вторым можно будет поэкспериментировать позже, в любое свободное время
Ничего нового мы не изобрели)) По этому принципу работает цифровой осциилограф..))

Вот например так выглядит сигнал приёмника (DATA) на простом аналоговом осциллографе:
3.jpg
(13.26 КБ) 401 скачивание
Цифровой осциллограф "оцифровывает" сигнал приёмника:
1.jpeg
(29.83 КБ) 383 скачивания
На экране цифрового осциллографа мы видим "цифровую копию" этого сигнала, с частотой дискретизации (семплов) 100 кГц:
5.jpg
(94.81 КБ) 406 скачиваний
Я просто предложит использовать этот же принцип для обработки сигнала на МК... Вот и всё)) Разница только в том, что по сравнению с цифровым осциллографом, у МК меньше тактовая частота, меньше память и соответственно меньше скорость обработки сигнала. Поэтому мы просто уменьшили частоту семплов для МК))
Nerevarine1810 писал(а):Видать, временные издержки не совпали, использовал библиотечную функцию, может надо было счетчик...
Для обработки сигнала важно точно выдерживать временные интервалы:
2.jpg
(234.86 КБ) 390 скачиваний
Для этого лучше использовать таймеры/счётчики. Тут на сайте даже статейка есть.. так сказать "для начинающих" )) ...
http://radiokot.ru/circuit/digital/game/65/
Там показали как лучше делать семплы:
4.jpg
(154.31 КБ) 388 скачиваний
Только, повторяю, онин семп на один бит - для радиоканала этого мало. Надо минимум 8...16. А вообще, чем больше семплов, тем лучше)) Количество семплов ограничена только вычислительной возможностью МК. ))
Nerevarine1810 писал(а):решил избавится от массива, так как один символ (0 или 1) занимает минимум байт памяти МК. В моем алгоритме ушло бы пол килобайта на 4 кода брелка
Eсли верить даташиту, то например у ATmega8 память... цитата из даташита: "8 Кбайт внутрисистемно программируемой Flash памяти"
Т.е. на четыре кода пульта хватит)) :))) Если МК больше ничем заниматься не будет... поэтому какая разниза сколько мы заняли памяти))
Хотя, я обычно использую в своих программах битовые операции. Да, я обычно записываю данные в переменные, побитно.))
Реклама
Аватара пользователя
Nerevarine1810
Родился
Сообщения: 14
Зарегистрирован: Пн апр 20, 2015 20:22:26
Откуда: Великий Новгород

Re: Автосигнализация постоянно срабатывает от помех

Сообщение Nerevarine1810 »

Для этого лучше использовать таймеры/счётчики
За идею благодарность приношу :) Раньше никогда им не пользовался, поэтому в расчет и не брал. Теперь же знаю, что это надежный и точный вариант подсчета времени (особенно очень мизерного). На будущее пригодится)
например у ATmega8
Камень этот только для опыта) В конечном случае все на ATtiny13 соберу (Мегу8 жалко для такой цели ничтожной :))) ), у него уже 1кб флеша и вроде 512 байт оперативки (а массивы я в оперативке определял, вот и хватало бы только-только). Да и плюс ко всему проги на СИ много больше памяти занимают, чем на асме)
Ничего нового мы не изобрели))
Зато обобщили все уже известное, "разжевали" так сказать)
...the best or nothing...
Аватара пользователя
Nerevarine1810
Родился
Сообщения: 14
Зарегистрирован: Пн апр 20, 2015 20:22:26
Откуда: Великий Новгород

Re: Автосигнализация постоянно срабатывает от помех

Сообщение Nerevarine1810 »

В общем все сделал) Attiny не прошить моим USBisp и решил использовать Мегу8. Жалко было ее пустую использовать, так прикрутил DS18B20 и сдвоенный семисегментный индикатор. Все прилагается, в архиве файлы проектов для AVRStudio 7 и Proteus 8.3. Код дублирую сюда)
Спойлер

Код: Выделить всё

#define F_CPU 1000000UL

#define DQ_IN  DDRB &= ~(1<<7)
#define DQ_OUT DDRB |= (1<<7)
#define S_DQ   PORTB |= (1<<7)
#define C_DQ   PORTB &= ~(1<<7)
#define DQ     PINB & (1<<7)

#include <avr/io.h>
#include <util/delay.h>

void init_ds18b20(void);			// Инициализация
unsigned char readbyte(void);		// Прочитать байт
void writecommand(unsigned char);	// Отправить байт
unsigned char readtemp(void);		// Функция получения температуры в десятичном виде
void Clear ();						// Высокий уровень на всех используемых выводах
void Vivod();						// Вывод на сдвоенный семисегментик
void Signal();						// Выдача сигнала со входа на декодер

/////////////////////////////////////////////////////////////////////////////////////////
void send_H0 () {
	PORTD &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5));
}
void send_H1 () {
	PORTD &= ~((1<<1) | (1<<2));
}
void send_H2 () {
	PORTD &= ~((1<<0) | (1<<1) | (1<<3) | (1<<4) | (1<<6));
}
void send_H3 () {
	PORTD &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6));
}
void send_H4 () {
	PORTD &= ~((1<<1) | (1<<2) | (1<<5) | (1<<6));
}
void send_H5 () {
	PORTD &= ~((1<<0) | (1<<2) | (1<<3) | (1<<5) | (1<<6));
}
void send_H6 () {
	PORTD &= ~((1<<0) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6));
}
void send_H7 () {
	PORTD &= ~((1<<0) | (1<<1) | (1<<2));
}
void send_H8 () {
	PORTD &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6));
}
void send_H9 () {
	PORTD &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | (1<<6));
}
void send_H () {
	PORTD &= ~(1<<7);
}
/////////////////////////////////////////////////////////////////////////////////////////
void send_L0 () {
	PORTC &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5));
}
void send_L1 () {
	PORTC &= ~((1<<1) | (1<<2));
}
void send_L2 () {
	PORTC &= ~((1<<0) | (1<<1) | (1<<3) | (1<<4));
	PORTB &= ~(1<<2);
}
void send_L3 () {
	PORTC &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3));
	PORTB &= ~(1<<2);
}
void send_L4 () {
	PORTC &= ~((1<<1) | (1<<2) | (1<<5));
	PORTB &= ~(1<<2);
}
void send_L5 () {
	PORTC &= ~((1<<0) | (1<<2) | (1<<3) | (1<<5));
	PORTB &= ~(1<<2);
}
void send_L6 () {
	PORTC &= ~((1<<0) | (1<<2) | (1<<3) | (1<<4) | (1<<5));
	PORTB &= ~(1<<2);
}
void send_L7 () {
	PORTC &= ~((1<<0) | (1<<1) | (1<<2));
}
void send_L8 () {
	PORTC &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5));
	PORTB &= ~(1<<2);
}
void send_L9 () {
	PORTC &= ~((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5));
	PORTB &= ~(1<<2);
}
void send_L () {
	PORTB &= ~(1<<1);
}
/////////////////////////////////////////////////////////////////////////////////////////

unsigned char des;
unsigned char temper;
unsigned char s;
unsigned int i;

int main(void)
{
	DDRB |= (1<<3) | (1<<2) | (1<<1); 
	DDRB &= ~(1<<0);					// Прием сигнала на вывод 0
	DDRC |= 0x3F;
	DDRD |= 0xFF;
	PORTB &= ~((1<<3) | (1<<0));		// Вывод сигнала на вывод 3
	volatile char u = 0;				// Вспомогательная переменная
	Clear();
	while(1)
	{
		if (PINB & (1<<4))				// Проверка ключа в замке зажигания (если вставлен ВКЛ термометр)
		{
			temper = readtemp();
			Clear();
			Vivod();
			u = 1;
		}
		
		for (unsigned long i = 0; i < 1000000; i++)	// Прием данных примерно 30 сек
		{
			Signal();

			if (!(PINB & (1<<4)))
			{
				Clear();
				u=0;
			}
			else
			{
				if (u == 0) break;
			}
		}
	}
	
	return 0;
}

void init_ds18b20(void)
{
	DQ_OUT;
	C_DQ ;
	_delay_us(600);
	S_DQ;
	_delay_us(50);
	DQ_IN;
	while(DQ);
	_delay_us(240);
	DQ_OUT;
	S_DQ;
	_delay_us(100);
}

unsigned char readbyte(void)
{
	unsigned char i = 0, data = 0;
	DQ_OUT;
	for (i=0; i<8; i++)
	{ C_DQ ;
		data >>= 1;
		_delay_us(3);
		S_DQ;
		DQ_IN;
		_delay_us(12);
		if(DQ)
		data |= 0x80;
		DQ_OUT;
		S_DQ;
		_delay_us(45);
		_delay_us(5);
	}
	return(data);
}

void writecommand(unsigned char data)
{
	unsigned char i;
	for(i=0; i<8; i++) {
		C_DQ;
		_delay_us(15);
		if(data & 0x01)
		S_DQ;
		else
		C_DQ;
		_delay_us(45);
		data >>= 1;
		S_DQ;
		_delay_us(2);
	}
}

unsigned char readtemp(void)
{
	unsigned char a, b, tt;
	init_ds18b20();
	// Convert
	writecommand(0xCC);
	writecommand(0x44);
	_delay_ms(800);
	init_ds18b20();
	// Read Scratch memory area
	writecommand(0xCC);
	writecommand(0xBE);
	a = readbyte();
	b = readbyte();
	init_ds18b20();

	des = 0;
	des = ((a & 0x0F) * 625) / 100;
	
	tt = 0;
	if (!(b>>7)) {
		// если положительная температура
		tt = ((b << 4) | (a >> 4));
	}
	else {
		// если отрицательная
		tt = ((b << 4) | (a >> 4));
		tt = (~tt + 1) & (0xFF);
		tt |= (1<<7);	// Обозначение минуса
	}
	
	if (des < 10)
	{
		if (des < 5) des = 0;
		else des = 1;
	}
	else
	{
		if ((tt & 0x80) == 0x80) 
		{
			tt &= ~(1<<7);
			if ((des % 10) < 5) des /= 10;
			else des = (des/10)+1;
			tt--; des = (10-des)%10;
			if (tt > 3)
			{
				if (des > 4) tt++;
			}
			tt |= (1<<7);
		}
		else
		{
			if ((des % 10) < 5) des /= 10;
			else des = (des/10)+1;
			if (tt > 3)
			{
				if (des > 4) tt++;
			}
		}
		
	}

	return(tt);
}

void Clear ()
{
	PORTB |= (1<<1) | (1<<2);
	PORTC |= 0x3F;
	PORTD |= 0xFF;
}

void Vivod()
{
	if ((temper & 0x80) == 0x80) {	// Если отрицательная T
		temper &= ~(1<<7);
		send_L();
	}
	
	if (((temper / 10) == 0) & ((temper % 10) < 4)) {
		send_H();
		
		switch (temper % 10) {
			case 1: send_H1 (); break;
			case 2: send_H2 (); break;
			case 3: send_H3 (); break;
			//case 4: send_H4 (); break;
			//case 5: send_H5 (); break;
			//case 6: send_H6 (); break;
			//case 7: send_H7 (); break;
			//case 8: send_H8 (); break;
			//case 9: send_H9 (); break;
			
			default: break;
		}

		switch (des) {
			case 1: send_L1 (); break;
			case 2: send_L2 (); break;
			case 3: send_L3 (); break;
			case 4: send_L4 (); break;
			case 5: send_L5 (); break;
			case 6: send_L6 (); break;
			case 7: send_L7 (); break;
			case 8: send_L8 (); break;
			case 9: send_L9 (); break;
			default: send_L0 (); break;
		}
	}
	else {
		switch (temper / 10) {
			case 1: send_H1 (); break;
			case 2: send_H2 (); break;
			case 3: send_H3 (); break;
			case 4: send_H4 (); break;
			case 5: send_H5 (); break;
			case 6: send_H6 (); break;
			case 7: send_H7 (); break;
			case 8: send_H8 (); break;
			case 9: send_H9 (); break;
			default: break;
		}

		switch (temper % 10) {
			case 1: send_L1 (); break;
			case 2: send_L2 (); break;
			case 3: send_L3 (); break;
			case 4: send_L4 (); break;
			case 5: send_L5 (); break;
			case 6: send_L6 (); break;
			case 7: send_L7 (); break;
			case 8: send_L8 (); break;
			case 9: send_L9 (); break;
			default: send_L0 (); break;
		}
	}
}

void Signal()
{
	do
	{
		if (!(PINB & (1<<0)))						// Проверка нуля на 0 ножке
		{
			for (i = 0; i < 21; i++)				// Проверяем 85 раз по 125мкс (11мс разрыв между кодами)
			{
				if (PINB & (1<<0))					// Если попалась 1, то прервать и подать 0
				{
					PORTB &= ~(1<<3);
					break;
				}
				_delay_us(500);

				if (i == 20)
				{
					_delay_ms(36);					// Пропустить импульсы одного кода
					for (i = 0; i < 99; i++)		// Вторая проверка нулей
					{
						if (PINB & (1<<0))
						{
							PORTB &= ~(1<<3);
							break;
						}
						_delay_us(100);
					}								// Конец второй проверки нулей
					
					for (i = 0; i < 2500; i++)		// Копирование входа на выход
					{
						s = (PINB & 0x01);
						if ((s % 2) == 1) PORTB |= (1<<3);
						else PORTB &= ~(1<<3);
					}
					PORTB &= ~(1<<3);
					break;							// Отправили код и выходим
				}
			}
		}
		break;
	} while (1);
}
Вложения
Projects.zip
Архив проектов
(109.4 КБ) 132 скачивания
Безымянный.jpg
Схема в Протеусе
(252.65 КБ) 417 скачиваний
22.jpg
Осциллограмма сигнала пульта ДУ
(130.55 КБ) 405 скачиваний
11.jpg
Осциллограмма шума
(102.36 КБ) 412 скачиваний
...the best or nothing...
roman.com
Друг Кота
Сообщения: 9149
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Автосигнализация постоянно срабатывает от помех

Сообщение roman.com »

Пойдёт))

датчик... https://masterkit.ru/zip/ds18b20-rus.pdf

можно ещё что-нить повесить на МК)) Что бы не пустую использовать..))
Ответить

Вернуться в «Радиотехника: приемники, передатчики, антенны»