Обсуждаем контроллеры компании Atmel.
Ответить

ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт окт 28, 2014 16:12:10

Всем привет, необходим ШИМ регулятор с изменяемой частотой (от 10Гц до 1000Гц шаг 10-20Гц) и скважностью(от 10% до 100% чем меньше тем лучше), но вся суть в том что бы частота была постоянной при изменении скважности. Режим FAST PWM меняет скважность только, а PHASE correct PWM наоборот постоянна скважность, а частота меняется.
Есть идея объединить 2 таймера, одним менять частоту, а другим скважность. Попробовал реализовать, ничего путевого на тиньке 2313 не вышло. Скважность не захотела меняться. Таймером0 хотел регулировать скважность, а таймером1 частоту. Таймер один настроил на частоту в 7кГц, в таймере0 выбрал внешнее тактирование от таймера1, режим ФАСТ, и расчитал значение OCR для скважности в 30%, запустил в проутосе, но на выходе было пусто, потом в регистр занес значение 254 появился сигнал со скважностью такой же как и у тактирующего сигнала.
Вопрос вот в чем, возможно на 2 таймерах замутить такую регулировку? Или не выйдет только с помощью МК. И если выйдет, то лучше тактировать мелкими импульсами или наоборот?
Идея такова на одном таймере вырабатываем тактирующие импульсы( скважности 100% ), тактируем второй таймер в режиме фаст, такая идея имеет право на жизнь?

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт окт 28, 2014 17:37:09

А чем не нравится режим PWM, Phase and Frequency Correct (у ATmega16 режим 8 таймера 1)?
ICR1 задает частоту, а OCR1A скважность.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт окт 28, 2014 20:59:43

я просто не знал про этот режим, а тут нашел когда читал про шим в инете, пока эксперементировал как раз Вы и отписались тут насчет этого режима. только вот не знаю какой лучше выбрать Ph. & fr. cor. PWM top=ICR1 или Ph. & fr. cor. PWM top=OCR1.
Последний раз редактировалось yur4ik Вт окт 28, 2014 23:45:20, всего редактировалось 2 раз(а).

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт окт 28, 2014 21:12:54

Лучше, когда TOP==ICR. OCR1 лучше использовать для генерации ШИМа.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт окт 28, 2014 21:23:51

Да, TOP==ICR лучше потому что сравнение OCR1 управляет выходом.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт окт 28, 2014 21:31:56

Так то управлять может как OCR1A, так и OCR1B, только второе не может быть TOP'ом. Но все равно лучше, когда оба регистра сравнения используются по назначению.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт окт 28, 2014 23:45:53

Выбрал первый вариант ICR1, настроил на частоту в 400Гц, скважность кинул чисто на вскидку. А когда захотел рассчитать то формулу так и не нашел. Может кто подскажет?

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Ср окт 29, 2014 10:02:25

ВСе разобрался, скважность от 0 и до верхнего значения :)
Может кому пригодиться скважность меняется и частота не зависимо.
Спойлер
Код:
/*****************************************************
Chip type               : ATtiny2313
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Tiny
External RAM size       : 0
Data Stack size         : 32
*****************************************************/

#include <tiny2313.h>
#include <delay.h>
// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
// Place your code here

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port A initialization
// Func2=In Func1=In Func0=In
// State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=Out Func3=Out Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=0 State3=0 State2=T State1=T State0=T
PORTB=0x03;
DDRB=0x18;

// Port D initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Ph. & fr. cor. PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xA0;
TCCR1B=0x11;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x07; //настраиваем скважность А 30% [1..ICR1-1]
OCR1AL=0xD0;
ICR1H=0x1A; //настраиваем частоту регистром захвата 600Hz
ICR1L=0x0B;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x80;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here
if(PINB.0 == 0) //если кнопка "больше" нажата
{
if (OCR1A < 13334)
{ // коэффициент заполнения ШИМ изменяется от 0 до ICR1
OCR1A = OCR1A+100; // записываем переменную в регистр сравнения
delay_ms(30); // задержка 30ms
}
}
if (PINB.1==0)
{
if(ICR1<13334)
{     
//TCNT1=0x00;
ICR1=ICR1+100;
delay_ms(30);
}
}
}
}

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Ср окт 29, 2014 19:14:44

