Задача на сегодня: как определить угол поворота инкрементального энкодера?


Сегодня в серии публикаций про ардуино головного мозга коротенькая статья с небольшим экспериментом и парой рецептов. В комментариях к одной из моих прошлых статей меня обвинили в том, что ардуиной подсчитывать импульсы энкодера — фу так делать:
Оптически энкодер 1000/оборот и ATMega не имеющая аппаратной схемы работы с энкодером (как у серий STM32, например) — это тупик.
Дальше в комментариях было много теоретизирования, которое лучше пропустить. Давайте лучше попробуем протестировать в железе, насколько это тупик. Для начала, что такое инкрементальный энкодер? Тот, кто помнит эпоху до-оптических мышек, ответ знает точно. Внутри энкодера есть диск с прорезями, вот для наглядности я сделал фотографию диска с пятьюстами прорезями:



С одной стороны этого диска помещают светодиод, с другой фотодиод:



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

Как же определяется направление вращения? Очень просто: в датчике не одна, а две пары светодиод-фотодиод. Давайте нарисуем наш диск, точки A и B показывают положение фотодатчиков. При вращении вала энкодера снимаем два сигнала с этих фотодатчиков:



Датчики поставлены на таком расстоянии, чтобы при вращении с постоянной скоростью генерировался меандр, свинутый на четверть периода. Это означает, что когда фотодатчик А стоит напротив середины прорези, то фотодатчик B стоит ровно на границе прорези. Когда датчик крутится (условно) по часовой стрелке, то при восходящем фронте на сигнале B сигнал A равен единице. Когда же датчик крутится в обратную сторону, то при восходящем фронте на сигнале B а равен нулю.

Это всё прекрасно, но что мне копипейстить в мой проект?


Вот это:

volatile long angle = 0;
volatile char ABprev = 0;
const int increment[16] = {0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0};

ISR (PCINT0_vect) { // D8 or D9 has changed
  char AB = PINB & 3;
  angle += increment[AB+ABprev*4];
  ABprev = AB;
}

void setup() {
  pinMode(8, INPUT);  // A
  pinMode(9, INPUT);  // B
  PCICR |= (1 << PCIE0);  // interrupt will be fired on any change on pins d8 and d9
  PCMSK0 |= 3;
  ABprev = PINB & 3;
  Serial.begin(115200);
}

void loop() {
  Serial.println(angle);
  delay(100);
}

Давайте объясню, как этот код работает. Я тестирую код на ATmega328p (Arduino nano), выходы энкодера поставлены на пины d8 и d9 arduino nano. В терминах ATmega328p это означает, что младшие два бита порта PINB дают текущее состояние энкодера. Функция ISR будет вызвана при любом изменении в этих двух битах. Внутри прерывания я сохраняю состояние энкодера в переменную AB:

  char AB = PINB & 3; // Внимание, ардуиновский digitalRead() противопоказан, 
                  // когда нам критична скорость работы

Для чего? Давайте посмотрим на предыдущий график, в нём пунктирными линиями обозначены моменты вызова прерывания (любой фронт на любом сигнале). Для каждого вызова прерывания цифры внизу — это состояние переменной AB:



Видно, что при вращении по часовой стрелке переменная AB меняется с периодом в четыре значения: 231023102310. При вращении против часовой стрели переменная AB меняется 013201320132.

Если у нас оба фотодатчика были перекрыты (переменная AB=0), а при вызове прерывания AB становится равной 2, то датчик вращается по часовой стрелке, добавим к счётчику единицу. Если же AB переходит от 0 к 1, то датчик вращается против часовой стрелки, отнимем единицу от счётчика. То же самое и с другими изменениями переменной AB, давайте составим таблицу:



Обратите внимание, что таблица заполнена не до конца. Что вставить на месте вопросительных знаков? Например, по идее, главная диагональ таблицы не должна использоваться никогда, прерывание вызывается при изменении переменной AB, поэтому перехода 0->0 случаться не должно. Но жизнь штука тяжёлая, и если микроконтроллер занят, то он может пропустить несколько прерываний и таки вызваться. В таком случае предлагаю ничего не прибавлять и не отнимать, так как нам явно не хватает данных; заполним недостающие клетки нулями, вот наша таблица:

const int increment[16] = {0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0};

Теперь, надеюсь, код понятен полностью.

В итоге на один период сигнала A у нас вызывается четыре прерывания, что при вращении датчика в одну сторону увеличит счётчик не на 1, но на 4. То есть, если на инкрементальном энкодере написано 2000PPR (две тысячи прорезей на диске), то реальное его разрешение составляет 1/8000 оборота.

Постойте, а что с дребезгом?


Пропуская синусоиду через компаратор, мы неизбежно получим дребезг на фронтах нашего сигнала прямоугольной формы. Давайте возьмём лупу и посмотрим на один фронтов:



Сигнал A постоянный, поэтому согласно нашей табличке, на восходящем фронте сигнала B мы добавляем единицу, а на нисходящем вычитаем. В итоге, если мы сумеем отработать все фронты нашего дребезга, то наш алгоритм его прекрасно проглотит. И вот тут становится интересно, а сможет ли наша ардуинка отработать такие прелести? Теоретизировать можно долго, давайте ставить эксперимент.

От теории к практике


Считать импульсы будем тремя способами:

Все три способа считают импульсы абсолютно одинаково, но, разумеется, хардверные способы имеют существенно большую скорость опроса сигналов. Энкодер используется Omron E6B2-CWZ6C (2000PPR).

Подключение


Софтверный счётчик


Подключение простейшее, достаточно два провода от энкодера завести на ноги d8 и d9 ардуины.

HCTL-2032


Подключение hctl-2032 к ардуине выглядит примерно вот так:



Чтобы не занимать все ноги ардуины, я поставил ещё 74hc165.

BeagleBone Blue




BeagleBone Blue имеет встроенный квадратурный декодер, поэтому 3.3В энкодеры можно просто завести на соответствующий коннектор. У меня энкодер имеет 5В логику, поэтому я добавил двусторонний преобразователь уровней на bss138:



Эксперимент первый


Я взял свой стенд с маятником, который уже описывал:



Каретка ездить не будет, просто повешу три счётчика на энкодер маятника. Почему именно маятник? Потому что сила тяжести даёт неуплывающий маркер: каждый раз, как маятник успокаивается в нижем положении, счётчики должны показывать число, кратное 8000 (у меня энкодер 2000ppr).

Вот три счётчика, подключенные параллельно, сверху вниз: биглбон, софтверный счётчик, hctl2032. ШИМ-драйвер для двигателя каретки в данном тесте не используется:



Начало испытаний, маятник неподвижен, два монитора последовательных портов и счётчик биглбона, запущенный по ssh:



Рукой делаю один полный поворот маятника, жду, пока он снова успокоится в нижнем положении:



Все три счётчика показывают ровно 8000, как и положено! Хорошо, из комментариев мы вынесли, что из-за дребезга софтверный счётчик должен сильно ошибаться при низких скоростях маятника. Десять раз повторяю процедуру: качаю маятник так, чтобы он сделал один оборот, а затем жду, пока полностью успокоится. Затем снова качаю, жду, покуда успокоится. Трение низкое, одна итерация занимает пару минут, в итоге примерно полчаса работы счётчиков.



Ха, а ведь опять ни один не ошибся!

Эксперимент второй


Итак, дребезг в реальности оказался не столь страшным, как казалось. Снимаю маятник, и цепляю к оси энкодера шуруповёрт:



Дальше потихоньку увеличиваю обороты, периодически останавливаясь, и проверяя, насколько все три счётчика согласны с происходящим. Именно поэтому у меня в одном из окон есть оценка скорости вращения вала энкодера.

100 оборотов в минуту — порядок. 500 оборотов в минуту — порядок, согласие полное. 900 оборотов в минуту: АГА! Останавливаю шуруповёрт:



Хардверные счётчики по-прежнему согласны между собой, а вот софтверный прилично отстал. Давайте считать, насколько это согласуется с теорией. Мануал на ATmega328p говорит, что обработка (пустого) прерывания — это минимум 10 тактов микроконтроллера. Работа со стеком, чуть кода внутри прерывания — это в сумме тактов 40 на одно прерывание. 8000 тысяч прерываний на 900 оборотов в минуту (15 оборотов в секунду) на 40 тактов = 4800000 тактов в секунду. В целом наша оценка весьма недалека от тактовой частоты ардуины, то есть, 1000 оборотов в минуту — это потолок для счётчика энкодера высокого разрешения на прерываниях, причём для ардуины, которая не делает ничего другого.

На 2000 оборотов в минуту оба хардверных счётчика работали без рассогласований, а больше у меня шуруповёрт выдать не может.

Подведём итог:


1. Считать на прерываниях вполне можно, 15 оборотов в секунду — это всё же весьма приличная скорость. Но если нужно обрабатывать больше одного счётчика, всё становится резко хуже. Выбор энкодера играет сильную роль, так как в хороших энкодерах подавление дребезга есть внутри, поэтому хороший энкодер и копеечный 8-битный микроконтроллер — вполне себе решение.

2. Хардверные счётчики надёжнее, но дороже.

3. hctl2032 существенно дешевле BeagleBone Blue, но и сложнее подключается к контроллеру, а биглбон и сам себе контроллер, и умеет четыре энкодера разом обрабатывать. Да и усилитель для двигателя там уже есть на борту, поэтому стенд с маятником можно собрать вообще малой кровью. С другой стороны, даже будучи довольно экзотичной, hctl-2032 стоит пять долларов за штуку, и может спасти ситуацию, когда схема с каким-нибудь пиком или атмелом уже есть, и сильно менять её не хочется.

4. Говорят, stm32 и дёшев, и имеет хардверный счётчик. Но цена вхождения (в смысле времени) в вопрос больно кусается.

