Функция умного энкодера с ускорением

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

Добрый день всем. Это мой первый пост, прошу снисхождения если чего не так. Буду рад хорошим замечаниям.
Код инициализации взят отсюда mycontroller.ru/stm32-podklyuchaem-enkoder/
Только у меня ARR установлен в 0xFFFF
TIM3->ARR = 0xFFFF; //значение, до которого считает CNT
Код функции.

#define counts_in_clicking 2                           //  need to power of two!!
#define accum_destroyer  10 // should be less than 0x80 //With every accum_destroyer-th call accum will be divided by 2
uint16_t smart_encoder(int16_t enc_val){
    static uint8_t i=0;
    static uint16_t  enc_result=0, accum =0;
    static int16_t tmp=0;

    enc_val &=~((1<<counts_in_clicking)-1);               //  value on the right will calculated by preprocessor
    int16_t diff=(enc_val-tmp)/(1<<counts_in_clicking);
    if ((++i & 0x7F) ==accum_destroyer) i&=0x80, accum>>=1;   //if function was entered accum_destroyer-th time, then accum divided by 2
    probe=accum;
    if (diff==0) return enc_result;                     // exit if no changes
    tmp=enc_val;
    //if ((i>>8) == (((uint16_t)diff)>>16)){            //if rotation direction  stays the same
    if ((i>=0x80) == (0< diff)){            //if rotation direction  stays the same
        if (diff>0) accum += diff;
        else accum -= diff;
    }
    else {
            accum = 1;
            i^=0x80 ;}
                              //
    if (-diff*accum*accum<=enc_result) enc_result+=diff*accum*accum;     //enc_result should be positive
    else enc_result=0;
    return enc_result;
}

При вращении происходит накопление в accum и в последствии ускорение приращения. Если поменять направление вращения, то accum очищается, и можно сразу точно установить значение. Как то так…
Вызов функции.
DAC->DHR12R1=(enc_cnt=smart_encoder(TIM3->CNT));

Видео работы первой версии. youtu.be/FpdNiBT-gEQ
Видео работы второй версии.


Слева вверху — счетчик 100мс, справа вверху — значение CNT, справа внизу — результат работы функции.
Чип stm32f100c4, демоборд сделал сам, экранчик от нокии 1202. Светодиод заведен на цап1, в цап 1 загружаю полученное значение от функции смарт энкодер, в функцию передаю значение регистра CNT, функцию вызываю 10 раз в секунду, собственно как и все остальные.

Спасибо за внимание.

UDP. В коде закрались 2 некритичные ошибки, и поведение было не таким как я хотел. Эти ошибки я исправил. Так же чуть модифицировал код: разницу умножаю на accum в квадрате. Залил новую демонстрацию. Так же обращаю Ваше внимание, что функция «чувствует» каждое четвертое изменение счетчика CNT, так что для оценки коэф. нужно верхний счетчик в уме разделить на 4.

Комментарии (51)

RSS свернуть / развернуть
1) кат
2) видео не видно
0
3) перед демонстрацией широким массам «девборду» можно было и отмыть от флюса
4) видушка «не цепляет»
0
3) Никогда не мою канифоль в поделках для себя.
4) По плану было снять видушник на спине у подруги, но было поздно и она уже глубоко спала, я решил ее не будить. А так учту. Спасибо за критику.

А из видео я хотел что бы было понятно, что можно регулировать очень быстро, в то же время можно изменять по единице.
0
Зря не смываете канифоль! Тут даже не в эстетике дело…
+3
По плану было снять видушник на спине у подруги, но было поздно и она уже глубоко спала, я решил ее не будить.
ээхэ… здесь все достаточно взрослые и состоявшиеся в сексуальной жизни люди (я надеюсь), чтобы привлекать внимание голой женской спиной.
для привлечения внимания надо хоть на обнаженных сиськах снять. тогда точно аншлаг будет. но не очень долго… ;)
+2
1) Кат для чего?
2) Делал по инструкции с we.easyelectronics.ru/page/about/, почему не видно — не знаю.
0
мдя. плохо инструкцию читал.
Разбивка длинной записи
чтобы главная не засиралась. вот зачем.
0
Подскажите кто, как поправить видео. Спасибо.
0
Не очень силен в STM32… но в них должен быть специальный модуль (как у TMS320 от TI — QEP)…
Энкодер рукой крутите?
0
:) Прикольный ответ дает гугл по поиску: TI — QEP.
Да, у ТИ есть такой модуль в 32-разрядные DSP-микроконтроллерах TMS320x2833x.

(eQEP)The enhanced quadrature encoder pulse (eQEP) module is used for direct interface with a linear or rotary incremental encoder to get position, direction, and speed information from a rotating machine for use in a high-performance motion and position-control system
Не знаю, что можно с помощью него делать, может у стм есть такое же, но они это не называли столь звучно.
Если работали, то расскажите, с чем его едят.
0
(eQEP)The enhanced quadrature encoder pulse (eQEP) module is used for direct interface with a linear or rotary incremental encoder to get position, direction, and speed information from a rotating machine for use in a high-performance motion and position-control system
Вот с этим и едят!
0
Был бы уместен пример из практики.
0
Система управление приводом. Объект — ДПТ и исполнительный механизм (передача винт-гайка).
Один энкодер установлен непосредственно на валу двигателя а второй «ЛИР» к рабочему механизму.
0
коллега, не грузите ребенка.
0
Пардонте=)) Просьба была выдать пример! И так старался скромно
0
Кстати, возник вопрос!
А зачем оно надо? Это подстраивание для такой крутилки?
0
Если нужно установить значение в несколько тысяч, то нужно либо очень долго крутить крутилку, или делать это поразрядно и использовать еще одно управление для изменения разряда. Я в нете пару раз встречал высказывания людей, о том что не плохо бы придумать такой умный энкодер, но еще ни разу не видел реализации, хотя и не искал специально.
0
Может стоит расписать все это поподробнее в самом посте? Как-то там не очень понятно расписано зачем нужна:
функция умного энкодера
И как это все реализовывается.
0
Существуют «неспортивные решения».
0
А зачем оно надо?
на самом деле это очень востребованное поведение.
пример:
есть: энкодер с 25 шагов/оборот (те самые ширпотребные энкодеры с ибея по одному баксу за штуку)
применение:(для примера) паялка с максимальной температурой 450 градусов цельсия.

вариант раз: БЕЗ ускорения. два десятка полных оборотов — устанешь крутить. даже на плюс-минус сотню — это пять полных оборотов.
вариант два: с ускорением можно крутнуть в «плюс-минус», а там уже довернуть точно.
0
Да, на оси ничего не одето, и стараюсь крутить кистью.
0
А можно нубский вопрос? Что даёт это приращение регулируемого значения?
0
Приращение==изменение
0
мнддяяя…
нормально не понимаем…
КАААТ, Б… Я!!!
0
Объясните человеческим языком, я не понимаю чего вы хотите.
0
кста. давайте разберем первое предложение.
Добрый день всем. Это мой первый пост, прошу снисхождения если чего не так.
за это традиционно пинают. т.е. не приветствуется. или это я хабра перечитал?.. хз.
Буду рад хорошим замечаниям.
только хорошим комментариям? ;) тогда у меня для вас плохие новости…
0
Спасибо за критику, исправил.
0
А чего к сайту нормальнео всраивание любых роликов не прикрутят? Могу отправить говнокод, я у себя на сайте парсер правил.
0
Там все нормально, это я отошел от инструкции добавления, лишние CR да и ссылку не правильную взял.
0
А у меня в голове другой алгоритм вырисовался.

