Странные проблемы с управлением оптопарой (PC123) с Nano

У меня возникли странные проблемы с тем, чтобы заставить Nano правильно управлять оптопарой PC123.

Что я пытаюсь сделать: в реальном мире мне нужно нажать кнопку ОДИН РАЗ, и устройство, к которому я подключаюсь, тоже, см. ПЯТЬ быстрых нажатий кнопок... (Вход 1 нажмите, и Выход 5 нажимается, в момент времени, который я установил в коде). Я использую сочетание светодиодов «мигание/мигание». код, чтобы делать то, что мне нужно.

С подключением к Opto все в порядке. Это работает отлично, если я запускаю это "BLINK" код: (с оптопарой PC123, подключенной к контакту 13):

// функция настройки запускается один раз, когда вы нажимаете сброс или включаете плату
void setup() {
  // инициализируем цифровой вывод LED_BUILTIN как выход.
  pinMode(LED_BUILTIN, OUTPUT);
}

// функция цикла запускается снова и снова навсегда
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // включаем светодиод (HIGH - уровень напряжения)
  delay(200);                       // немного подождать
  digitalWrite(LED_BUILTIN, LOW);    // выключаем светодиод, понижая напряжение
  delay(200);                       // немного подождать
}

Когда я запускаю это, оптопара включается и выключается, когда мне нужно, и устройство, которым я управляю, счастливо, но очевидно, что оно работает вечно, так как у меня нет счетчиков или чего-то еще.. (Это доказывает, что мое оборудование хорошо справляется с этим точка!)

Но когда я пробую следующий код с точно такой же аппаратной схемой, выход становится ВЫСОКИМ, как только я заземляю контакт 2, и остается ВЫСОКИМ! Он удерживает оптопару во включенном состоянии, и нет ни включения, ни выключения, ни «мигания, ни мигания». НО, это происходит только тогда, когда OPTO подключен (есть нагрузка) на выходе Nano. Если я отключу Opto, светодиод Pin13 будет мигать, как и ожидалось. И мой код, похоже, работает нормально (на встроенном светодиоде Pin 13).

Однако ОЧЕНЬ интересно и очень странно, когда "включение" Светодиод на выводе 13 мигает (т. е. когда вы выключаете и снова включаете Nano или нажимаете кнопку сброса), это приводит к идеальному включению/выключению Opto! Но когда код начинает выполняться через мой входной переключатель Pin 2, когда Opto подключен к Nano, выход снова становится ВЫСОКИМ! Что за!?

int ledPin = 13;   // светодиод подключен к цифровому выводу 13
int switchPin = 2;   // переключатель подключен к цифровому выводу 2
int switchValue;   // переменная для отслеживания при нажатии переключателя
int counter = 0;

void setup()    
{    
      pinMode(ledPin, OUTPUT);   // устанавливает ledPin как выход
      pinMode(switchPin, INPUT);   // устанавливает switchPin как вход
      digitalWrite(switchPin, HIGH);   // устанавливает состояние switchPin по умолчанию (ненажатое) в HIGH
}    
      
void loop()   // запускаем снова и снова
{    
    
    switchValue = digitalRead(switchPin);   // проверяем, нажат ли переключатель
      if ((switchValue == LOW) && (counter <= 1)) {   // если переключатель нажат, то
          for(int ii = 0; ii <= 5; ii++)   // 7 = 4 вспышки, 5 = 3 вспышки и т. д.
      {
          digitalWrite(ledPin, !digitalRead(ledPin));
          delay(100); // Длина вспышек в мс
          counter++;
      }
    }
      if (switchValue == HIGH)
      //if ((switchValue == HIGH) && (counter > 2))
      {
           counter = 0;
           delay(100); // Отказаться
           
      }
}    

