Страница 1 из 1
Вопрос кодерам
Добавлено: 10 мар 2023, 12:02
Ingwar
Подскажите, почему этот код из функции работает на stm и rp2040, но не работает (хотя компилится без проблем) на ардуино и esp?
Код: Выделить всё
curState = digitalRead(_pin_A) | digitalRead(_pin_B) << 1;
if (resetFlag && curState == 0b11) {
if (prevState == 0b10) _ou++;
if (prevState == 0b01) _ou--;
_ou_= _ou;
resetFlag = 0;
}
if (curState == 0b00) resetFlag = 1;
prevState = curState;
Переменные задекларированы так
volatile boolean resetFlag;
volatile byte curState, prevState;
int _ou_=0;
int _ou =0;
Вопрос кодерам
Добавлено: 10 мар 2023, 12:31
ecoins
Из приведенного кода не все понятно.
Думаю, что номера пинов _pin_A и _pin_B в разных контроллерах соответствует пинам для конкретного контроллера.
Из видимого в первой строке расставил скобки - в разных контроллерах физически используются разные компиляторы C++, которые могут "подбрасывать"...
И не стоит избегать фигурных скобок (строки 3,4,8).
С этого бы начать...
Вопрос кодерам
Добавлено: 10 мар 2023, 13:51
Dryundel
[ref]Ingwar[/ref], вопрос не совсем корректный.
Данный код у Вас входит в состав функции по прерыванию. Это раз.
Второе. digitalRead для AVR достаточно длительная операция с проверками. А их целых две в функции. (не смотрел что там в ESP)
Я же говорил, попробуй впихнуть в проект (для AVR) вместе с энкодером мой блок оптимизации. Может быть поможет.
Третье. Зачем проверять пин на котором произошло прерывание? По прерыванию уже понятно в каком он состоянии. Надо проверить только второй пин.
Ну и последнее. Счетчик то вероятно и будет с оптимизацией работать, а вот выходы Up Down (ну или как они там у Вас). Не смогут корректно отработать тики, т.к. они вообще находятся в Loop. И требуется код, который завязан на счетчик, а не на прерывания. До этого момента я довольно долго доходил в свое время.
Отправлено спустя 57 секунд:
ecoins писал(а): 10 мар 2023, 12:31
И не стоит избегать фигурных скобок (строки 3,4,8).
А в чем проблема? Если не секрет.
Отправлено спустя 56 минут 37 секунд:
Dryundel писал(а): 10 мар 2023, 12:54
А в чем проблема? Если не секрет.
В чем проблема, браток?
А в ответ тишина.
Не спешит брат делиться секретами.

