PWM kullanarak sinüs sinyali üretimi


16

Bir MC68HC908GP32 mikrodenetleyici kullanarak sinüs sinyali doğru şekilde üretemiyoruz . PWM açıklaması sayfa 349'da başlar. Saat frekansı 2.4MHz iken, ön ölçekleyiciyi kullanarak ve zamanlayıcı modulo'unu 350'ye aşağıdaki gibi ayarlayarak 7 kHz PWM kullandık:

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

PWM çıkışı aşağıdaki RLC filtresi ile filtrelenir ve daha sonra DC bir seri 1 uF kapak kullanılarak çıkarılır. Kesme frekansı PWM'nin 7kHz'in çok altında.

resim açıklamasını buraya girin

İlk olarak, bir LUT kullanarak denedik, bu örnekler bu site kullanılarak üretildi (100 örnek, genlik = 250). Bu tek bir dönemden oluşur.

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

Aşağıdaki darbenin genişliği her PWM döngüsünde hesaplanır:

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

Kapsam içine eklediğinizde, aşağıdaki sinyali alırız. Minimum seviyeye yakın bu tuhaf tepeden kaçınamıyoruz.

resim açıklamasını buraya girin

Bu tepe noktasını yakınlaştırırken, PWM çıkışının (yukarı) aslında nasıl yanlış olduğunu görebiliriz.

resim açıklamasını buraya girin

Bu nedenle, bir süre uğraştıktan ve ondan kurtulamadan sonra, her bir numune için değeri sabit kodlamak yerine MCU'daki sinüs sinyalini hesaplamayı denedik. Tüm sayaç kurulumundan hemen önce ana fonksiyona aşağıdaki kodu ekledik:

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

Ancak sonuçlar sinüsoid gibi görünmüyor:

resim açıklamasını buraya girin

Saatlerce uğraştıktan sonra hatamızı bulamadık. Biz bir tavsiye için teşekkür ederiz.


Tüm PWM değerleri listesini gönderebilir misiniz?
pjc50

@ pjc50 İşte: pastebin.com/sNyA0Hki . Çok teşekkür ederim.
Serge

Ortadaki tüm "0" değerlerini "1" ile değiştirmeyi deneyin; 0'ın, istediğiniz düşük bir sinyalden ziyade o yüksek sinyali verdiğinden şüpheleniyorum.
pjc50

@Serge - Lütfen verileri satır içine alın. Macun kaybolabilir ve sorunun bir kısmını kaybetmek kötü olurdu. Ama lütfen o kadar çok yer kaplamayacak şekilde biçimlendirin Teşekkürler.
Trygve Laugstøl

Açıkçası filtre değil - iyi şanslar - tablonuz bozuluyor ya da işaretçinizi kaybediyorsunuz.
Andy aka

Yanıtlar:


16

Mikrodenetleyici veri sayfasının 350. sayfasının altında, taşma kesintisi sırasında zamanlayıcı değeri kaydına küçük bir değer yazmanın, bir sonraki kesmenin yalnızca bir sonraki pwm yinelemesinde tetiklenmesine neden olabileceğinden bahseder, çünkü zamanlayıcı kesme rutini yürütülüyor.

Darbe genişliği değerini değiştirmek için TIM kanal kayıtlarına senkronize olmayan bir yazma, iki PWM periyoduna kadar yanlış çalışmaya neden olabilir. Örneğin, sayaç eski değere ulaşmadan yeni bir değer yazmak, ancak sayaç yeni değere ulaştıktan sonra söz konusu PWM döneminde karşılaştırmayı engeller. Ayrıca, yeni, daha küçük bir darbe genişliği değeri yazmak için bir TIM taşma kesme rutini kullanmak karşılaştırmanın kaçırılmasına neden olabilir. TIM yeni değeri yazılmadan önce geçebilir.

Bu, pwm değerinin tüm bir pwm saat periyodu + zamanlayıcı uzunluğuna benzeyen (çevredeki uzunluklara bağlı olarak) için yüksek tutulması gerçeğiyle doğrulanır. Zamanlayıcı uzunluk kaydına yazılan değer, hata anında muhtemelen 0'a yakındır, bu nedenle sayacın kesme sırasında daha küçük bir değeri geçmesi ve yalnızca aşağıdaki döngüde tetiklenmesi oldukça uygundur.

Bu, sinüsoid minimum seviyesini ISR'nin yürütülmesi için gereken süreden daha yüksek bir düzeye çıkararak veya yeni seviyenin ayarlandığı mekanizmayı değiştirerek düzeltilebilir. Sayfanın üstü 351 bunun nasıl yapılabileceğini açıklar.


1
Veri sayfasını okurken bunu nasıl atlayabileceğimi bilmiyorum. Teşekkür ederim!
Serge
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.