|
|
  |
Энкодер и дребезг, нужна помощь |
|
|
|
Apr 12 2007, 11:55
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 9-03-07
Из: г. Днепропетровск
Пользователь №: 26 009

|
Цитата(ZAO @ Apr 12 2007, 11:41)  Вы вполне можете завести одно таймерное прерывание, которое будет фильтровать дребезг и обновлять индикаторы. При каждом вызове обрабатывается один из индикаторов и определяется сигнал от датчика. Если для обновления индикатора период таймера слишком маленький, Вы можете организовать внутри прерывания счетчик, по достижении определенного значения которого и обрабатывать индикатор. Тоесть в обработчике прерываний от таймера смотренть состояние датчика, если оно не изменяется в течение 2-3 прерываний дребезга нет?
|
|
|
|
|
Apr 12 2007, 13:05
|
Группа: Новичок
Сообщений: 8
Регистрация: 17-01-06
Пользователь №: 13 289

|
Цитата(BigCoster @ Apr 12 2007, 12:55)  Тоесть в обработчике прерываний от таймера смотренть состояние датчика, если оно не изменяется в течение 2-3 прерываний дребезга нет? Да. Только для гарантированной фильтрации дребезга, период прерываний надо подобрать раза в 64 меньше минимального периода изменений датчика. И если в течении 64 прерываний состояние датчика не изменилось, то можно говорить о достоверности состояния. В идеале чем период меньше - тем фильтрация лучше.
Сообщение отредактировал ZAO - Apr 12 2007, 13:05
|
|
|
|
|
Apr 12 2007, 13:44
|

Частый гость
 
Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901

|
Цитата(BigCoster @ Apr 12 2007, 11:25)  У меня осцилографом работает звуковая карточка, надеюсь скоро обзавестись настояшим, так что дребезга особо я заметить не могу. Но он проявляется когда крыльчатка останавливается на границе срабатывания оптопары. Я это вижу на дин. индикации (считает, а двигатель стоит  ) Сейчас у меня датчик подключен так: [attachment=10800:attachment] Настоятельно рекомендую R2 "разместить" в непосредственной близости от входа МП, и "+5в" "брать" от шины питания МП (от вывода питания МП). Конденсатор или убрать совсем, или емкость снизить с 1мкФ до <1нФ. На мой взгляд, приведенная схема датчика вполне работоспособна, и при условии исправных элементов, "сбоев" давать не должна. Для того, чтобы исключить программную ошибку попробуйте разделить работу программы на этапы (на время отладки): 1 этап: - посчет импульсов; - индикация НЕ ОТОБРАЖАЕТСЯ; 2 этап: - вывод значения на индикатор; - импульсы не подсчитываются. Программу подсчета импульсов на время отладки нужно максимально упростить (подсчитал -> вывел). Всяческие ветвления аглоритма убрать! Определение направления, расчет скорости и т.д. не выполнять. Это позволит Вам выяснить работоспосбность связки датчик<->МП. И только когда удастся добиться устойчивой работы постого алгоритма, можно переходить к усложнению программы. Re..Опубликуйте программу..
|
|
|
|
|
Apr 12 2007, 14:04
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 9-03-07
Из: г. Днепропетровск
Пользователь №: 26 009

|
Вот осцилограмма работы датчика, записанная в SoundForge. Щуп подключен к ноге контроллера:
Из нее видно, что частота около 70Гц, а не 200Гц, как я говорил ранее извините... И ещё осцилограмка обновления индикации. Щуп к R9 (см. на схемке несколькими постами выше):
В прерывании по таймеру обрабатывается вся индикация, а не по одному знаку в каждом прерывании. Видим, что частота 40Гц (мерцания не видно!  хотя странно) Я так понимаю, что метод с подсчётом импульсов в прерывании от таймера для индикации не подходит (программа не маленькая и на асме, переделывать не очень то и хочется) Триггер Шмидта???
|
|
|
|
|
Apr 12 2007, 14:29
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 9-03-07
Из: г. Днепропетровск
Пользователь №: 26 009

|
Цитата(Stas633 @ Apr 12 2007, 13:44)  Настоятельно рекомендую R2 "разместить" в непосредственной близости от входа МП, и "+5в" "брать" от шины питания МП (от вывода питания МП). Конденсатор или убрать совсем, или емкость снизить с 1мкФ до <1нФ. На мой взгляд, приведенная схема датчика вполне работоспособна, и при условии исправных элементов, "сбоев" давать не должна.
Re..Опубликуйте программу.. R2 датчика и +5в близко к контроллеру, он mcs51, программа соответственно... 1.Задание расстояния Код ;-------------------------- ;Настройка позиционирования| ;-------------------------- upr: mov th1,#0 mov tl1,#0 mov kol_post_down,#0 mov kol_post_up,#0 mov addr_length,#0 setb tr0 ;разрешить счёт таймеру setb et0 ;разрешить прерывания от таймера upr_set: jb k_set,upr_menu upr_set_1: clr tr0 clr tr1 call time2 call save_pos setb tr0 setb tr1 upr_menu: jb k_menu,upr_plus pr_menu_1: clr tr0 clr tr1 clr et0 clr et1 call time2 ret upr_plus: jb k_plus,upr_minus upr_plus_1: call r_up upr_minus: jb k_minus,upr_set upr_minus_1: call l_down jmp upr_set ;FUNCTIONS upr_minus ;------------------------------------------- ;Крутит нижний двигатель, увеличивает длину | ;------------------------------------------- l_down: ;Крутим (L/DOWN) двигатель clr tr1 clr et0 clr type_count;инкрементирующий счётчик call on_down setb et0 setb tr1 down_m1: jnb k_minus,down_m1 ;clr tr0 ;call time1 ;setb tr0 ;jnb k_minus,down_m1 clr tr1 clr tr0 call on_all setb tr0 ret ;FUNCTIONS upr_plus ;------------------------------------------ ;Крутит верхний двигатель, уменьшает длину | ;------------------------------------------ r_up: ;Крутим (R/UP) двигатель clr tr1 clr et0 mov a,th1 cpl a mov th1,a mov a,tl1 cpl a mov tl1,a setb type_count;декрементирующий счётчик call on_up setb et0 setb tr1 up_m1: jnb k_plus,up_m1 ;clr tr0 ;call time1 ;setb tr0 ;jnb k_plus,up_m1 clr tr1 clr tr0 call on_all setb tr0 ret 2.Прерывания Код ;************************ ;* ОБРАБОТКА ПРЕРЫВАНИЙ * ;************************
;------------------------------------------------ ;Обслуживание прерывания при переполнении таймера| ;------------------------------------------------ t0_overflow: jb type_count,t0_overflow_1 call inc_counter reti t0_overflow_1: call dec_counter reti ;FUNCTIONS t0_overflow ;------------------------ ;Инкрементирующий счётчик| ;------------------------ inc_counter: clr tr0 ;запретить счёт таймеру call inc_bcd call bin_to_bcd call display setb tr0 ;разрешить счёт таймеру ret ;sub FUNCTIONS inc_counter ;--------------------------------------------- ;Предварительная обработка значений для работы| ; счётчика в инкрементирующем режиме | ;--------------------------------------------- inc_bcd: mov a,th1 mov dph,a mov a,tl1 mov dpl,a ret ;FUNCTIONS t0_overflow ;------------------------ ;Декрементирующий счётчик| ;------------------------ dec_counter: clr tr0 call dec_bcd call bin_to_bcd call display setb tr0 ret ;sub FUNCTIONS dec_counter ;--------------------------------------------- ;Предварительная обработка значений для работы| ; счётчика/2 в декрементирующем режиме | ;--------------------------------------------- dec_bcd: mov a,th1 cpl a mov dph,a mov a,tl1 cpl a mov dpl,a ret ;common sub FUNCTIONS dec_counter & inc_counter ;---------------------------------------------------- ;Подготовка значений для отображения функцией DISPLAY| ; во время работы дв. | ;---------------------------------------------------- bin_to_bcd: mov disp0,#2fh ;устанавливаем mov disp1,#30h ;начальные mov disp2,#30h ;значения bin_to_bcd_go: inc disp0 ;подсчёт едениц dec_dptr: dec dpl ;ументшаем dptr mov a,dpl ;пока не станет cjne a,#0ffh,bin_to_bcd_m1 ;равен 0ffh dec dph bin_to_bcd_m0: mov a,disp0 cjne a,#3ah,bin_to_bcd_go ;если переполнение едениц inc disp1 ;подсчёт десятков mov disp0,#30h mov a,disp1 cjne a,#3ah,bin_to_bcd_go ;если переполнение десятков inc disp2 ;подсчёт сотен mov disp1,#30h mov a,disp2 cjne a,#3ah,bin_to_bcd_go ;если переполнение сотен overload_bcd: ;пишем Е в разряд сотен mov disp2,#3eh sjmp bin_to_bcd_exit ;выход, если переполнение сотен bin_to_bcd_m1: mov a,dph ;выход, если значения cjne a,#0ffh,bin_to_bcd_m0 ;подготовлены bin_to_bcd_exit: ret ;common sub FUNCTIONS dec_counter & inc_counter ;------------------------------------------- ;Отображение чисел по адресам предварительно| ; записаных в disp0, disp1, disp2 | ;------------------------------------------- display: mov r0,disp2 mov p0,@r0 mov p2,#1h call time1 mov r0,disp1 mov p0,@r0 mov p2,#2h call time1 mov r0,disp0 mov p0,@r0 mov p2,#4h call time1 clr p2.2 ret ;------------------------------------------------- ;Обслуживание прерывания при переполнении счётчика| ;------------------------------------------------- t1_overflow: clr tr0 ;запретить счёт таймеру clr tr1 ;запретить счёт счётчику mov p0,#0 call stop setb yet setb tr0 ;разрешить счёт таймеру setb tr1 ;разрешить счёт счётчику reti ;FUNCTIONS t1_overflow ;--------------------------- ;Паузa перед следующим движением двигателя| ;--------------------------- stop: call on_all call pause clr yet ret ;sub FUNCTIONS stop ;------------------ ;Изменяющаяся пауза| ;------------------ pause: push 7 push 5 mov r0,pauses mov a,@r0 mov r3,a inc r3 t55: mov r4,#05h t66: mov r5,#0a0h t77: mov r7,#0ffh djnz r7,$ djnz r5,t77 djnz r4,t66 djnz r3,t55 pop 5 pop 7 ret если кто то захочет разбираться, я могу продолжать, думаю некто не захочет
Сообщение отредактировал BigCoster - Apr 12 2007, 14:31
|
|
|
|
|
Apr 12 2007, 14:43
|

