Можно ли вывести переменные часы с помощью Fast PWM?

Я пытаюсь вывести часы и динамически изменить их частоту с помощью поворотного энкодера.

Когда включен код для поворотного энкодера, часы не достигают своей максимальной частоты (31 кГц). Но без кода поворотного энкодера это возможно. Что происходит, что он не может достичь своей максимальной частоты?

const byte CLOCKOUT = 9;
int val;
int encoder0PinA = 3;
int encoder0PinB = 4;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {
  pinMode (CLOCKOUT, OUTPUT); 
  // устанавливаем Таймер 1
  TCCR1A = bit (COM1A0);  // включить OC1A при сравнении совпадений
  TCCR1B = bit (WGM12) | bit (CS12);   // CTC, без предварительного масштабирования
  OCR1A =  0;

  pinMode (encoder0PinA, INPUT);
  pinMode (encoder0PinB, INPUT);
  Serial.begin (9600);
}

void loop() {
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      OCR1A-=100;
    } else {
      OCR1A+=100;
    }
    Serial.print (OCR1A);
    Serial.print ("/");
  }
  encoder0PinALast = n;
}

Код, который правильно достигает максимальной частоты, приведен ниже

void setup ()
  {
  pinMode (CLOCKOUT, OUTPUT); 
  // устанавливаем Таймер 1
  TCCR1A = bit (COM1A0);  // включить OC1A при сравнении совпадений
  TCCR1B = bit (WGM12) | bit (CS12);   // CTC, без предварительного масштабирования
  OCR1A =  0;
  }

void loop (){
  }

, 👍0

Обсуждение

вы исключаете много значений, если вы увеличиваете их на 100 .... пожалуйста, опубликуйте код, который достигает максимальной частоты, @jsotola

Обратите внимание, что когда OCR1A-=100 делает TCNT1 ниже, чем OCR1A, вы пропустите совпадение сравнения и должны будете ждать целую секунду, пока таймер не переполнится. Чтобы избежать этого, используйте режим генерации сигнала 15 вместо 4 (CTC)., @Edgar Bonet

Хорошо, я обновил код, который достигает полной частоты. Я намерен пропустить много значений в приращении, поскольку я не пытаюсь получить каждое значение. Что дает переход в режим генерации волн 15?, @user2242960


2 ответа


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

1

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

Вы написали что-то вроде этого:

if (pulseFromEncoder)
  if (direction1)
    OCR1A -= 100;
  else
    OCR1A += 100;

Теперь OCR1A представляет собой 16-битное целое число без знака. Значение 100 соответствует задержке таймера в 1,6 мс (см. комментарий Эдгара Боне ниже). Вот что происходит, когда вы поворачиваете в направлении 2:

        OCR1A  Time delay
Rotate:   300      4.8ms
Rotate:   200      3.2ms
Rotate:   100      1.6ms
Rotate:     0      0ms
Rotate: 65436   1047ms

Видишь? Значение прокручивается, и время полностью меняется.

Теперь, возможно, проблемы в другом (например, изменение режима на 15 вместо 4, как сказал EdgarBonet (не знаю, что это значит, вам следует дважды проверить различия в таблице данных atmega), но я настоятельно рекомендую вам исправить эту проблему, например, так:

const uint16_t OCR1A_Min = 0
const uint16_t OCR1A_Max = 20000
const uint16_t OCR1A_Step = 100

...

if (pulseFromEncoder)
  if (direction1)
  {
    if (OCR1A > OCR1A_Min + OCR1A_Step)
      OCR1A -= OCR1A_Step;
    else
      OCR1A = OCR1A_Min;
  }
  else
  {
    if (OCR1A < OCR1A_Max - OCR1A_Step)
      OCR1A += OCR1A_Step;
    else
      OCR1A = OCR1A_Max;
  }

Примечание: разве ваш кодировщик не нуждается в подавлении дребезга?

,

Относительно «_давайте предположим, что OCR1A представляет собой 16-битное целое число без знака_»: это действительно так. Относительно «_Давайте также предположим, что 100 соответствует 1 мс задержки_»: на самом деле это 100 × 256 ÷ F\_CPU = 1,6 мс., @Edgar Bonet

@EdgarBonet Спасибо, я обновил ответ вашими подтверждениями и исправил данные. В качестве примечания, я был довольно близок, даже если я дал совершенно случайное значение;), @frarugi87


0

ШИМ не меняет частоту. Он поддерживает постоянную частоту и изменяет рабочий цикл выходного сигнала. (Процент времени включения к общему времени.) Таким образом, если быстрый Arduino PWM не делает что-то очень нетрадиционное, ответ на заданный вами вопрос — нет.

,