Я перепробовал фильтрующие конденсаторы, диоды, резисторы, подтягивающие и понижающие резисторы, все, что мог придумать, и я в растерянности. Может кто-нибудь мне помочь? Я думаю, что это проблема с кодом (потому что я новичок в Arduino — пожалуйста, будьте осторожны!), Или, может быть, недостаток в аппаратном обеспечении Nano? К вашему сведению, я проделал все это на разных входных и выходных контактах с теми же результатами.

Мы будем очень признательны за любую помощь!

, 👍-1

Обсуждение

у вас есть digitalWrite(switchPin, HIGH), который активирует внутренний подтягивающий резистор, @Juraj

Да, но разве это не требуется для того, чтобы мой НИЗКИЙ переключатель (D2) запускал код? Иначе будет плавать? Также он работает без нагрузки (с неподключенным оптом). Он будет мигать светодиодом Pin 13. Но с нагрузкой на выходе (вывод 13 или любой другой вывод, который я выберу), выход становится ВЫСОКИМ, когда код выполняется, и остается ВЫСОКИМ., @Pez

Я пробовал изменить digitalWrite(switchPin, HIGH) на LOW, а также удалил все вместе. Независимо от этого, срабатывание входа D2 всегда приводит к одному и тому же результату... Верен ли код счетчика? Может быть, он как-то застревает в цикле счетчика ??, @Pez

просто примечание о комментариях в коде..... digitalWrite(switchPin, HIGH); // устанавливает состояние переключателя по умолчанию (ненажатое) в HIGH ... комментарий вводит в заблуждение ... хотя технически это верно, поскольку он включает подтягивающий резистор, начинающий программист может подумать, что digitalWrite(switchPin, LOW) ; устанавливает состояние вывода по умолчанию на НИЗКИЙ, @jsotola

почему вы не используете тот же код, чтобы мигать светодиодом во второй программе? ... вторая программа делает предположение о состоянии выходного вывода ... «устанавливает» состояние вместо «инвертирования» предыдущего состояния, @jsotola

Спасибо за ответ. Я так понимаю подтягивающий код и как следствие состояние штифта. Все в порядке. Почему я не использую блинк-код, который работает? Потому что он не делает то, что мне нужно. Я новичок, и я не знаю, как заставить этот код запускаться и останавливаться, используя мгновенный ввод кнопки, и чтобы он мигал только *пять раз*, когда я нажимаю эту кнопку... Если вы можете помочь мне с этим, я был бы очень признателен. Ваше здоровье, @Pez


2 ответа


Лучший ответ:

0

Спасибо @DrG за отличный ответ! Я очень ценю время, которое вы потратили на это. Я отвечу на ваши вопросы здесь:

  • Что я пытаюсь сделать? Я добавляю Nano к приемопередатчику любительского радио, который может изменять частоту (путем нажатия кнопок на микрофоне) с шагом всего в 1 кГц или 10 кГц. Что я здесь делаю, так это добавляю этот Nano в схему кнопки микрофона и выбираю «1kKz». ступенчатый вариант, я получу "5kHz" шаг! Это отлично подходит для быстрого поиска сигналов SSB (1 кГц - это медленно, 10 кГц - слишком много, и вы пропустите некоторые из них!). Итак, я нажимаю 1 раз, радио будет шагать 5 раз. Это цель моего проекта. :)

  • Как я его подключил? Точно то же самое, что вы показали, и я также использовал как D13 (не рекомендуется, как вы сказали, так и D10 (как вы использовали в своем предложенном ответе).

  • У вас отличный код, и мне очень нравится, что он будет использовать D13, чтобы показать, что он делает на светодиоде, и использовать D10, чтобы управлять Opto. ОТЛИЧНО!

Теперь самое интересное... Даже с вашим кодом и точной схемой (кроме моего PC123 и вашего 4N25 (здесь у меня тоже есть 4N35) я получаю ту же проблему, что и раньше! Как только поскольку Nano управляет Opto, независимо от того, какой GPIO я настроил, он фиксирует ВЫСОКИЙ уровень! Светодиод D13 мигает, как и ожидалось, но D10 становится высоким и никогда снова не становится низким, до перезагрузки или выключения питания...

Теперь я считаю, что даже мой исходный код в порядке (не лучший способ сделать это, но все еще функциональный), но мой NANO неисправен! Это "ELEGOO NANO" клон. И я думаю, что это проблема!!!

Ваш вклад не пропадет даром, так как я буду использовать ваш код, он намного лучше моего! :) Я собираюсь получить новый NANO и попробовать еще раз, и теперь я почти уверен, что с новым Arduino это сработает! Я отчитаюсь и дам вам знать, как все прошло.

С уважением,

Пез

,

0

Признаюсь, я не совсем понимаю, что вы пытаетесь сделать, но у меня есть идея, и я надеюсь, что она поможет. Во-первых, есть несколько Nano, и не все они основаны на AVR. Я использовал СТАРЫЙ клон Nano и даже должен был выбрать ATMega 328P (старый загрузчик) - это было давно. Я также использовал оптику 4N25 [это может иметь значение, посмотрите технические характеристики вашего устройства)..

Вы не показали, как именно у вас все подключено. Давайте предположим, что это так - и я НЕ думаю, что это хороший способ делать вещи (потерпите меня), и

НЕВЕРНЫЙ ПУТЬ

При использовании этого кода он работает именно так, как должен.

int ledPin = 13;  
int switchPin = 2;       
int nflashes=10;
void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT);
}