В общем, как обычно, идеального решения нет, всё зависит от задачи и от доступных ресурсов.

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


  1. rstepanov
    18.10.2017 23:01

    Спасибо, интересный эксперимент


  1. Shtucer
    18.10.2017 23:02

    angle += increment[AB+ABprev*4];

    сильно ли изменит картину замена операции умножения сдвигом?


    1. haqreu Автор
      18.10.2017 23:02

      не изменит вообще, gcc сам ставит сдвиг вместо умножения в ассемблере


  1. GarryC
    18.10.2017 23:15

    Если позволите, два соображения по поводу точности софтверного варианта:
    1. Может влиять вывод в сериал при собственно формировании вывода (они обожают блокировать прерывания) и при собственно передаче (во время прерывания после очередного байта).
    2. Дребезг может быть слишком быстрым и к моменту считывания текущего значения в прерывании Вы теряете, к примеру +1 и делаете лишнюю -1.
    Посоветовал бы попробовать вариант с отключением прерывания по тому пину, что только что сработал и оставлять второй, и так их постоянно менять — тогда дребезг просто не заметен и таблица инкрементов становится проще — лет 10 назад я так делал с обычными, не настолько быстрыми, энкодерами — получалось неплохо.


    1. haqreu Автор
      18.10.2017 23:19

      Если отключать прерывание по сработавшему пину, то тогда плохо будет отрабатываться смена направления, разв нет?


      1. GarryC
        18.10.2017 23:22

        Это так, но приводит только к +-1 при смене направления и не накапливается, что есть очень хорошо.


        1. haqreu Автор
          18.10.2017 23:22

          Интересное замечание, спасибо большое!


    1. ploop
      19.10.2017 10:27

      2. Дребезг может быть слишком быстрым

      4. Дребезга может не быть вообще, т.к. в правильном энкодере он подавлен аппаратно.


  1. areht
    19.10.2017 00:57

    > 4. Говорят, stm32 и дёшев, и имеет хардверный счётчик. Но цена вхождения (в смысле времени) в вопрос больно кусается.

    А в чем сложность? Туда же вроде тот же код ардуины можно залить, не?


    1. haqreu Автор
      19.10.2017 01:11

      Я могу только в режиме «Мойша напел», так как сам вопросом не владею. Возможно, уже допилили оболочку ардуины для поддержки stm32, но относительно недавно я ещё читал статью, где до мигания светодиодом дошли в конце второй, причём не самой короткой, статьи:
      статья 1
      статья 2


      1. areht
        19.10.2017 01:58

        Не, там про нативную разработку, это совсем другая история (тем более на асме).

        Я сам то с обычной ардуины на ESP перепрыгнул. Там именно код от ардуины «как есть» можно брать, через ту же arduino IDE (хотя я взял VisualStudio). И забыть про нехватку памяти и производительности.

        Вроде и для STM так можно, только настроить один раз по инструкции.

        Правда как хардверный счётчик цеплять — это отдельно надо думать, но вообще производительности STM может и на софтверном хватить с большим запасом.


  1. poznawatel
    19.10.2017 03:43

    > 4. Говорят, stm32 и дёшев, и имеет хардверный счётчик. Но цена вхождения (в смысле времени) в вопрос больно кусается.
    А если stm32+Micropython?


  1. Ghost_nsk
    19.10.2017 06:51

    А не проще ставить прерывание по фронту только на одну ногу, а в прерывании читать состояние второй, её состояние и будет направление движения? кода меньше, скорость больше.


    1. Arastas
      19.10.2017 12:04

      Если я правильно понял предложение, то в два раза падает точность. Вместо четырёх отсчётов на прорезь получится два.


      1. Ghost_nsk
        19.10.2017 14:51

        если только по фронту то в 4, но надо ли оно при 2000ppr? Нужна ли точность в 3 минуты при 1000+RPM? Зато учитывая что при текущей схеме оно обрабатывает до 1000rpm, то при моей будет условно до 4000


  1. Armleo
    19.10.2017 08:03

    Мда… STM32 Blue Pill стоит 1.8$. Ардино 3$. Помоему ардуино просто лишняя трата денег. В stm32 частота выше, а код пишеться за 5 минут не спешего ковыряние STM32CubeMX, одного make, openocd -l stm32f103c8t6.cfg --init


    1. haqreu Автор
      19.10.2017 08:52

      Предлагаю эксперимент. Я за свои деньги покупаю blue pill, затем ставлю секундомер, если за 10 минут я не могу воспроизвести подсчёт энкодера с выводом в последовательный порт, то вы мне возмещаете потраченные деньги.


      1. Armleo
        19.10.2017 08:57

        Купите blue pill за 1.8$. Я настолько уверен, что готов сделать перевод денег, хоть сейчас. Но подождите я щас вам статью забацаю :).


        1. Armleo
          19.10.2017 08:58

          (1.8$ с бесплатной доставкой)


        1. haqreu Автор
          19.10.2017 08:59

          Хорошо, спасибо за совет, заказал пару плат. Ехать будут недели три, так что ждать статьи перед заказом ни к чему :)


          1. Armleo
            19.10.2017 09:26

            Рекомендую еще st-link заказать. Отладка с ним просто рай. И хорошо, что два. Из одного можно сделать BLACK MAGIC PROBE


            1. haqreu Автор
              19.10.2017 13:38

              Докупил и его, спасибо. Жду статью!


            1. holomen
              19.10.2017 16:52

              А из третьего Jlink-OB


      1. x67
        19.10.2017 14:14

        А вы уверены, что впервые прикоснувшись к ардуино, вы написали бы это за 10 минут?


        1. haqreu Автор
          19.10.2017 14:15

          Подскажите, где я это утверждал?


  1. Valentinec
    19.10.2017 08:29

    Хм. В даташите на atmega328p в разделе 27 описан аппаратный компаратор. Он умеет генерировать прерывания по изменению состояния на выходе. Можно попробовать считать импульсы на нем. Для определения направления не годится — он однопороговый.


    1. Alyoshka1976
      20.10.2017 08:47

      Компаратор там вполне годный, я на нем импульсный металлодетектор делал.


  1. WFrag
    19.10.2017 09:10
    +2

    С STM32 ситуация такая, что там программно особо ничего не сделаешь с дребезгом, если подсчёт через таймер делать. Я смог 100% побороть только аппаратно, через фильтр + триггер Шмитта.


  1. roboter
    19.10.2017 09:38

    Я ардуинщик так что сильно не пинайте за вопросы.
    на некоторых atmel только 2 прерывания, как быть если надо несколько энкодеров?
    даже если есть несколько прерываний не будут ли они конфликтовать при одновременной работе?


    1. haqreu Автор
      19.10.2017 09:44
      +1

      на некоторых atmel только 2 прерывания


      Я не очень понял, можете пояснить?


      1. roboter
        19.10.2017 10:28

        Например UNO int0, int1 получается можно подключить только один энкодер?
        image


        1. haqreu Автор
          19.10.2017 12:19
          +1

          А, это среда ардуины умеет только два, сам микроконтроллер умеет больше. Посмотрите параграф 13.2.8 руководства на микроконтроллер.


          1. roboter
            19.10.2017 12:38

            The External Interrupts are triggered by the INT0 and INT1
            pins or any of the PCINT23...0 pins.

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


            1. kotomyava
              19.10.2017 14:05

              Там ещё есть прерывания по изменению уровня на пине, т.е. не два, а
              EXT_INT0, EXT_INT1, PCINT0, PCINT1, PCINT2 т.е. 5. И потенциально можно использовать как внешнее прерывание ANA_COMP(от встроенного компаратора).


  1. Zolg
    19.10.2017 09:54

    А кто вам чушь про дребезг на плавно меняющихся фронтах рассказал?
    Расскажите ему про гистерезис логических уровней.
    'дребезг' в данном случае может возникнуть только если энкодер физически вибрирует.


    1. ploop
      19.10.2017 10:32

      Энкодеры бывают (да и в 100500 раз популярнее у любителей) механические. Да да, это те самые ручки. Там дребезг имеет место быть.
      Правда там угол вычислять не требуется, но всё равно вещь неприятная, и аппаратно никак не давится без дополнительной схемы, в отличии от промышленных оптических, где всё уже внутри.


      1. Zolg
        19.10.2017 10:49

        Ага, а бывают еще на датчиках холла или вообще потенциометры многооборотные.
        Но в данной конкретной статье, в данном конкретном устройстве, автор использует оптический и героически пытается найти у него дребезг.

        ps:
        Вы много видели механических энкодеров с разрешением бОльшим нескольких десятков импульсов? А это уже немного другие временнЫе параметры и дребезг там вполне можно давить софтово.


        1. haqreu Автор
          19.10.2017 12:20

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


          1. Zolg
            19.10.2017 13:21

            компаратор без гистерезиса?


            1. haqreu Автор
              19.10.2017 13:27

              Видимо да, т.к. дребезг присутствует.


              1. mayorovp
                19.10.2017 14:17

                Так ведь можно выход на один из входов кинуть и получить гистерезис с нужными характеристиками. Или там диапазоны напряжений разные?


                1. haqreu Автор
                  19.10.2017 14:20

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


                  1. mayorovp
                    19.10.2017 14:21

                    Ну, тут разница между приличным и неприличным энкодером в один резистор выходит...


                    1. kotomyava
                      19.10.2017 14:27

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


                      1. haqreu Автор
                        19.10.2017 14:39

                        К чему эта высокомерность? Если можете привести код без «костылей», был бы очень благодарен.


                        1. kotomyava
                          19.10.2017 15:14

                          Это не высокомерность: просто смысл давить дребезг программно, да ещё в очень ограниченных ресурсах, есть, в основном, тогда, когда у вас готовое устройство в котором забыли сделать это аппаратно.

                          Ну и подавляющее большинство тех, кто балуется с ардуино, пришли из программирования в лучшем случае, или вообще со стороны, а не из схемотехники, или тем более, проектирования встраиваемых систем, и не имеют профильного образования. Т.е. это не высокомерие, это констатация факта — многие просто не знают о том, как это делается. И уровень поделок на ардуино весьма низок, как и порог вхождения, кстати.


    1. izzholtik
      19.10.2017 11:24

      В прошлой статье комментарии посмотрите, там какой-то душевнобольной целый день втирал дичь про волшебный STM и невозможность подавления дребезга другими способами.


  1. Arastas
    19.10.2017 12:13
    +1

    У высокоточных оптических энкодеров нет перобразования синусоиды в меандр. Вместо этого есть специальные коробочки (умножители), которые анализируют две входны синусоиды A и B и по ним восстанавливают угол с повышенной точностью. Например, 1000 отсчётов на прорезь.
    Это я так, для информации, захотелось поделиться.


    1. haqreu Автор
      19.10.2017 12:32

      Дурацкий вопрос: а корректно ли вообще использовать слова «синусоида» и «меандр» применительно к энкодерам? Ведь они же не с постоянной скоростью вращаются…


      1. Arastas
        19.10.2017 12:43

        Про меандр можно пообсуждать и подокапываться до формальных определний, а про синусоиду — можно. То есть y1=sin(t) это гармонический сигнал, синусоида времени, периодическая функция и всё такое. А y2=sin(phi(t)) — это синусоидальная функция с аргументом phi. Про y2 можно говорить "синусоида угла", но не стоит говорить "гармоническая функция".
        Вообще, это всё вопрос терминологий и догворённостей. Например, сумму двух гармонических функций уже нельзя называть периодическим сигналом, но все называют. Главное, чтобы люди друг друга понимали. :)


        1. haqreu Автор
          19.10.2017 14:18

          Главное, чтобы люди друг друга понимали. :)


          Ну я как бы согласен, но меня тут уже не раз закидывали тухлыми яйцами за нестрогое следование терминологии. Этажинтернет ;)


  1. Crazy_Pit
    19.10.2017 12:21

    вообще я не увидел антидребезг. а без него нельзя. все три счетчика посчитают дребезг правильно. а количество пройденных оборотов неправильно. самое правильное это конечно на stm 32 квадратурный аппаратный счетчик.
    можно посмотреть реализацию в проекте по «автономному контроллеру на stm32»


    1. haqreu Автор
      19.10.2017 12:22

      Подскажите, а чем квадратурный аппаратный счётчик STM32 лучше квадратурного аппаратного счётчика ARM8 или квадратурного аппаратного счётчика hctl2032, описанных в статье?


  1. ZlodeiBaal
    19.10.2017 14:48

    А почему не код Грея? Тогда энкодер можно абсолютным сделать.


    1. haqreu Автор
      19.10.2017 15:30

      Не надо менять сценарий по ходу пьесы! У меня была задача именно инкрементальный энкодер считать. А абсолютные того же разрешения стоят совсем других денег. Инкрементальный энкодер 2000ppr даёт разрешение 1/8000 оборота, стоит 30 долларов. Сколько стоит 13 битный энкодер с кодом Грея?


      1. syrompe
        19.10.2017 17:18

        Лучше посмотрите в сторону AS5048A и им подобных.


  1. Vindicar
    19.10.2017 15:12

    Я по ходу работы столкнулся с такой же задачей.
    Есть оптический энкодер ЛИР-158Б, и к нему родной преобразователь ЛИР-917 с выходом на USB. Производитель уверяет что преобразователь тянет частоту запросов до 50Гц, а мне для задачи (оценка ускорений при разрушении маятником образца) требуется суб-миллисекундная точность. Потому тоже пробую приспособить Arduino Uno для чтения энкодера. Поначалу повторил вашу мысль о таблице преобразований, но затем упростил её до следующей логики (упрощенно):

    volatile bool StateA, StateB; //глобальные, инициализируются при запуске чтением ножек.
    volatile long Coord; //глобальная, при запуске 0
    // Прерывание по каналу A датчика угла поворота
    void interruptChannelA() {
      // меняем состояние канала (чтобы не делать digitalRead())
      StateA = !StateA; 
      // корректируем координату
      if (StateA != StateB) Coord++;
      else Coord--;
    }
    
    // Прерывание по каналу B датчика угла поворота
    void interruptChannelB() {
      // меняем состояние канала (чтобы не делать digitalRead())
      StateB = !StateB;
      // корректируем координату
      if (StateA == StateB) Coord++;
      else Coord--;
    }
    


    Собственно скорости вращения небольшие, порядка 5-10 радиан/сек (60-100 rpm).
    Проблема в памяти — 2КБ всё-таки маловато для регистрации даже одного маха маятника (я регистрирую число микросекунд, прошедших с предыдущего тика энкодера). Но если верить вашим результатам, хотя бы с быстродействием все будет в порядке.


    1. haqreu Автор
      19.10.2017 15:33

      Я не понял, что именно вы хотите хранить в памяти? Динамику поведения маятника? Почему бы её не выдавать наружу вместо хранения внутри ардуины? Пусть хранят те, у кого память есть.


      1. Vindicar
        19.10.2017 17:38

        Да, динамику поведения.
        Проблема в том, что по моим подсчетам получается следующее:
        6 радиан/сек дают порядка 9500 тиков энкодера в секунду. Я собираюсь передавать интервалы между тиками в микросекундах, т.е. у меня будет 1 пакет на тик.
        Максимальная заявленная скорость виртуального серийного порта для Uno — 115200 бод, что даёт порядка 11КБ/с. Т.е. я успеваю передавать данные быстрее, чем они генерируются, только если каждый тик будет кодироваться 8-10 битами — а такой разрядности мне может не хватить.
        Сейчас я планирую использовать ОЗУ ардуины как кольцевой буффер, с таким расчетом чтобы он не успел переполниться за характерный интервал измерения. Но все равно, как-то ненадежно.
        И всё это при допущении, что Ардуино реально вытянет эти 11КБ/с. Если завязаться на протокол USB напрямую, наверняка можно выжать куда больше, но это уже сложнее чем написать Serial.begin(115200). =)


        1. haqreu Автор
          19.10.2017 17:40

          Не используйте последовательный порт, используйте SPI, он гораздо, гораздо быстрее. Я когда делал контур тока, выдавал с ардуины данные в SPI, читал их логическим анализатором, сохранял логи и парсил потом логи.


          1. Vindicar
            19.10.2017 17:48

            Интересная идея. Но если нужно ставить промежуточную ступень, то тогда проще уж сразу задействовать что-то с большим объемом памяти. Я Uno-то выбрал потому что дешево (для proof of concept, что я вообще смогу читать этот энкодер саомстоятельно) и потому что 5В выходы есть. Соотв. порог вхождения примерно на уровне плинтуса — как раз для меня. =)
            Соглашусь, это может быть оверкилл, но сейчас, на этапе прототипирования, простота может оказаться важнее.


  1. Stochkas
    19.10.2017 17:39

    это пять с большим плюсом


  1. alexey_public
    20.10.2017 08:41

    Я конечно все понимаю, но ATMega и STM32 — изначально сильно отличные микроконтроллеры.
    Но почему бы не взять Xmega — где вообще аппаратный блок для работы с энкодером.
    Причем та же Atmel студия, только библиотеки ASF для удобства.
    Я активно работаю над сложным проектом с STM32, но в своих проектах часто использую Atmel Xmega.
    Кроме того — у Atmel полно недорогих ARM процессоров, весьма доступных. От 100 руб. за штуку, и там тоже хватает интересной периферии. Те же M0+ — это 32 бита и 48 МГц. И даже в soic корпусе.


    1. holomen
      20.10.2017 23:39

      Вот только стм стартует от примерно 50р в розницу.


      1. alexey_public
        21.10.2017 09:25

        STM8 или STM32?


        1. holomen
          21.10.2017 18:42

          1. alexey_public
            21.10.2017 18:57

            Да, неплохо. У Atmel будет в два раза дороже.


  1. PKav
    20.10.2017 14:19

    Метод на прерываниях вообще непредсказуемый — никогда не угадаешь, найдется ли среди всех этих прерываний время для выполнения основного кода.

    А «Ардуино головного мозга» — это когда делают отдельную плату на STM32, которая считает энкодер и передает в Ардуину показания энкодера по UART.