Код пока плохочитаем. Уберите мусор, который конфигуратор cvavr заботливо навалил по всему коду. Особенно, бессмысленные комментарии в десятки строк. Если прерывание от таймера не используется - удалите его. (у меня был один случай, когда прерывание от АЦП было фактически без обработчика, но там оно служило для выхода МК из сна, так что там по-другому было трудно. Здесь случай явно не тот)
Приведите выражения вида TIMSK=0x80; к читаемому - TIMSK=(1<<TOIE1); Речь, разумеется, не только о TIMSK, но и о PORTB, ACSR и прочих.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Пт окт 31, 2014 18:39:40

Я подобное делал.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вт июл 25, 2023 22:15:17

Добрый вечер. Подскажите пожалуйста какой режим Fast PWM для 16 битного таймера предпочтительней согласно таблице в Datasheet - 14 или 15 если частота задается фиксированной, а необходимо менять только коэффициент заполнения (порядка 10-90%). Для МК ATmega.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Ср июл 26, 2023 09:48:00

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

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Ср июл 26, 2023 19:10:13

режим Fast PWM для 16 битного таймера предпочтительней согласно таблице в Datasheet - 14 или 15 если частота задается фиксированной, а необходимо менять только коэффициент заполнения (порядка 10-90%). Для МК ATmega.
Вот тебе образец на 16 битном, с регулируемой частотой и регулированной длительностью, с исходником на СИ в CodeVision и протеус. Там сам поиграешься с частотой на делителях в программе и в протеусе на на контроллере.
Вложения
ШИМ на ATmega 8.rar
(17.2 KiB) Скачиваний: 44

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Ср июл 26, 2023 19:20:20

Не много копипасты из своих шпаргалок :))
РЕЖИМ 14: Fast PWM (Быстрый ШИМ)
TCCR1A |= (1 << WGM11);
TCCR1B |= (1 << WGM12) | (1 << WGM13);
//------
частота регулируется предделителем и ICR1, в ICR1 записывается верхний предел
скважность регулируется OCR1A и OCR1B, при этом значение в OCR1A и OCR1B не может
быть больше значения в ICR1, при OCR1A = ICR1 / 2 будет меандр
доступны два канала: OC1A, OC1B
Частота рассчитывается по формуле:
Частота = Частота_мк / (Предделитель * ICR1)
А значение в ICR1, если известна необходимая частота - по формуле:
ICR1 = Частота_мк / (Предделитель * Частота)
Чем больше значение в ICR1 тем меньше частота
Например при предделителе 8, значении ICR1 = 100 получится частота 20 кГц,
при этом значение OCR1A и OCR1B должно быть в пределах от 0 до 100
// ====
РЕЖИМ 15: Fast PWM (Быстрый ШИМ)
TCCR1A |= (1 << WGM10) | (1 << WGM11);
TCCR1B |= (1 << WGM12) | (1 << WGM13);
частота регулируется предделителем и OCR1A, в OCR1A записывается верхний предел
скважность регулируется OCR1B, при этом значение в OCR1B не может
быть больше значения в OCR1A, при OCR1B = OCR1A / 2 будет меандр
доступен один канал: OC1B
Частота рассчитывается по формуле:
Частота = Частота_мк / (Предделитель * OCR1A)
А значение в OCR1A, если известна необходимая частота - по формуле:
OCR1A = Частота_мк / (Предделитель * Частота)
Чем больше значение в OCR1A тем меньше частота
Например при предделителе 8, значении OCR1A = 100 получится частота 20 кГц,
при этом значение OCR1A и OCR1B должно быть в пределах от 0 до 100
// ====

В режиме 14 регистром сравнения является OCR1, значение TOP устанавливается через регистр ICR1.
В режиме 15 регистром сравнения является ICR1, значение TOP устанавливается через регистр OCR1.

В чем разница у двух последних режимов?

Регистр OCR1 благодаря использованию внутреннего буфера обновляется быстрее, чем ICR1. Поэтому, если частота меняется часто, и важно быстродействие, лучше выбрать режим 15.
Почему в этом режиме только один канал OC1B? OCR1A используется в качестве регистра хранения TOP, то его канал OC1A становится недоступен, и остается только OC1B.

Если частота фиксированная, а чаще меняется скважность, можно использовать режим 14.

Кароч. Режимы 14/15 тот же Х, только в другой руке.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Ср июл 26, 2023 19:39:52

[size=85]
Чем больше значение в OCR1A тем меньше частота
.
Так это и коню понятно. Кварц / TCCR1B (CS10-11-12)/OCR1AH,AL = частота тика

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Сб июл 29, 2023 10:11:39

Накрапал библиотечку для экспериментов с ШИМ на 16-ибитном таймере ATmega328/2560. Файлик main.cpp
Код:
/* ATmega328 AtmelStudio  -std=c++14 */
#define F_CPU 8000000UL

#include <avr/io.h>
#include "E:\lib\src\AVR\GPIO.h"
#include "E:\AVR_PWM\Timers328(test)\src\TimerHelpers.h"

using TimHelp1 = TimerHelper16<14, PRESCALE::PRESCALE_8, (PORT::CLEAR_A_ON_COMPARE | PORT::CLEAR_B_ON_COMPARE)>;
      TimHelp1 timer16;
 
 GPIO<BOARD::OC1A> OC1A;  // PinB1
 GPIO<BOARD::OC1B> OC1B;  // PinB2
 
int main(void){
   
// Порты на выход
 OC1A.output();
 OC1B.output();

timer16.init<TCCR::TCCR_1A, TCCR::TCCR_1B>();
 
// 100 = 8000000 / (8 * 10000) Частота ШИМ 100 Герц
 
 ICR1 = 10000;//
 OCR1A = 4400;// 9999 верхний предел
 OCR1B = 3300;
 
  while (1) {  }
      
return 0;   
} // main/
Файлик TimerHelpers.h
Код:
#ifndef TIMERHELPERS_H
#define TIMERHELPERS_H

#include <avr/io.h>
#include <assert.h>

// ATmega640/1280/1281/2560/2561
#if defined(__AVR_ATmega640__)  || \
    defined(__AVR_ATmega1280__) || \
    defined(__AVR_ATmega1281__) || \
    defined(__AVR_ATmega2560__) || \
    defined(__AVR_ATmega2561__)

// Timer control registers
enum struct TCCR : uint16_t {

   // Timer1 Control_Register_A/_B/_C (16:bit)
   TCCR_1A = (const uint16_t) &TCCR1A, // (0x80)
   TCCR_1B = (const uint16_t) &TCCR1B, // (0x81)
   TCCR_1C = (const uint16_t) &TCCR1C, // (0x82)
   
   // Timer3 Control_Register_A/_B/_C (16:bit)
   TCCR_3A = (const uint16_t) &TCCR3A, // (0x90)
   TCCR_3B = (const uint16_t) &TCCR3B, // (0x91)
   TCCR_3C = (const uint16_t) &TCCR3C, // (0x92)

   // Timer4 Control_Register_A/_B/_C (16:bit)
   TCCR_4A = (const uint16_t) &TCCR4A, // (0xA0)
   TCCR_4B = (const uint16_t) &TCCR4B, // (0xA1)
   TCCR_4C = (const uint16_t) &TCCR4C, // (0xA2)

   // Timer5 Control_Register_A/_B/_C (16:bit)
   TCCR_5A = (const uint16_t) &TCCR5A, // (0x120) = 288
   TCCR_5B = (const uint16_t) &TCCR5B, // (0x121) = 289
   TCCR_5C = (const uint16_t) &TCCR5C  // (0x122) = 290
};

