реклама на сайте
подробности

 
 
> Опрос валкодера, Дребезг
Anjey_N
сообщение Nov 14 2007, 09:49
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Все привет!
Вопрос такой:
В системе стоит механический валкодер. Опрашиваю его я вот так

signed char ReadEncoder(void)
{
register signed char temp = 0;
encoder = (~PIN_Coder & 0x03);//i?iaa?yai PD0,PD1
if(status != encoder)
{
switch(encoder)
{
case 0:
if(status == 1) temp = 1;
else if(status == 2) temp = -1;
break;
case 1:
if(status == 3) temp = 1;
else if(status == 0) temp = -1;
break;
case 2:
if(status == 0) temp = 1;
else if(status == 3) temp = -1;
break;
case 3:
if(status == 2)temp = 1;
else if(status == 1) temp = -1;
break;
}
status = encoder;
}
return temp;
}
Єту программку скачал с нета. При медленном вращении валкодера показания на индикаторе меняются стабильно, а при быстром вращении - не изменяются.
Похоже на дребезг контактов. Как можно от этого избавиться?
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
psw
сообщение Nov 14 2007, 13:24
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 16
Регистрация: 8-06-06
Пользователь №: 17 866



похоже, что я писал этот кусок smile.gif как часто опрашиваешь валкодер?
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 14 2007, 16:35
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Цитата(psw @ Nov 14 2007, 17:24) *
похоже, что я писал этот кусок smile.gif как часто опрашиваешь валкодер?


1 раз в 1 мсек
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 15 2007, 08:27
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Валкодеры, их два, подключены по такой схеме

Длительность строба 2 мс

Вместе с валкодерами подключены и кнопки. Валкодеры опрашиваются, когда на их средний вывод приходит "0".
Опрос валкодера, если незадействованы кнопки 1раз в 12 мс

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
Alex B._
сообщение Nov 15 2007, 08:40
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 943
Регистрация: 6-07-04
Из: Санкт-Петербург
Пользователь №: 274



Обязательно нужно через фильтр пропускать отсчеты. Ниже старый, но рабочий код. Сканируется раз в 200 мкс

Код
typedef struct __ENC_CB
{
    U08 phs_sample_period;

    U16 A_window;
    U16 B_window;

    U16 A_sum;
    U16 B_sum;

    U08 A_mask;
    U08 B_mask;

    U08 Current;
    U08 Previous;

    U08 State;

} ENC_CB;

ENC_CB ENC;

/* =================== */

void adsf (void)
{
    port = ENC_PORT;

    if (++ENC.phs_sample_period > (ENC_PHS_SAMPLE_PERIOD_VAL - 1))
    {
        ENC.phs_sample_period = 0;

        if (port & ENC_A_PIN)
        {
            ENC.A_sum++;
            ENC.A_window |= ENC.A_mask;
        }
        else
        {
            if (ENC.A_sum > 0)
                ENC.A_sum--;
            ENC.A_window &= ~ENC.A_mask;
        }

        ENC.A_mask <<= 1;
        if (ENC.A_mask == 0)
            ENC.A_mask = 1;

        if ((ENC.A_window & ENC.A_mask) &&
            (ENC.A_sum > 0)
           )
            ENC.A_sum--;

        if (port & ENC_B_PIN)
        {
            ENC.B_sum++;
            ENC.B_window |= ENC.B_mask;
        }
        else
        {
            if (ENC.B_sum > 0)
                ENC.B_sum--;
            ENC.B_window &= ~ENC.B_mask;
        }

        ENC.B_mask <<= 1;
        if (ENC.B_mask == 0)
            ENC.B_mask = 1;

        if ((ENC.B_window & ENC.B_mask) &&
            (ENC.B_sum > 0)
           )
            ENC.B_sum--;

        ENC.Current = ENC.Previous;

        if      (ENC.A_sum > 5)  ENC.Current |=  0x01;
        else if (ENC.A_sum < 2)  ENC.Current &= ~0x01;

        if      (ENC.B_sum > 5)  ENC.Current |=  0x02;
        else if (ENC.B_sum < 2)  ENC.Current &= ~0x02;

        if (!ENC.Current)
        {
            if (ENC.Previous == 0x01)
                ENC.State |= ENC_EVENT_UP;
            if (ENC.Previous == 0x02)
                ENC.State |= ENC_EVENT_DW;
        }

        ENC.Previous = ENC.Current;
    }
}
Go to the top of the page
 
