Конфликт Arduino Uno PWM

Я построил этот экран двигателя на основе чипа L298N для управления двумя двигателями бака. Он использует контакты 5 и 6 для одного двигателя, а штыри 10 и 11 для другого.

При попытке добавить TSOP 4838, чтобы управлять баком с ИК-пульта, я заметил, что перемещение двигателя на штырьках 10/11 в обратном направлении работает только на полной скорости, то есть значение HIGH (255) на выводе 11. Все, что ниже этого значения, не выводит ничего на вывод 11 (измеренное напряжение на этих контактах равно 0 V).

Для пульта я использую эту библиотеку. Приемник IR подключен к контакту 2 (но штырь не имеет значения). Проблема заключается в самом коде библиотеки. Линия, которая разрешает ИК-прослушивание irrecv.enableIRIn();, вызывает проблемы. Я узнал, что существует конфликт внутренних таймеров Arduino и штырей, используемых для ШИМ щитом.

Это код для управления двигателем в обратном направлении:

#include <IRremote.h>

// IR receiver configuration
const int irPin = 2;
IRrecv irrecv(irPin);

// Motors configuration
const int mLeftPin1  = 10;
const int mLeftPin2  = 11;
const int mRightPin1 = 5;
const int mRightPin2 = 6;

void setup()
{
  // Start IR
  irrecv.enableIRIn();

  // Setup motors
  pinMode(mLeftPin1, OUTPUT);
  pinMode(mLeftPin2, OUTPUT);
  pinMode(mRightPin1, OUTPUT);
  pinMode(mRightPin2, OUTPUT);

  // Move left motor in reverse, slower speed
  analogWrite(mLeftPin2, 100); // This works only with 255 instead of 100
  digitalWrite(mLeftPin1, LOW);
}

Теперь я нашел здесь, что контакты, используемые таймерами на Arduino Uno:

  • Штырьки 5 и 6: управляются таймером
  • Штыри 9 и 10: управляются таймером
  • Штыри 11 и 3: управляются таймером

Итак, мои вопросы:

  • Почему щит в инструктивных штифтах 10 и 11 для PWM? Они соответствуют двум разным таймерам. Почему не 9 и 10?

  • Чтобы использовать ИК вместе с экраном двигателя, какой таймер я должен настроить для использования библиотеки ИК?

  • Если ответ равен 2, строка должна быть раскомментирована в IRremoteInt.h. Я предполагаю, что Uno возьмет ветвь else в строке 68, хотя есть только таймер 1 и timer2. Интересно, почему timer0 нельзя использовать для Uno.

Хотя я бы хотел оставить режущие следы и регенерировать в качестве последнего варианта, другой возможностью было бы изменить штыри, используемые щитом, но что? И я предполагаю, что это также будет сопряжено с настройкой таймеров на PWM на других контактах, чем по умолчанию, но я ничего не знаю о таймерах/прерываниях, и мои знания о Arduino и C ограничены.

Я сделал этот длинный вопрос, потому что хочу научиться не просто решить проблему, поэтому не стесняйтесь объяснять больше, чем того, что задано.

При поиске решения я также нашел, что другие конфликты следует учитывать при использовании PWM или таймеров:

  • Timer0 - это 8-битный таймер, он может содержать максимальное значение 255. Он используется delay() и millis(), поэтому есть последствия, когда он возится с ним
  • Timer1 - это 16-разрядный таймер, он может содержать максимум 65535 (неподписанное 16-битное целое число). Библиотека Arduino Servo использует этот таймер
  • Timer2 - это 8-разрядный таймер, используемый функцией Arduino tone()

И, конечно, библиотека IRremote использует TIMER_RESET, поэтому в зависимости от того, какой таймер она использует, она может конфликтовать с связанными контактами.

Ответ 1

  • Не все оборудование разработано наилучшим образом. Использование 10 и 11 действительно расточительно, потому что для этого требуется два таймера.

2/3. В идеале вы будете использовать таймер, который не является Timer0. Вот еще несколько деталей о таймерах/прерываниях:

Микросхема Arduino (328P) имеет три таймера. Каждый таймер может использоваться для нескольких применений, однако важно отметить, что для каждого таймера можно включить только одно прерывание таймера.

Возьмите Timer0, например. Он прерывает, чтобы генерировать правильные задержки для методов delay() и delay_us(). Он также используется для выходов PWM на контактах 5 и 6. Это может произойти из-за того, что выходы PWM не используют прерывание таймера, они используют отдельные модули сравнения вывода.

Теперь, глядя конкретно на вашу проблему, он должен работать нормально, даже если у вас есть выход PWM с использованием timer2, PWM не принимает прерывания по таймеру2, поэтому библиотека IR должна иметь возможность использовать это прерывание. Однако, просматривая код библиотеки IR, мы видим этот фрагмент кода:

ISR(TIMER_INTR_NAME)
{
   TIMER_RESET; 

Кажется, что каждый раз, когда он прерывается, он сбрасывает счетчик таймера. Это может быть причиной того, что ваш выход PWM работает неправильно. Модуль сравнения вывода ожидает определенного количества меток, и он никогда не достигает этого.

Как это почему-то работает на 255, мы можем взглянуть на код analogWrite:

void analogWrite(uint8_t pin, int val)
{
    // We need to make sure the PWM output is enabled for those pins
    // that support it, as we turn it off when digitally reading or
    // writing with them.  Also, make sure the pin is in output mode
    // for consistenty with Wiring, which doesn't require a pinMode
    // call for the analog output pins.
    pinMode(pin, OUTPUT);
    if (val == 0)
    {
        digitalWrite(pin, LOW);
    }
    else if (val == 255)
    {
        digitalWrite(pin, HIGH);
    }

Таким образом, записывая 255, код analogWrite игнорирует всю PWM и выводит сравнение, и просто пишет пин-код.

Наконец, что касается решения вашей проблемы, я бы лично пошел по пути не используя контакты 11 и 3 (timer2). Да, для этого потребуется небольшая перезагрузка, но вы можете освободить таймер2 для использования библиотеки IR.

В качестве альтернативы вы можете сориентироваться вокруг ИК-библиотеки и попытаться заставить ее работать без сброса счетчика.

Ответ 2

Обратите внимание на используемую плату, если вы используете Arduino Uno, тогда ответственный код будет://Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio и т.д. еще // определить IR_USE_TIMER1//tx = pin 9 определить IR_USE_TIMER2//tx = pin 3 ENDIF

Ответ 3

У меня была такая же проблема с предварительно сконструированным L298 V2 экраном двигателя.

Штыри были отмечены как на щите:

Двигатель1: контакты 3 и 5 Motor2: контакт 6 и 9

Я использую PIN10 вместо 3 и используя небольшой обходной путь: я помещаю провод от PIN10 к PIN3 на SHIELD. Мой проект состоял в том, чтобы управлять моим роботом с помощью пульта дистанционного управления SAMSUNG TV.