Pembuatan sinyal sinus menggunakan PWM

16

Kami tidak dapat menghasilkan sinyal sinus dengan benar menggunakan mikrokontroler MC68HC908GP32 . Deskripsi PWM dimulai di halaman 349. Frekuensi clock adalah 2,4MHz, sementara kami telah menggunakan PWM 7 kHz dengan menggunakan prescaler dan mengatur timer ke 350 sebagai berikut:

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

Output PWM adalah filter oleh filter RLC berikut, dan kemudian DC dihapus menggunakan tutup seri 1uF. Frekuensi cutoff jauh di bawah 7kHz PWM.

masukkan deskripsi gambar di sini

Pertama, kami telah mencoba menggunakan LUT, sampel mana yang dihasilkan menggunakan situs ini (100 sampel, amplitudo = 250). Ini terdiri dari satu periode.

 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}; 

Lebar pulsa berikut dihitung setiap siklus PWM:

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(;;);   
}

Saat memasukkannya ke dalam ruang lingkup, kami mendapatkan sinyal berikut. Kami tidak dapat menghindari puncak aneh di dekat minimum.

masukkan deskripsi gambar di sini

Ketika memperbesar di sekitar puncak itu, kita dapat melihat bagaimana output PWM (naik) sebenarnya salah.

masukkan deskripsi gambar di sini

Jadi, setelah bermain-main sebentar dan tidak dapat menghilangkannya, kami telah mencoba menghitung sinyal sinus di MCU, alih-alih mengkodekan nilai untuk setiap sampel. Kami telah menambahkan kode berikut dalam fungsi utama, tepat sebelum semua pengaturan penghitung:

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

Tetapi hasilnya bahkan tidak terlihat seperti sinusoid:

masukkan deskripsi gambar di sini

Setelah berjam-jam berjuang dengan itu, kami belum dapat menemukan kesalahan kami. Kami akan sangat menghargai saran.

Serge
sumber
Bisakah Anda memposting seluruh daftar nilai PWM?
pjc50
@ pjc50 Ini dia: pastebin.com/sNyA0Hki . Terima kasih banyak.
Serge
Coba ganti semua nilai "0" di tengah dengan "1"; Saya menduga bahwa 0 memberi Anda sinyal tinggi lebar daripada sinyal rendah yang Anda inginkan.
pjc50
@Serge - Harap sebariskan data. Rekatnya mungkin hilang dan akan buruk jika kehilangan sebagian dari pertanyaan. Tapi tolong format itu sehingga tidak menggunakan banyak ruang. Terima kasih.
Trygve Laugstøl
Ini jelas bukan filter - semoga sukses - terlihat meja Anda menjadi rusak atau Anda kehilangan pointer ke sana.
Andy alias

Jawaban:

16

Di bagian bawah halaman 350 dari lembar data mikrokontroler, disebutkan bahwa menulis nilai kecil ke register nilai timer selama interupsi melimpah dapat menyebabkan interupsi berikutnya dipicu hanya pada iterasi pwm berikutnya, karena timer terus menghitung sementara interupsi rutin sedang dijalankan.

Tulisan yang tidak disinkronkan ke register saluran TIM untuk mengubah nilai lebar pulsa dapat menyebabkan operasi yang salah hingga dua periode PWM. Misalnya, menulis nilai baru sebelum penghitung mencapai nilai lama tetapi setelah penghitung mencapai nilai baru mencegah perbandingan apa pun selama periode PWM itu. Selain itu, menggunakan rutin interupsi overflow TIM untuk menulis nilai lebar pulsa yang lebih kecil dapat menyebabkan perbandingan terlewatkan. TIM mungkin meneruskan nilai baru sebelum ditulis.

Hal ini dikonfirmasikan oleh fakta bahwa nilai PWM bertahan tinggi untuk satu periode clock PWM keseluruhan + yang terlihat seperti panjang timer (berdasarkan panjang sekitarnya). Nilai yang ditulis ke register panjang timer mungkin mendekati 0 pada saat kesalahan, sehingga cukup layak bahwa penghitung telah melewati nilai yang lebih kecil selama interupsi, dan hanya akan memicu pada siklus berikut.

Ini bisa diperbaiki dengan meningkatkan level minimum sinusoid ke level yang lebih tinggi dari waktu yang diperlukan untuk menjalankan ISR, atau mengubah mekanisme yang digunakan untuk mengatur level baru. Bagian atas halaman 351 menjelaskan bagaimana ini dapat dilakukan.

stanri
sumber
1
Saya tidak tahu bagaimana saya bisa melewatkan itu ketika membaca lembar data. Terima kasih!
Serge