Вопрос кодерам

На этом форуме Вы можете задать вопросы знатокам программы и автору.
Ответить
Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#1

Сообщение Ingwar » 10.03.2023{, 12:02}

Подскажите, почему этот код из функции работает на 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;
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

ecoins
Полковник
Сообщения: 2924
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 453
Откуда: Шатура
Имя: Энвер

Вопрос кодерам

#2

Сообщение ecoins » 10.03.2023{, 12:31}

Из приведенного кода не все понятно.
Думаю, что номера пинов _pin_A и _pin_B в разных контроллерах соответствует пинам для конкретного контроллера.
Из видимого в первой строке расставил скобки - в разных контроллерах физически используются разные компиляторы C++, которые могут "подбрасывать"...
И не стоит избегать фигурных скобок (строки 3,4,8).
С этого бы начать...

Аватара пользователя
Dryundel
Полковник
Сообщения: 2401
Зарегистрирован: 22.05.2017{, 23:15}
Репутация: 783
Откуда: Ярославль
Имя: Андрей
Контактная информация:

Вопрос кодерам

#3

Сообщение Dryundel » 10.03.2023{, 12:54}

Ingwar, вопрос не совсем корректный.
Данный код у Вас входит в состав функции по прерыванию. Это раз.
Второе. digitalRead для AVR достаточно длительная операция с проверками. А их целых две в функции. (не смотрел что там в ESP)
Я же говорил, попробуй впихнуть в проект (для AVR) вместе с энкодером мой блок оптимизации. Может быть поможет.
Третье. Зачем проверять пин на котором произошло прерывание? По прерыванию уже понятно в каком он состоянии. Надо проверить только второй пин.
Ну и последнее. Счетчик то вероятно и будет с оптимизацией работать, а вот выходы Up Down (ну или как они там у Вас). Не смогут корректно отработать тики, т.к. они вообще находятся в Loop. И требуется код, который завязан на счетчик, а не на прерывания. До этого момента я довольно долго доходил в свое время.

Отправлено спустя 57 секунд:
ecoins писал(а):
10.03.2023{, 12:31}
И не стоит избегать фигурных скобок (строки 3,4,8).
А в чем проблема? Если не секрет.

Отправлено спустя 56 минут 37 секунд:
Dryundel писал(а):
10.03.2023{, 12:54}
А в чем проблема? Если не секрет.
В чем проблема, браток?
А в ответ тишина.
Не спешит брат делиться секретами.
:)

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#4

Сообщение Ingwar » 10.03.2023{, 15:19}

ecoins писал(а):
10.03.2023{, 12:31}
Из видимого в первой строке расставил скобки - в разных контроллерах физически используются разные компиляторы C++, которые могут "подбрасывать"...
И не стоит избегать фигурных скобок (строки 3,4,8).
Сделал, "не взлетает"... :smile469:

Код: Выделить всё

      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.03.2023{, 13:51}
Второе. digitalRead для AVR достаточно длительная операция с проверками. А их целых две в функции. (не смотрел что там в ESP)
Я же говорил, попробуй впихнуть в проект (для AVR) вместе с энкодером мой блок оптимизации. Может быть поможет.
Да мне для простого ручного энкодера хотелось сделать универсальный.
Твой хорош, но причина в стм32...

Отправлено спустя 5 минут 48 секунд:
ecoins писал(а):
10.03.2023{, 12:31}
Думаю, что номера пинов _pin_A и _pin_B в разных контроллерах соответствует пинам для конкретного контроллера.
Это пользовательские параметры из блока.
Там при компиляции чисто указанные цифры.

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

ecoins
Полковник
Сообщения: 2924
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 453
Откуда: Шатура
Имя: Энвер

Вопрос кодерам

#5

Сообщение ecoins » 10.03.2023{, 15:32}

Ingwar писал(а):
10.03.2023{, 15:19}
Сделал, "не взлетает"...
Все не видно, но из уже вышесказанного повторю гипотезу:
В цикле прерывания очень длинная функция:
1.AVR действительно digitalRead занимает >4mcs (там их две), и еще битовые операции не быстрые (если они есть). В наших библиотеках мы для всех контроллерах используем вывод через быстрый доступ к регистрам.
2.ESP32 - не раз уже писал, даже через доступ к регистрам ввод/вывод на поверку оказывается даже медленнее чем ESP8266. Немного помогает размещение функции в оперативной памяти. После версии ядра >2 медленнее стало работать и работающие библиотеки 1-Wire перестали успевать считывать последовательность принимаемых бит(посылки примерно 80 бит). Если коротко, то имеет значение длинная адресация в этом контроллере. Некоторыми методами для 1-Wire эту проблему разрешили.
------
Непосредственно реализацию можно посмотреть в библиотеках ecoins HC-SR04(прерывания) и DS1820(быстрая работа с пинами).
-----
Успехов.

Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