// ATmega48A/PA/88A/PA/168A/PA/328/P
#elif defined(__AVR_ATmega48__)   ||\
      defined(__AVR_ATmega48A__)  ||\
      defined(__AVR_ATmega48PA__) ||\
      defined(__AVR_ATmega48P__)  ||\
      defined(__AVR_ATmega88__)   ||\
      defined(__AVR_ATmega88A__)  ||\
      defined(__AVR_ATmega88PA__) ||\
      defined(__AVR_ATmega168__)  ||\
      defined(__AVR_ATmega168A__) ||\
      defined(__AVR_ATmega168PA__)||\
     defined(__AVR_ATmega328__)  ||\
      defined(__AVR_ATmega328P__)
 
enum struct TCCR : uint16_t {

   // Timer1 Control_Register_A/_B/_C (16:bit)
   TCCR_1A = (const uint16_t) &TCCR1A, // (0x80)
   TCCR_1B = (const uint16_t) &TCCR1B, // (0x81)
   TCCR_1C = (const uint16_t) &TCCR1C  // (0x82)
};

#else
#error *!*!* AVR MCUs NOT SUPPORTED *!*!*
#endif

enum struct PRESCALE : uint8_t {
   
      NO_CLOCK = 0b00000'000, // (0) - таймер/счетчик остановлен
    PRESCALE_1 = 0b00000'001, // (1) - тактовый генератор CLK
    PRESCALE_8 = 0b00000'010, // (2) - CLK/8
   PRESCALE_64 = 0b00000'011, // (3) - CLK/64
  PRESCALE_256 = 0b00000'100, // (4) - CLK/256
 PRESCALE_1024 = 0b00000'101, // (5) - CLK/1024
    Tn_FALLING = 0b00000'110, // (6) - Внешний источник тактирования на выводе Tn. Часы на падающем фронте.
     Tn_RISING = 0b00000'111  // (7) - Внешний источник тактирования на выводе Tn. Часы на переднем фронте.
};

// способы вывода
enum struct PORT : uint8_t {
   
               NO_PORT = 0b00'00'00'00,
    
   TOGGLE_A_ON_COMPARE = 0b01'000000,
    CLEAR_A_ON_COMPARE = 0b10'000000,
      SET_A_ON_COMPARE = 0b11'000000,
    
   TOGGLE_B_ON_COMPARE = 0b00'01'0000,
    CLEAR_B_ON_COMPARE = 0b00'10'0000,
      SET_B_ON_COMPARE = 0b00'11'0000,
   
   TOGGLE_C_ON_COMPARE = 0b0000'01'00,
    CLEAR_C_ON_COMPARE = 0b0000'10'00,
      SET_C_ON_COMPARE = 0b0000'11'00
}; 

constexpr PORT operator | (const PORT P0, const PORT P1) {
   return static_cast<PORT>(
   static_cast<uint8_t>(P0) | static_cast<uint8_t>(P1) );
}

constexpr uint8_t operator | (const uint8_t p0, const PORT P1) {
   return static_cast<uint8_t>( p0 | static_cast<uint8_t>(P1) );
}

constexpr uint8_t operator | (const uint8_t p0, const PRESCALE P1) {
   return static_cast<uint8_t>( p0 | static_cast<uint8_t>(P1) );
}

