When the INT1 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled.
Всё четко. Только для INT1 надо использовать биты ISC11 and ISC10...
• Bit 7 – INT1: External Interrupt Request 1 Enable When the INT1 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled. The Interrupt Sense Control1 bits 1/0 (ISC11 and ISC10) in the MCU general Control Register (MCUCR) define whether the external interrupt is activated on rising and/or falling edge of the INT1 pin or level sensed. Activity on the pin will cause an interrupt request even if INT1 is configured as an output. The corresponding interrupt of External Interrupt Request 1 is executed from the INT1 Interrupt Vector.
• Bit 6 – INT0: External Interrupt Request 0 Enable When the INT0 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled. The Interrupt Sense Control0 bits 1/0 (ISC01 and ISC00) in the MCU general Control Register (MCUCR) define whether the external interrupt is activated on rising and/or falling edge of the INT0 pin or level sensed. Activity on the pin will cause an interrupt request even if INT0 is configured as an output. The corresponding interrupt of External Interrupt Request 0 is executed from the INT0 Interrupt Vector.
Я тоже так думаю, читаю дальше с осторожностью. Собственно полез в эти, еще пока для меня дебри, во-первых немного по разбираться, а во-вторых энкодер на внешнем прерывании (отлично работающий на Arduino Nano с Atmega328):
PCICR |= (1 << PCIE2); // |
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); // | Нужно для работы прерываний ISR (PCINT2_vect) ATmega88/ATmega168/ATmega328
sei(); // |
ISR(PCINT2_vect) {
Не заработал на Atmega8:
GICR |= (1 << INT0) | (0 << INT1); // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
MCUCR &= ~((1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11)); // | Сбрасываем биты ISCxx в "ноль"
MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11); // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
sei();
ISR(INT0_vect) {
GICR |= (0 << INT1) | (1 << INT0); // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00)); // | Сбрасываем биты ISCxx в "ноль"
MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00); // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
sei(); // | Разрешаем глобальные прерывания
Собственно я тут пытаюсь изобразить следующую логику: Включаем прерывание на PD2, как только происходит любое изменение уровня - происходит прерывание INT0_vect (может не правильно последнее назвал).
Нет, у меня на энкодер только PD2 (INT0) подключено. PD3 (INT1) вообще пока не задействовано.
Странно вот что, в книге написано, что ISC01=0, ISC00=1 - "ЗАРЕЗЕРВИРОВАНО". А в даташите как "Any logical change on INT0 generates an interrupt request."
Переносил код из ISR() в loop(), срабатывало, но как-то непонятно. Медленно крутишь - срабатывает, покрутил быстро - нет, потом опять медленно крутишь - опять нет. Немного погодя - опять начинает "работать". Непонятка.
ЗЫ: Энкодер новый, но на всякий случай смотрел осциллографом - отличное качество энкодера, даже дребезга нет. Четкие "импульсы".
Насколько я вижу из примеров библиотеки - используются прерывания с обоих каналов энкодера ! То есть надо настраивать и разрешать оба прерывания. А из ISR(INT0_vect) и ISR(INT1_vect) вызывать общий обработчик.
Насколько я вижу из примеров библиотеки - используются прерывания с обоих каналов энкодера ! То есть надо настраивать и разрешать оба прерывания. А из ISR(INT0_vect) и ISR(INT1_vect) вызывать общий обработчик.
Так как у меня уже готовая плата, использовать эту библиотеку мне просто не получится значит.
#include "Rotary.h"
// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК = { 15, 16, 17, 19, 14, 10, 9, 18}
// значения для вывода цифр 0-9
Rotary r = Rotary(PIN_PD2, PIN_PC5);
uint32_t number = 1234000;
byte numbers[] = {
0B11111100, // | '0' // Байт: ABCDEFGH
0B01100000, // | '1' // A
0B11011010, // | '2' // -----
0B11110010, // | '3' // | |
0B01100110, // | '4' // F| G |B
0B10110110, // | '5' // |-----|
0B10111110, // | '6' // E| |C
0B11100000, // | '7' // | D |
0B11111110, // | '8' // ----- * H
0B11110110, // | '9'
};
// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
// выводы МК = { 25, 23, 26, 24 }
void setup() {
// Сконфигурировать контакты как выходы
DDRB = 0B11111111;
/*
for (uint8_t i = 0; i < 8; i++) {
pinMode(pinSegments[i], OUTPUT);
}
*/
for (uint8_t i = 0; i < 4; i++) {
pinMode(pinAnode[i], OUTPUT);
digitalWrite(pinAnode[i], HIGH); // Выключаю
}
/*
GICR |= (0 << INT1) | (1 << INT0); // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00)); // | Сбрасываем биты ISCxx в "ноль"
MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00); // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
sei(); // | Разрешаем глобальные прерывания
*/
/*
Komandir:
*/
MCUCR &= ~(1 << ISC00);
MCUCR |= (1 << ISC01);
GICR |= (1 << INT0);
sei();
r.begin();
}
ISR(INT0_vect) { // Это для Atmega8/16/32
int8_t tick;
digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
number += (int16_t)tick * 10000;
/*
unsigned char result = r.process();
if (result) {
if (result == DIR_CW) {
number += 10000;
} else {
number -= 10000;
}
}
*/
}
void printNum (uint16_t num) {
uint16_t bitNum;
uint16_t temp = 1000;
for (uint8_t i = 0; i < 4; i++) {
bitNum = (uint16_t)(num / temp);
for (int j = 0; j < 8; j++) {
digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
}
digitalWrite(pinAnode[i], LOW); // | Зажигаю цифру позиции i
delayMicroseconds(500);
digitalWrite(pinAnode[i], HIGH); // | Гашу цифру позиции i
num = num - temp * bitNum;
temp = temp / 10;
}
}
void loop() {
printNum (number / 1000);
}
Эффект следующий - при повороте в любую сторону срабатывает только одно (в моем случае - уменьшение значения). Но это уже прогресс!!! Срабатывает чётко (почти как "пацанчики", это шутка)) )!
#include "Rotary.h"
// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК = { 15, 16, 17, 19, 14, 10, 9, 18}
// значения для вывода цифр 0-9
Rotary r = Rotary(PIN_PD2, PIN_PC5);
uint32_t number = 1234000;
byte numbers[] = {
0B11111100, // | '0' // Байт: ABCDEFGH
0B01100000, // | '1' // A
0B11011010, // | '2' // -----
0B11110010, // | '3' // | |
0B01100110, // | '4' // F| G |B
0B10110110, // | '5' // |-----|
0B10111110, // | '6' // E| |C
0B11100000, // | '7' // | D |
0B11111110, // | '8' // ----- * H
0B11110110, // | '9'
};
// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
// выводы МК = { 25, 23, 26, 24 }
void setup() {
// Сконфигурировать контакты как выходы
DDRB = 0B11111111;
/*
for (uint8_t i = 0; i < 8; i++) {
pinMode(pinSegments[i], OUTPUT);
}
*/
for (uint8_t i = 0; i < 4; i++) {
pinMode(pinAnode[i], OUTPUT);
digitalWrite(pinAnode[i], HIGH); // Выключаю
}
/*
GICR |= (0 << INT1) | (1 << INT0); // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00)); // | Сбрасываем биты ISCxx в "ноль"
MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00); // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
sei(); // | Разрешаем глобальные прерывания
*/
/*
Komandir:
*/
MCUCR &= ~(1 << ISC00);
MCUCR |= (1 << ISC01);
GICR |= (1 << INT0);
sei();
r.begin();
}
ISR(INT0_vect) { // Это для Atmega8/16/32
int8_t tick;
digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
number += (int16_t)tick * 10000;
/*
unsigned char result = r.process();
if (result) {
if (result == DIR_CW) {
number += 10000;
} else {
number -= 10000;
}
}
*/
}
void printNum (uint16_t num) {
uint16_t bitNum;
uint16_t temp = 1000;
for (uint8_t i = 0; i < 4; i++) {
bitNum = (uint16_t)(num / temp);
for (int j = 0; j < 8; j++) {
digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
}
digitalWrite(pinAnode[i], LOW); // | Зажигаю цифру позиции i
delayMicroseconds(500);
digitalWrite(pinAnode[i], HIGH); // | Гашу цифру позиции i
num = num - temp * bitNum;
temp = temp / 10;
}
}
void loop() {
printNum (number / 1000);
}
Эффект следующий - при повороте в любую сторону срабатывает только одно (в моем случае - уменьшение значения). Но это уже прогресс!!! Срабатывает чётко (почти как "пацанчики", это шутка)) )!
Его бы допилить и отлично будет! )
Для данного метода прерывание надо настроить на отслеживание RISING ! Анализировать не digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
Странно ... по RISING - PD2 должен быть ВСЕГДА в HIGH
А как так то? Коммутация идет энкодером на GND, при покое VCC (HIGH) на выводе энкодера всегда (на обоих выводах, смотрел осциллографом). При вращении "пульсации" идут к GND как раз.
Я на самом деле удивлен - Почему в решении этого вопроса мне откликнулся помогать только komandir?
На вопрос о ветре и его обгоне уже сотни комментариев - а вы же даже это проверить не сможете (одни умозаключения, на сколько я смог увидеть). Мой пример (и его решение) можно проверить в реальном железе. Но никого. ))
Наверное решение (как обычно) простое и всем просто лень отвечать. А на "сотрясание ветра" потратить часть жизни только в радость )))
ЗЫ: Я без негатива, просто интересное наблюдение. )
Надо в прерывании сохранять текущий micros или millis и на входе проверять сколько прошло от последнего срабатывания - если мало (опытным путем), то сразу на выход ... Как то так...
Странно, но даже с задержкой в обработке прерывания (доводил до неприличных 250мс) не поменялось в лучшую сторону. Даже стало не через 1-2 "перепрыгивать", а срузу через 4-5. Я вообще ленивый человек, но... Hantek DSO5102P к выводам энкодера подключен (даже второй шнурок для наглядности достал), работа самого энкодера:
(Да, ему для таких измерений не сильно хватает памяти, DSO5102B с 2Мб был бы предпочтительнее, но и такие измерения я за несколько лет делаю второй или третий раз).
Я не совсем понимаю почему разные интервалы, это неисправность самого энкодера? Поменять не проблема - штук 20-30 есть в "запасе".
И код (последний вариант):
#include "Rotary.h"
#include "kakmyc_btn.h"
// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК = { 15, 16, 17, 19, 14, 10, 9, 18}
Rotary r = Rotary(PIN_PD2, PIN_PC5);
uint32_t number = 1234000;
uint16_t prevTime = millis(); // | Для устранения дребезга энкодера
const uint8_t Rotary1 = PIN_PD2; // | Первый пин энкодера
const uint8_t Rotary2 = PIN_PC5; // | Второй пин энкодера
const uint16_t rtInterval = 250; // | Интервал между срабатыванием энкодера (устранение дребезга контактов энкодера)
// значения для вывода цифр 0-9
byte numbers[] = {
0B11111100, // | '0' // Байт: ABCDEFGH
0B01100000, // | '1' // A
0B11011010, // | '2' // -----
0B11110010, // | '3' // | |
0B01100110, // | '4' // F| G |B
0B10110110, // | '5' // |-----|
0B10111110, // | '6' // E| |C
0B11100000, // | '7' // | D |
0B11111110, // | '8' // ----- * H
0B11110110, // | '9'
};
// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
// выводы МК = { 25, 23, 26, 24 }
void setup() {
// Сконфигурировать контакты как выходы
DDRB = 0B11111111;
/*
for (uint8_t i = 0; i < 8; i++) {
pinMode(pinSegments[i], OUTPUT);
}
*/
for (uint8_t i = 0; i < 4; i++) {
pinMode(pinAnode[i], OUTPUT);
digitalWrite(pinAnode[i], HIGH); // Выключаю
}
/*
GICR |= (0 << INT1) | (1 << INT0); // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00)); // | Сбрасываем биты ISCxx в "ноль"
MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00); // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
sei(); // | Разрешаем глобальные прерывания
*/
/*
Komandir:
*/
MCUCR |= (1 << ISC01);
MCUCR |= (1 << ISC00);
GICR |= (1 << INT0);
sei();
r.begin();
}
ISR(INT0_vect) { // Это для Atmega8/16/32
int8_t tick, res1, res2;
uint16_t currentTime = millis();
if (currentTime - prevTime > rtInterval) {
res1 = digitalRead(PIN_PC5);
res2 = digitalRead(PIN_PD2);
if ( (( digitalRead(PIN_PC5) ? tick = 1 : tick = -1) == 1) && ((digitalRead(PIN_PD2) ? tick = 1 : tick = -1) == -1 ) ) {
number += (int16_t)tick * 1000;
} else {
number -= (int16_t)tick * 1000;
}
}
}
void printNum (uint16_t num) {
uint16_t bitNum;
uint16_t temp = 1000;
for (uint8_t i = 0; i < 4; i++) {
bitNum = (uint16_t)(num / temp);
for (int j = 0; j < 8; j++) {
digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
}
digitalWrite(pinAnode[i], LOW); // | Зажигаю цифру позиции i
delayMicroseconds(500);
digitalWrite(pinAnode[i], HIGH); // | Гашу цифру позиции i
num = num - temp * bitNum;
temp = temp / 10;
}
}
void loop() {
printNum (number / 1000);
}
Да уж, откуда только эта мания «гигантизма» берётся?
Кажется разобрался.
Данные макросы (PBx, PCx, PDx), как я понял, используются в конструкциях обращения к регистрам, например:
Соответственно имеют значения от 0 до 7 (максимум)?
Да, эксперимент тоже это подтвердил. Век живи - век учись.
Но где это все описано я так и не нашел ((
BOOM Ищите файл iom8a.h в папке ...\hardware\tools\avr\avr\include\avr- там всё описано...
iom8a.h в папке ...\hardware\tools\avr\avr\include\avr- там всё описано...
Ничего я там не нашел. Вот содержимое файла:
Там же лежит файл portpins.h они все подтягиваются по цепочке Arduino.h-io.h-файл под конкретный камень-portpins.h...
Ладно, не суть. Разобрался для чего и на том хорошо. Не буду в эти дебри лезть пока.
Читаю книгу Евстифеева, и мне кажется в ней ошибка:
Страница 241, Таблица 2.63 Разряды регистров GICR (GIMSK), читаю о INT0 и INT1
А книгу все нахваливают в интернете...
PS: Странно, ссылку на файл заменяет на хрен пойми что.
А что не нравится то ? ISC11 ISC10 ISC01 ISC00 это ?
А смысл читать не даташит ? -
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2486-8-bit-AVR-mi...
А что не нравится то ? ISC11 ISC10 ISC01 ISC00 это ?
))) Вот ты все знаешь и понимаешь, поэтому сразу видно - не читал. Не нравится мне "Описание" у INT0 и INT1. Прочти внимательно (скрин выше).
Стараюсь для начала понять что к чему и почему. А это мне на русском удобнее (да и не особо я с англицким дружу).
When the INT1 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled.
Всё четко. Только для INT1 надо использовать биты ISC11 and ISC10...
• Bit 7 – INT1: External Interrupt Request 1 Enable When the INT1 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled. The Interrupt Sense Control1 bits 1/0 (ISC11 and ISC10) in the MCU general Control Register (MCUCR) define whether the external interrupt is activated on rising and/or falling edge of the INT1 pin or level sensed. Activity on the pin will cause an interrupt request even if INT1 is configured as an output. The corresponding interrupt of External Interrupt Request 1 is executed from the INT1 Interrupt Vector.
• Bit 6 – INT0: External Interrupt Request 0 Enable When the INT0 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled. The Interrupt Sense Control0 bits 1/0 (ISC01 and ISC00) in the MCU general Control Register (MCUCR) define whether the external interrupt is activated on rising and/or falling edge of the INT0 pin or level sensed. Activity on the pin will cause an interrupt request even if INT0 is configured as an output. The corresponding interrupt of External Interrupt Request 0 is executed from the INT0 Interrupt Vector.
Не троль меня )) В книге Евстифеева описания для INT0 и INT1 идентичны как под копирку.
Уже боюсь эту книгу, но ничего другого русскоязычного не знаю...
Думаю это ошибка копи-паста ...
Это мелочи. В даташитах тоже попадается. Просто логику нужно включать.
Думаю это ошибка копи-паста ...
Я тоже так думаю, читаю дальше с осторожностью. Собственно полез в эти, еще пока для меня дебри, во-первых немного по разбираться, а во-вторых энкодер на внешнем прерывании (отлично работающий на Arduino Nano с Atmega328):
Не заработал на Atmega8:
PCIINT одно на обе ноги, а INT0 и INT1 это разные прерывания
А:
MCUCR &= ~((1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11));
MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11);
принято писать от старшего бита к младшему
А:
MCUCR &= ~((1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11));
MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11);
принято писать от старшего бита к младшему
Вот так?
Собственно я тут пытаюсь изобразить следующую логику: Включаем прерывание на PD2, как только происходит любое изменение уровня - происходит прерывание INT0_vect (может не правильно последнее назвал).
Вам надо отслеживать прерывание на двух каналах ? Тогда надо оба разрешать и оба отслеживать !
PCINT разбиты на группы по этому там было одно прерывание на два канала сразу
Нет, у меня на энкодер только PD2 (INT0) подключено. PD3 (INT1) вообще пока не задействовано.
Странно вот что, в книге написано, что ISC01=0, ISC00=1 - "ЗАРЕЗЕРВИРОВАНО". А в даташите как "Any logical change on INT0 generates an interrupt request."
Я выставлял по даташиту. Может стоит сменить?
Atmega8 нет в наличии, а на Atmega328p код:
четко входит в прерывание на каждое изменение.
Komandir, огромное спасибо за участие. Но, блин, где-то косяк - не работает. Приведу весь код:
Библиотека Rotary.h (использовал ее в 2х проектах на Arduino Nano v2, лежит в той же папке): https://github.com/brianlow/Rotary
Переносил код из ISR() в loop(), срабатывало, но как-то непонятно. Медленно крутишь - срабатывает, покрутил быстро - нет, потом опять медленно крутишь - опять нет. Немного погодя - опять начинает "работать". Непонятка.
ЗЫ: Энкодер новый, но на всякий случай смотрел осциллографом - отличное качество энкодера, даже дребезга нет. Четкие "импульсы".
Насколько я вижу из примеров библиотеки - используются прерывания с обоих каналов энкодера ! То есть надо настраивать и разрешать оба прерывания. А из ISR(INT0_vect) и ISR(INT1_vect) вызывать общий обработчик.
P.S. я перелопатил массив в теме про Фантомное свечение...код будет сильно меньше !
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/fantomnaya-zasvetka-na-semisegmentnike?page=1#comment-642821
Насколько я вижу из примеров библиотеки - используются прерывания с обоих каналов энкодера ! То есть надо настраивать и разрешать оба прерывания. А из ISR(INT0_vect) и ISR(INT1_vect) вызывать общий обработчик.
Так как у меня уже готовая плата, использовать эту библиотеку мне просто не получится значит.
Rotary(PIN_PD2, PIN_PC5); - так нет. На PIN_PC5 нет внешнего прерывания.
Я попробовал ради эксперимента код Kakmyc'а:
Эффект следующий - при повороте в любую сторону срабатывает только одно (в моем случае - уменьшение значения). Но это уже прогресс!!! Срабатывает чётко (почти как "пацанчики", это шутка)) )!
Его бы допилить и отлично будет! )
Rotary(PIN_PD2, PIN_PC5); - так нет. На PIN_PC5 нет внешнего прерывания.
Я знаю, поэтому и сказал, что библиотека Rotary мне не подойдет. Плата уже в железе имеется.
Как вариант использовать для прерываний таймер - на частоте, достаточной для обслуживания энкодера ...
Я попробовал ради эксперимента код Kakmyc'а:
Эффект следующий - при повороте в любую сторону срабатывает только одно (в моем случае - уменьшение значения). Но это уже прогресс!!! Срабатывает чётко (почти как "пацанчики", это шутка)) )!
Его бы допилить и отлично будет! )
Для данного метода прерывание надо настроить на отслеживание RISING ! Анализировать не digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
а digitalRead(PIN_PС5) ? tick = 1 : tick = -1;
Для данного метода прерывание надо настроить на отслеживание RISING ! Анализировать не digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
а digitalRead(PIN_PС5) ? tick = 1 : tick = -1;
Попробовал сделать вот так:
Получил ошибку при компиляции:
То есть, как я понимаю - ругается на то, что в прерывании я обрабатываю вообще "левую ногу". Я прав?
Скорее всего я не верно понял #78 (((
Может у меня русская С попала ?
ругается на то, что в прерывании я обрабатываю вообще "левую ногу". Я прав?
Нет, я не прав тут. "Тупо скопировал", "С" была русской. Заменил на английскую - то же самое. Нужно оба состояния сравнивать.
Может у меня русская С попала ?
Да, так и было. Но не работает. Состояние обоих контактов нужно анализировать.
https://www.customelectronics.ru/arduino-vneshnie-preryivaniya-podklyuchenie-enkodera/
Тут по RISING на канале A, проверяют канал B и все работает ... (второй же канал на PC5 ?)
Может конечно у вас какой то хитрый энкодер
Komandir! Вот так заработало "в обе стороны":
Но, видимо, дребезг все-же есть, так как не точно по 1 единице уменьшается/прибавляется, а бывает через несколько.
Я думаю и сам "if" проще можно записать и как-то еще дребезг нужно погасить.
ОГРОМНОЕ ТЕБЕ СПАСИБО! Долго тупил бы один.
Может конечно у вас какой то хитрый энкодер
Вот такие энкодеры у меня: https://aliexpress.ru/item/1005003084166943.html
Странно ... по RISING - PD2 должен быть ВСЕГДА в HIGH
B все что касается tick в крайнем скетче ЛИШНЕЕ !
Странно ... по RISING - PD2 должен быть ВСЕГДА в HIGH
А как так то? Коммутация идет энкодером на GND, при покое VCC (HIGH) на выводе энкодера всегда (на обоих выводах, смотрел осциллографом). При вращении "пульсации" идут к GND как раз.
Но, видимо, дребезг все-же есть, так как не точно по 1 единице уменьшается/прибавляется, а бывает через несколько.
Да, заметил, что при уменьшении иногда прибавляется. И наоборот. Думаю это все же дребезг.
Тогда может проверить FALLING ?
Тогда может проверить FALLING ?
Только поменялось направление. То есть было влево - меньше, стало больше и все.
Проанализировал сам энкодер более глубже - при одном "тике" происходит дребезг контактов (считай уже когда почти 360гр). Как победить можно дребезг?
Последний вариант кода:
Я на самом деле удивлен - Почему в решении этого вопроса мне откликнулся помогать только komandir?
На вопрос о ветре и его обгоне уже сотни комментариев - а вы же даже это проверить не сможете (одни умозаключения, на сколько я смог увидеть). Мой пример (и его решение) можно проверить в реальном железе. Но никого. ))
Наверное решение (как обычно) простое и всем просто лень отвечать. А на "сотрясание ветра" потратить часть жизни только в радость )))
ЗЫ: Я без негатива, просто интересное наблюдение. )
Надо в прерывании сохранять текущий micros или millis и на входе проверять сколько прошло от последнего срабатывания - если мало (опытным путем), то сразу на выход ... Как то так...
надо апаратно устранять дребезг от энкодера и не е@ать мозги себе и контролеру.
xDriver
Плата уже в железе имеется.
Я на самом деле удивлен - Почему в решении этого вопроса мне откликнулся помогать только komandir?
Наверно потому, что Komandir с детьми/внуками ещё не наняньчился.)
На вопрос о ветре и его обгоне уже сотни комментариев - а вы же даже это проверить не сможете (одни умозаключения, на сколько я смог увидеть).
какие умозаключения? просто вспомнить курс Теоретической механики )))
Странно, но даже с задержкой в обработке прерывания (доводил до неприличных 250мс) не поменялось в лучшую сторону. Даже стало не через 1-2 "перепрыгивать", а срузу через 4-5. Я вообще ленивый человек, но... Hantek DSO5102P к выводам энкодера подключен (даже второй шнурок для наглядности достал), работа самого энкодера:
(Да, ему для таких измерений не сильно хватает памяти, DSO5102B с 2Мб был бы предпочтительнее, но и такие измерения я за несколько лет делаю второй или третий раз).
Я не совсем понимаю почему разные интервалы, это неисправность самого энкодера? Поменять не проблема - штук 20-30 есть в "запасе".
И код (последний вариант):
Что то вы совсем поплыли ...
1 Интервалы обратно пропорционально зависят от скорости вращения энкодера !!!
2 Где обновление prevTime ?
3 Дребезг по паспорту энкодера - около 2 мс !!!
4 На осциллограмме дребезга не видно СОВСЕМ.
5 Внешняя подтяжка выходов энкодера есть ?
Код:
работает идеально на 328 (энкодер подключен на 2 3)