Синусогенерація за допомогою ШІМ


16

Ми не можемо генерувати синусоїду належним чином за допомогою мікроконтролера MC68HC908GP32 . Опис ШІМ починається на сторінці 349. Тактова частота становить 2,4 МГц, тоді як ми використовували ШІМ 7 кГц за допомогою докалера та встановивши модуль таймера на 350 таким чином:

T1SC = 0x60;    // Prescaler: Div entre 64
//Counter modulo = 0x015E = 350
T1MODH = 0x01;   // High
T1MODL = 0x5E;   // Low

Вихід ШІМ фільтрується за допомогою наступного фільтра RLC, а потім постійний струм видаляється за допомогою кришки серії 1uF. Частота відсікання значно нижче 7 кГц ШІМ.

введіть тут опис зображення

По-перше, ми спробували використовувати LUT, зразки яких були створені за допомогою цього сайту (100 зразків, амплітуда = 250). Це включає один період.

 int seno[100]={ 125, 133, 141, 148, 156, 164, 171, 178, 185, 192, 198, 205, 211, 216, 221, 226, 231, 235, 238, 241, 244, 246, 248, 249, 250, 250, 250, 249, 248, 246, 244, 241, 238, 235, 231, 226, 221, 216, 211, 205, 198, 192, 185, 178, 171, 164, 156, 148, 141, 133, 125, 117, 109, 102, 94, 86, 79, 72, 65, 58, 52, 45, 39, 34, 29, 24, 19, 15, 12, 9, 6, 4, 2, 1, 0, 0, 0, 1, 2, 4, 6, 9, 12, 15, 19, 24, 29, 34, 39, 45, 52, 58, 65, 72, 79, 86, 94, 102, 109, 117}; 

Ширина наступного імпульсу обчислюється в кожному циклі ШІМ:

interrupt 4 void rsi_t1ch0 (void)
{
    //-- disable interruption flag
    T1SC0&=(~0x80);
    //-- pwm to '0' 
    PTB&=0xFD;

    //some sensor measures are done here.... 100 out of the 350 cycles are left for this                
}
/************************************************************/
/* TIM1 overflow rutine                                     */
/************************************************************/
interrupt 6 void rsi_ov1 (void)
{

    T1SC&=(~0x80);
    //-- set PWM to 1
    PTB|=0x02;
    T1CH0H = ((seno[fase])>>8);   // high bits
    T1CH0L = (seno[fase])&0xFF;   // low bits
    fase+=1;
    if (fase >= 99)
      fase=0;
}

void main(void)
{
float temp;
    int i;

    CONFIG1|=0x01;  
    DDRB=0xFF;      //-- Port B is set as output
    PTB=0x00;       
    //Timer setup
    T1SC = 0x60;    // Prescaler: Div by 64  
    T1MODH = 0x01;   //Counter modulo
    T1MODL = 0x5E;  
    T1SC0 = 0x50;  //Comparator setup
    //-- Initial width
    T1CH0H = 0x00;
    T1CH0L = 0x53;

    EnableInterrupts;
    T1SC&=~(0x20); //Run timer forever
    for(;;);   
}

Підключаючи його до області, ми отримуємо наступний сигнал. Ми не можемо уникнути цієї дивної вершини, що знаходиться біля мінімуму.

введіть тут опис зображення

Під час збільшення цього піку ми можемо побачити, як вихід (вгору) ШІМ насправді є неправильним.

введіть тут опис зображення

Тож, певний час возившись і не в змозі позбутися цього, ми спробували обчислити синусоїду в MCU замість жорсткого кодування значення для кожного зразка. Ми додали наступний код до основної функції, безпосередньо перед усіма налаштуваннями лічильника:

 for(i=0;i<99;i++) {
     temp=100*(sin(2*3.14159*i/100)+1);
     seno[i]=(int)temp;
 }

Але результати навіть не схожі на синусоїду:

введіть тут опис зображення

Після години боротьби з ним ми не змогли знайти свою помилку. Ми будемо вдячні за пораду.


Чи можете ви опублікувати весь список значень ШІМ?
pjc50

@ pjc50 Ось це: pastebin.com/sNyA0Hki . Велике спасибі.
Серж

Спробуйте замінити всі значення "0" в середині на "1"; Я підозрюю, що 0 дає тобі широкий високий сигнал, а не низький сигнал, який ти хочеш.
pjc50

@Serge - введіть ці дані. Паста може піти, і було б погано втратити частину питання. Але відформатуйте його, щоб він не використовував стільки місця. Спасибі.
Trygve Laugstøl

Очевидно, це не фільтр - удача - виглядає, що ваша таблиця стає пошкодженою або ви втрачаєте вказівник на неї.
Енді ака

Відповіді:


16

Внизу сторінки 350 аркуша даних мікроконтролера згадується, що запис малого значення в регістр значень таймера під час переривання переповнення може призвести до того, що наступне переривання буде запущене лише при наступній ітерації Pwm, оскільки таймер продовжує рахувати виконується рутина переривання.

Несинхронізоване записування в регістри каналів TIM для зміни значення ширини імпульсу може спричинити неправильну роботу до двох періодів ШІМ. Наприклад, записування нового значення до того, як лічильник досягне старого значення, але після досягнення лічильника нового значення запобігає будь-якому порівнянню протягом цього періоду ШІМ. Крім того, використання процедури переривання переповнення TIM для запису нового, меншого значення ширини імпульсу може призвести до пропуску порівняння. TIM може передати нове значення ще до його написання.

Це підтверджується тим, що значення pwm залишається високим протягом одного цілого періоду тактової частоти pwm +, що виглядає як довжина таймера (виходячи з довколишніх довжин). Значення, що записується в регістр довжини таймера, ймовірно, близьке до 0 на момент помилки, тому цілком життєздатним є те, що лічильник передав менше значення під час переривання і запускав би лише наступний цикл.

Це можна виправити, збільшивши мінімальний рівень синусоїди до рівня, що перевищує час, необхідний для виконання ISR, або змінивши механізм, за допомогою якого встановлюється новий рівень. Вгорі сторінки 351 детально описано, як це можна зробити.


1
Я не знаю, як я міг пропустити це під час читання даних. Дякую!
Серж
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.