LINUX.ORG.RU

Банальный алгоритм последовательного чтения

 , , ,


0

2

Здравствуйте!

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

Так вот: в качестве опытного образца я взял брэдборду, atmega8, кварц 7372800 Гц, PC3388(приёмник, который работает хорошо - я мультиметром протыкал и с порта меги уже принял его данные).

//Здесь еще все хорошо.

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

/* IR Reciever OUTPUT -> MCU PB0
   LED on PB1
*/
for(;;){
	status = (PINB & 0b00000001);
	status ^= 0b00000001;
	if(status == 0b00000001){
		PORTB |= 0b00000010;
	} else {
		PORTB &= 0b00000001;
	}
}
Здесь все работает - обычный диод мигает аналогично ИК, но и мозг остановился. Как примерно запихать в минимальный массив эти мигания, чтобы затем выделить из него коды кнопок, код пульта, и так далее? Наверняка более умные товарищи решали проблемы последовательной передачи данных и обошли грабли, которые я себе тут подложил.

Спасибо!

★★★★★

Да, кастую Eddy_Em.

Проблема в том, что у меня целая куча данных приходит, я сравниваю уровни, которые скачут как бешеные, обрубаю счетчик при логическом нуле на пине(второй сигнал), а в итоге получаю бяку в виде ~300 итераций на ~100мс

minakov ★★★★★ ()
Ответ на: комментарий от Dron

Это я как понимаю не бяка

В моём случае - это бяка, которую нужно от плевел почистить.

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

minakov ★★★★★ ()

Лол, слишком сложная задача, ИМХО. Я со своего развалившегося пульта от телика намерил сигналы осциллографом и запихал в массив (автоматом). А потом запал угас и до железной реализации я так и не дошел.

hvatitbanit ()
Ответ на: комментарий от hvatitbanit

Лол, слишком сложная задача, ИМХО.

Вот смотри, у тебя на одну единицу предложения - 11 лишних символов. А у меня задача всего лишь чуть более сложнее. Разбирайся со сленгом, потом подключайся в построение алгоритма для считывания.

//Дополнение: если 7372800 поделить на поднесущую 38400, получается 192. Направление правильное, или я так все пропущу в последовательности?

minakov ★★★★★ ()
Ответ на: комментарий от minakov

Ты какой-то фигней занимаешься! Вешай прерывания по таймеру. А еще лучше — используй UART в режиме IR. Даже такая халява, как STM8, это умеет делать!

В общем — марш читать даташит!

Eddy_Em ☆☆☆☆☆ ()

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

если совсем-совсем лень реализовывать протокол, то складываешь биты последовательно в кольцевой буфер размером 2*макс размер блока. По каким-то своим эмпирическим правилам решаешь когда-же пора искать разные коды. Алгоритм поиска последнего вхождения заданных строк в другой строке наверное вам известен.

Повторяеш пока в буфере гипотетически может помещаться хотя-бы один блок. Чтоб облегчить поиск - можешь не экономит память и расширить биты до байтов

MKuznetsov ★★★★★ ()

Приходится самому все делать!

//Ужасы нашего городка
	if(status == 0b00000001){
		for(ltemp = 0;ltemp <= 512;ltemp++){
			status = (PINB & 0b00000001);
			status ^= 0b00000001;
			buffer[ltemp] = status+0x30;
			_delay_us(150); //192 good!
		}
		SendStr(buffer);
		SendByte(0x0A);
	}
Шлёт практически адекватные
#SAMSUNG AA59-00603A "POWER_BTN"
11111111111111111111111111111100000000000000000000000000001111000000000011110
00000000011110000000000111100011110001111000111110001111000111100000000001111
00000000001111000000000011110001111000111110001111000111100011110001111000000
00001111000111100011110001111000111100001111000111100000000001111000111100000
00000111100000000001111000000000001111000000000011110000000000111100000000001
11100000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000
Но это не все - чувствую, что всё это хреново реализовано, хотя вижу за что зацепиться для результата

minakov ★★★★★ ()

теорема про 2 раза решит твои проблемы

visual ★★★ ()
Ответ на: комментарий от Eddy_Em

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

minakov ★★★★★ ()
Ответ на: комментарий от MKuznetsov

Почти так и сделал - для наколенного дебага сойдёт, а потом буду Эдварда слушать

minakov ★★★★★ ()
Ответ на: комментарий от Dron

Ну дык там из кода только инициализация портов и uart(easyelectronics.ru) осталась, всё выше скопипастил сюда. Сишечка же позволяет экономить на простынях

minakov ★★★★★ ()
Ответ на: комментарий от minakov
#SAMSUNG AA59-00603A "POWER_BTN"
11111111111111111111111111111100000000000000000000000000001111000000000011110
00000000011110000000000111100011110001111000111110001111000111100000000001111
000000000011

это на входе. А что должно быть на выходе?

emulek ()
Ответ на: комментарий от emulek

То же самое, в обратной последовательности.

Dron ★★★★★ ()
Ответ на: комментарий от qbe

Вот если бы ты не сказал, что там именно эти коды, я бы мучался и не понял, что в апноате имелось в виду под краткой и длинной задержкой. А тут нарисовал полосочки после нулей, посчитал длину и все. Спасибо!

minakov ★★★★★ ()
Ответ на: комментарий от minakov

Или вообще - больше 6 '0' = единица, меньше = нуль. Ну крутяк!

minakov ★★★★★ ()
Ответ на: комментарий от Dron

Под атмегу стыдно давать - там еще ничего не готово. Вот тебе декодер с оверхедами:

#include <stdio.h>
#include <string.h>