Пошли щелчки в одну сторону.
10 штук считаем по одному. Следующие 10шт по десять, следующие 10шт по 100. Если стали крутить в обратную сторону, то множитель не снимаем. Множитель снимается если подождали с пол секунды и перестали крутить, причем обратно уходит не сразу, а также, ступенчато. Тогда можно будет быстро докрутить до нужных значений, скорректировать если промахнулись на сотню другую, или десяток.
0
//if ((i>>8) == (((uint16_t)diff)>>16)){  //Кто подскажет, в чем ошибка?
у вас в правой части:
— всегда 0 — беззнаковое 16 битное значение сдвинуть поразрядно на 16 разрядов
— либо само значение diff — толи undefined, толи unspecified behavior — поведение не определено иными словами, т.к. сдвиг на величину большую или равную количеству разрядов.
— либо ещё чего, опять же по вышеуказанной причине.
в левой то же самое относительно значения i.
вероятно вы хотели сбвиги i>>7 и diff>>15.
if (!((i>=0x80) ^ (0< diff))){            //if rotation direction  stays the same
ксорить булевские значения — не аккуратно то как. лучше сразу сравнение примените. читаемость повыше, с сопровождением кода полегче.
0
блин, мимо. изначально хотел хальту ответить, что точная подкрутка может быть без предварительной паузы в магические пол секунды.
0
Благодарю.
0
Если реализовать на прерываниях, то алгоритм проще получается — достаточно сделать величину приращения обратно пропорциональной времени между прерываниями. Быстрее крутим — быстрее считается. Задержек никаких при этом не надо. Нужен только счетчик времени, но он, обычно, и так уже есть (часто нужен для других задач).
+2
Предложу свою идею. Сделать приращение значения нашей переменной нелинейной функцией от скорости вращения энкодера.

1. Измеряем скорость вращения (dx) на некотором промежутке (dt). Для простоты, пусть dt это одна секунда, и скорость у нас измеряется в щелчках в сек. Положительная при вращении в одну сторону и отрицательная в другую.

2. Через каждый интервал dt рассчитываем значение интересующей нас величины (x) как x = x + k * (dx^2), k – подбираем исходя из удобства использования.

Например, для k = 1:
крутим энкодкр медленно, со скоростью один щелчок в сек — получаем приращение х на единицу в сек. Крутим в два рада быстрее — приращение 4 единицы в сек. Крутанули со скоростью 10 щелчков в сек — получили за секунду приращение в 100 единиц и т. д.

Из минусов — интерфейс будет «лагать» на величину dt.
0
Можно уменьшить лаг до времени одного щелчка, если измерять не частоту, а период щелчков.
0
Да. Можно замерять время (dt) между «соседними» шелками. Тогда скорость будет w = 1 / dt, и пересчитывать переменную после каждого щелчка. Тогда лагать не будет (хотя первый щелчок после долгой паузы будет «теряться») и потребуется нецелочисленная арифметика.
0
(хотя первый щелчок после долгой паузы будет «теряться»)
Почему? Засчитывать его на минимльной скорости.
Еще в принципе можно замерять скорость, но умножать текущие щелчки на значение скорости с предыдущего замера. Тогда несколько лагать будет подстройка скорости, а не реакция на щелчки.
0
Почему? Засчитывать его на минимльной скорости.

Да, вариант.
Можно будет пробовать реализовать подобный интерфейс на практике, посмотреть насколько он удобен (я высказал только идею, на практике не проверял). Можно немного усложнить, и реализовать подобие «физического» интереса с эффектом «инерции от вращения».
0
«Физического» интереса?
0
Я имел ввиду подобие интереса кинематической прокрутки, когда эмулируется «физическое подобие» движения виртуальных объектов — ускорение, инерция…
0
Упс. Вроде как правильно этот эффект назвать «кинетической прокруткой» а не кинематической.
0
«физического» интереса
Физического чего? Тебе не кажется, что ты опечатался?
+1
Сразу не заметил. Да, естественно, отпечатался. Извиняюсь. Хотя в моих постах/комментариях, увы, постоянно куча ошибок и опечаток.
0
А на вопрос так и не ответил…
+1
А на вопрос так и не ответил…
Да, естественно, отпечатался

Хм, дружище, я, честно говоря, не сразу понял суть твоего комментария, пока несколько раз не перечитал свой ответ:) Наверное, можно было-бы списать все на автоисправление в LibreOffice – но я сам не верю в такую «отмазку»…
0
На первый вопрос. Хотя я и полагаю, что под «интерес» подразумевался «интерфейс», но на 100% в том не уверен.
0
Да, естественно речь шла о физическом интерфейсе
0
Зачем нецелочисленная? Можно обойтись if/else или switch/case для нескольких ступеней скорости.
0
В принципе можно. Нужно поэкспериментировать — на сколько ступеней нужно разбить скорость, что-бы реакция интерфейса выглядела естественно, например, как «кинематическая прокрутка» в интерфейсе смартфонов (с учетом того, что наша функция приращения нелинейна).
0
Вот не стоило менять заголовок без нужды. И засорять его всякими там «обновлено» комментаторы это и так увидят. А для тех кто впервые зашел сюда это не имеет значения.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.