+Quote Post
alexander55
сообщение Nov 15 2007, 08:44
Сообщение #6


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(Anjey_N @ Nov 15 2007, 11:27) *
Опрос валкодера, если незадействованы кнопки 1раз в 12 мс

Прикрепленное изображение

Опрашивать надо чаще. Чем выше максимальная скорость, тем чаще.
Частота опроса д.б. более, чем в 2 раза больше скорости изменения показаний.
Теорема Котельникова- Шенона, однако. 07.gif
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 15 2007, 15:24
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Цитата(alexander55 @ Nov 15 2007, 12:44) *
Опрашивать надо чаще. Чем выше максимальная скорость, тем чаще.
Частота опроса д.б. более, чем в 2 раза больше скорости изменения показаний.
Теорема Котельникова- Шенона, однако. 07.gif



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

Цитата(Alex B._ @ Nov 15 2007, 12:40) *
Обязательно нужно через фильтр пропускать отсчеты. Ниже старый, но рабочий код. Сканируется раз в 200 мкс

Код
typedef struct __ENC_CB
{
    U08 phs_sample_period;

    U16 A_window;
    U16 B_window;

    U16 A_sum;
    U16 B_sum;

    U08 A_mask;
    U08 B_mask;

    U08 Current;
    U08 Previous;

    U08 State;

} ENC_CB;

ENC_CB ENC;

/* =================== */

void adsf (void)
{
    port = ENC_PORT;

    if (++ENC.phs_sample_period > (ENC_PHS_SAMPLE_PERIOD_VAL - 1))
    {
        ENC.phs_sample_period = 0;

        if (port & ENC_A_PIN)
        {
            ENC.A_sum++;
            ENC.A_window |= ENC.A_mask;
        }
        else
        {
            if (ENC.A_sum > 0)
                ENC.A_sum--;
            ENC.A_window &= ~ENC.A_mask;
        }

        ENC.A_mask <<= 1;
        if (ENC.A_mask == 0)
            ENC.A_mask = 1;

        if ((ENC.A_window & ENC.A_mask) &&
            (ENC.A_sum > 0)
           )
            ENC.A_sum--;

        if (port & ENC_B_PIN)
        {
            ENC.B_sum++;
            ENC.B_window |= ENC.B_mask;
        }
        else
        {
            if (ENC.B_sum > 0)
                ENC.B_sum--;
            ENC.B_window &= ~ENC.B_mask;
        }

        ENC.B_mask <<= 1;
        if (ENC.B_mask == 0)
            ENC.B_mask = 1;

        if ((ENC.B_window & ENC.B_mask) &&
            (ENC.B_sum > 0)
           )
            ENC.B_sum--;

        ENC.Current = ENC.Previous;

        if      (ENC.A_sum > 5)  ENC.Current |=  0x01;
        else if (ENC.A_sum < 2)  ENC.Current &= ~0x01;

        if      (ENC.B_sum > 5)  ENC.Current |=  0x02;
        else if (ENC.B_sum < 2)  ENC.Current &= ~0x02;

        if (!ENC.Current)
        {
            if (ENC.Previous == 0x01)
                ENC.State |= ENC_EVENT_UP;
            if (ENC.Previous == 0x02)
                ENC.State |= ENC_EVENT_DW;
        }

        ENC.Previous = ENC.Current;
    }
}



Спасибо за код, изучаю. Вы какой компилятор используете?
Go to the top of the page
 
+Quote Post
Kirill Frolov
сообщение Nov 15 2007, 17:06
Сообщение #8


Частый гость
**

Группа: Новичок
Сообщений: 111
Регистрация: 10-02-07
Из: St.Petersburg, Russia
Пользователь №: 25 241



Цитата(Anjey_N @ Nov 14 2007, 12:49) *
Вопрос такой:
В системе стоит механический валкодер. Опрашиваю его я вот так


Суть вопроса вот какая. Частота опроса входного сигнала должна быть минимум вдвое больше его частоты с которой он изменяется. Это очевидный факт. Но реализовать это в случае многократного пересечения валкодером края одной метки, когда он колеблется возле этого самого края сложно... И не нужно!. Тем более, если валкодер обрабатывается аппаратным прерыванием (к вопросу о том как прибору сделать "DoS" путём перепиливания тупой ножёвкой жгута проводов...)