char string[] = "111111111111111111111111111111000000000000000000000000000011110000000000111100000000001111000000000011110001111000111110011111000111100011110000000000111100000000001111000000000011110001111100111110001111000111100011110001111000000000011110001111000111100011111001111100011110001111000000000011110001111000000000011110000000000111100000000001111100000000001111000000000011110000000000111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
char array[32];
long temp;
int counter = 0, status = 0, counter2 = 0;

int main(int argc,char* argv[]){
	for(temp = 0;temp<=(sizeof(string))/(sizeof(char))-1;temp++){
		if(string[temp] == '1'){
			if(status == 0){
				fprintf(stderr, "[D] char: %d :: counter: %d :: status: %d \n", temp, counter, status);
				if(counter < 5 && counter > 1){
					array[counter2] = '0';
					counter2++;
				} else if(counter < 15 && counter >= 5){
					array[counter2] = '1';
					counter2++;
				}
				counter = 0; // RESET COUNTER
			}
			status = 1;
		} else {
			counter++;
			status = 0;
		}
	}
		fprintf(stderr, "%s\n", array);
return 0;
}

minakov ★★★★★ ()
Ответ на: комментарий от minakov

К тому же, атмега загнулась от непосильной задачи постоянного дергания массива из ~450 байт. В итоге - глюки и отсутствие адекватности(первое значение нормально обрабатывает, второе вроде начинает парсить, но выкидывает первое...). Придется оптимизировать

minakov ★★★★★ ()
Ответ на: комментарий от hvatitbanit

Сам ты лол. Все решено. Если тебя послушать, то вообще надо сидеть в бункере и ничего не трогать, "чтобы темочки не создавать".

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от hvatitbanit

Ололо, атмель — мало того, что говно мамонта, так еще и дорогое говно мамонта. И функционал у атмеля хреновый.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

А нафиг для такой задачи что-то навороченное? И говно или не говно - не знаю, не особо слежу, но работает (компилируется/прошивается) под фрёй/драгонфлаем и хрен бы с ним. А как ты решил проблему с stm? Венду поставил?

hvatitbanit ()
Ответ на: комментарий от hvatitbanit

А нафиг для такой задачи что-то навороченное?

Я уже говорил про STM8, которые (S003) стоят как транзистор какой-нибудь...

А как ты решил проблему с stm?

А ты не читал ту тему, которой меня тыкал? Элементарно решил: sdcc скомпилял. А STM32 поддерживается в gcc.

Венду поставил?

Ты со мной говоришь? Говоришь. Вот если бы я это говнище поставил, ты бы со мной уже не разговаривал, т.к. я бы "сделал вдоль".

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от hvatitbanit

Мегу берешь и не имеешь себе мозг

Может у тебя найдется пример работы с TWI/I2C для XMega? Я работал с I2C на обычных AVR, на Microblaze, на Linux/ARM - везде всё просто. А XMega засада какая-то, пока не осилил.

Так что с мегами тоже не всё просто, это миф что 8-мибитники от атмел самые простые. Вот Xmega та ещё мозголомня.

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

Может у тебя найдется пример работы с TWI/I2C для XMega?

Увы, нет.

Xmega та ещё мозголомня

А то! А я ещё сдуру купил какой-то development board на ней и на какой-то at*usb. И ниасилил.

hvatitbanit ()
Ответ на: комментарий от minakov

Ребяты, у меня правда мозг заплыл от таймеров. Поясните пожалуйста!

То, что я примерно понял при частоте 7372800 Герц (поправьте, если неправ):

У 8 атмеги есть три счетчика, два из которых считают до 255 с нуля, потом генерируют прерывание на регистре каком-то там, который можно прочитать, и узнать, что случился новый такт с частотой 7372800/255 = 28,8 кГц, а один - считает до 65535, т.е. генерирует прерывание 7372800/65535 ≈ 112,5 раз в секунду, или раз в 0,0089 сек, или 112,5 Гц. У пульта несущая частота 37,9кГц, а у атмеги еще есть прескалер, которым можно туда-сюда баловаться с частотой. Вот на этом мои познания окончились и я не могу сообразить, в какую сторону двигать эти регистры, счетчики... Есть у кого время примерно описать работу этой железяки в плане таймеров, чтобы сварщик понял? Спасибо!

// pbx-call Eddy_Em, I-Love-Microsoft, ip, false, Dron

minakov ★★★★★ ()
Ответ на: комментарий от minakov

Так, лучше приглашу более компетентного чем я.

DDRD = 0xff; PORT ncrmnt|= _BV(PD0);

Dron ★★★★★ ()
Ответ на: комментарий от minakov

Делитель емнип 1, 256, 1024 или типа того.

Прервание, емнип, можно не только по переполнению, но и по сравнению сделать.

false ★★★★★ ()
Ответ на: комментарий от minakov

Во-первых см. режимы таймера в шит-о-дате. TOP не всегда 0xff, может быть и ICR1, например. Потому прескейлер + макс значение счета можно настроить на любой в принципе период с хорошей точностью.

ncrmnt ★★★★★ ()
Ответ на: комментарий от Dron

F_CPU это константа, которая говорит макросам типа _delay_ms на какой частоте работает камень, не более. Источник тактирования выставляется фьюзами, а дальше все зависит откуда тактируемся.

ncrmnt ★★★★★ ()
Последнее исправление: ncrmnt (всего исправлений: 1)
Ответ на: комментарий от Dron

Некромант выше ответил :) А подробнее в даташите где-то есть.

false ★★★★★ ()
Ответ на: комментарий от minakov

Ну ты, итить-колотить, догадался, кого призвать на решение проблем этих древних МК!

Меня исключи из списка, т.к. я никогда с атмелями не работал, и не собираюсь работать! Есть более приличные МК.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от ncrmnt

Во блин. Спасибо, просветил. Вникать ещё мне и вникать.

Dron ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.