Вопрос кодерам
Добавлено: 10 мар 2023, 15:30
Ingwar
ecoins писал(а): 10 мар 2023, 12:31
Из видимого в первой строке расставил скобки - в разных контроллерах физически используются разные компиляторы C++, которые могут "подбрасывать"...
И не стоит избегать фигурных скобок (строки 3,4,8).
Сделал, "не взлетает"...
Код: Выделить всё
curState = (digitalRead(_pin_A)) | (digitalRead(_pin_B)) << 1;
if (resetFlag && curState == 0b11)
{
if (prevState == 0b10)
{
_ou++;
}
if (prevState == 0b01)
{
_ou--;
}
_ou_= _ou;
resetFlag = 0;
}
if (curState == 0b00)
{
resetFlag = 1;
}
prevState = curState;
Отправлено спустя 3 минуты 7 секунд:
Dryundel писал(а): 10 мар 2023, 13:51
Второе. digitalRead для AVR достаточно длительная операция с проверками. А их целых две в функции. (не смотрел что там в ESP)
Я же говорил, попробуй впихнуть в проект (для AVR) вместе с энкодером мой блок оптимизации. Может быть поможет.
Да мне для простого ручного энкодера хотелось сделать универсальный.
Твой хорош, но причина в стм32...
Отправлено спустя 5 минут 48 секунд:
ecoins писал(а): 10 мар 2023, 12:31
Думаю, что номера пинов _pin_A и _pin_B в разных контроллерах соответствует пинам для конкретного контроллера.
Это пользовательские параметры из блока.
Там при компиляции чисто указанные цифры.
Отправлено спустя 2 минуты 2 секунды:
Можно эти операции с битами преобразовать в другой способ без потери условий?
Вопрос кодерам
Добавлено: 10 мар 2023, 15:32
ecoins
Ingwar писал(а): 10 мар 2023, 15:19
Сделал, "не взлетает"...
Все не видно, но из уже вышесказанного повторю гипотезу:
В цикле прерывания очень длинная функция:
1.AVR действительно digitalRead занимает >4mcs (там их две), и еще битовые операции не быстрые (если они есть). В наших библиотеках мы для всех контроллерах используем вывод через быстрый доступ к регистрам.
2.ESP32 - не раз уже писал, даже через доступ к регистрам ввод/вывод на поверку оказывается даже медленнее чем ESP8266. Немного помогает размещение функции в оперативной памяти. После версии ядра >2 медленнее стало работать и работающие библиотеки 1-Wire перестали успевать считывать последовательность принимаемых бит(посылки примерно 80 бит). Если коротко, то имеет значение длинная адресация в этом контроллере. Некоторыми методами для 1-Wire эту проблему разрешили.
------
Непосредственно реализацию можно посмотреть в библиотеках ecoins HC-SR04(прерывания) и DS1820(быстрая работа с пинами).
-----
Успехов.
Вопрос кодерам
Добавлено: 10 мар 2023, 15:45
Sancho
_ou_ - в обработчике прерывания и в коде - должна быть volatile !!!
Вопрос кодерам
Добавлено: 10 мар 2023, 16:22
Dryundel
Ingwar писал(а): 10 мар 2023, 15:30
Можно эти операции с битами преобразовать в другой способ без потери условий?
Ну в принципе можно. А зачем?
Битовые операции самые быстрые.
Алгоритм построен именно на битовых данных.
Единственный не правильный момент, это digitalRead.
Я бы заменил это на чтение регистров отвечающих за состояние пинов. Но там тоже надо думать как.
Отправлено спустя 5 минут 22 секунды:
Sancho писал(а): 10 мар 2023, 15:45
_ou_ - в обработчике прерывания и в коде - должна быть volatile !!!
Возможно. Но не факт. Она же объявлена не в обработчике, а глобальная.
А вот если бы это был обработчик по прерыванию таймера, то точно надо было бы volatile в любом случае. Проверено.
У компилятора по этому поводу пунктик. Или бзик. Не знаю как точно
Отправлено спустя 7 минут 1 секунду:
Но по идее работать в функциях с глобальными переменными, это не очень правильно. Хотя иногда оправдано.
Вопрос кодерам
Добавлено: 10 мар 2023, 16:31
Ingwar
ecoins писал(а): 10 мар 2023, 15:32
В цикле прерывания очень длинная функция:
В этом случае мне важна не скорость, а принципиальная возможность.
Sancho писал(а): 10 мар 2023, 15:45
_ou_ - в обработчике прерывания и в коде - должна быть volatile !!!
Впихнул в оба - не помогло...
Dryundel писал(а): 10 мар 2023, 16:22
Битовые операции самые быстрые.
Алгоритм построен именно на битовых данных.
Во время поисков решения, встречал мнения
Также возможно, что используемая версия Arduino IDE или библиотеки не поддерживает использование << для битового сдвига, что может вызвать ошибки компиляции.
Отправлено спустя 2 минуты 50 секунд:
Если бы код не работал совсем, это одна история.
Но на как минимум на двух "внешних" ядрах работает. Вопрос - почему ))))?
Вопрос кодерам
Добавлено: 10 мар 2023, 16:42
Sancho
Ingwar писал(а): 10 мар 2023, 12:02
Подскажите, почему этот код из функции работает на stm и rp2040, но не работает (хотя компилится без проблем) на ардуино и esp?
Для правильности нужен весь код, а не "цитата". Иначе кофейная ...
Потому-что я не знаю, а Андрей догадывается, что
Dryundel писал(а): 10 мар 2023, 16:22
Возможно. Но не факт. Она же объявлена не в обработчике, а глобальная.
А вот если бы это был обработчик по прерыванию таймера, то точно надо было бы volatile в любом случае.
Это обработчик прерывания, как я догадываюсь.
Отправлено спустя 3 минуты 29 секунд:
Ingwar писал(а): 10 мар 2023, 16:31
Также возможно, что используемая версия Arduino IDE или библиотеки не поддерживает использование << для битового сдвига, что может вызвать ошибки компиляции.
Об этом слышу впервые. так не бывает - это описанные возможности IDE. Это можно легко проверить опытным путём.
Вопрос кодерам
Добавлено: 10 мар 2023, 16:44
Ingwar
Sancho писал(а): 10 мар 2023, 16:39
Для правильности нужен весь код
Промежуточный из тестов
кривой энкодер.flp
8.0.2
Вопрос кодерам
Добавлено: 10 мар 2023, 16:48
Sancho
[ref]Ingwar[/ref], Игорь, ты хочешь получить максимальный энкодер, 4 числа на щелчок?
Отправлено спустя 1 минуту 9 секунд:
Хочется понять конечную цель - т.к. используется два прерывания.
Вопрос кодерам
Добавлено: 10 мар 2023, 16:53
Ingwar
Sancho писал(а): 10 мар 2023, 16:47
Игорь, ты хочешь получить максимальный энкодер, 4 числа на щелчок?
По факту на стм он дает +- 1 на "щелчек".
Ну на моих энкодерах.
Мне понравилось, что этот вариант не дает "ложных" срабатываний если поворачивать медленно.
Отправлено спустя 1 минуту 31 секунду:
Я делал на одном, примитивный вариант, так там если медленно крутить, мог давать ложные повороты.
Вопрос кодерам
Добавлено: 10 мар 2023, 17:13
Dryundel
Ingwar писал(а): 10 мар 2023, 16:31
Также возможно, что используемая версия Arduino IDE или библиотеки не поддерживает использование << для битового сдвига, что может вызвать ошибки компиляции.
Бред. Не слушай это.
Ingwar писал(а): 10 мар 2023, 16:31
Если бы код не работал совсем, это одна история.
А на AVR хоть что то шевелится?
Sancho писал(а): 10 мар 2023, 16:42
Потому-что я не знаю, а Андрей догадывается, что
Просто я смотрел код энкодера от [ref]Ingwar[/ref].
Отправлено спустя 11 минут :
Ingwar писал(а): 10 мар 2023, 16:53
Я делал на одном, примитивный вариант, так там если медленно крутить, мог давать ложные повороты.
Для того, что бы хорошо работало, необходима серьезная отработка всех возможный инстансов действий энкодера и еще предыдущее состояние, а не только - "есть контакт, нет контакта". Утрирую конечно. Но данный код не далек от этого.
В библиотеке Encoder.h это все объяснено и описано.
Вот это все надо учесть, тогда и проблем не будет
Код: Выделить всё
// new new old old
// pin2 pin1 pin2 pin1 Result
// ---- ---- ---- ---- ------
// 0 0 0 0 no movement
// 0 0 0 1 +1
// 0 0 1 0 -1
// 0 0 1 1 +2 (assume pin1 edges only)
// 0 1 0 0 -1
// 0 1 0 1 no movement
// 0 1 1 0 -2 (assume pin1 edges only)
// 0 1 1 1 +1
// 1 0 0 0 +1
// 1 0 0 1 -2 (assume pin1 edges only)
// 1 0 1 0 no movement
// 1 0 1 1 -1
// 1 1 0 0 +2 (assume pin1 edges only)
// 1 1 0 1 -1
// 1 1 1 0 +1
// 1 1 1 1 no movement
Вопрос кодерам
Добавлено: 10 мар 2023, 17:25
Ingwar
Dryundel писал(а): 10 мар 2023, 17:13
Для того, что бы хорошо работало, необходима серьезная отработка всех возможный инстансов действий энкодера и еще предыдущее состояние, а не только - "есть контакт, нет контакта". Утрирую конечно.
Ничего ты не утрируешь, так должно быть. К этому потом приду (но это не точно)
Просто я "закусился" из-за выборочной работы, казалось бы примитивного кода. Тут работать буду, а тут сука нет...
Отправлено спустя 1 минуту 43 секунды:
Dryundel писал(а): 10 мар 2023, 17:13
А на AVR хоть что то шевелится?
Работает (из проверенных мною) только stm и rp2040. Ардуино и esp как в танке.
Отправлено спустя 3 минуты 15 секунд:
Может это пресловутая "оптимизация", которая в последних версиях IDE включена для авр по умолчанию (где-то читал, но это не точно).
Вопрос кодерам
Добавлено: 10 мар 2023, 17:31
Dryundel
Ingwar писал(а): 10 мар 2023, 17:22
Ардуино и esp как в танке.
Вот что я подумал. А может ли вообще AVR читать пин находящийся под прерывание во время прерывания?
Я этого не знаю.
Отправлено спустя 2 минуты 14 секунд:
Вот другой пин точно можно прочитать, а самого себя, не знаю. Может и нет.
Вопрос кодерам
Добавлено: 10 мар 2023, 17:32
Ingwar
Dryundel писал(а): 10 мар 2023, 17:29
Вот что я подумал. А может ли вообще AVR читать пин находящийся под прерывание во время прерывания?
Я этого не знаю.
А как предлагаешь определить его состояние, если условие chance?
Ладно бы другое.
Вопрос кодерам
Добавлено: 10 мар 2023, 17:40
Dryundel
Сделать две функции на конкретное изменение.
Отправлено спустя 41 секунду:
Хотя так нельзя. (((
Отправлено спустя 44 секунды:
Или можно?
Отправлено спустя 4 минуты 6 секунд:
Эко-сенсей молчит.
Знает.
Наверняка знает.
Но скрывает.
Вопрос кодерам
Добавлено: 10 мар 2023, 18:54
Ingwar
Причина найдена тут
https://www.arduino.cc/reference/en/lan ... interrupt/
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)(рекомендуемые)
attachInterrupt(interrupt, ISR, mode)(не рекомендуется)
attachInterrupt(pin, ISR, mode)(Не рекомендуется. Кроме того, этот синтаксис работает только на платах Arduino SAMD, Uno WiFi Rev2, Due и 101.)
Код работает если обьявить прерывания так
Код: Выделить всё
attachInterrupt(digitalPinToInterrupt(_pin_A), encIsr, CHANGE);
attachInterrupt(digitalPinToInterrupt(_pin_В), encIsr, CHANGE);
Отправлено спустя 1 минуту 7 секунд:
Всем участникам огромное спасибо
Отправлено спустя 17 минут 1 секунду:
STMка нормально "приняла" скорректированный" код.