| Форум РадиоКот https://radiokot.ru/forum/ |
|
| ШИМ регулятор с изменяемой частотой и скважностью на МК https://radiokot.ru/forum/viewtopic.php?f=57&t=109176 |
Страница 1 из 2 |
| Автор: | yur4ik [ Вт окт 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% ), тактируем второй таймер в режиме фаст, такая идея имеет право на жизнь? |
|
| Автор: | BorisSPB [ Вт окт 28, 2014 17:37:09 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
А чем не нравится режим PWM, Phase and Frequency Correct (у ATmega16 режим 8 таймера 1)? ICR1 задает частоту, а OCR1A скважность. |
|
| Автор: | yur4ik [ Вт окт 28, 2014 20:59:43 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
я просто не знал про этот режим, а тут нашел когда читал про шим в инете, пока эксперементировал как раз Вы и отписались тут насчет этого режима. только вот не знаю какой лучше выбрать Ph. & fr. cor. PWM top=ICR1 или Ph. & fr. cor. PWM top=OCR1. |
|
| Автор: | COKPOWEHEU [ Вт окт 28, 2014 21:12:54 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Лучше, когда TOP==ICR. OCR1 лучше использовать для генерации ШИМа. |
|
| Автор: | BorisSPB [ Вт окт 28, 2014 21:23:51 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Да, TOP==ICR лучше потому что сравнение OCR1 управляет выходом. |
|
| Автор: | COKPOWEHEU [ Вт окт 28, 2014 21:31:56 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Так то управлять может как OCR1A, так и OCR1B, только второе не может быть TOP'ом. Но все равно лучше, когда оба регистра сравнения используются по назначению. |
|
| Автор: | yur4ik [ Вт окт 28, 2014 23:45:53 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Выбрал первый вариант ICR1, настроил на частоту в 400Гц, скважность кинул чисто на вскидку. А когда захотел рассчитать то формулу так и не нашел. Может кто подскажет? |
|
| Автор: | yur4ik [ Ср окт 29, 2014 10:02:25 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
ВСе разобрался, скважность от 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); } } } } |
|
| Автор: | COKPOWEHEU [ Ср окт 29, 2014 19:14:44 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Код пока плохочитаем. Уберите мусор, который конфигуратор cvavr заботливо навалил по всему коду. Особенно, бессмысленные комментарии в десятки строк. Если прерывание от таймера не используется - удалите его. (у меня был один случай, когда прерывание от АЦП было фактически без обработчика, но там оно служило для выхода МК из сна, так что там по-другому было трудно. Здесь случай явно не тот) Приведите выражения вида TIMSK=0x80; к читаемому - TIMSK=(1<<TOIE1); Речь, разумеется, не только о TIMSK, но и о PORTB, ACSR и прочих. |
|
| Автор: | YS [ Пт окт 31, 2014 18:39:40 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Я подобное делал. |
|
| Автор: | Эйлер Леонард [ Вт июл 25, 2023 22:15:17 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Добрый вечер. Подскажите пожалуйста какой режим Fast PWM для 16 битного таймера предпочтительней согласно таблице в Datasheet - 14 или 15 если частота задается фиксированной, а необходимо менять только коэффициент заполнения (порядка 10-90%). Для МК ATmega. |
|
| Автор: | Starichok51 [ Ср июл 26, 2023 09:48:00 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
разберись, чем отличаются эти режимы, а потом решай, какой режим тебе нужен. |
|
| Автор: | Alex_ka [ Ср июл 26, 2023 19:10:13 ] | ||
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК | ||
режим Fast PWM для 16 битного таймера предпочтительней согласно таблице в Datasheet - 14 или 15 если частота задается фиксированной, а необходимо менять только коэффициент заполнения (порядка 10-90%). Для МК ATmega. Вот тебе образец на 16 битном, с регулируемой частотой и регулированной длительностью, с исходником на СИ в CodeVision и протеус. Там сам поиграешься с частотой на делителях в программе и в протеусе на на контроллере.
|
|||
| Автор: | Эйлер Леонард [ Ср июл 26, 2023 19:20:20 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Не много копипасты из своих шпаргалок РЕЖИМ 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 тот же Х, только в другой руке. |
|
| Автор: | Alex_ka [ Ср июл 26, 2023 19:39:52 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
[size=85] Так это и коню понятно. Кварц / TCCR1B (CS10-11-12)/OCR1AH,AL = частота тика
Чем больше значение в OCR1A тем меньше частота . |
|
| Автор: | Эйлер Леонард [ Сб июл 29, 2023 10:11:39 ] | ||
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК | ||
Накрапал библиотечку для экспериментов с ШИМ на 16-ибитном таймере ATmega328/2560. Файлик main.cpp Код: /* ATmega328 AtmelStudio -std=c++14 */ Файлик TimerHelpers.h#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/ Код: #ifndef TIMERHELPERS_H ICRx OCRxA OCRxB OCRxC и пр. устанавливаютя самостоятельно.#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 Вообще-то затея у меня разработать схему/код/алгоритм управления топливными форсунками на двигатель спортивного мотоцикла. Перебрал все ШИМы. И все-каки пока остановился на 14 режиме (с возможным внешним тактированием на лапе T1). Ну это так, мысли вслух.
|
|||
| Автор: | Эйлер Леонард [ Сб июл 29, 2023 19:12:31 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Впрыск — Это Просто. Но не легок путь джедая - грабли и капканы на каждом шагу. К стати, там по ссылке в конце темы форума есть и мой вопрос (без ответа) - может поделитесь знаниями? |
|
| Автор: | Alex_ka [ Сб июл 29, 2023 19:58:39 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Про моцики фиг его знает. На авто 800 об/ мин. это 800/60 сек/3 = 4,44 Гц. С такой частотой на ХХ на форсунки цилиндров подаётся сигнал. А длительность это уже от объёма цилиндра, температуры двигателя, от количества подаваемого воздуха, от показаний зондов на выхлопе и от пропускной возможности форсунки. В моцике тоже ведь частота с датчика холла снимается по показаниям которого искра появляется. Твоя длительность впрыска должна быть привязана к оборотам. |
|
| Автор: | Starichok51 [ Вс июл 30, 2023 10:58:32 ] |
| Заголовок сообщения: | Re: ШИМ регулятор с изменяемой частотой и скважностью на МК |
Alex_ka писал(а): На авто 800 об/ мин. это 800/60 сек/3 = 4,44 Гц. это что, один импульс на 3 (ТРИ) оборота коленвала?
|
|
| Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


