Как предотвратить вмешательство тональной функции Arduino Esplora в работу светодиода RGB

На Arduino Esplora, основанном на плате Leonardo, поддержка PWM контакта 5, который управляет красным компонентом светодиода RGB, выглядит так, как будто он использует таймер с функцией tone. Это имеет непреднамеренное последствие: красный компонент становится бесполезным после воспроизведения тона, так как его поведение становится непредсказуемым.

Вот простая setup процедура, демонстрирующая проблему:

void setup()
{
    //analogWrite(5, 255);
    //delay(1000);
    analogWrite(5, 1);
    delay(2000);
    Esplora.tone(440);
    delay(1000);
    Esplora.noTone();
}

Это включает красный канал светодиода до минимального значения и удерживает его в течение двух секунд, затем воспроизводит тон 440 Гц в течение 1/4 секунды, но как только тон начинается, вместо того, чтобы оставаться на низкой яркости, светодиод включается. полностью выключен.

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

Я не могу понять, как восстановить правильную работу красного компонента (или, точнее, ШИМ на выводе 5) после вызова tone.

Я предполагаю, что для генерации правильного Гц для звука tone изменяет настройки таймера, который затем влияет на функцию ШИМ. Если я смогу узнать, как вручную сбросить таймер, чтобы снова правильно поддерживать ШИМ для светодиода, это может быть решением. Однако я новичок в Arduino, таймерах и т. .

Итак, кто-нибудь знает, как восстановить правильную работу ШИМ на этом контакте?

отметка


person Mark A. Donohoe    schedule 25.04.2014    source источник
comment
Каковы значения TCCR3A, TCCR3B, TCCR4A, TCCR4B, TCCR4C, TCCR4D и TCCR4E до и после ошибки (в шестнадцатеричном формате)?   -  person Ignacio Vazquez-Abrams    schedule 25.04.2014
comment
Впервые в Arduino. Как их проверить? Приветствуется любой код эскиза. (И были ли вы тем, кто проголосовал против меня? Если да, не забудьте подробнее, почему ??)   -  person Mark A. Donohoe    schedule 25.04.2014
comment
Просто выведите их через последовательное соединение.   -  person Ignacio Vazquez-Abrams    schedule 25.04.2014
comment
Вызывая Serial.write () с этими именами, я получаю следующее: До: TCCR3A: 1 TCCR3B: 3 TCCR4A: 2 TCCR4B: 7 TCCR4C: 1 TCCR4D: 1 TCCR4E: 0 После: TCCR3A: 0 TCCR3B: 9 TCCR4A: 2 TCCR4B : 7 TCCR4C: 1 TCCR4D: 1 TCCR4E: 0 (Вы случайно не имели в виду двоичный код? Hex и Decimal одинаковы для всех значений 9 и ниже.)   -  person Mark A. Donohoe    schedule 26.04.2014


Ответы (2)


Я немного изучил документацию 32U4 и взял специфическую логику Esplora из библиотек Arduino, которые они используют для инициализации ресурсов PWM при запуске. Полученную ниже процедуру timerFix () можно использовать для восстановления правильных настроек.

void loop()
{
  Esplora.writeRGB(127,0,0);
  delay(1000);
  Esplora.tone(311);
  delay(1000);
  timerFix();
  Esplora.writeRGB(32,0,0);
  delay(1000);  
}
void timerFix()
{
  #define sbi(sfr,b) (_SFR_BYTE(sfr) |= _BV(b))

  //Tone will have hijacked the timer used for the 
  //RGB led RED channel so once we're done we need
  //to restore it.  First shutdown the tone internals
  //if not done already...
  Esplora.noTone();

  //Now clear the Timer Count Control Registers to
  //have them in a known state.
  TCCR3A = 0;
  TCCR3B = 0;

  //Setup the clock source - clk/64 
  sbi(TCCR3B, CS31);
  sbi(TCCR3B, CS30);

  //Set the wave form generator for 10-bit PWM
  sbi(TCCR3A, WGM30);

  //re-link the PWM timer to output channel
  //by passing something other than 0 and 255
  //so that the analogWrite function is forced to
  //recompute the correct value for either the
  //OCR3A or OCR3B register (output control register) 
  //as appropriate
  analogWrite(5, 1);

  //turn the LED channel off
  analogWrite(5, 0);
}
person Community    schedule 29.04.2014

Ваши подозрения относительно tone() перенастройки таймера верны. На 32U4 таймер 3 используется для tone(), но на Esplora OC3A используется для красного компонента (OC1B и OC1A используются для зеленого и синего компонентов соответственно). Это означает, что каждый раз, когда tone() вызывается на Esplora, таймер 3 перенастраивается для CTC (WGM3 [3: 0] = 0b0100), тогда как красный компонент требует ШИМ для правильного использования (а analogWrite() специально использует 8-битную фазу -правильный ШИМ [WGM [3: 0] = 0b0001]). А поскольку таймер требуется до тех пор, пока не прекратится звуковой сигнал, нет разумного способа переключать его туда и обратно между режимами.

Обычно самый простой способ исправить это - сказать tone() использовать другой таймер. К сожалению, на Esplora нет таймера, который он мог бы использовать: таймер 0 используется delay() и др., Таймер 1 используется зеленым и синим компонентами, таймер 4 работает совершенно иначе, чем библиотеки Arduino. запрограммированы на, а таймер 2 даже не существует на 32U4.

Однако вывод для OC3A на 32U4 - это тот же вывод для nOC4A. Это означает, что вместо этого мы можем использовать таймер 4 для управления красным компонентом. Значения для TCCR4 * не были равны 0, когда вы их исследовали, но это может быть из-за того, что загрузчик возится с ними; Мне не удалось найти что-либо в ядре Arduino или библиотеке Esplora, что их изменяет.

Есть 2 проблемы с использованием таймера 4:

  1. Вывод 13 подключен к OC4A. Это означает, что вывод 13 всегда должен быть настроен как вход, поскольку на выходе из него будет сигнал ШИМ, который имеет фазу, противоположную красной составляющей.

  2. Библиотеки Arduino не запрограммированы для работы с таймером 4. Это означает, что нам потребуется доступ к таймеру 4 на низком уровне, чтобы настроить и использовать его.

И так:

pinMode(13, INPUT);
// disable timer 4 interrupts
TIMSK4 = 0;
// reset TCCR4C
TCCR4C = 0;
// set OCR4C to maximum
OCR4C=0xff;
// clear dead time register
DT4 = 0;
// enable PWM based on OCR4A and connect nOC4A (and OC4A)
TCCR4A = _BV(PWM4A) | _BV(COM4A0);
// match analogWrite() prescaling
TCCR4B = _BV(CS42) | _BV(CS41) | _BV(CS40);
// enable fast PWM
TCCR4D = 0;
// set minimum brightness
OCR4A = 0xff;

delay(1000);
OCR4A = 0xbf; // low brightness
delay(1000);
OCR4A = 0x3f; // high brightness
delay(1000);
OCR4A = 0x7f; // mid brightness
delay(1000);
OCR4A = 0x00; // max brightness
person Ignacio Vazquez-Abrams    schedule 26.04.2014
comment
Привет, Игнасио! Это отличное описание проблемы. Вы на самом деле сделали все возможное, и waaaaay мимо того, что мне нужно, а именно: просто перенастроить Timer3 для PWM после воспроизведения тона. Причина в том, что пока я создаю прототип на Esplora, я хочу защитить себя от любой платы, где это может быть проблемой. Но это слишком хороший ответ для изменения / обновления, поэтому могу ли я заставить вас создать второй простой фрагмент о том, как перенастроить таймер, чтобы вернуться к поддержке ШИМ? Я просто переключаюсь между тоном и RGB, если мне нужно, не используя светодиод при воспроизведении звуков. - person Mark A. Donohoe; 27.04.2014
comment
Кроме того, хотя это не отвечает моим непосредственным потребностям, мне все еще интересно понять, что вы здесь сделали. Не могли бы вы расширить комментарии о том, что такое OCR4A и тому подобное? Я гуглю, но не могу найти хорошего учебника по таймерам и тому, как связаны все эти значения. - person Mark A. Donohoe; 27.04.2014
comment
Еще одна вещь ... в вашем «предостережении» выше относительно контакта 13, это обычно вывод светодиода по умолчанию. Есть ли вред, если просто оставить его как выход, чтобы увидеть инверсию красного? Будет ли это что-нибудь испортить, или вы просто делали это, чтобы этого не увидеть? - person Mark A. Donohoe; 27.04.2014
comment
Только что нашел и ОТЛИЧНО написано о таймерах и этих значениях! - engblaze.com/ - person Mark A. Donohoe; 27.04.2014
comment
Вы можете перенастроить время назад, установив биты WGM3 и CS3 обратно на 0b001 и 0b011 соответственно. Документацию по различным периферийным устройствам, регистрам и битам можно найти в таблице данных для MCU, доступной на веб-сайте производителя. Вы можете оставить вывод 13 как выход; это не мешает, только выглядит странно. Обратите внимание, что мой комментарий относительно таймера 4 на 32U4 как совершенно другого не является преувеличением; эта статья не подготовит вас к этому полностью, но даст вам основы. - person Ignacio Vazquez-Abrams; 27.04.2014
comment
Спасибо! Поместите образец кода в новый ответ, и я помечу его как принятый (не то чтобы он вам нужен на 298 КБ !!) - person Mark A. Donohoe; 27.04.2014