Відповісти

Введіть повідомлення і натисніть Надіслати
Параметри

Назад

Огляд теми (нові повідомленні вгорі)

jokeR
2025-02-10 11:14:06

Заміть 1000 слів - дивіться як зроблено в Arduino

НЯП всередині ISR присідання з атомарністю не потрібні, бо переривання забороняється автоматично.

#if defined(TIM0_OVF_vect)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
	// copy these to local variables so they can be stored in registers
	// (volatile variables must be read from memory on every access)
	unsigned long m = timer0_millis;
	unsigned char f = timer0_fract;

	m += MILLIS_INC;
	f += FRACT_INC;
	if (f >= FRACT_MAX) {
		f -= FRACT_MAX;
		m += 1;
	}

	timer0_fract = f;
	timer0_millis = m;
	timer0_overflow_count++;
}

А ззовні - читайте коментар до коду

unsigned long millis()
{
  unsigned long m;
  uint8_t oldSREG = SREG;

  // disable interrupts while we read millis_timer_millis or we might get an
  // inconsistent value (e.g. in the middle of a write to millis_timer_millis)
  cli();
  m = millis_timer_millis;
  SREG = oldSREG;

  return m;
}
vigor53
2025-02-10 00:00:48

Честно? Ничего не понял... Я ведь только учусь smile Но все равно спасибо!

dimich
2025-02-09 23:37:12
jokeR пише:

тут викликається якийсь метод з ліби енкодера, хз що він робитиме.

Rotary::process() лише читає стани пінів та перемикає стан внутрішнього конечного автомата. Викликати той Rotary::process() в ISR - норм. Хоча в програмі топікстартера взагалі немає особливого сенсу використовувати переривання.

jokeR пише:

Якщо всередині Serial.print, буде ой.

Якщо не змішувати з викликами до Serial поза контекстом цього ISR, то буде працювати. HardwareSerial::write() не робить нічого такого, чого не можна робити в ISR.

jokeR пише:

Приблизно так:

ISR()
..
cli();
do_some_sheet
sei();

Не робіть так. ISR() викликається з уже вимкненими перериваннями. sei() їх увімкне і дозволить переривати цей обробник.

jokeR
2025-02-09 23:13:22
ISR(PCINT2_vect) {
  unsigned char result = r.process();

Так робити стрьомно. ISR повинно виконуватись максимально швидко, а тут викликається якийсь метод з ліби енкодера, хз що він робитиме. Якщо всередині Serial.print, буде ой.
Як правило, регулярні дії (process(), tick(), ..) викликають в loop - там воно точно спрацює як треба.
Якщо в ISR ви щось робите з глобальною змінною, яка більша ніж uint8_t - на цей час треба забороняти переривання.  Приблизно так:

ISR()
..
cli();
do_some_sheet
sei();
loop()
..
cli();
do_some_sheet
sei();
dimich
2025-02-09 22:52:08

Але помилки при роботі з глобальними змінними раджу все-таки виправити. Переривання може виникнути (і виникне) посередині читання глобальної змінної, і змінить її значення. Прочитане значення буде некоректним. Це призведе до неправильної роботи, а за законом Мерфі це станеться в самий критичний момент  hmm Крім того, компілятор взагалі може заоптимізувати звернення до них, вважаючи, що їх значення ніколи не змінюються. Тому потрібні atomic-блоки та volatile.
Краще винести всю ту логіку із ISR в основний цикл, а в ISR тільки репортувати події від енкодера у змінну з атомарним доступом (на AVR8 це 8-бітні типи). А у вашому випадку краще взагалі обійтись без переривань.

vigor53
2025-02-09 21:43:22

Блин - я хренею без баяна!!! Переставил концы на кодере и все пошло .... Таки да! Центральный с края
Спасибо Всем ОГРОМНОЕ !!!!!!

vigor53
2025-02-09 21:26:24

ОК - буду пробовать. Столько всего непонятного написали smile На дребег проверял - ставил емкости.К плюсу тоже подтягивал . Счас переставлю контакты ....

dimich
2025-02-09 21:11:39

Доречі, перевірте сам енкодер. Мені зустрічались екземпляри, у яких загальний вивод (GND) не посередині як на цьому фото, а збоку. Тобто послідовно йдуть: GND, OutA, OutB. Якщо продзвонювати кожний пін окремо, то при обертанні виглядає наче все ок. Але в схемі, де їх стани читаються одночасно, звісно що зчитується фігня. Колись витратив мабуть із годину, поки не виявив таку невідповідність розпіновки.

jokeer
2025-02-09 20:26:32

https://alexgyver.ru/encoder/
добре розписано.

jokeer
2025-02-09 20:14:43

якщо немає четкого срабатывания - скоріше за все брязкіт контактів. Звичайно його душать rc фільтром. Тому і спитав. А щодо коду - ви ж його з прикладу скопіювали, правда? приклад робочий.

dimich
2025-02-09 20:13:35
vigor53 пише:

Думаю что проблема в строчке :Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses. Must be interrupt pins.

У вас енкодер підключений до пінів D2 та D3? Зовнішні підтяжки на них є? Якщо немає, макрос ENABLE_PULLUPS був визначений на момент компіляції бібліотеки? У вас бібліотека в архіві в трьох екземплярах. Який із двох Rotary.h інклудився при компіляції Rotary.cpp, той що Rotary/Rotary.h чи Rotary-1.0.0/src/Rotary.h ?

Якщо ENABLE_PULLUPS не був визначений при компіляції бібліотеки, то піни без зовнішніх або внутрішніх підтяжок ловлять шуми космоса.

Якщо компілюєте в IDE, увімкніть "Show verbose output: compile" і показуйте вивод. Окрім вас ніхто не може знати, що там у вас як компілюється. Крім того, arduino IDE кешує артефакти компіляції.

Створіть окремий скетч, в якому просто читайте енкодер і пишіть в послідовний порт, що повертає Rotary::process(). Для початку без усяких переривань.

Доречі, у вас операції зі змінними, які апдейтяться в обробнику переривань, неатомарні. Це помилка. Навіть якщо енкодер працюватиме правильно, результат буде непередбачуваним. Якщо, як самі кажете, тільки починаєте, то не звʼязуйтесь із перериваннями. В Rotary є приклад циклічного опитування (polling). Впевніться в стабільній роботі цього приклада, потім інтегруйте його у свій скетч.

г0cть
2025-02-09 19:30:47
vigor53 пише:

Вы вообще то скетч смотрели ?

А вы сделали что вас спрашивали?

jokeer пише:

Як правило разом з лібою для енкодера є демо-програма. Очікується що вона працює.

В папке с библиотекой есть пример Interrupt.ino. Вы его загружали?

vigor53
2025-02-09 18:41:56

Все что было необходимо я напаял ! Вопрос остается - правильно ли прописана работа энкодера в скетче ??
Вы вообще то скетч смотрели ?

jokeer
2025-02-09 17:40:38

конденсатори напаяли, як в букварі намальовано?

vigor53
2025-02-09 16:44:03

Положим что энкодер - нормально. Что по поводу самого скетча? В двух вариантах программного кода  - по разному прописано работа энкодера , и в обоих случаях нет четкого срабатывания . Вопрос именно - в чем причина ?

Підвал форуму