ШИМ на выводах не ШИМ

Почему этот код не работает аналогично примеру fade sketch? Мне пришлось прибегнуть к использованию бит-бинга в качестве способа реализации ШИМ на не ШИМ-контактах из-за отсутствия доступных свободных контактов на Arduino Pro Mini. Я использую скетч, который предположительно должен выцветать в светодиоде от максимальной яркости до минимальной яркости. Мой код, однако, не работает. Может ли кто-нибудь понять, почему мой код не работает так же, как скетч fade?

Мой текущий код:

int brightness = 0;
int fadeAmount = 50;  
void setup()
{
  pinMode(12, OUTPUT);
}
void loop()
{
  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }
  digitalWrite(13, HIGH);
  delayMicroseconds(brightness); // Приблизительно 10% рабочий цикл @ 1 кГц
  digitalWrite(13, LOW);
  delayMicroseconds(1000 - 100);
}

И я хочу, чтобы он работал так же, как:

int led = 9;
int brightness = 0;
int fadeAmount = 5;
void setup() {
  pinMode(led, OUTPUT);
}
void loop() {
  analogWrite(led, brightness);
  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }
  delay(30);
}

Если возможно, кто-нибудь может предоставить правильную версию, чтобы помочь мне с моим проектом.

, 👍2


4 ответа


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

1

Похоже, у вас опечатка на номере контакта: вы настраиваете контакт 12 и вводите контакт 13.

Другими словами:pinMode(12, OUTPUT); и digitalWrite(13, HIGH); не совпадают.

,

1

Ваш код здесь не совсем правильный:

digitalWrite(13, HIGH);
delayMicroseconds(brightness);
digitalWrite(13, LOW);
delayMicroseconds(1000 - 100);

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

Следовательно, - 100 во второй задержке - это вычитание времени "включения" из общего времени, необходимого для предоставления времени "выключения". Его следует заменить на - яркость как таковую:

digitalWrite(13, HIGH);
delayMicroseconds(brightness);
digitalWrite(13, LOW);
delayMicroseconds(1000 - brightness);

И, конечно, яркость находится в диапазоне 0-1000, а не 0-25, как у analogWrite(). Чтобы сделать его 0-255, вы должны заменить 1000 на 255, что, конечно, заставляет все это работать на гораздо более высокой частоте. (1/00000255 = 3922 Гц).

digitalWrite(13, HIGH);
delayMicroseconds(brightness);
digitalWrite(13, LOW);
delayMicroseconds(255 - brightness);

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

,

1

Это не сильно связано с вашим вопросом, но я предлагаю вам использовать внешнюю библиотеку в качестве SoftPWM.h

Вы можете найти всю документацию по https://github.com/bhagman/SoftPWM

,

0

Более общая версия вашего подхода была бы такой.

  1. Установите выходной контакт - не вводите жестко pin, а вместо этого используйте для него макрос.

  2. Задержка для его рабочих циклов.

  3. Очистите выходной вывод.

  4. Задержка для рабочих циклов периода, используемых на шаге 2 выше.

Вы можете включить это в рутину и назвать это.

С учетом сказанного процедура имеет ограниченное применение в реальном приложении, поскольку она может управлять одним выходным выводом и бесполезно связывает весь микроконтроллер.

Лучший подход заключается в использовании прерывания и проверке рабочих циклов в прерывании . Это может приводить в движение несколько контактов с независимыми рабочими циклами. И все это без подключения микроконтроллера.

,