Один и тот же код в последовательном порядке с разными результатами: яркий встроенный светодиод против тусклого того же светодиода, Arduino Nano Every

В коде ниже на 5-м контакте порта F горит обычный яркий светодиод, а на портах B, 0, 1, 2 — более тусклые. Даже если удерживать одну кнопку, а через мгновение одновременно нажать другую, отпустив предыдущую, яркость изменится. Для устранения дребезга всех кнопок, включая энкодер, используется КМОП-инвертор.

Поведение трех стандартных кнопок такое же, как и у кнопки поворотного энкодера.

void loop(){

  if (VPORTB.IN & PIN0_bm) { // стандартная кнопка
    VPORTE.OUT = 1 << PIN2;
  } else {
    VPORTE.OUT = 0 << PIN2;
  }

  if (VPORTB.IN & PIN1_bm) { // стандартная кнопка
    VPORTE.OUT = 1 << PIN2;
  } else {
    VPORTE.OUT = 0 << PIN2;
  }

  if (VPORTB.IN & PIN2_bm) { // стандартная кнопка
    VPORTE.OUT = 1 << PIN2;
  } else {
    VPORTE.OUT = 0 << PIN2;
  }
  // кодер А
  // если (VPORTA.IN & PIN1_bm) {
  // VPORTE.OUT = 1 << PIN2;
  // } еще {
  // VPORTE.OUT = 0 <& lt;& lt; PIN2;
  // }
  // кодер B
  // если (VPORTA.IN & PIN0_bm) {
  // VPORTE.OUT = 1 << PIN2;
  // } еще {
  // VPORTE.OUT = 0 <& lt;& lt; PIN2;
  // }

  if (VPORTF.IN & PIN5_bm) { // нажать кнопку энкодера
    VPORTE.OUT = 1 << PIN2;
  } else {
    VPORTE.OUT = 0 << PIN2;
  }


do {
    asm volatile("nop\n\t"); // изменение конфигурации таймера A, delay(...) перестала работать правильно
    temp++;
  } while (temp < 0);
}
temp = 0;

, 👍0

Обсуждение

Судя по ограниченному количеству предоставленной информации, я могу предположить, что поворотный энкодер не открытого типа, а имеет заднюю плату, где каждый контакт подавлен дребезгом с помощью цепи конденсатор/резистор. Возможно, конденсатор в какой-то степени поддерживает период включения светодиода. Возможно, полный код, схема и ссылка на энкодер помогут., @6v6gt

@6v6gt, спасибо, но у меня просто голый роторный ALPS STEC12E08 без печатной платы, конденсатор для устранения дребезга на всех одинаковый (включая энкодер), красный конденсатор Wima на 100 нФ и 10 кОм перед КМОП-инвертором, между КМОП-инвертором и микроконтроллером нет ничего, кроме дорожки., @NaturalDemon

5-й контакт порта F - это F4, @jsotola

@jsotola нет, я это уже исследовал, но это тоже не работает., @NaturalDemon


2 ответа


1

Так много ошибок:

  • Сдвиг 0 на любое число даст в результате 0.
    Вы уже знаете о PINx_bm (bm = битовая маска), вы можете использовать его вместо этого.

  • Вы полностью провалили манипуляцию битами
    Вы можете использовать PORTE.OUTSET = PINx_bm; или PORTE.OUTCLR = PINx_bm;
    Или более глупый способ: VPORTE.OUT |= PINx_bm; или VPORTE.OUT &= ~PINx_bm;

  • Ты тоже полностью провалил логику
    Все операторы «if» изменяют один и тот же бит (в настоящее время целый байт) и перезаписывают предыдущее состояние. В данном случае тусклый свет означает, что сигнал был в состоянии ВЫСОКОГО уровня примерно несколько сотен наносекунд, прежде чем был сброшен следующим блоком if. Последний блок немного ярче, поскольку существует некоторая странная задержка, поэтому, когда последний оператор if приводит к высокому уровню, он будет оставаться относительно дольше, чем любой другой предшествующий ему оператор.

,

Да, у меня сейчас только один светодиод, и я просто тестирую. Купил Arduino nano буквально пару дней назад. Странность была в том, что 4 одинаковые кнопки с одинаковым кодом и одна из них ведут себя по-разному. Действительно, если я перемещаю последний блок выше, тот же эффект возникает на другом последнем блоке кода/кнопке., @NaturalDemon


