Дискретность частоты ШИМ

mozart86
Offline
Зарегистрирован: 25.12.2014

Привет всем!

Возникла такая вот задача: необходимо изменять частоту ШИМ (коэффициент заполнения импульсов 50%) в пределах от 9 до 10 кГц с дискретностью ~12 Гц. При задействовании 8-битного таймера минимум, что мог достигнуть  это изменение на 50 Гц. С 16-битным таймером ситуация чуть получше — шаг снизился до 30 Гц, но этого недостаточно.

Может кто подскажет, реально ли в принципе достигнуть на этих частотах такой дискретности, и если да, то как? Вот код программки:

// Arduino Mega
#define PIN_POTENT   A1    // Подключение потенциометра
#define PIN_PWM      11    // Выводимый ШИМ

const byte averageFactor = 10;
unsigned int potentValue = 0;

unsigned long freqValue = 0;

void setup()
{
  pinMode(PIN_PWM, OUTPUT);

  // Задание режима быстрого ШИМ с изменением значения OCR1A, делитель 8
  TCCR1A = (1<<COM1A0) | (1<<COM1B1) | (1<<WGM11) | (1<<WGM10);
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);
}

void loop()
{
  // Считывание значения с потенциометра
  unsigned int oldPotentValue = potentValue;
  potentValue = analogRead(PIN_POTENT);

  // Усреднение значения
  potentValue = (oldPotentValue * (averageFactor - 1) + potentValue) / averageFactor; 

  // Преобразование его значения в частоту с пределом от 9 до 10 кГц
  long freqBound = map(potentValue, 0, 1023, 9000, 10000);

  // Формирование ШИМ
  freqValue = 16000000UL/8/2/freqBound/2;
  OCR1A = (unsigned int)freqValue;
}

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Phase and Frequency Correct PWM Mode

счёт до ICR, переключение по OCR, для 50% OCR=ICR/2

Logik
Offline
Зарегистрирован: 05.08.2014

Настройте TCCR1 на коэффициент 1 и в расчете freqValue соответственно исправте.

П.С.При постоянном заполнении это уже не ШИМ, это просто генерация частоты.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

  // Считывание значения с потенциометра
  int oldPotentValue = potentValue;
  potentValue = analogRead(PIN_POTENT);

  // Усреднение значения
  potentValue = (oldPotentValue * (averageFactor - 1) + potentValue) / averageFactor; 

  // Преобразование его значения в частоту с пределом от 9 до 10 кГц
  int freqBound = map(potentValue, 0, 1023, 9000, 10000);

  // Формирование меандра
  ICR1A = 1000000000UL/freqBound/8;
  OCR1A = ICR1A >> 1;

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

потенциометр шумит - частота будет прыгать, лучше энкодер

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

строка 32 - 16000000/8/2/10000/2=50 тиков

0,0625*8*50=25 uS - > 40 kHz

строка 15 - зачем канал В ? 1<<COM1B1

счётчик лучше в режим 4 и OCR1A = 1000000000UL/freqBound/8;

1000000000/9000/8= 13888 тиков по 0,0625 uS с делителем на 64 = 55555 uS -> toggle 9000 Hz

1000000000/9001/8= 13887 тиков по 0,0625 uS с делителем на 64 = 55549 uS -> toggle 9001 Hz

1000000000/9999/8=12501 тиков по 0,0625 uS с делителем на 64 = 50005 uS -> toggle 9999 Hz

1000000000/10000/8=12500 тиков по 0,0625 uS с делителем на 64 = 50000 uS -> toggle 10000 Hz

mozart86
Offline
Зарегистрирован: 25.12.2014

Спасибо за подробный ответ!

Канал B использовался просто для сравнения — проверял, будет ли на нем точнее. Как и ожидалось, дискретность таже. Режимы CTC и Phase and Frequency Correct PWM Mode по сравнению с мною использованным (PWM с OCR1A) также не дали никакого выигрыша в минимизации шага.

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

Касательно ответа мне непонятно: почему Вы в формуле вычисления OCR1A используете тактовую частоту 1 ГГц (1000000000UL)? 

 

P.S. Я там ошибся в формуле расчета частоты для ШИМ: менял режимы и забыл вернуть к первоначальному значению. Правильно так:

freqValue = 16000000UL/8/2/freqBound;
mozart86
Offline
Зарегистрирован: 25.12.2014

Logik пишет:

Настройте TCCR1 на коэффициент 1 и в расчете freqValue соответственно исправте.

П.С.При постоянном заполнении это уже не ШИМ, это просто генерация частоты.

Странно, вчера первым делом изменил коэффициент деления на 1, но получилась какая-то чепуха, а с коэффициентом 8 заработало сразу. Сегодня попробовал снова поменять на 1 и заработало! Дискретность шага составила около (11—12) Гц.

Спасибо за помощь!

 

P.S. ШИМ или генерация частоты — вопрос философский... но в целом, согласен))