Светодиоды становятся тусклее после достижения определенной яркости, почему?

Даже если я не использую кнопки и использую автоматическую функцию, которая делает светодиод ярче (даже не-RGB), через некоторое время он сбрасывается на более тусклый свет, почему?*

int Gled = 5;
int Bled = 6;
int Rv;
int Gv;
int Bv;

int b1 = 7;
int b2 = 8;
void setup() 
{

  pinMode(b1, INPUT_PULLUP);
  pinMode(b2, INPUT_PULLUP);
  Rv = 0;
  Gv = 0;
  Bv = 0;
  analogWrite(Rled, Rv);
  analogWrite(Gled, Gv);
  analogWrite(Bled, Bv);

}

void loop() 
{
  
  if(digitalRead(b1) == LOW)
  {
    Rv += 10;
    analogWrite(Rled, Rv);
  }
  if(digitalRead(b2) == LOW)
  {
    Gv += 10;
    analogWrite(Gled, Gv);
  }

}

, 👍2

Обсуждение

Цикл довольно быстрый, представляете, сколько раз он переходит в раздел if, когда вы нажимаете кнопку? Также вы предоставляете значение int в AnalogWrite, но обычные значения 0-255..., @KIIV


1 ответ


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

3

Описанное поведение связано с двумя важными фактами:

  1. Функция loop() будет работать очень быстро (микросекунды), в то время как нажатия кнопок обычным человеком будут довольно медленными (десятки или даже сотни миллисекунд). Это означает, что одним нажатием кнопки вы будете вводить соответствующий оператор if много раз, каждый раз добавляя 10 к значению. Вы не можете контролировать, сколько раз будет вводиться оператор if, поэтому значение, которое выводится после нажатия кнопки, несколько случайным образом растет.

  2. Хотя функция analogWrite() принимает int в качестве параметра значения (16 бит в AVR), внутри она присваивает это значение соответствующему регистру таймера. , который имеет размер всего 8 бит. Так что в любом случае он может хранить только значения от 0 до 255. Если вы укажете большее число в качестве параметра, более высокая часть будет просто обрезана. Например: Предоставление 257 приведет к значению 1 (= 257 % 256 = 257 % 2^8 --> 257 по модулю 256). Более высокие значения возвращаются обратно в диапазон от 0 до 255.

Итак, вместе у вас есть значение, которое растет очень быстро и несколько случайным образом, в то время как функция analogWrite() будет принимать только младшие 8 бит этого значения. Результатом является довольно неустойчивая, несколько случайная яркость светодиодов, которую трудно контролировать.

Что теперь делать? Это зависит от того, какое именно поведение вы хотите иметь:

  • Нажатие одной кнопки (нажатие + отпускание) должно увеличить значение соответствующего светодиода на 10:

    • В настоящее время вы проверяете, нажата ли кнопка. Вместо этого вам нужно искать переход между ненажатым и нажатым, то есть переход от ВЫСОКОГО к НИЗКОМУ. Вы можете сделать это, сохранив последнее прочитанное значение в переменной в конце части чтения кнопки и сравнив это предыдущее значение с новым прочитанным значением в начале. Хотя это по-прежнему оставляет вас с проблемой отказов. Есть много измерений, которые вы можете сделать, чтобы устранить дребезг кнопки (это легко можно найти в Google), но здесь я просто предлагаю использовать библиотеку Bounce2. Вы можете найти его здесь на github или в менеджере библиотек (я думаю). Это значительно упрощает надежное считывание кнопок. В нем есть хорошие примеры, чтобы научиться его использовать.
  • Значение должно увеличиваться, пока кнопка нажата, и прекращать расти, когда ее снова отпускают:

    • Здесь следует ограничить частоту ввода оператора if. Вы можете сделать это, ограничив скорость выполнения функции loop() простым вызовом delay(), хотя это не является хорошей практикой кодирования и может ограничить вы, когда добавляете больше функций в свой код (потому что это блокирует выполнение другого кода). Вместо этого вы можете использовать неблокирующий стиль кодирования с использованием функции millis(), которую вы можете увидеть в примере BlinkWithoutDelay. Вы используете переменную метки времени, чтобы сохранить время последнего выполнения оператора if. Затем оператор if должен проверять (в дополнение к состоянию кнопки), прошло ли достаточно времени, то есть достаточно ли велика разница между millis() и отметкой времени. Вы можете изменить интервал для этого сравнения, чтобы изменить скорость увеличения значения.
,