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;
	}
}
Здесь все работает - обычный диод мигает аналогично ИК, но и мозг остановился. Как примерно запихать в минимальный массив эти мигания, чтобы затем выделить из него коды кнопок, код пульта, и так далее? Наверняка более умные товарищи решали проблемы последовательной передачи данных и обошли грабли, которые я себе тут подложил.

Спасибо!

★★★★★

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

А вообще, конечно, по задаче надо МК выбирать, если только у тебя нет россыпи халявных STM32F429. Тогда, ясен пень, на них можно такого навертеть...

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

Для новичков лучше AVR ничего не придумали. Ибо там регистровая карта простая и документация не содержит «STшного Элитарного упоризма(tm)».

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

Регистровая карта проста у PIC'ов. Вот там — благодать... Только стенки у этой благодати дюжеть близко, и потолок дюжеть низкий...

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

Кстати, а что значит "элитарный упоризм"? Ты про бесконечные errata? Или про их тонкий расчет на то, что читающий даташит будет читать твердую копию, имея кучу закладок?

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

PIC'и при мне не упоминай. Я тут как раз методичку про Microchip PIC32 пишу и думаю, как бы потоньше сказать чтобы студенты поняли «держитесь от микрочиповского говна подальше», и в тоже время все остальные подумали, что я отлично рекламирую PIC32.

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

Тебе за это микрочип платит? ☺

Дал PDF-ку, сказал RTFM - там все есть, и все написано понятно.

Ну, ХЗ. Я почему перешел на STM32: у меня ж было пару лет назад такое, что надо было решать, на основе чего делать систему управления. Я вроде как даже здесь по этому поводу засветился... Там почитал, сям почитал, и понял, что AVR — говно, а STM32 намного лучше (как в плане набортных возможностей, так и в плане цены). Вот так и получился из меня хаяльщих атмелей (при том, что я атмели ни разу в жизни не программировал).

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

Тебе за это микрочип платит? ☺

MIPS Technologies и Microchip отгрузили нам на кафедру хорошие, годные макеты. Хоть есть на чем студентов мучить, вместо двух с половиной НИИСИшных плат с багетом.

что AVR — говно, а STM32 намного лучше

Bullshit! Любой мк хорош для своих целей! Я привык выбирать мк под задачу, а не прилипать к какой-то одной серии. Под какую железку на С кодить мне давно пофиг.

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

Я даже не пытаюсь их запоминать. Все равно история рано или поздно отправит эти камни на свалку и сделает эти знания пустыми.

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

возьми осциллограф и смотри какую частоту получаешь и генерируешь - путем нехитрых изменений доведешь частоту до нужной

т.е. эмпирическим путем если лень считать

I-Love-Microsoft ★★★★★
()

Шо за хрень вы тут развели, уважаемые? Таймеры с запуском от прерывания по изменению уровня спасут отца русской демократии. Задача миллион раз разжеванная уже.

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

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

Слямзил, проверил, слегка переделав под атмегу8. На 7372800 в таком виде настроить не выходит - мусор идёт. Да и на 8000000 мусорит, хотя и немного. Тупое чтение пина как в примере выше адекватнее читает. Но за подсказки спасибо, заставили-таки почитать, что же такое таймеры и счетчики. Хоть ни хрена не понял, зачем столько опций для них, но зато как Поле Чудес посмотрел - и интересно, и для головы полезно. Планирую все-же читать пин последовательно, забивая массив количеством сигналов одного уровня по счетчику или саморучно, а потом сдвигать в переменную. Все примеры, что в сети нашел - вроде красивые, а по факту: либо не понимаю как посчитать делитель для этого кварца(у него 0,0% ошибок в UART зато), либо грузят мегу также, как дергание массива из 450 ячеек(память кирдык почему-то)

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

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

OCR1 = 65000 //на всякий. Теоретически, он не должен сюда дойти до конца посылки, 
ибо с делителем /64 он раз в секунду переполняется примерно, а пульт в секунду раза 4 дергается

// COUNTER
TCCR1B |= (1 << WGM12);
TIMSK |= (1 << OCIE1A);

//INT0
MCUCR |= ((0 << ISC00)|(1 << ISC01));
GICR |= (1 << INT0);

TCCR1B выключен
INT0_vect{
  выключаем TCCR1B
    ultoa TCNT1 в char*
    шлем в UART этот массив(тут возможен сбой, ибо хз есть ли \0 после него, а посылка по \0 тормозится, но это неважно)
    обнуляем TCNT1 (первый цикл пустой - для дебага)
  включаем TCCRB с 1<<CS11 и 1<<CS10 // делитель /64
}
TIMER1_COMPA_vect{
  дебажный PORTB |= (1<<1);
}

Итого:

Timer
0
6
1
5
3
9
113
6
12113
3
12113
3
12113
3
12113
3
12113
3
Если я еще не надоел, то ЧЯДНТ?

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

Лень ковырять даташиты, опишу так. У всех известных мне протоколов ДУ есть старт-последовательность, стоп-последовательность и кодирование нулей и единиц идет двумя интервалами низкого и высокого уровня разной длины. Точнее даже не совсем так, на примере Сони - http://users.telenet.be/davshomepage/diagrams/sony.JPG у нас тут сначала идет низкий уровень фиксированой длины, а затем длинный импульс для единицы и короткий - для нуля. У панасоника похоже, только уровни инвертированы

Стало быть, единожды поймав длинный высокий уровень, настраиваем прерывания следующим образом - по переднему фронту (перепад с низкого в высокий) запускаем таймер и уходим ждать. По заднему фронту (с высокого в низкий) - отключаем таймер и смотрим, сколько натикало. Если мало, то ноль, если много, то 1, если еще больше, то стоп. По стопу записываем байт в массив, по 1 или 0 к текущему байту дописываем соответствующий бит. Для RC-5 будет несколько по-другому, но тоже можно сообразить. Сколько именно будет «мало» или «много» - определяем по старт-посылке. Как правило длительности всех импульсов кратны какой-то величине, например как тут http://3.bp.blogspot.com/-IqTs-gQCrDY/T6_slajADNI/AAAAAAAABVk/70pGmZ2MAPY/s16...

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

То есть мне режим прерывания постоянно менять с одного уровня на другой? Ладно, спасибо, друг, высплюсь, добьюсь результата

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

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

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

Пытался считать по разным состояниям ноги - но во всех случаях какой-то неадекватный шлак в TCNT1(счетчик). Хотя при проверке вроде правильно считает, прерывание по переполнению генерирует. В общем, я так и не добился пока, чтобы в UART выводился нормальный результат. Возможно это из-за скорости, все-же посылка короткая и уарт может не успевать. Пока проверяю разные варианты

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

Взял, собрал, прошил. С родной частотой (8000000) у меня 1/5 посылок битые(вне зависимости от расстояния пульта от приемника), а на 7372800 адаптировать вообще не вышло. Иной раз думаю, что мк дохлый, но потом перешиваю вариантом выше - посылки всегда одинаковы(почти. Дальше пульт отводишь - падает чувствительность, ближе - растет). Сменить кварц не предлагать - на нём 0,0% ошибок в UART, а это критично для самолюбия.

//А вообще, я уже кучу исходников на 8 мегу портировал с других мк, родные к 8 собирал, все либо неочевидное(что работает, хоть и сошибками на моей частоте), либо не работает совсем

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

Да что ж ты там делаешь? Заведи буфер, байт так на 128. Собирай туда пришедшие данные (уж 128 байт — это давить и давить кнопки). Потом откидывай по уарту.

Элементарно же длительность импульсов считается! Ну возьми, с моего stm8samples примерчик реализации считывания данных по zacwire. Это ж халява!

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

Эдвард, у меня на руках распечатка апноата самсунга. Уж 7,3мГц поделить на 0,56 мс я могу. Да и искусственный дебилизм, которым я тут пострадал в треде помог разобраться в таймерах и счетчиках почти во всех вариациях. Однако мусор идет стабильно. Тред поправлю на «решенный», ибо уже верю, что сам где-то в коде затупил - когда мысленно видишь код идеально прилизанным, обязательно вылезет жук. И наоборот. В любом случае спасибо за сотрудничество!

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

Приходится делать ручками - таймеры неадекватны. TCNT1 выдает зеро в переменную, хотя читаю его как в даташите написано. Приходится считывать TCNT1H, потом TCNT1L, сдвигать все в один long, потом закидывать в буфер, а он бьётся... Но это еще не все - он досчитывает до 32767, потом уходит в -32768 и декремент вниз пошёл до 0. И это без ultoa(); и ltoa();, где можно препутать чего, а простым sprintf(«%ld»)...

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

Всем спасибо, все свободны!

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

Мать моя женщина! Да что ж ты такое творишь-то?!

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

P.S. Я готов забесплатно сделать нужный код, если ты обеспечишь меня необходимым железом. Микроконтроллер у меня есть (хочешь — STM8, хочешь — STM32), остается остальное.

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

а чем позвольте поинтересоваться функционал хреновый у атмеля? возьмите два проца с одинаковой ценой и сравните функционал. а то я подозреваю что берёте attiny и smt32 super-puper-edition и говорите про функционал.. сам работал с мегой, очень интересно сравнение на самом деле. но только нормальнео сравнение а не полевание говном.

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

подтверждаю, сам был полным нубом, вполне разобрался пока читал атмеловскую pdf-ку

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

а чем позвольте поинтересоваться функционал хреновый у атмеля?

Соотношение функционал/цена очень низкое. Ну и то, что они в ардуйне стоят, не делают им благую рекламу ☺

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

Ну по факту, я вместо прерывания торможу мк на 500*150us+~1500 тактов из 7372800 в сек. Это занимает, субъективно, меньше полсекунды. Да и для понимания правильного подхода иногда полезно сделать неправильно. Наверное. Со счетчиком я выигрываю только на исключении задержки для основного цикла.

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

http://www.atmel.com/images/doc8154.pdf восьмая мега аналогичный таймер имеет. Кварц 7372800 герц. Готовое решение не нужно, их валом в сети, достаточно лишь пояснить, почему счетчик в минус уходит после половины - либо sprintf виноват, либо я настроил криво. Хз, вв даташите этого не увидел...

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

Кстати, в большинстве виденных мнойдатчиков с сертификатами имеет на борту pic16-18, а в сети их многие хаят и даже с атмегами простыми сравнивают не в пользу

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

И все они "программируются" из ардуйной гуйни?

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

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

я вместо прерывания торможу мк

Вот же японский городовой! Ну неужто трудно по прерываниям все сделать? Что это за детский сад?!

в большинстве виденных мной датчиков с сертификатами имеет на борту pic16-18

Ну и что? Я тоже когда-то с пиками дело имел. Очень у них хороший даташит, потому как функционала — что у бревна. И цена приличная.

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

Да. Только порты дурины с гуйней разные. С разными степенями наркомании

ncrmnt ★★★★★
()

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

PRESS POWER BUTTON!!!
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
11100000111000000100000010111111
Основной цикл не задет вообще - по прерыванию вызывается функция-тормоз как в пееееервом примере рабочем, подсчитываются нули, при совпадении нужного количества в массив пишется 1 или 0. После рефакторинга стресс-тест не гасит мегу, можно наверное еще что-нибудь туда загнать, хотя с L она стоит копейки, потому не критично даже если это будет МК ради пульта.

Теперь точно тема закрыта до выяснения обстоятельств со счетчиком(почему он не unsigned), почему битовые сдвиги на uint32_t у меня не срабатывают адекватно и почему я говорю писать в буфер 0x31 и 0x30 ЯВНО, а она пишет иногда 0x34 а то и вообще 0x38, а если МК виснет от нагрузки то в массиве появляются 0xff и растут...

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

Битовый сдвиг работал криво потому что я сначала писал единицу, потом сдвигал. А надо было сдвигать, а потом писать. Теперь я считываю адекватные коды. Спасибо!

//А счетчик я мельком глянул - в даташите есть пунктик про коррекцию фазы, в общем там рядом и описание его работы

minakov ★★★★★
() автор топика
Последнее исправление: minakov (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.