0

Вот мой совет. Проверьте, меняются ли VPORTB.IN и VPORTF.IN так, как вы ожидаете. Даже без осциллографа вы можете убедиться в этом с помощью следующего кода. Если хотите проверить и VPORTF.IN, просто добавьте аналогичные строки. Для простоты я показываю только VPORTB.IN.

#define LEN_HISTORY 100  // Сохранить 100 изменений

int hist_ct = 0;  // Счетчик для истории
uint32_t hist_timestamp[LEN_HISTORY];  // Сохраняем время при изменении входных данных
uint8_t hist_vportb_in[LEN_HISTORY];   // Сохранить входное значение
uint8_t last_vportb_in = 0;  // Запоминаем последний ввод

// Печать истории на последовательном мониторе
void dump_hist() {
    Serial.println("Dumping history:");
    for (int i = 0; i < hist_ct; i++) {
        Serial.print(hist_timestamp[i]);  // Показать время
        Serial.print(" : ");
        Serial.println(hist_vportb_in[i], BIN);  // Вывести входное значение в двоичном формате
    }
}

void loop() {
    uint8_t val = VPORTB.IN;  // Чтение ввода порта B

    if (val != last_vportb_in) {  // Проверяем, изменилось ли значение
        if (hist_ct < LEN_HISTORY) {  // Если история не полная
            hist_timestamp[hist_ct] = micros();  // Экономьте время
            hist_vportb_in[hist_ct] = val;  // Сохранить значение
            hist_ct++;  // Увеличить счетчик
        } else {  
            dump_hist();  // Вывести историю при заполнении
            while (true) { asm volatile("nop\n\t"); }  // Остановить цикл навсегда
        }
        last_vportb_in = val;  // Обновить последний ввод
    }
}

Редактировать:

Помимо проблемы с дребезгом, ответ @KIIV интересен. В вашем коде VPORTE.OUT зависит только от VPORTF.IN, независимо от значения VPORTB.IN. Рекомендую пересмотреть логику. Вот пример (псевдокод):

В цикле loop(),

bool vport_e = false;
if (VPORTB.IN & PIN0_bm)
    vport_e = true;
if (VPORTB.IN & PIN1_bm)
    vport_e = true;

// вырезка

if (VPORTF.IN & PIN5_bm)
    vport_e = true;

// Окончательно...
if (vport_e) {
    VPORTE.OUT = 1 << PIN2;
} else {
    VPORTE.OUT = 0 << PIN2;
}

Не знаю, соответствует ли эта логика вашим ожиданиям, но надеюсь, она поможет.

Кстати, насколько я понимаю, .OUTSET нельзя использовать с VPORT.

,

Привет, спасибо. Это всего лишь тест, так как я разработал печатную плату для Arduino Nano Every с 3 кнопками, вращающимся энкодером и mcp23s17 для использования с перемычками, но на данный момент только с 1 светодиодом. Я использовал временные метки, чтобы измерить, сколько времени занимает «код Arduino». также, похоже, есть несоответствие в заголовках Arduino Nano Every: некоторые порты имеют «DIRSET», а некоторые — «DIR». в противном случае возникает ошибка и компиляция не выполняется. PORTE.DIRSET не работает для V-порта., @NaturalDemon

Понятно. Эти два вопроса следует решать по отдельности. 1. Что касается подозрений на дребезг, пожалуйста, проверьте, действительно ли это происходит, следуя моим советам. Если код не компилируется или не работает, покажите исходный код, который вы протестировали. Я тоже могу попробовать его скомпилировать. 2. В любом случае, в приведённом вами коде значение VPORTB.IN неизвестно. Независимо от того, что вы считываете из VPORTB.IN, результат VPORTE.OUT зависит только от VPORTF.IN. Значение, считываемое из VPORTB.IN, фактически скрыто., @Atsushi Yokoyama

Я пытался получить указатель на такие вещи, как VPORTB.IN, VPORTB.DIR, VPORTB.OUT. Мне удалось получить 4-значное число, но использование этих 4-значных чисел для изменения чего-либо не удалось. Я использую CD40106 для устранения дребезга кнопок, поворотного энкодера., @NaturalDemon

Что именно вы сделали с этими «указатели»? Если покажете свой код, думаю, я смогу помочь., @Atsushi Yokoyama