Аппаратное прерывание на Arduino UNO

Прошу вашей помощи.

Собрал следующую модель: Arduino Nano включает лазерный модуль с частотой, которая пропорциональна углу вращения энкодера.
Датчик света, подключён к UNO к пину с аппаратным прерыванием, программа считает длительность импульсов начиная с 1 по 5 и включает светодиод на 5 пине пропроциональным шим сигналом.

Есть в наличии два вида UNO, с смд и дип версиями. С дип версией программа не работает, переменная R (количество прерываний) не обнуляется, яркость светодиода не регулируется, с смд версией все отлично, пример на видео.
Пробовал ввести переменную с классификатором volatile, не помогло.
Прошу вашей помощи.
Возможно нужно перепрошить UNO, раз это встречается только у конкретных плат

Код для UNO:

int R = 0;
int T = 0;
int T2 = 0;

void interrupt_3(){
  R = R + 1;
}


void setup() {
  Serial.begin(9600);
  pinMode(5, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(3),interrupt_3,RISING);
}

void loop() {
    if (R == 1) {
      T = millis();
    }
    if (R == 5) {
      T2 = millis();
      T = T2 - T;
      T = map(T, 200, 900, 255, 0);
       analogWrite(5, T);
      R = 0;
      T = 0;
      T2 = 0;
    }

}

photo_2024-01-23 18.39.31
photo_2024-01-23 18.39.34
https://youtube.com/shorts/cOXL32A7f9M

Приводит мама своего сына к врачу:

  • Доктор посмотрите, у моего сына что-то с писей.
    Доктор смотрит:
  • Так, с этого момента писю называем членом и начинаем лечить сифилис.

В “схеме” с “энкодером” так же ошибка. Может это реально специфический энкодер за кучку деняк(ссылку пожалуйста), но тогда может это вопрос не для любительского форума?

Потом уже и аналоговый “датчик света” на прерывании обсудим.

Чтобы как с “энкодером” не получилось, выкладывайте качественные фото Вашего UNO, который не работает. Надо смотреть, такой ли уж он UNO…
А что-нибудь на нём работает? (Хотя бы из примеров)



До этого момента все программы работали на платах.

При малейшем “дребезге” строгие условия не сработают !

Я бы начал с проверки контактов. Вообще, на “штырьках” что-то серьёзное лучше не собирать. Пайка понадёжнее будет.

Да это так, но я не утверждаю, что это лучший выбор. Я проверил на 8 платах: 4 спокойно заработали, которые были из одной поставки, остальные нет

Прерывание отрабатывает, но там сразу 20 импульсов от дребезга … не знаю как там с вашими датчиками с дребезгом или нет идет сигнал…

Но почему тогда характерный случай только на конкретных платах? Может быть дело в загрузчике и перепрошить их?

Загрузчик работает только на старте после сброса/выхода из сна …

Может быть тогда указать пределы для срабатывания обнуления переменной? а не конкретное число?

Так я вам про это и написал …

На “конкретных” платах контакты могут быть плохие, бывают не пропаянные…

Попробовал, ничего не изменилось, но начал отправлять в монитор порта значения переменной R, значения отсекаются правильно. Видимо проблема в функции millis()

Извините за такой скрин, но главное результат

То есть вы считает что на разных платах millis выполняется по разному ???

Вроде только вторник …

Хорошо, а есть ли альтернатива моему алгоритму с подсчетом времени?

конечно есть, но для начала попробовать поправить явный косяк:

#include <util/atomic.h>

volatile int RRR = 0;
volatile uint32_t TTT = 0;
volatile uint32_t TTT2 = 0;
bool flag = false;

void interrupt_3() {
  RRR = RRR + 1;
}


void setup() {
  Serial.begin(9600);
  pinMode(5, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(3), interrupt_3, RISING);
}

void loop() {

  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    if (RRR == 1) {
      TTT = millis();
    }
  }

  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    if (RRR == 5) {
      TTT2 = millis();
      flag = true;
    }
  }
  
  if(flag){
      TTT = TTT2 - TTT;
      TTT = map(TTT, 200, 900, 255, 0);
      analogWrite(5, TTT);
      RRR = 0;
      TTT = 0;
      TTT2 = 0;
      flag = false;
    }
  }

Я отказался от подобных сборок, как на фото у ТС после первого случая ковыряния со схемой 4 (!) дня, а оказалось - контакт хреновый. Только пайка, только хардкор!

2 лайка