Решение, вкратце таково: алгоритм модифицируется таким образом, что при прохождении края какой-либо метки в одном направлении её прохождение в обратном направлении попросту не фиксируется (запрещается прерывание, например). А фиксируется только прохождение следующего края метки в том же направлении (+1 к позиции) или прохождение не только что пройденного, а предшествующего ему края метки в обратном направлении (-2 к позиции). Может смутно объяснил. Советую просто расписать код Грея в круге и тогда легко будет понять как это работает, и что для реализации алгоритма достаточно запретить (допустим, валкодер имеет два выхода) прерывание от того выхода, который вызвал вот прямо сейчас прерывание -- т.е. поочерёдно разрешается прерывание от первого или второго выхода.

Алгоритм полностью решает проблему "дребезга", когда валкодер колеблется на краю метки (быстрая смена +1, -1, +1, -1...) -- не имея возможности его, валкодер, опрашивать с достаточно большой частотой можно потерять в точности, или же, используя прерывания легко заблокировать весь микроконтроллер исключительно в процессе обработки прерываний от валкодера. С описанным алгоритмом подобных проблем нет.


--------------------
[ZX]
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 16 2007, 08:25
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Спасибо, думаю a14.gif
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 16 2007, 15:45
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Мне тут посоветовали применить компъютерную мышь! Что вы думаете по этому поводу?
Go to the top of the page
 
+Quote Post
676038
сообщение Nov 16 2007, 19:39
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 31
Регистрация: 25-07-06
Пользователь №: 19 070



Мой опыт смотри здесь:
http://electronix.ru/forum/index.php?s=&am...st&p=218642
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 17 2007, 15:33
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Ходил по ссылке, читал. Так вы закончили этот проект?
Если это возможно, хотелось бы посмотреть на код, желательно на Си!
Go to the top of the page
 
+Quote Post
676038
сообщение Nov 17 2007, 18:29
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 31
Регистрация: 25-07-06
Пользователь №: 19 070



По ссылке выше во вложении есть весь проект на С (компилируется и работает, как это было описано там) для IAR.
Дальше эта работа не пошла по причинам, описанным там же.

Себе жа нашел совсем другой вариант решения опроса двух энкодеров и нескольких кнопок:
- Взял Atmega48-88-168, там есть pin change interrupt.
- На две линии порта повесил один энкодер, еще на две линии - другой энкодер, и на оставшиеся линии - кнопки. Затем опрос порта в обработчике прерывания.

Если это вариант интересен - могу описать подробнее.
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 18 2007, 17:44
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Цитата(676038 @ Nov 17 2007, 22:29) *
По ссылке выше во вложении есть весь проект на С (компилируется и работает, как это было описано там) для IAR.
Дальше эта работа не пошла по причинам, описанным там же.

Себе жа нашел совсем другой вариант решения опроса двух энкодеров и нескольких кнопок:
- Взял Atmega48-88-168, там есть pin change interrupt.
- На две линии порта повесил один энкодер, еще на две линии - другой энкодер, и на оставшиеся линии - кнопки. Затем опрос порта в обработчике прерывания.

Если это вариант интересен - могу описать подробнее.



Извините, я сразу не заметил. Буду разбираться с программой, если будут вопросы - задам. Спасибо
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Nov 20 2007, 15:29
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Я тут провёл один эксперимент. На макетке собрал схему: ATmega16, валкодер, индикация, кварц на 16 МГц. Валкодер подсоединил так: Выводы А и В на PA2 и PA3, средний вывод на землю.
Код привожу, если кому-то интересно.
Результаты такие: энкодер начал нормально работать , не так , как в предыдущих постах.
Начал эксперементировать с задержкой. До 2мс энкодер работает хорошо, потом начинаются глюки.
Теперь хочу посадить средний вывод на стробирование. Результаты отпишу позже.
Прикрепленные файлы
Прикрепленный файл  Valcoder.rar ( 26.52 килобайт ) Кол-во скачиваний: 115
 
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 23:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.04754 секунд с 7
ELECTRONIX ©2004-2016