void loop() {
  if ( digitalRead(switchPin)==HIGH) {
  for (int i = 0; i < nflashes; i++) {
      digitalWrite(ledPin, !digitalRead(ledPin));
      delay(100);
    }
    while (digitalRead(switchPin) == HIGH); // ждем, пока переключатель не будет отпущен
  }
}

Оптор включается, когда D13 зажигает дополнительный светодиод, а также включается встроенный светодиод. Обратите внимание, что встроенный светодиод тусклее, потому что вы управляете ДВУМЯ светодиодами; бортовой подключен к D13, а светодиод внутри опто, и у вас нет токоограничивающего резистора на опто светодиоде. Я не уверен, что вы подключили его таким образом, но если да, то, на мой взгляд, это не очень хороший способ.

Кроме того, подумайте о том, что происходит, когда вы нажимаете кнопку сброса... я предполагаю, что ATMega устанавливает все GPIO на вход, И загрузчик инициализирует встроенный светодиод выходом и, по-видимому, мигает этим светодиодом - я предполагаю, что и код не прошел. Я заметил, что в приведенной выше схеме я вижу, как новый светодиод и встроенный светодиод кратковременно мигают при сбросе, как я и ожидал.

Подключение переключателя, как я показал, (заземление) устранит любые проблемы с плавающими состояниями во время сброса. Он будет считываться как ВЫСОКИЙ, только если вы нажмете переключатель после инициализации GPIO.


Я бы поместил опто на отдельный GPIO вот так:

...и используя этот слегка измененный код

int ledPin = 13;  
int switchPin = 2;  
int optoPin=10;      
int nflashes=10;
void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT);
  pinMode(optoPin, OUTPUT);
}


void loop() {
  if ( digitalRead(switchPin)==HIGH) {
  for (int i = 0; i < nflashes; i++) {
      digitalWrite(ledPin, !digitalRead(ledPin));
      digitalWrite(optoPin, !digitalRead(optoPin));
      delay(100);
    }
    while (digitalRead(switchPin) == HIGH); // ждите здесь, пока переключатель не будет отпущен
  }
}

Все работает нормально, при сбросе новый светодиод не мигает и ничего не залипает.

Я бы хотел, чтобы вы показали, какие именно связи вы установили, и прошу прощения, если я что-то упустил.

Опять же, надеюсь, это поможет.

,

Спасибо @DrG за отличный ответ! Я отвечу на ваши вопросы в новом «ответе», потому что я не могу набрать здесь достаточно символов..., @Pez