Энкодер от прерывания INT1
- Войдите на сайт для отправки комментариев
Сб, 23/11/2019 - 18:15
Покритикуйте!
PCINT использовать нельзя, так как обрабатывает еще один энкодер, в loop тоже нельзя, в нём цикл 70 миллисекунд, использовать PCINT на других блоках тоже нельзя, при этом свободны пины INT0 и INT1
Сделал так:
/******* Простой энкодер *******/
#include <RotaryEncoder.h>
RotaryEncoder encoder(4, 5);
volatile int newPos;
unsigned long Freq = 300000;
static int pos = 0;
/*** Обработчик энкодера через ШИМ ***/
void startEncoder(){
attachInterrupt(1, Encoder2, RISING );
analogWrite(3,0x80); // установим на пине частоту
} // 490 гц скважность 2
void Encoder2(){ // процедура вызываемая прерыванием
encoder.tick();
}
void setMyFreq(int myPos){
Freq = Freq + ((newPos-pos)*100);
}
void setup(){
Serial.begin(115200);
startEncoder();
} // setup()
void loop(){
newPos = encoder.getPosition();
if (pos != newPos) {
setMyFreq(newPos);
pos = newPos;
Serial.println(Freq);
} // if
} // loop ()
// The End
Неужели всё правильно? Аж не верится...
И еще вариант: (код поправил, с учётом атомарности чтения)
/******* Простой энкодер *******/ #include <util/atomic.h> // для атомарности чтения данных в прерываниях #include <RotaryEncoder.h> RotaryEncoder encoder_0(2, 3); //Первый энкодер RotaryEncoder encoder_1(4, 5); //Второй энкодер volatile int newPos; unsigned long Freq = 300000; static int pos = 0; /*** Обработчик энкодера через ШИМ *** void startEncoder(){ attachInterrupt(1, Encoder2, RISING ); analogWrite(3,0x80); // установим на пине частоту } // 490 гц скважность 2 void Encoder2(){ // процедура вызываемая прерыванием encoder.tick(); } */ void setMyFreq(int myPos){ Freq = Freq + ((newPos-pos)*100); } // Обработчики прерываний ISR(PCINT0_vect) { encoder_1.tick(); // just call tick() to check the state. } /* ISR(PCINT1_vect) { encoder.tick(); // just call tick() to check the state. }*/ ISR(PCINT2_vect) { encoder_0.tick(); // just call tick() to check the state. } void setup(){ Serial.begin(115200); PCICR |= (1 << PCIE0); PCMSK0 |= (1 << PCINT1); // Обработчик прерывания на пине 9 analogWrite(9,0x80); // будем шимить пин с частотой 490 герц PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); // startEncoder(); // Configure interrupt for rotary encoder and enable. // D8 .. D13 - генерируют запрос прерывания PCINT0 // PCICR |= (1 << PCIE0); // PCMSK0 |= (1 << PCINT0) | (1 << PCINT1) | (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4) | (1 << PCINT5); // A0 .. A5 - генерируют запрос прерывания PCINT1 // PCICR |= (1 << PCIE1); // PCMSK1 |= (1 << PCINT8) | (1 << PCINT9) | (1 << PCINT10) | (1 << PCINT11) | (1 << PCINT12) | (1 << PCINT13); // D0 .. D7 - генерируют запрос прерывания PCINT2 // PCICR |= (1 << PCIE2); // PCMSK2 |= (1 << PCINT16) | (1 << PCINT17) | (1 << PCINT18) | (1 << PCINT19) | (1 << PCINT20) | (1 << PCINT21) | (1 << PCINT22) | (1 << PCINT23); // sei(); //для этой библиотеки в примерах нет этого } // setup() void loop(){ ATOMIC_BLOCK(ATOMIC_RESTORESTATE){newPos = encoder_1.getPosition();} if (pos != newPos) { setMyFreq(newPos); pos = newPos; Serial.println(Freq); } // if } // loop () // The EndДа. Оба верно, закрывай тему ;)
Да. Оба верно, закрывай тему ;)
через три года начал что-то понимать в вашем лживом СИ )))
Просто Ложик уже наливки накидался, ему сейчас всё равно.
А так... оба варианта имеют потенциальный баг из-за отсутствия атомарности в операции чтения позиции.
Просто Ложик уже наливки накидался, ему сейчас всё равно.
А так... оба варианта имеют потенциальный баг из-за отсутствия атомарности в операции чтения позиции.
поясни плиз
http://arduino.ru/forum/programmirovanie/preryvaniyaserial-budet-li-konflikt
http://arduino.ru/forum/programmirovanie/preryvaniyaserial-budet-li-konflikt
вызываю библиотечную функцию, в примерах автор оборачивать вызов не приводит, может сама функция внутри библиотеки обёрнута?
нет, не обёрнута и, вроде особого смысла нет
RotaryEncoder::getPosition() { return _positionExt; } // getPosition()Можете за это свечку поставить - авось поможет Господь.
Какая связь между библиотечной функцией, её автором и прерыванием?
Можете за это свечку поставить - авось поможет Господь.
Какая связь между библиотечной функцией, её автором и прерыванием?
сломаться жеж она может только в этой функции, если я что-то понимаю? (строка 28 первого скетча)
Прочитаем ещё раз... http://arduino.ru/forum/programmirovanie/preryvaniyaserial-budet-li-konflikt#comment-406308
Прочитаем ещё раз... http://arduino.ru/forum/programmirovanie/preryvaniyaserial-budet-li-konflikt#comment-406308
это-то понятно, меня интересует другое, прерывание будет поставлено в очередь и отработано, INT0 и INT1 обязаны, а вот PCINT? Что-то об этом не нашёл
А воще sadman41 в чем то прав, а в чем то нет. К наливке я еще только вот щас приступлю, тут он не прав. А про атомарность - смотрите какой несчастный случай возможен. Допустим _positionExt равна 0х000000ff. Мы вызвали getPosition(), она побайтово начинает копировать данные, пусть с конца (без разницы если с начала) скопировало 0хff, и тут прерывание ввалило. И сделало +1, теперь 0х00000100. Вернувшись из прерывания продолжается копирование остальных 3-х байт и имеем 0х000001ff. Херня 8| Правда на следующем вызове getPosition() мы таки получим 0х00000100, но неприятный осадочок останется.
А что, PCINT получило четвертной без права переписки?
https://microchipdeveloper.com/8avr:int
Испугано глянул себе в либу енкодера.
word Get(void) { volatile word t; cbi(PCICR, PCIE0); t = m_Val; sbi(PCICR, PCIE0); return t; };Ниче , с наливкой покатит.
А воще sadman41 в чем то прав, а в чем то нет. К наливке я еще только вот щас приступлю, тут он не прав. А про атомарность - смотрите какой несчастный случай возможен. Допустим _positionExt равна 0х000000ff. Мы вызвали getPosition(), она побайтово начинает копировать данные, пусть с конца (без разницы если с начала) скопировало 0хff, и тут прерывание ввалило. И сделало +1, теперь 0х00000100. Вернувшись из прерывания продолжается копирование остальных 3-х байт и имеем 0х000001ff. Херня 8| Правда на следующем вызове getPosition() мы таки получим 0х00000100, но неприятный осадочок останется.
ну так про это Садман и твердил, там тип данных как раз long, был бы байт - без разницы
ага. Но по моему Вы недооценили эту проблему. Она просто редко проявляться будет, но неприятно. А в остальном все не плохо, насколько конечно это возможно в ноябре.
ага. Но по моему Вы недооценили эту проблему. Она просто редко проявляться будет, но неприятно. А в остальном все не плохо, насколько конечно это возможно в ноябре.
Это я просто два разных скетча в одной железке пытаюсь подружить, по пинам чтобы не пересечься и чтобы можно было сторонний скетч генератора залить )))
А что, PCINT получило четвертной без права переписки?
https://microchipdeveloper.com/8avr:int
там так коряво написано )))
22 вектора, значит надо минимум 3 регистра флагов, чтобы их запомнить и обработать, ...работает и ладно, стока энкодеров нет, чтобы проверить
И там на одном векторе еще и кучка разного может быть. Я их раз написал в либу енкодера так.
//управляем прерываниями по изменению состояния от группы ног #define ENCODER_INTERRUPT_ENABLE cbi(EICRA, ISC01);sbi(EICRA, ISC00);sbi(PCICR, PCIE0); /* разрешаем прерывания PCINT3 */ #define ENCODER_INTERRUPT_DISABLE cbi(PCICR, PCIE0); // запрещаем прерывания PCINT0..7 //разрешим прерватся прм изменении ENCODER_INPUT_PIN1 #define ENCODER_INTERRUPT_PIN1 cbi(PCMSK0, ENCODER_INPUT_PIN2);sbi(PCMSK0, ENCODER_INPUT_PIN1); //разрешим прерватся прм изменении ENCODER_INPUT_PIN2 #define ENCODER_INTERRUPT_PIN2 cbi(PCMSK0, ENCODER_INPUT_PIN1);sbi(PCMSK0, ENCODER_INPUT_PIN2);И забыл что где ))
Я не Гайвер, мне библиотеки не осилить, пользуюсь наработанным опытом )))
на этой остановился из-за её стабильности...
Считал, что объявление переменных ВОЛАТИЛЬНЫМИ
заставляет компилятор их должным способом обрабатывать, иначе зачем всё это? Как в присказке получается про барышню и огурец )))
Я еще не научился как DIMAX смотреть в коде, как это выглядит, а было бы интересно...
А Дед (и Садман) был прав - нельзя верить вашему лживому Си
// ATOMIC_BLOCK(ATOMIC_RESTORESTATE){newPos = encoder_1.getPosition();} 516: f8 94 cli 518: 40 91 1d 01 lds r20, 0x011D 51c: 50 91 1e 01 lds r21, 0x011E 520: 60 91 1f 01 lds r22, 0x011F 524: 70 91 20 01 lds r23, 0x0120 528: 40 93 10 01 sts 0x0110, r20 52c: 50 93 11 01 sts 0x0111, r21 530: 60 93 12 01 sts 0x0112, r22 534: 70 93 13 01 sts 0x0113, r23 538: 8f bf out 0x3f, r24 ; 63 53a: 00 00 nop 53c: 00 00 nop 53e: 00 00 nop // newPos = encoder_1.getPosition(); 512: d0 e0 ldi r29, 0x00 ; 0 514: 80 91 1d 01 lds r24, 0x011D 518: 90 91 1e 01 lds r25, 0x011E 51c: a0 91 1f 01 lds r26, 0x011F 520: b0 91 20 01 lds r27, 0x0120 524: 80 93 10 01 sts 0x0110, r24 528: 90 93 11 01 sts 0x0111, r25 52c: a0 93 12 01 sts 0x0112, r26 530: b0 93 13 01 sts 0x0113, r27 534: 00 00 nop 536: 00 00 nop 538: 00 00 nopА Дед (и Садман) был прав - нельзя верить вашему лживому Си
Никада такого не говорил, Си - честен и чист, как слеза ребёнка, особенно у Онкеля. Лжив, как Госдеп, тока С++.
А Дед (и Садман) был прав - нельзя верить вашему лживому Си
Никада такого не говорил, Си - честен и чист, как слеза ребёнка, особенно у Онкеля. Лжив, как Госдеп, тока С++.
так тама вроде С++ и есть!?
Какое совпадение... :)
третий день с энкодером развлекаюсь.
Вижу тут люди знающие собрались, позвольте вопрос от начинающего ?
Какую библиотеку лучше использовать для работы с энкодером с использованием прерывания INT0/1 ?
(цель - управление кухонным радиоприемником-термометром-часами-МП3-плейером на 328 атмеге, предпочтение - компактность кода - а то хотелок много, как видите)
Попал в затруднительную ситуацию - для решения которой своих знаний/опыта - явно мало:
GyverEncoder.h в процессе разбухания кода - перестал работать после подключения библиотеки для дисплея Нокия5110 - LCD5110_Basic.h
вместо четкого - тик влево, тик вправо пока с Serial работал - стал гнать все время вправо...
Да как такое вообще то возможно ? :(
Какое совпадение... :)
третий день с энкодером развлекаюсь.
Вижу тут люди знающие собрались, позвольте вопрос от начинающего ?
Какую библиотеку лучше использовать для работы с энкодером с использованием прерывания INT0/1 ?
(цель - управление кухонным радиоприемником-термометром-часами-МП3-плейером на 328 атмеге, предпочтение - компактность кода - а то хотелок много, как видите)
Попал в затруднительную ситуацию - для решения которой своих знаний/опыта - явно мало:
GyverEncoder.h в процессе разбухания кода - перестал работать после подключения библиотеки для дисплея Нокия5110 - LCD5110_Basic.h
вместо четкого - тик влево, тик вправо пока с Serial работал - стал гнать все время вправо...
Да как такое вообще то возможно ? :(
я Гайверовскую только глянул, увидел, что он там нагородил (Человек гора) побежал дальше, возьмите попробуйте сделать как у меня на INT1, если он свободен, а лучше схему, что по пинам свободно, к каким пинам сейчас прикручен энкодер?
GyverEncoder.h в процессе разбухания кода - перестал работать после подключения библиотеки для дисплея Нокия5110 - LCD5110_Basic.h
вместо четкого - тик влево, тик вправо пока с Serial работал - стал гнать все время вправо...
Да как такое вообще то возможно ? :(
Задайте этот вопрос здесь адептам Гайвера
ua6em, у меня проект в стадии когда все что угодно можно прикручивать куда угодно. :) Макет.
Энкодер на 2,3 посажен,(именно с расчетом на INT0 INT1, кнопка на 4 - канонически можно сказать... Пока прерывания больше никому не нужны.
Попробую как у вас , особенно если подскажете есть ли описание библиотеки енкодера - которой вы пользуетесь.
alkotester1 , Да вы что ? :)
Я случайно влез в секту ? :)
За ссылку спасибо.
ua6em, у меня проект в стадии когда все что угодно можно прикручивать куда угодно. :) Макет.
Энкодер на 2,3 посажен,(именно с расчетом на INT0 INT1, кнопка на 4 - канонически можно сказать... Пока прерывания больше никому не нужны.
Попробую как у вас , особенно если подскажете есть ли описание библиотеки енкодера - которой вы пользуетесь.
это стандартная библиотека, доступна через менеджер библиотек называется RotareEncoder by Matthias Hertel v1.3 там есть пример, если PCINT на этом блоке не используются, то проще через них, INT1 я использовал неоднозначно жеж )))
Могу помочь с кодом, там пару десятков строк
/******* Простой энкодер *******/ #include <util/atomic.h> // для атомарности чтения данных в прерываниях #include <RotaryEncoder.h> RotaryEncoder encoder(2, 3); //Пины энкодера volatile long newPos; // Переменная для данных энкодера ISR(PCINT2_vect) { encoder.tick(); // На каждый щелчок энкодера запускается эта процедура } void setup() { PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); // Настройка прерывания } void loop() { // Так читать данные с энкодера ATOMIC_BLOCK(ATOMIC_RESTORESTATE){newPos = encoder.getPosition();} }это стандартная библиотека, доступна через менеджер библиотек называется RotareEncoder by Matthias Hertel v1.3 там есть пример, если PCINT на этом блоке не используются, то проще через них, INT1 я использовал неоднозначно жеж )))
Могу помочь с кодом, там пару десятков строк
/******* Простой энкодер *******/ #include <util/atomic.h> // для атомарности чтения данных в прерываниях #include <RotaryEncoder.h> RotaryEncoder encoder(2, 3); //Пины энкодера volatile long newPos; // Переменная для данных энкодера ISR(PCINT2_vect) { encoder.tick(); // На каждый щелчок энкодера запускается эта процедура } void setup() { PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); // Настройка прерывания } void loop() { // Так читать данные с энкодера ATOMIC_BLOCK(ATOMIC_RESTORESTATE){newPos = encoder.getPosition();} }Премного благодарен, и хоть "атомарность" для меня пока слова непонятные, в общем и целом ясно :) - прям сейчас попробую ваш блок вставить в свой скетч.
Кстати вопрос - а в этой библиотеке с подавлением дребезга контактов энкодера все нормально ? или аппаратно давить ? А то есть неприятный опыт...
Oleg Smirnoff, вариант 100% не имеющий проблем с дребезгом
http://arduino.ru/forum/apparatnye-voprosy/ispolzuem-enkoder?page=5#comment-449417
Кстати вопрос - а в этой библиотеке с подавлением дребезга контактов энкодера все нормально ? или аппаратно давить ? А то есть неприятный опыт...
не надо ничего там аппаратно давить, если энкодер глючит, автор библиотеки советует его просто выкинуть )))
кручу два дня, полёт нормальный пропусков не было, энкодер нонаме, да в библиотеке пины подтягиваются к +5V так что замыкать надо на землю общий контакт
Oleg Smirnoff, вариант 100% не имеющий проблем с дребезгом
http://arduino.ru/forum/apparatnye-voprosy/ispolzuem-enkoder?page=5#comment-449417
и библиотека не нужна )))
ua6em, ой спасибо !!!
Щелкает тики гладенько, и памяти много не заедает !!
73! ex UK4PNZ/UA4-094-301
ua6em, ой спасибо !!!
Щелкает тики гладенько, и памяти много не заедает !!
73! ex UK4PNZ/UA4-094-301
подключи сериал, выведи данные с энкодера в порт монитора и посмотри, я так библиотеки подбирал, на этой остановился, так как пропусков и перескакиваний не было
Oleg Smirnoff, вариант 100% не имеющий проблем с дребезгом
http://arduino.ru/forum/apparatnye-voprosy/ispolzuem-enkoder?page=5#comment-449417
quote=dimax]
//Энкодер на пинах А0, А1. Используется внутренняя подтяжка.
[/quote]dimax, благодарю, я обязательно попробую и без библиотеки - особенно если память это сэкономит.
ВОт только я читал что у ардуины на 328-м - прерывания возможны только на D2 и D3....
Видимо заблуждался ? :)
ua6em, ой спасибо !!!
Щелкает тики гладенько, и памяти много не заедает !!
73! ex UK4PNZ/UA4-094-301
подключи сериал, выведи данные с энкодера в порт монитора и посмотри, я так библиотеки подбирал, на этой остановился, так как пропусков и перескакиваний не было
Уже... :)
Все четко... :)
ua6em, ой спасибо !!!
Щелкает тики гладенько, и памяти много не заедает !!
73! ex UK4PNZ/UA4-094-301
подключи сериал, выведи данные с энкодера в порт монитора и посмотри, я так библиотеки подбирал, на этой остановился, так как пропусков и перескакиваний не было
Уже... :)
Все четко... :)
то аппаратные, с высоким приоритетом, они для другого могут пригодиться...
В этом варианте даже Садман41 не придерётся, не к чему, вдобавок смотрел ассемблерный код, всё чётко )))
ВОт только я читал что у ардуины на 328-м - прерывания возможны только на D2 и D3....
Видимо заблуждался ? :)
Под прерываниями часто имеют ввиду индивидуальные. Их в меге 328 действительно всего 2. А групповые есть на каждом пине, и они образуют 3 группы. Есть ещё прерывание компаратора, которое тоже полнофункциональное:)
Да. Прерывания есть на всех пинах.Я энкодер на порт B вешаю по прерываниям, все жужу.
dimax, тот код что ссылку выше дали далеко не лучший. Радует что мысль о ненужности конденсаторов принята. Следующая мысль - дребезг вызывает очень большое количество не нужных прерываний. По хорошему надо бы запрещать иногда некоторые, когда они не требуются в алгоритме.
Чё это не придерусь... Могу, если надо.
ты можешь ))) А вообще нет пределу совершенства и лучшее враг хорошего
Могу помочь с кодом, там пару десятков строк
/******* Простой энкодер *******/ #include <util/atomic.h> // для атомарности чтения данных в прерываниях #include <RotaryEncoder.h> RotaryEncoder encoder(2, 3); //Пины энкодера volatile long newPos; // Переменная для данных энкодера ISR(PCINT2_vect) { encoder.tick(); // На каждый щелчок энкодера запускается эта процедура } void setup() { PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); // Настройка прерывания } void loop() { // Так читать данные с энкодера ATOMIC_BLOCK(ATOMIC_RESTORESTATE){newPos = encoder.getPosition();} }Если надо докопатся, то извольте:
1) volatile long newPos - volatile тут уже не требуется, если newPos не будет использоваться в других необычных местах типа обработчика прерывания;
2) библиотеку энкодера я не потрошил, но если она, в принципе, не требует двух пинов с прерываниями, то занимать два external interrupt pin под один энкодер несколько бессмысленно.