// положение битов WGMn1, WGMn0, WGMn3, WGMn2 в регистрах TCCRnA, TCCRnB
const uint8_t Modes[16][2] = {

{ 0b0000'0000, 0b0000'0000 },  //  0: Normal, top = 0xFFFF
{ 0b0000'0001, 0b0000'0000 },  //  1: PWM, Phase-correct, 8 bit, top = 0xFF
{ 0b0000'0010, 0b0000'0000 },  //  2: PWM, Phase-correct, 9 bit, top = 0x1FF
{ 0b0000'0011, 0b0000'0000 },  //  3: PWM, Phase-correct, 10 bit, top = 0x3FF
{ 0b0000'0000, 0b0000'1000 },  //  4: CTC, top = OCR1A
{ 0b0000'0001, 0b0000'1000 },  //  5: Fast PWM, 8 bit, top = 0xFF
{ 0b0000'0010, 0b0000'1000 },  //  6: Fast PWM, 9 bit, top = 0x1FF
{ 0b0000'0011, 0b0000'1000 },  //  7: Fast PWM, 10 bit, top = 0x3FF
{ 0b0000'0000, 0b0001'0000 },  //  8: PWM, phase and frequency correct, top = ICR1
{ 0b0000'0001, 0b0001'0000 },  //  9: PWM, phase and frequency correct, top = OCR1A
{ 0b0000'0010, 0b0001'0000 },  // 10: PWM, phase correct, top = ICR1A
{ 0b0000'0011, 0b0001'0000 },  // 11: PWM, phase correct, top = OCR1A
{ 0b0000'0000, 0b0001'1000 },  // 12: CTC, top = ICR1
{ 0b0000'0001, 0b0001'1000 },  // 13: reserved
{ 0b0000'0010, 0b0001'1000 },  // 14: Fast PWM, TOP = ICR1
{ 0b0000'0011, 0b0001'1000 }   // 15: Fast PWM, TOP = OCR1A
    
}; // end of Timers::Modes

// ***********************************************************
template<uint8_t mode, PRESCALE prescale, PORT port>
struct TimerHelper16 {

static_assert( !(mode < 0 || mode > 15), "*!*!* BAD MODE *!*!*" );

template<TCCR tccrA = TCCR::TCCR_1A, TCCR tccrB = TCCR::TCCR_1B>
static inline __attribute__((always_inline)) void init() {

 *(volatile uint8_t*)(tccrA) |= Modes[mode][CHANNEL::A] | port;
 *(volatile uint8_t*)(tccrB) |= Modes[mode][CHANNEL::B] | prescale;
}

 private:
  enum CHANNEL : uint8_t { A, B };
};

#endif    // TIMERHELPERS_H
ICRx OCRxA OCRxB OCRxC и пр. устанавливаютя самостоятельно.
Вообще-то затея у меня разработать схему/код/алгоритм управления топливными форсунками на двигатель спортивного мотоцикла. Перебрал все ШИМы. И все-каки пока остановился на 14 режиме (с возможным внешним тактированием на лапе T1). Ну это так, мысли вслух. :))
Вложения
ШИМ-14.png
Протеус
(98.01 KiB) Скачиваний: 23

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Сб июл 29, 2023 13:25:29

А зависимость от частоты оборотов двигателя или подачи искры и длительность открытия или дозу впрыска знаешь, что решил заняться написалавкой проги? Да и двигатели бывают разные, однотактные, двухтактные и четырёх. С какой частотой открывается форсунка цилиндра четырёхтактного двигла, при показаниях тахометра 800 об/мин? Чтобы было понятно о чём это я базар веду ниже скрины. А может прошивку карты впрыска с какого-то двигуна с сопоставимыми лошадями в WinOls разобрал?
Изображение Изображение

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Сб июл 29, 2023 19:12:31

Впрыск — Это Просто. Но не легок путь джедая - грабли и капканы на каждом шагу. К стати, там по ссылке в конце темы форума есть и мой вопрос (без ответа) - может поделитесь знаниями? :idea:

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Сб июл 29, 2023 19:58:39

Про моцики фиг его знает. На авто 800 об/ мин. это 800/60 сек/3 = 4,44 Гц. С такой частотой на ХХ на форсунки цилиндров подаётся сигнал. А длительность это уже от объёма цилиндра, температуры двигателя, от количества подаваемого воздуха, от показаний зондов на выхлопе и от пропускной возможности форсунки. В моцике тоже ведь частота с датчика холла снимается по показаниям которого искра появляется. Твоя длительность впрыска должна быть привязана к оборотам.

Re: ШИМ регулятор с изменяемой частотой и скважностью на МК

Вс июл 30, 2023 10:58:32

Alex_ka писал(а):На авто 800 об/ мин. это 800/60 сек/3 = 4,44 Гц.
это что, один импульс на 3 (ТРИ) оборота коленвала?
Ответить