Частый гость
 
Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901

|
Цитата(BigCoster @ Apr 12 2007, 15:04)  Положительный фронт "затягивается" из-за зарядки конденсатора. Уберите его из схемы, и посмОтрите как изменится сигнал. Я считаю, что, судя по приведенной осциллограмме, датчик работает "правильно", а ошибка "формируется" программой. Цитата(BigCoster @ Apr 12 2007, 15:04)  ... Я так понимаю, что метод с подсчётом импульсов в прерывании от таймера для индикации не подходит (программа не маленькая и на асме, переделывать не очень то и хочется) Триггер Шмидта??? Не переделывайте, не нужно.. Напишите новую, но очень маленькую (настроечную). А триггер Шмидта только "выпрямит" фронты, и "добавит" в работу датчика гистерезис. .... пишу по поводу программы... Неправильный "подход" уже очевиден...
|
|
|
|
|
Apr 12 2007, 15:10
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 9-03-07
Из: г. Днепропетровск
Пользователь №: 26 009

|
Цитата(Stas633 @ Apr 12 2007, 14:43)  Положительный фронт "затягивается" из-за зарядки конденсатора. Уберите его из схемы, и посмОтрите как изменится сигнал.
Я считаю, что, судя по приведенной осциллограмме, датчик работает "правильно", а ошибка "формируется" программой. Не переделывайте, не нужно.. Напишите новую, но очень маленькую (настроечную).
А триггер Шмидта только "выпрямит" фронты, и "добавит" в работу датчика гистерезис.
.... пишу по поводу программы... Неправильный "подход" уже очевиден... Убрал ёмкость, вот что получилось:
Думаю на мой "осцилограф" не сильно стоит обращать внимание т.к. 44.1кГц, 16 бит + у него на входе наверное фильтр какой нить. Ошибка увеличилась почти на целый оборот вала двигателя.
|
|
|
|
|
Apr 12 2007, 15:13
|

Частый гость
 
Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901

|
Цитата(BigCoster @ Apr 12 2007, 15:29)  Код 2.Прерывания [code];************************ ;* ОБРАБОТКА ПРЕРЫВАНИЙ * ;************************
;------------------------------------------------ ;Обслуживание прерывания при переполнении таймера| ;------------------------------------------------ t0_overflow: jb type_count,t0_overflow_1 call inc_counter reti t0_overflow_1: call dec_counter reti ;FUNCTIONS t0_overflow ;------------------------ ;Инкрементирующий счётчик| ;------------------------ inc_counter: clr tr0 ;запретить счёт таймеру call inc_bcd call bin_to_bcd call display setb tr0 ;разрешить счёт таймеру ret ;sub FUNCTIONS inc_counter ;--------------------------------------------- ;Предварительная обработка значений для работы| ; счётчика в инкрементирующем режиме | ;--------------------------------------------- inc_bcd: mov a,th1 mov dph,a mov a,tl1 mov dpl,a ret ;FUNCTIONS t0_overflow ;------------------------ ;Декрементирующий счётчик| ;------------------------ dec_counter: clr tr0 call dec_bcd call bin_to_bcd call display setb tr0 ret Общеизвестно, что при работе систем realtime, коей является Ваше устройство, программа обработки прерываний должна содержать минимум кода. Например алгоритм работы по прерыванию, может быть таким: 1. сохранил значение (таймера-счетчика или еще чего-либо) во временной переменной. 2. установил флаг обновления этой временной переменной 3.конец. И уж совсем не допустимым, на мой взгляд является использование вызова подпрограмм (call) из прерывания. Если нет возможности отказаться от использования какой-либо функции при отработке прерывания, то размещайте её (функцию) внутри прерывания! Код interrupt [EXT_INT1] void ext_int1_isr(void) { if(PIND.4)Encod=Encod-vc_step; else Encod=Encod+vc_step; valcod=1; } или Код interrupt [TIM2_OVF] void timer2_ovf_isr(void) { if (--Time2==0){Time2=15;vzvod=1;} } Ещё.... Если Вы используете работу по прерываниям в realtime системе, то необходимо "расставить" приоритеты. Точнее выбрать ГЛАВНУЮ ЗАДАЧУ, выполнение которой не может быть "отодвинуто" ни чем другим. Если для Вас главное - подсчет импульсов, то если "мешает" вывод на индикатор, то им нужно жертвовать... и т.д.
|
|
|
|
|
Apr 12 2007, 15:30
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 9-03-07
Из: г. Днепропетровск
Пользователь №: 26 009

|
Цитата(Stas633 @ Apr 12 2007, 15:13)  Общеизвестно, что при работе систем realtime, коей является Ваше устройство, программа обработки прерываний должна содержать минимум кода. Например алгоритм работы по прерыванию, может быть таким: 1. сохранил значение (таймера-счетчика или еще чего-либо) во временной переменной. 2. установил флаг обновления этой временной переменной 3.конец. И уж совсем не допустимым, на мой взгляд является использование вызова подпрограмм (call) из прерывания. Если нет возможности отказаться от использования какой-либо функции при отработке прерывания, то размещайте её (функцию) внутри прерывания! Код interrupt [EXT_INT1] void ext_int1_isr(void) { if(PIND.4)Encod=Encod-vc_step; else Encod=Encod+vc_step; valcod=1; } или Код interrupt [TIM2_OVF] void timer2_ovf_isr(void) { if (--Time2==0){Time2=15;vzvod=1;} } Ещё.... Если Вы используете работу по прерываниям в realtime системе, то необходимо "расставить" приоритеты. Точнее выбрать ГЛАВНУЮ ЗАДАЧУ, выполнение которой не может быть "отодвинуто" ни чем другим. Если для Вас главное - подсчет импульсов, то если "мешает" вывод на индикатор, то им нужно жертвовать... и т.д. Приоритеты для прерываний установлены так: счётчик->таймер->внешние прерывания (пока не задействованы). По поводу всех замечаний на счёт написания программы согласен, но на том этапе, когда она писалась оправданы были все действия (перед собой)
|
|
|
|
|
Apr 12 2007, 15:44
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Ну, если счетчик считает при остановленном двигателе, и двигатель управляется тем же контроллером, то поможет только одно программное извращение - не считать, если двигатель установлен :-) Ничто другое не поможет, если крыльчатка вибрирует - только изменение конструкции датчика. Второй канал датчика, как уже предложили. И непонятно, для чего нужно знать точное количество импульсов. А приоритетов прерываний в AVR не существует. Так, теоретически можно искусственно сделать два уровня.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Apr 12 2007, 15:55
|

Частый гость
 
Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901

|
Цитата(BigCoster @ Apr 12 2007, 16:30)  Приоритеты для прерываний установлены так: счётчик->таймер->внешние прерывания (пока не задействованы). По поводу всех замечаний на счёт написания программы согласен, но на том этапе, когда она писалась оправданы были все действия (перед собой) Действительно, "разобраться в чужой программе сложнее, чем написать свою"..., но если Вы поясните алгоритм функционирования Вашего устройства, в части касающейся обработки вращения (углового перемещения) двигателя, то возможно Вам предложат КАК написать программу. Ну а "не правильно" написанную (равно как и работающую с ошибками) программу придется переписывать...
|
|
|
|
|
Apr 12 2007, 16:13
|

Участник

Группа: Свой
Сообщений: 71
Регистрация: 9-03-07
Из: г. Днепропетровск
Пользователь №: 26 009

|
Цитата(Dog Pawlowa @ Apr 12 2007, 15:44)  Ну, если счетчик считает при остановленном двигателе, и двигатель управляется тем же контроллером, то поможет только одно программное извращение - не считать, если двигатель установлен :-) Это програмное извращение уже реализовано Код t1_overflow: clr tr0 ;запретить счёт таймеру clr tr1 ;запретить счёт счётчику mov p0,#0 call stop setb yet setb tr0 ;разрешить счёт таймеру setb tr1 ;разрешить счёт счётчику reti Цитата(Dog Pawlowa @ Apr 12 2007, 15:44)  И непонятно, для чего нужно знать точное количество импульсов. Чтобы проехать заданное расстояние Цитата(Dog Pawlowa @ Apr 12 2007, 15:44)  А приоритетов прерываний в AVR не существует. Так, теоретически можно искусственно сделать два уровня. У меня не AVR Добъюсь работы на этом контроллере потом буду "ковырять" AVR Цитата(Stas633 @ Apr 12 2007, 15:55)  Действительно, "разобраться в чужой программе сложнее, чем написать свою"..., но если Вы поясните алгоритм функционирования Вашего устройства, в части касающейся обработки вращения (углового перемещения) двигателя, то возможно Вам предложат КАК написать программу. Алгоритм такой: НАСТРОЙКА -нажимаем кнопку-едем едем сколько надо -нажимаем кнопку-сохраняем и так необходимое кол-во раз РАБОТА -едим, сколько сохранили -проехали, остановились, постояли некоторое время и так столько, сколько раз сохраняли потом тоже самое в обратную сторону
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|