oldbrowze 0 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба Всем здравствуйте! Стоит задача: нужно на выходе трех ножек(PA8-10) получить соответственно 3 фазы ШИМ, который определяется по закону синуса(3 синусоидальные фазы нужно получить). Столкнулся с проблемой неправильной настройки. Фазу 2 и 3 вырезал, пока не разберусь с первой. В общем: таймер 1 отвечает за вывод значений на ножки. Его частота рассчитывается по формуле: Fcpu / ((arr+1) (psc+1)) = 72*10^6 / 2402 = 29.9kHz!!!!!! <<<< Второй таймер грузит значение в таймер 2. Его частота: Fcpu / ((arr+1) (psc+1)) = 65kHz!!!!!!!!! <<<<<<<< В одной беседе подсказали такие формулы(они в коде). Очень большие частоты. Но формул, по которым нужно считать правильно, я не знаю. Подскажите, пожалуйста, если знаете. Синус формировал по формуле: 2^16 / 2 * sin(T) + 2^16 / 2. т.е чтобы в отрицательную часть не заходить, сместил его на половину 2^16. Буду очень признателен, если подскажите. где тут ошибка. Понимаю, что где-то намутил воду.... Этот сигнал потом пойдет на 3-х фазный драйвер, который уже и будет управлять ключами. Заранее спасибо! Константы: Скрытый текст constexpr auto _F_CPU = 72000000u; // частота процессора constexpr auto _SIGNAL_FREQUENCY_MAX = 50u; // максимальная частота синусоиды constexpr auto _SIGNAL_FREQUENCY_MIN = 100u; // минимальная частота синусоиды constexpr auto _DISCRETIZE = 300u; // дискретизация синусоиды(количество точек) constexpr auto _VOLTAGE_ON_PORT = 3.3f; // напряжение на порту(напряжение питания) constexpr auto _BITNESS = 16u; // разрядность таймера[~цап] constexpr auto _AMPLITUDE = ((1 << 16) - 1) / 2; // максимальное значение таймера constexpr auto _ADC_MAX_VALUE = (1 << 12) - 1; // максимальное значение в АЦП Массив значений, размером 300: Скрытый текст static inline std::array<T, _DISCRETIZE> phase_A { 32768, 33456, 34144, 34832, 35519, 36204, 36888, 37570, 38250, 38928, 39603, 40275, 40943, 41608, 42269, 42926, 43578, 44226, 44868, 45506, 46137, 46763, 47382, 47995, 48602, 49201, 49793, 50377, 50954, 51523, 52083, 52635, 53178, 53713, 54237, 54753, 55259, 55754, 56240, 56715, 57180, 57634, 58077, 58508, 58929, 59338, 59735, 60120, 60493, 60854, 61202, 61538, 61861, 62172, 62469, 62753, 63024, 63282, 63526, 63757, 63974, 64177, 64366, 64541, 64702, 64850, 64983, 65101, 65206, 65296, 65372, 65433, 65480, 65513, 65531, 65535, 65524, 65498, 65459, 65404, 65336, 65253, 65155, 65044, 64918, 64778, 64624, 64455, 64273, 64077, 63867, 63643, 63406, 63155, 62890, 62613, 62322, 62018, 61701, 61372, 61030, 60675, 60308, 59929, 59538, 59135, 58720, 58294, 57857, 57408, 56949, 56479, 55998, 55508, 55007, 54496, 53976, 53447, 52908, 52360, 51804, 51240, 50667, 50086, 49498, 48902, 48299, 47690, 47073, 46451, 45822, 45188, 44548, 43903, 43253, 42598, 41939, 41276, 40609, 39939, 39266, 38589, 37910, 37229, 36546, 35861, 35175, 34488, 33800, 33112, 32423, 31735, 31047, 30360, 29674, 28989, 28306, 27625, 26946, 26269, 25596, 24926, 24259, 23596, 22937, 22282, 21632, 20987, 20347, 19713, 19084, 18462, 17845, 17236, 16633, 16037, 15449, 14868, 14295, 13731, 13175, 12627, 12088, 11559, 11039, 10528, 10027, 9537, 9056, 8586, 8127, 7678, 7241, 6815, 6400, 5997, 5606, 5227, 4860, 4505, 4163, 3834, 3517, 3213, 2922, 2645, 2380, 2129, 1892, 1668, 1458, 1262, 1080, 911, 757, 617, 491, 380, 282, 199, 131, 76, 37, 11, 0, 4, 22, 55, 102, 163, 239, 329, 434, 552, 685, 833, 994, 1169, 1358, 1561, 1778, 2009, 2253, 2511, 2782, 3066, 3363, 3674, 3997, 4333, 4681, 5042, 5415, 5800, 6197, 6606, 7027, 7458, 7901, 8355, 8820, 9295, 9781, 10276, 10782, 11298, 11822, 12357, 12900, 13452, 14012, 14581, 15158, 15742, 16334, 16933, 17540, 18153, 18772, 19398, 20029, 20667, 21309, 21957, 22609, 23266, 23927, 24592, 25260, 25932, 26607, 27285, 27965, 28647, 29331, 30016, 30703, 31391, 32079 }; Код инициализации таймеров: Скрытый текст void FreqConverter::timer_initialize() { RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // включаем TIM1 (тактирование от APB2 - 72 MHz) RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN; // включаем тактирование портов А и В /* Частота таймера прерываний равна = кол-во отсчетов * частоту сигнала. ARR = 1000 для видной скважности. на ARR != 1000 проверено не было!. */ //TIM1->ARR = ((_F_CPU / (1 << _BITNESS)) - 1); TIM1->ARR = (F_CPU / (_DISCRETIZE * _SIGNAL_FREQUENCY_MIN)) - 1; TIM1->PSC = 0; //TIM1->PSC = 0; //TIM1->ARR = (_F_CPU / (1 << _BITNESS)) - 1; TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E; // включаем выход 1, 2, 3 каналов ножек как выход TIM1->CCER |= (TIM_CCER_CC1P | TIM_CCER_CC2P | TIM_CCER_CC3P); // устанавливаем норм. полярность(1 - высокий) TIM1->BDTR |= TIM_BDTR_MOE; // разрешили работу выводов TIM1->CCMR1 |= (0b110 << TIM_CCMR1_OC1M_Pos) | (0b110 << TIM_CCMR1_OC2M_Pos); // установили работу каналов 1,2 как PWM1 TIM1->CCMR2 |= (0b110 << TIM_CCMR2_OC3M_Pos); // установили работу канала 3 как PWM1 //TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; TIM1->CR1 &= ~TIM_CR1_DIR; TIM1->CR1 &= ~TIM_CR1_CMS; // установим выводы каналов как alternative push-pull выходы GPIOA->CRH &= ~(GPIO_CRH_MODE8 | GPIO_CRH_MODE9 | GPIO_CRH_MODE10); //mode 01 - alernative push-pull GPIOA->CRH |= GPIO_CRH_MODE8_1 | GPIO_CRH_MODE9_1 | GPIO_CRH_MODE10_1; GPIOA->CRH &= ~(GPIO_CRH_CNF8_0 | GPIO_CRH_CNF9_0 | GPIO_CRH_CNF10_0); GPIOA->CRH |= (GPIO_CRH_CNF8_1 | GPIO_CRH_CNF9_1 | GPIO_CRH_CNF10_1);//cnf 10 - mode output TIM1->CR1 |= TIM_CR1_CEN; TIM2->ARR = ((_F_CPU / (1 << _BITNESS)) - 1); //TIM2->ARR = (F_CPU / (_DISCRETIZE * _SIGNAL_FREQUENCY_MIN)) - 1; TIM2->PSC = 0; TIM2->DIER = TIM_DIER_UIE; NVIC_EnableIRQ(TIM2_IRQn); TIM2->CR1 |= TIM_CR1_CEN; } extern "C" void TIM2_IRQHandler() { if (TIM2->SR & TIM_SR_UIF) { static uint16_t _counter_phase{0}; TIM1->CCR1 = FreqConverter::phase_A[_counter_phase]; //TIM1->CCR2 = FreqConverter::phase_B[_counter_phase]; //TIM1->CCR3 = FreqConverter::phase_C[_counter_phase]; if(++_counter_phase == _DISCRETIZE) _counter_phase = 0; TIM2->SR &= ~TIM_SR_UIF; } } Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Priest_89 8 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба Из сообщения непонятно, в чем конкретно проблема, и какая модель контроллера, но вот что бросилось в глаза. Таймер в выбранном режиме работает так - после перезапуска (СNT = 0) на выходе выставляется логическая единица, затем, когда таймер досчитает до значения, записанного в регистр CCRx, на выходе устанавливается логический ноль. Когда же таймер досчитает до значения в регистре ARR, он перезапускается и цикл начинается по новой. Вы же задаете частоту ШИМ, записывая в ARR значение 2400, при этом большинство значений в таблице, записываемых в CCRx, больше этого числа, и они никак не влияют на работу таймера - он перезапускается раньше. А вообще, вся работа периферии подробно описана в Reference Manual на соответствующий контроллер. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
oldbrowze 0 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба Спасибо за ответ. Микроконтроллер - STM32F103C8T6. По поводу ARR понял. Но как быть в таком случае? И, все же, интересует вопрос по поводу частоты: правильно ли я посчитал, не велика ли она? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Priest_89 8 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба Задавать частоту значением регистра PSC. Тем более, у STM32 тут хороший бонус - можно выбрать любой предделитель от 1 до 65536. Quote И, все же, интересует вопрос по поводу частоты: правильно ли я посчитал, не велика ли она? Ну для заданных значений - да, только в знаменателе 2400 должно быть Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба Какую частоту синуса вы хотите получить ? Пускай 50 Гц. Сделайте ваш ШИМ 8-ми битный. Тогда на период синуса у вас получится 256 отсчетов. И пускай скважность ШИМ у вас меняется каждый период таймера. Тогда ARR можно сделать равным 256. Остается найти частоту предделителя PSC. PSC = 72000000/50/256 - 1= 5624. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба 22 минуты назад, dimka76 сказал: Тогда на период синуса у вас получится 256 отсчетов. Которые, увы, нацело не делятся на три фазы. Я подобную задачу решал методом прямого цифрового синтеза - https://kit-e.ru/elcomp/dds-pryamoj-czifrovoj-sintez-chastoty-2/ Таким способом можно получить частоту с очень высокой точностью как частоты так и сдвига фаз при любой, даже некратной несущей частоте ШИМ. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба 9 minutes ago, Сергей Борщ said: Которые, увы, нацело не делятся на три фазы. Ошибка 0.4% А вот интересно по ГОСТ или МЭК или ISO какое допустимое отклонение на сдвиг фаз между фазами в трехфазной сети ? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
oldbrowze 0 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба 33 минуты назад, dimka76 сказал: Остается найти частоту предделителя PSC. PSC = 72000000/50/256 - 1= 5624. Таким образом, вместо TIM1->ARR = (F_CPU / (_DISCRETIZE * _SIGNAL_FREQUENCY_MIN)) - 1; TIM1->PSC = 0; я получил: TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / 256) - 1; TIM1->ARR = 256; где 256 в PSC - это значение, которое мы внесли в ARR? 13 минут назад, Сергей Борщ сказал: Которые, увы, нацело не делятся на три фазы. Я подобную задачу решал методом прямого цифрового синтеза - https://kit-e.ru/elcomp/dds-pryamoj-czifrovoj-sintez-chastoty-2/ Таким способом можно получить частоту с очень высокой точностью как частоты так и сдвига фаз при любой, даже некратной несущей частоте ШИМ. Спасибо за информацию! Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 6 ноября, 2021 Опубликовано 6 ноября, 2021 · Жалоба 8 minutes ago, oldbrowze said: я получил: TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / 256) - 1; TIM1->ARR = 256; где 256 в PSC - это значение, которое мы внесли в ARR? Да. Можно так #define ARR_VAL (256UL) TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / ARR_VAL) - 1UL; TIM1->ARR = ARR_VAL - 1UL; Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
oldbrowze 0 7 ноября, 2021 Опубликовано 7 ноября, 2021 · Жалоба Спасибо за ответы! 12 часов назад, dimka76 сказал: Можно так Можно, но предпочитаю constexpr. :) Сделал, как сказали. Эта осциллограмма - и есть шим, формированный по закону синуса? Скрытый текст Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 7 ноября, 2021 Опубликовано 7 ноября, 2021 · Жалоба 2 hours ago, oldbrowze said: Эта осциллограмма - и есть шим, формированный по закону синуса? Подключите к выходу вашего ШИМ RC цепочку с частотой среза 100 Гц и смотрите осциллографом после нее. Если все правильно, то увидите синус. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
oldbrowze 0 7 ноября, 2021 Опубликовано 7 ноября, 2021 · Жалоба Точных номиналов на R, C нет. Приблизительно подобрал. Получается какая-то пила. Я в правильном направлении? Огромное спасибо за консультацию!) Скрытый текст Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 7 ноября, 2021 Опубликовано 7 ноября, 2021 · Жалоба 19 minutes ago, oldbrowze said: Получается какая-то пила. Покажите вашу таблицу синуса. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
oldbrowze 0 7 ноября, 2021 Опубликовано 7 ноября, 2021 · Жалоба Скрытый текст static inline std::array<T, _DISCRETIZE> phase_A { 128, 131, 134, 137, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 191, 194, 197, 199, 202, 205, 207, 209, 212, 214, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 256, 256, 256, 256, 256, 256, 256, 255, 255, 254, 254, 253, 253, 252, 251, 250, 249, 248, 247, 246, 245, 243, 242, 240, 239, 237, 236, 234, 232, 230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198, 195, 193, 190, 187, 184, 181, 179, 176, 173, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 126, 123, 120, 117, 114, 111, 108, 104, 101, 98, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 41, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 47, 49, 51, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 119, 122, 125 }; Генерировал в матлабе по формуле: Y = round(2^bitness / 2 * sin(T) + 2^bitness / 2); Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 7 ноября, 2021 Опубликовано 7 ноября, 2021 · Жалоба 4 minutes ago, oldbrowze said: Hide contents static inline std::array<T, _DISCRETIZE> phase_A { 128, 131, 134, 137, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 191, 194, 197, 199, 202, 205, 207, 209, 212, 214, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 256, 256, 256, 256, 256, 256, 256, 255, 255, 254, 254, 253, 253, 252, 251, 250, 249, 248, 247, 246, 245, 243, 242, 240, 239, 237, 236, 234, 232, 230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198, 195, 193, 190, 187, 184, 181, 179, 176, 173, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 126, 123, 120, 117, 114, 111, 108, 104, 101, 98, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 41, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 47, 49, 51, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 119, 122, 125 }; Значения должны быть от 0 до 255. А у вас встречаются 256. Y = round(((((2^bitness)-1) / 2) * sin(T)) + (((2^bitness)-1) / 2)); Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться