ATmega. Формирование ШИМ сигнала

Решил научиться управлять 4-х контактными кулерами, для этого необходим ШИМ с частотой 25 кГц. Разбираемся, реализуем требуемое.

Задача

Для управления скоростью вращения вентилятора при помощи МК ATmega 328P организовать 2-х канальный ШИМ, с частотой 25 кГц. Проверить, что при помощи настроенной схемы можно управлять вентиляторами.

Отступление

Не имею профильного образования по работе с МК, в данный момент самостоятельно изучаю данное направление. Например на изучение работы таймеров и закрепления материала в виде написания данной статьи потрачено ~ 10 часов. Как следствие решение может содержать некоторые не точности.

Решение

Как обычно расписывать много теории не буду, благо много информации в интернетах и есть документация от производителя(далее по тексту буду ссылаться на эту документацию с указанием номеров страниц и таблиц). Для облегчения жизни МК организуем ШИМ при помощи таймеров.

По условиям задачи необходимо реализовать 2 канала, в ATmega 328P можно реализовать двумя способами:

  1. Использовать два 8-ми битных таймера T0 и T2;
  2. Использовать один 16-ти битный таймер T1.

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

Расчет таймера

В документации есть раздел с описанием работы T1 стр. 149-185(в целом не мало), а на страницах 171-172 размещена таблица 20-6 с режимами работы таймера.

Как писал выше интересен вариант независимого управления двумя каналами на частоте 25 кГц, из прочитанного понял, что не подойдут следующие:

  1. Нормальный режим(Normal), счет происходит от нижнего до разрядности таймера. Даже с применением делителя, его не достаточно. Рассчитать можно по формуле:

    ШИМ = Тактовая частота / ( Делитель * Разрядность таймера )

    16 000 000 / ( 1 * 65 535 ) = 244,144 Гц

  2. Режим очистки по совпадению(Clear Timer on Compare Match, CTC), в которых переполнение в происходит при достижения установленного значения в регистре OCR1A — на выходе имеем только один канал;
  3. Режимы быстрого ШИМ(Fast PWM) и с коррекцией фазы(Phase Correct), с разрядностью 8, 9 , 10 бит смотри пункт 1.

Остаются режимы работы в которых переполнение в происходит при достижения установленного значения в регистре ICR1,

Режим Fast PWM

Режим 14 в таблице 20-6 на странице 172. В этом режиме счетчик считает до верхнего предела и сбрасывается, формула расчета следующая:

ШИМ = Тактовая частота / Делитель * ( 1 + Верхний предел )

16 000 000 / 1 * ( 1 + 639 ) = 25 000 Гц

Ну и напишу формулу, которой я получил верхний предел:

Верхний предел = ( Тактовая частота * Делитель  /  ШИМ ) — 1 

( 16 000 000 * 1 / 25 000 ) — 1 = 639

Полученное значение помещаем в регистр ICR1. Скважность сигнала будет регулироваться регистрами OCR1A  и  OCR1B. Предполагал, что диапазон должен быть от 0 до 639, но по работе вентилятора пришел к значениям от 320 до 640(при условии, что по документации вентилятор не меняет скорости, при скважности 0-30%). Попробую позже разобрать(TODO).

Остается воспользоваться таблицей выходного сигнала 20-4, параметрами режима 14 таблицы 20-6, таблицей делителей 20-7, и написать функцию инициализации:

void pwm_initial() {

    DDRB |= 1 << 1; // PB1 как выход, канал 1
    DDRB |= 1 << 2; // PB2 как выход, канал 2

    TCCR1A = 0; // Сброс данных регистра
    TCCR1B = 0; // Сброс данных регистра
    TCNT1  = 0; // Установка нижнего предела

    TCCR1B |= (1 << CS10); // Работа без делителя

    TCCR1A |= (1 << COM1A1) | (1 << COM1B1);  // Не инверсный режим работы
    ICR1    = 639;                            // 16 МГц / 1 * ( 1 + 639 ) = 25 кГц

    // Установка верхнего предела
    // значением в бите ICR1
    // Режим 14 из документации
    TCCR1A |= (1 << WGM11);
    TCCR1B |= (1 << WGM12) | (1 << WGM13);

    OCR1A = 416;  // Начальное значение уровня 30%
    OCR1B = 416;  // Начальное значение уровня 30%

}

Режим Phase Correct

Режим 10 в таблице 20-6 на странице 172. В этом режиме счетчик считает от 0 до верхнего предела, а потом обратно до 0,  формула расчета следующая:

ШИМ = Тактовая частота / 2* Делитель *  Верхний предел

16 000 000 / 2 * 1 * 320 = 25 000 Гц

Ну и напишу формулу, которой я получил верхний предел:

Верхний предел = Тактовая частота / ( 2 * Делитель  *  ШИМ )

16 000 000 / ( 2 * 1 * 25 000 ) = 320

Полученное значение помещаем в регистр ICR1. Скважность сигнала будет регулироваться регистрами OCR1A  и  OCR1B, по документации диапазон от 0 до 320.

Остается воспользоваться таблицей выходного сигнала 20-5, параметрами режима 10 таблицы 20-6, таблицей делителей 20-7, и написать функцию инициализации:

void pwm_initial() {

    DDRB |= 1 << 1; // PB1 как выход, канал 1
    DDRB |= 1 << 2; // PB2 как выход, канал 2

    TCCR1A = 0; // Сброс данных регистра
    TCCR1B = 0; // Сброс данных регистра
    TCNT1  = 0; // Установка нижнего предела

    TCCR1B |= (1 << CS10); // Работа без делителя

    TCCR1A |= (1 << COM1A1) | (1 << COM1B1);  // Не инверсный режим работы
    ICR1    = 320;                            // 16 МГц / 2 * 1 * 320 = 25 кГц

    // Установка верхнего предела
    // значением в бите ICR1
    // Режим 10 из документации
    TCCR1A |= (1 << WGM11);
    TCCR1B |= (1 << WGM13);

    OCR1A = 96;  // Начальное значение уровня 30%
    OCR1B = 96;  // Начальное значение уровня 30%

}

Режим Phase and Frequency Correct

Режим 8 в таблице 20-6 на странице 172. В этом режиме возможно менять не только скважность, но и частоту сигнала. В остальном аналогичен режиму Phase Correct PWM, в рамках данной статьи разбирать не буду.

Проверка работы

Теперь при остается вызвать описанную функцию при начале работы программы, и на ножках PB1 и PB2 будет работать ШИМ с частотой 25 кГц

Для проверки работы нам хватит одного вентилятора. К вентилятору производим подключение к контактам

  1. GND вентилятора к  Atmega;
  2. + 12 В;
  3. Не задействован;
  4. ШИМ сигнал  от порта PB1 или PB2.

После запуска вентилятор начнет вращаться с небольшой скоростью. Для управления скоростью необходимо менять значение битов OCR1A  и  OCR1B  для портов  PB1  и  PB2 соответственно.

Для проверки частоты можно воспользоваться осциллографом или написать небольшую программку на том же МК, об этом опубликована статья ATmega. Счетчик импульсов ШИМ.

Понравилась статья? Поделиться с друзьями:
Комментарии: 4
  1. Vladimir

    Спасибо за материал. Режим 15 (ШИМ) не смог настроить, а 14 режим заработал на ATmega328.

    1. Guesto (автор)

      Vladimir, рад, что пригодилось!

  2. Артём

    Здравствуйте, уважаемый Guesto! Возникло несколько вопросов. Прошу прощения, если они глупые.
    1. -12В и +12В от какого источника питания вы подали на вентилятор?
    2. Вы в коде указали, что «TCCR1A |= (1 << COM1A1) | (1 << COM1B1); // Не инверсный режим работы». А инверсный это какой? С отрицательным напряжением?

    1. Guesto (автор)

      Артём, добрый день!

      Вопросы не глупые, просто некоторые моменты со временем кажутся примитивными, хотя ранее на них было потрачено не мало времени.

      По вопросам:
      1. Использовал компьютерный блок питания, он умеет выдавать 5 и 12 Вольт одновременно и имеет общий GND. И правильней написать именно GND, а не -12 Вольт(в статье поправил);
      2. Тут я намудрил, дословно переведя документацию. Правильнее для понимания будет «Порямой» и «Обратный» режимы.
      Если очень грубо, различие в установке высокого или низкого сигнала на выходе, при совпадении счетчика с верхним переделом. Надеюсь не запутал еще больше.
      Рекомендую изучить документацию, в ней подробно описаны механизмы работы.
      Сам же освежу знания и поправлю статью, после прочтения остались вопросы(

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: