Контроллер освещения и сирены аэросаней/лодки
Задумывался как услада для глаз и слуха 😁. Подключается к трем каналам управления - CH1 влево-вправо, CH2 - вперед-назад, CH3 - дополнительный (AUX). Имеет 9 выходов - 8 светодиодных через ULN2308 и один для мощной сирены через FET.
Симуляция выполнена в PROTEUS, после переноса в реал все заработало сразу - фантастика. К контроллеру можно подключить отладочный LCD, за счет некоторых выходных каналов (см. исходник), но я это делал только в PROTEUS. При симуляции лучше выкинуть FET, из-за него PROTEUS глючит и не может моделировать в нем переходные процессы.
Алгоритм работы понятен из программы (на PICC), но вы целом таков:
Алгоритм работы
При включении мигается всеми каналами несколько раз;
Определяется исходное положение канала CH1 (влево-вправо) и запоминается, как его центральная точка;
Входит в цикл;
Каналы считываются по прерыванию;
Если в каналах CH1 или CH2 ошибка - мигает всеми лампочками и верещит. Эти каналы считаются обязательными.
Ошибка в канале CH3 (AUX) просто сохраняет старое значение. Можно его не подключать вообще.
Если CH2 в нейтрали, горят задние красные светодиоды (тормоз).
Если CH2 в положении Взад, горят задние белые светодиоды (задний ход).
Если CH1 в положении Влево, мигает задний красный Левый светодиод.
Если CH1 в положении Вправо, мигает задний красный Правый светодиод.
Если CH3 на ~1/3 от минимума, включается белый ореол спереди на тоннеле вокруг мотора.
Если CH3 на ~2/3 от минимума, включается дополнительно сине-красная мигалка сверху на тоннеле над мотором.
Если CH3 на на максимуме, включается дополнительно сирена ФБР из набора MasterKit c 50ом 0.5W динамиком.
Бортовые светодиодные ленты имитируют “бегущий огонь”, зависящий от скорости и направления, если CH2 не в нейтрали.
Просьба к понимающим тонкости обработки RC-каналов
Я старался сдалать так, чтобы порядок следования каналов был не важен - хоть все одновременно. Но иногда алгоритм сбоит и проскакивают ложные значения каналов. Побороть проблему я не смог и сделал пост-фильтрацию - чтобы логическое состояние внутренней переменной, связанной с каналом, изменилось, надо чтобы она несколько циклов подряд была в одном значени (подавление дребезга).
Кстати, ложные срабатывания удобно отлавливать в PROTEUS. 😒 Кто знает, как модифицировать обработчик прерываний, чтобы он не давал ложных считываний?😵
Кто знает, как модифицировать обработчик прерываний,
Нужно первым делом после входа в процедуру считать значение порта в 8-битную переменную, затем слить таймер, затем уже работать с ними. У вас условия напрямую с портом работают, хотя значение могло давно поменяться.
И не используйте непрямую адресацию (массивы) в прерываниях! только глобальные переменные. Времени жрет дико.
Спасибо за советы, все верно, но я не могу согласиться, что у меня не так, как Вы написали.
Я первым делом считываю TMR1 в t. Цикл do нужен для повторного выполнения обработчика прерывания если за время первого его выполнения пришло еще одно прерывание - при этом оно обрабатывается без потерь времени на вход/выход в прерывание. С портов я при этом ничего не читаю, только с памятью.
Дальше - массивы. Я работаю с константными индексами, следовательно адрес ячейки массива вычисляется при компиляции, и обращение к элементу массива в результате не отличается от обычной переменной.
С таймером у Вас как раз все нормально.
if (RX1_LEFT_RIGHT != RX1_signal) - вот что я имею ввиду, таймер считан один раз, а работа с физ. пинами разбросана по всему обработчику. Это означает, что определенному значению пина может соответствовать уже другая метка времени, с разницей в пару мкс. В статике ничего страшного, но при изменении состояния будет “дребезг”. Надо вычитывать TRISA в переменную одновременно с таймером, а потом работать уже только с ней. Тогда, кстати, и цикл не нужен, можно все условия пробегать за один раз.
В сигнале с приемника дребезг отсутствует как класс.
Хмм. Наверное про пару мкс верно, попробую так сделать. Но там скачки были на 200 мкс, что уж совсем не укладывается в это объяснение.
P.S. Наверное имелось ввиду PORTA а не TRISA…
Переделал как Syberian написал, вроде стало получше (в Proteus). Дрожание не больше 7 мкс.
Спасибо, отличный совет!
Вот изменения:
#define RX3_AUX 0b00001000 // RA3
#define RX2_FORWARD_BACKWARD 0b00010000 // RA4
#define RX1_LEFT_RIGHT 0b00100000 // RA5
static volatile byte _PORTA;
static void interrupt
isr(void) // Here be interrupt function - the name is unimportant.
{
// handle the interrupt (insert application code here)
// needs 3-4 cycles to get into interrupt;
uint16 t;
byte portA = PORTA;
byte delta = portA ^ _PORTA;
// Reading TMR1 16 bit value in the safe manner;
t = TMR1;
if (TMR1H != *((byte*)(&t)+1) )
t = TMR1;
if (delta & RX1_LEFT_RIGHT) {
if (portA & RX1_LEFT_RIGHT) { // front edge;
RX_timer[CH1] = t;
} else {
RX_channel[CH1] = t-RX_timer[CH1];
}
}
if (delta & RX2_FORWARD_BACKWARD) {
if (portA & RX2_FORWARD_BACKWARD) { // front edge;
RX_timer[CH2] = t;
} else {
RX_channel[CH2] = t-RX_timer[CH2];
}
}
if (delta & RX3_AUX) {
if (portA & RX3_AUX) { // front edge;
RX_timer[CH3] = t;
} else {
RX_channel[CH3] = t-RX_timer[CH3];
}
}
input_error = 0;
_PORTA = portA;
RAIF = 0; // reset flag
}
Рад, что получилось 😃
Тут еще поправочку внесу:
byte portA = PORTA;
byte delta = portA ^ _PORTA;
// Reading TMR1 16 bit value in the safe manner;
t = TMR1;
if (TMR1H != *((byte*)(&t)+1) )
t = TMR1;
желательно переставить так:
portA = PORTA;
// Reading TMR1 16 bit value in the safe manner;
t = TMR1;
if (TMR1H != *((byte*)(&t)+1) )
t = TMR1;
delta = portA ^ _PORTA;
Тогда джиттер будет еще меньше. Причем portA и delta определить как глобальные в шапке.
Потому что иначе память на них будет выделяться из data stack каждый раз заново, а это - лишние микросекунды.
Если в прерывании не используются локальные переменные,
вход будет проводиться быстрее.
Супер, спасибо за поправку!
Кстати, на PIC16 стек для переменных не используется, все сохраняется в глобальных переменных и так. Даже регистр W и флаги. А поскольку переменные, используемые в прерывании, описаны как volatile, они не будут делить один и тот же адрес с другими переменными из других областей видимости, даже если оптимизатор этого захочет. Так что выносить их в статические вроде смысла нет 😃
{"assets_hash":"a8b26fa7f6e768b07a72c8c9aadb9422","page_data":{"users":{"41b8a4ac3df9550077792e83":{"_id":"41b8a4ac3df9550077792e83","hid":5271,"name":"Prikupets","nick":"Prikupets","avatar_id":null,"css":""},"48f3a40c3df9550077776944":{"_id":"48f3a40c3df9550077776944","hid":39391,"name":"Syberian","nick":"Syberian","avatar_id":null,"css":""}},"settings":{"blogs_can_create":false,"blogs_mod_can_delete":false,"blogs_mod_can_hard_delete":false,"blogs_mod_can_add_infractions":false,"can_report_abuse":false,"can_vote":false,"can_see_ip":false,"blogs_edit_comments_max_time":30,"blogs_show_ignored":false,"blogs_reply_old_comment_threshold":30,"votes_add_max_time":168},"entry":{"_id":"4d29726999707300771011cb","hid":10888,"title":"Контроллер освещения и сирены аэросаней/лодки","html":"<p><strong data-nd-pair-src=\"**\">Контроллер освещения и сирены аэросаней/лодки</strong><br>\nЗадумывался как <a href=\"https://rcopen.com/blogs/5271/10852\" class=\"link link-int\" data-nd-link-orig=\"https://rcopen.com/blogs/5271/10852\">услада для глаз и слуха </a><span class=\"emoji emoji-grin\" data-nd-emoji-src=\":grin:\">😁</span>. Подключается к трем каналам управления - CH1 влево-вправо, CH2 - вперед-назад, CH3 - дополнительный (AUX). Имеет 9 выходов - 8 светодиодных через ULN2308 и один для мощной сирены через FET.<br>\nСимуляция выполнена в PROTEUS, после переноса в реал все заработало сразу - фантастика. К контроллеру можно подключить отладочный LCD, за счет некоторых выходных каналов (см. исходник), но я это делал только в PROTEUS. При симуляции лучше выкинуть FET, из-за него PROTEUS глючит и не может моделировать в нем переходные процессы.</p>\n<p>Алгоритм работы понятен из программы (на PICC), но вы целом таков:</p>\n<p><strong data-nd-pair-src=\"**\">Алгоритм работы</strong></p>\n<p>При включении мигается всеми каналами несколько раз;<br>\nОпределяется исходное положение канала CH1 (влево-вправо) и запоминается, как его центральная точка;<br>\nВходит в цикл;</p>\n<!--cut-->\n<p>Каналы считываются по прерыванию;<br>\nЕсли в каналах CH1 или CH2 ошибка - мигает всеми лампочками и верещит. Эти каналы считаются обязательными.<br>\nОшибка в канале CH3 (AUX) просто сохраняет старое значение. Можно его не подключать вообще.</p>\n<p>Если CH2 в нейтрали, горят задние красные светодиоды (тормоз).<br>\nЕсли CH2 в положении Взад, горят задние белые светодиоды (задний ход).<br>\nЕсли CH1 в положении Влево, мигает задний красный Левый светодиод.<br>\nЕсли CH1 в положении Вправо, мигает задний красный Правый светодиод.<br>\nЕсли CH3 на ~1/3 от минимума, включается белый ореол спереди на тоннеле вокруг мотора.<br>\nЕсли CH3 на ~2/3 от минимума, включается дополнительно сине-красная мигалка сверху на тоннеле над мотором.<br>\nЕсли CH3 на на максимуме, включается дополнительно сирена ФБР из набора MasterKit c 50ом 0.5W динамиком.<br>\nБортовые светодиодные ленты имитируют “бегущий огонь”, зависящий от скорости и направления, если CH2 не в нейтрали.</p>\n<p><strong data-nd-pair-src=\"**\">Файлы</strong></p>\n<p>Схема, исходник, прошивка: <a href=\"http://narod.ru/disk/26012455001/BoatController.rar.html\" class=\"link link-ext\" data-nd-link-orig=\"http://narod.ru/disk/26012455001/BoatController.rar.html\" target=\"_blank\" rel=\"nofollow noopener\">BoatController.rar.html</a></p>\n<p>Схема полностью: (также на <a href=\"http://fotki.yandex.ru/users/prikupets/album/43467/?p=0\" class=\"link link-ext link-auto\" data-nd-link-type=\"autolink\" data-nd-link-orig=\"http://fotki.yandex.ru/users/prikupets/album/43467/?p=0\" target=\"_blank\" rel=\"nofollow noopener\">fotki.yandex.ru/users/prikupets/album/43467/?p=0</a>)<br>\n<span class=\"image\" style=\"width: 800px\" data-nd-image-orig=\"https://img-fotki.yandex.ru/get/5002/prikupets.0/0_4f18c_d1049c3_XL\"><img src=\"https://img-fotki.yandex.ru/get/5002/prikupets.0/0_4f18c_d1049c3_XL\" alt referrerpolicy=\"no-referrer\"><span class=\"image__spacer\" style=\"padding-bottom: 58.5000%\"></span></span></p>\n<p><strong data-nd-pair-src=\"**\">Просьба к понимающим тонкости обработки RC-каналов</strong><br>\nЯ старался сдалать так, чтобы порядок следования каналов был не важен - хоть все одновременно. Но иногда алгоритм сбоит и проскакивают ложные значения каналов. Побороть проблему я не смог и сделал пост-фильтрацию - чтобы логическое состояние внутренней переменной, связанной с каналом, изменилось, надо чтобы она несколько циклов подряд была в одном значени (подавление дребезга).<br>\nКстати, ложные срабатывания удобно отлавливать в PROTEUS. <span class=\"emoji emoji-unamused\" data-nd-emoji-src=\":unamused:\">😒</span><br>\n<strong data-nd-pair-src=\"**\">Кто знает, как модифицировать обработчик прерываний, чтобы он не давал ложных считываний?</strong> <span class=\"emoji emoji-dizzy_face\" data-nd-emoji-src=\":dizzy_face:\">😵</span></p>\n","user":"41b8a4ac3df9550077792e83","ts":"2011-01-09T08:31:37.000Z","st":1,"cache":{"comment_count":8,"last_comment":"514463e6997073007716af62","last_comment_hid":8,"last_ts":"2013-03-16T12:21:58.000Z","last_user":"41b8a4ac3df9550077792e83"},"views":2720,"bookmarks":0,"votes":0},"subscription":null},"locale":"en-US","user_id":"000000000000000000000000","user_hid":0,"user_name":"","user_nick":"","user_avatar":null,"is_member":false,"settings":{"can_access_acp":false,"can_use_dialogs":false,"hide_heavy_content":false},"unread_dialogs":false,"footer":{"rules":{"to":"common.rules"},"contacts":{"to":"rco-nodeca.contacts"}},"navbar":{"tracker":{"to":"users.tracker","autoselect":false,"priority":10},"forum":{"to":"forum.index"},"blogs":{"to":"blogs.index"},"clubs":{"to":"clubs.index"},"market":{"to":"market.index.buy"}},"recaptcha":{"public_key":"6LcyTs0dAAAAADW_1wxPfl0IHuXxBG7vMSSX26Z4"},"layout":"common.layout"}