Вопрос кодерам

#6

Сообщение Sancho » 10.03.2023{, 15:45}

_ou_ - в обработчике прерывания и в коде - должна быть volatile !!!
мой ник в нете и почте omelchuk890, если что. запомните на всякий. многие знают номер тлф.

Аватара пользователя
Dryundel
Полковник
Сообщения: 2401
Зарегистрирован: 22.05.2017{, 23:15}
Репутация: 783
Откуда: Ярославль
Имя: Андрей
Контактная информация:

Вопрос кодерам

#7

Сообщение Dryundel » 10.03.2023{, 16:10}

Ingwar писал(а):
10.03.2023{, 15:30}
Можно эти операции с битами преобразовать в другой способ без потери условий?
Ну в принципе можно. А зачем?
Битовые операции самые быстрые.
Алгоритм построен именно на битовых данных.
Единственный не правильный момент, это digitalRead.
Я бы заменил это на чтение регистров отвечающих за состояние пинов. Но там тоже надо думать как. :)

Отправлено спустя 5 минут 22 секунды:
Sancho писал(а):
10.03.2023{, 15:45}
_ou_ - в обработчике прерывания и в коде - должна быть volatile !!!
Возможно. Но не факт. Она же объявлена не в обработчике, а глобальная.

А вот если бы это был обработчик по прерыванию таймера, то точно надо было бы volatile в любом случае. Проверено.
У компилятора по этому поводу пунктик. Или бзик. Не знаю как точно :yes:

Отправлено спустя 7 минут 1 секунду:
Но по идее работать в функциях с глобальными переменными, это не очень правильно. Хотя иногда оправдано.

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#8

Сообщение Ingwar » 10.03.2023{, 16:29}

ecoins писал(а):
10.03.2023{, 15:32}
В цикле прерывания очень длинная функция:
В этом случае мне важна не скорость, а принципиальная возможность.
Sancho писал(а):
10.03.2023{, 15:45}
_ou_ - в обработчике прерывания и в коде - должна быть volatile !!!
Впихнул в оба - не помогло...
Dryundel писал(а):
10.03.2023{, 16:22}
Битовые операции самые быстрые.
Алгоритм построен именно на битовых данных.
Во время поисков решения, встречал мнения
Также возможно, что используемая версия Arduino IDE или библиотеки не поддерживает использование << для битового сдвига, что может вызвать ошибки компиляции.

Отправлено спустя 2 минуты 50 секунд:
Если бы код не работал совсем, это одна история.
Но на как минимум на двух "внешних" ядрах работает. Вопрос - почему ))))?
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

Вопрос кодерам

#9

Сообщение Sancho » 10.03.2023{, 16:39}

Ingwar писал(а):
10.03.2023{, 12:02}
Подскажите, почему этот код из функции работает на stm и rp2040, но не работает (хотя компилится без проблем) на ардуино и esp?
Для правильности нужен весь код, а не "цитата". Иначе кофейная ...
Потому-что я не знаю, а Андрей догадывается, что
Dryundel писал(а):
10.03.2023{, 16:22}
Возможно. Но не факт. Она же объявлена не в обработчике, а глобальная.
А вот если бы это был обработчик по прерыванию таймера, то точно надо было бы volatile в любом случае.
Это обработчик прерывания, как я догадываюсь.

Отправлено спустя 3 минуты 29 секунд:
Ingwar писал(а):
10.03.2023{, 16:31}
Также возможно, что используемая версия Arduino IDE или библиотеки не поддерживает использование << для битового сдвига, что может вызвать ошибки компиляции.
Об этом слышу впервые. так не бывает - это описанные возможности IDE. Это можно легко проверить опытным путём.
мой ник в нете и почте omelchuk890, если что. запомните на всякий. многие знают номер тлф.

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#10

Сообщение Ingwar » 10.03.2023{, 16:44}

Sancho писал(а):
10.03.2023{, 16:39}
Для правильности нужен весь код
Промежуточный из тестов
кривой энкодер.flp
(183.87 КБ) 22 скачивания
8.0.2
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

Вопрос кодерам

#11

Сообщение Sancho » 10.03.2023{, 16:47}

Ingwar, Игорь, ты хочешь получить максимальный энкодер, 4 числа на щелчок?

Отправлено спустя 1 минуту 9 секунд:
Хочется понять конечную цель - т.к. используется два прерывания.
мой ник в нете и почте omelchuk890, если что. запомните на всякий. многие знают номер тлф.

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#12

Сообщение Ingwar » 10.03.2023{, 16:52}

Sancho писал(а):
10.03.2023{, 16:47}
Игорь, ты хочешь получить максимальный энкодер, 4 числа на щелчок?
По факту на стм он дает +- 1 на "щелчек".
Ну на моих энкодерах.
Мне понравилось, что этот вариант не дает "ложных" срабатываний если поворачивать медленно.

Отправлено спустя 1 минуту 31 секунду:
Я делал на одном, примитивный вариант, так там если медленно крутить, мог давать ложные повороты.
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

Аватара пользователя
Dryundel
Полковник
Сообщения: 2401
Зарегистрирован: 22.05.2017{, 23:15}
Репутация: 783
Откуда: Ярославль
Имя: Андрей
Контактная информация:

Вопрос кодерам

#13

Сообщение Dryundel » 10.03.2023{, 17:02}

Ingwar писал(а):
10.03.2023{, 16:31}
Также возможно, что используемая версия Arduino IDE или библиотеки не поддерживает использование << для битового сдвига, что может вызвать ошибки компиляции.
Бред. Не слушай это.
Ingwar писал(а):
10.03.2023{, 16:31}
Если бы код не работал совсем, это одна история.
А на AVR хоть что то шевелится?
Sancho писал(а):
10.03.2023{, 16:42}
Потому-что я не знаю, а Андрей догадывается, что
Просто я смотрел код энкодера от Ingwar. :)

Отправлено спустя 11 минут :
Ingwar писал(а):
10.03.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

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#14

Сообщение Ingwar » 10.03.2023{, 17:20}

Dryundel писал(а):
10.03.2023{, 17:13}
Для того, что бы хорошо работало, необходима серьезная отработка всех возможный инстансов действий энкодера и еще предыдущее состояние, а не только - "есть контакт, нет контакта". Утрирую конечно.
Ничего ты не утрируешь, так должно быть. К этому потом приду (но это не точно) :smile38:
Просто я "закусился" из-за выборочной работы, казалось бы примитивного кода. Тут работать буду, а тут сука нет...

Отправлено спустя 1 минуту 43 секунды:
Dryundel писал(а):
10.03.2023{, 17:13}
А на AVR хоть что то шевелится?
Работает (из проверенных мною) только stm и rp2040. Ардуино и esp как в танке.

Отправлено спустя 3 минуты 15 секунд:
Может это пресловутая "оптимизация", которая в последних версиях IDE включена для авр по умолчанию (где-то читал, но это не точно).
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

Аватара пользователя
Dryundel
Полковник
Сообщения: 2401
Зарегистрирован: 22.05.2017{, 23:15}
Репутация: 783
Откуда: Ярославль
Имя: Андрей
Контактная информация:

Вопрос кодерам

#15

Сообщение Dryundel » 10.03.2023{, 17:29}

Ingwar писал(а):
10.03.2023{, 17:22}
Ардуино и esp как в танке.
Вот что я подумал. А может ли вообще AVR читать пин находящийся под прерывание во время прерывания?
Я этого не знаю.

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

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#16

Сообщение Ingwar » 10.03.2023{, 17:32}

Dryundel писал(а):
10.03.2023{, 17:29}
Вот что я подумал. А может ли вообще AVR читать пин находящийся под прерывание во время прерывания?
Я этого не знаю.
А как предлагаешь определить его состояние, если условие chance?
Ладно бы другое.
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

Аватара пользователя
Dryundel
Полковник
Сообщения: 2401
Зарегистрирован: 22.05.2017{, 23:15}
Репутация: 783
Откуда: Ярославль
Имя: Андрей
Контактная информация:

Вопрос кодерам

#17

Сообщение Dryundel » 10.03.2023{, 17:35}

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

Отправлено спустя 41 секунду:
Хотя так нельзя. (((

Отправлено спустя 44 секунды:
Или можно?
:smile37:

Отправлено спустя 4 минуты 6 секунд:
Эко-сенсей молчит.
Знает.
Наверняка знает.
Но скрывает.

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Вопрос кодерам

#18

Сообщение Ingwar » 10.03.2023{, 18:36}

Причина найдена тут
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 секунд:
Всем участникам огромное спасибо :smile9:

Отправлено спустя 17 минут 1 секунду:
STMка нормально "приняла" скорректированный" код.
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

Ответить

Вернуться в «Спросить у знатоков»