Вопрос к специалистам! Энкодер часть 2.

evgeny_zaryanov
Offline
Зарегистрирован: 23.06.2012

Доброго времени суток товарищи!

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

Проблема заключается в следующем, когда я макетировал все я делал все на 328 меге, но перенеся все на 2560 выяснилось что у них есть серьезные отличия. На 328меге у меня при повороте энкодера вызывалась программа которая и занималась обработкой данных с энкодера (у меня там просто фиксация влево вправо и к одной из переменных мы прибавляем или удаляем число но суть не в этом)... Далее я все это перенес на 2560 и выяснилось что подпрограмма не вызывается, немного разобравшись выяснили что порты все же разные.. Переписал программу и ввел в основной цикл обработку энкодера, и все бы хорошо. Но при добавлении обработки аналоговых портов (чтения) энкодер жутко тормозит. Энкодер это главный орган управления трансивера, но и аналоговые надо считывать. Все вместе если то энкодер тормозит.. Отказаться от одного и другого ни как..

По этому прошу помощи у специалистов, энкодер находится на 2 и 3 цифровом порте, перекинуть ни как т.к. плата самодельная. Мне нужно сделать так чтоб обработка энкодера вызывалась и была отдельной подпрограммой именно с этих портов. Использовал библиотеку Rotary.. Я все перерыл перечитал но не понимаю этих тонкостей, помогите пожалуйста!!! 

sadman41
Offline
Зарегистрирован: 19.10.2016

Помочь чем?

evgeny_zaryanov
Offline
Зарегистрирован: 23.06.2012

sadman41 пишет:

Помочь чем?

ПРиветствую!

Вот этот код оптимизировать под 2560.

/*
    Rotary Encoder - Interrupt Example
    
    The circuit:
    * encoder pin A to Arduino pin 2
    * encoder pin B to Arduino pin 3
    * encoder ground pin to ground (GND)
*/
 
#include <Rotary.h>
 
Rotary r = Rotary(2, 3);
 
void setup() {
  Serial.begin(9600);
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
}
 
void loop() {
 
}
 
ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result == DIR_NONE) {
    // do nothing
  }
  else if (result == DIR_CW) {
    Serial.println("ClockWise");
  }
  else if (result == DIR_CCW) {
    Serial.println("CounterClockWise");
  }
}
sadman41
Offline
Зарегистрирован: 19.10.2016

Не совсем понимаю, на чем вы отсчитываете ноги, но если ваша конструкция аналогична Arduino Mega2560, то почему бы не воспользоваться следующей конструкцией: attachInterrupt(digitalPinToInterrupt(_пин_на_котором_висит_энкодер_), _имя_функции_обработки_энкодера_, CHANGE) ?

https://www.arduino.cc/reference/en/language/functions/external-interrup...

evgeny_zaryanov
Offline
Зарегистрирован: 23.06.2012

К сожалению опыта нету, я примерно понял что вы имеете ввиду, попробую сейчас.
Т.е. с ваших слов у нас получается следующее: Мы следим за изменением ноги (допустим 2) где висит энкодер, если произошло изменение то запускаем подпрограмму где и происходит обработка энкодера? 

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, можете следить, конечно... функция attachInterrupt() языка Wiring делает то же самое, что и вы написали в setup() и цепляет вашу функцию-обработчик к ISR для внешнего прерывания, связанного с определенным пином (их ограниченное количество). Только всё это скрыто под капотом.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

evgeny_zaryanov пишет:

К сожалению опыта нету, я примерно понял что вы имеете ввиду, попробую сейчас.
Т.е. с ваших слов у нас получается следующее: Мы следим за изменением ноги (допустим 2) где висит энкодер, если произошло изменение то запускаем подпрограмму где и происходит обработка энкодера? 


Как раз не следим.
Следим - это когда регулярно читаем, опрашиваем.
А тут приходит прерывание и программа его обрабатывает немедленно.

evgeny_zaryanov
Offline
Зарегистрирован: 23.06.2012

Попробовал, чтото не  отрабатывает.

вот кусок подпрогрммы и то что я вставил в основной цикл:

void enc() {
 
  unsigned char result = r.process();
  if (result == DIR_NONE) {
  }
  else if (result == DIR_CW) {
    st = st + ss;
   ch();
   lcd_up();
   // Serial.println(f);
  }
  else if (result == DIR_CCW) {
    st = st - ss;
    ch();
    lcd_up();
    //Serial.println(f);
  } 
}
 
void loop() {
 
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), enc, CHANGE);
 
PS: Извиняюсь не внимательность.. надо было в Setup... Но только всеравно не работает.
 
sadman41
Offline
Зарегистрирован: 19.10.2016

interruptPin = 2 ?

И не шарахайте туда сложные вычисления, хватит просто одного Serial.println() в период отладки. Потом, конечно, никаких продолжительных вызовов из обработчика не делайте. Если INPUT_PULLUP сделали пину, то позамыкайте его на GND - обработчик должен вызываться.

Хотя, конечно, для начала надо бы определиться: 2 - это вывод чего? Чипа или Arduino-вский...

evgeny_zaryanov
Offline
Зарегистрирован: 23.06.2012

Все выводы что я пишу это выводы Arduino!

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

evgeny_zaryano,

во-первых, присоединить функцию к прерыванию нужно один раз, а не повторять это миллион раз в секунду.

Во-вторых,  в прерывании нужно лишь фиксировать тот факт, что что-то случилось. Например, фиксировать, что повернулся энкодер. Всю реакцию на это изменение нужно вынести из прерывания в основной цикл.

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Для написания программы надо сделать 4 этапа:1-написать ТЗ(техническое задание),2-составить проект программы,3 написать код,4 загрузить в плату и протестировать. И если программа не так работает или работа не устраивает, то делать по кругу 1->2->3->4. А точнее вносить изменения в каждую часть. И теперь конкретно. Вы просто не можете спроектировать программу- разделить на независимые части и найти место и роль энкодера в вашей программе. Вот от сюда и все Ваши непонятки.

5N62V
Offline
Зарегистрирован: 25.02.2016

Я делаю сейчас нечто похожее. У меня опрос энкодера происходит по прерыванию по таймеру раз в 250мкс, опрашивается и крутилка и кнопка выбора. Обработчик сделан как можно короче  - изменяются только две переменные : положение энкодера, и счетчик состояния "кнопка нажата". Ничего не тормозит.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

5N62V,где-то так. Возьмем к примеру компьютерную мышку. С одной стороны похоже на кнопку. Но с разаличном положении вызываются различные программы. Энкодер тоже похож на это. Обработчик энкодера выявляет события : поворот по часовой,поворот против и нажатие кнопки и если надо запускает уже обработчики этих событий. И разумеется функции обслуживающие эти события должны меняться в зависимости от позиции в меню. Вот почему я говорю, что перед тем как писать код желательно программу распланировать на листке бумаги, что бы знать что за что отвечает и что на что воздействует.

evgeny_zaryanov
Offline
Зарегистрирован: 23.06.2012

Товарищи! Спасибо большое, внимательно изучил ваши рекомендации. Разобрался с прерываниями. 
У меня вызов обработки энкодера идет по 2 и 3 порту и все работает замечательно, и аналоговые порты теперь в основном цикле опрашиваюися. И ничего в общем не тормозит!!! Работает помоему даже быстрее чем было. Единственно то что обновление экрана из подпрограммы энкодера весит все.. но я обновление экрана поставил в основной цикл. В общем все круто!!!! 

Спасибо всем большое! Для радиолюбителей 73!!! R0AGL!!!

5N62V
Offline
Зарегистрирован: 25.02.2016

evgeny_zaryanov пишет:

Спасибо всем большое! Для радиолюбителей 73!!! R0AGL!!!

Выйду на пенсию - тоже трансивер сделаю, руки аж чешутся.

73, mny dx, gl es will be gld cuagn.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

evgeny_zaryanov пишет:

...внимательно изучил ваши рекомендации...

...обновление экрана из подпрограммы энкодера весит все..

Рекомендации мало изучить, нужно еще им следовать.