logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[MSP430][CCS4] Kłopocik z PWM-em jako DAC

ZbeeGin 27 Sty 2010 09:36 9363 38
  • #1 7598949
    ZbeeGin
    Poziom 39  
    Witam.

    Natrafiłem wczoraj na problem z użyciem PWMa opartego o TIMER_A3 jako DAC. W czym rzecz?
    Układzik, który aktualnie znajduje się na tapecie ma mieć możliwość wypowiadania krótkich sentencji głosowych za pomocą głośnika 50R podłączonego bez zbędnych elementów - najlepiej wprost na nogi procesora. Ponieważ już coś podobnego robiłem na AVRku wszystko szło sprawnie. Do czasu pierwszego uruchomienia dźwięku...

    Okazało się bowiem, że DAC z PWMa co prawda odtwarza dźwięk PCM z poprawną częstotliwością próbkowania to w treści dźwiękowej pojawiają się dziwne wysokoczęstotliwościowe zakłócenia. Nie jest to szum kwantyzacji tylko jakieś niezidentyfikowane szpilki. Zatem ponownie sprawdziłem próbkę dźwiękową w CoolEdit czy nie wkradły się tam jakieś przekłamania podczas konwersji do danych RAW. Nic takiego nie występuje. Postanowiłem więc na szybko zaimportować program do AVR i tam... tą samą metodą próbka odtwarzana jest poprawnie.
    Przypuszczam zatem, iż winę za całe zamieszanie ponosi brak układu buforowania rejestrów porównania TACCRx, co powoduje iż zapis do tych rejestrów w czasie trwania cyklu licznika generuje tzw. glitch-e (fałszywe wypełnienia) w przebiegu z PWM.

    Czy rzeczywiście liczniki z MSP nie posiadają możliwości sprzętowego buforowania lub synchronizacji zapisu nowej wartości zawsze na początku pojedynczego cyklu liczenia? Gdyż w dokumentacji nie ma słowa na temat tego, iż PWMy z liczników są glitch free (o czym poniekąd chwali się Atmel).

    Próbowałem już skorzystać z flagi TAIFG i poczekać z zapisem do TACCRx aż zostanie ona ustawiona, lecz efekt jest wtedy jeszcze gorszy - zniekształcenia się nasilają. Zamiast gongu jest garnek :D

    Czy ma ktoś jakieś pomysły jak wyeliminować tą przypadłość? Robienie oversamplingu jak to pokazano w nocie aplikacyjnej MSP jest tu bardziej skomplikowane gdyż różnica pomiędzy nośną a próbką jest o wiele większa niż 4 razy, co znacznie wydłuży przerwanie.

    Kodzik wygląda tak (dane próbki podcięto):

    #include  "msp430x21x2.h"
    
    #define TEST       BIT1        // P2
    #define BUZZ       BIT3        // P2
    #define BUZZH      BIT4        // P2
    
    #define DONGLEN 4530
    const unsigned char dong[] = {
      2, 2, 244, 252, 24, 3, 218, 0, 52, 251, (itd...)
    };
    
    unsigned int  volatile buf_pointer = 0;           // wskaźnik w buforze
    unsigned int  volatile play_sample = 0;           // stan odgrywania
    unsigned char one_byte;                           // próbka do obróbki
    
    // ##################################################################
    void do_config(void)
    {
      DCOCTL  = CALDCO_8MHZ;                    // DCO 8MHz
      BCSCTL1 = CALBC1_8MHZ;
      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog
    // P2 = mix
      P2DIR |=  BUZZ | BUZZH;                   // wejścia(0)-wyjścia(1)
      P2OUT  =  BUZZ;                           // stany początkowe (buzzer off)
      P2SEL  =  0x18;          // 0b00011000    // funkcja podstawowa, P2.3-P2.4 timer
    // ustawienie pracy TIMER_A0 - generator dźwięku  
      TA0CCR0  = 0x00FF;                        // pełne wychylenie licznika
      TA0CCR1  = 0x00FF;                        // rejestry porównania zero wypełnienia
      TA0CCR2  = 0x0000;
      TA0CCTL1 = CM_0 | CCIS_2 | OUTMOD_2;      // ustaw PWM - wysoki->niski
      TA0CCTL2 = CM_0 | CCIS_2 | OUTMOD_6;      //             niski->wysoki
      TA0CTL   = TASSEL_2 | ID_0 | MC_1;        // szybki PWM 31kHz
    // ustawienie pracy TIMER_A1 - generator czasu
      TA1CCR0 = 1500;                         
      TA1CTL  = TASSEL_2 | ID_1 | MC_1 | TAIE;  // próbkowanie ok. 2kHz
    }
    
    // ##################################################################
    int main(void)
    {
      do_config();                              // przeprowadź niezbędne konfiguracje peryferii
      __enable_interrupt();                     // przerwania włącz
      while(1)
      {
        if ((P2IN & TEST) == TEST)               // czy wejście aktywne?
          play_sample = 1;
      } 
    }
    
    // #######################################################################
    // ISR Timer1_A1 Interrupt Vector (TAIV)
    #pragma vector=TIMER1_A1_VECTOR
    __interrupt void Timer1_A1(void)
    {
      switch(TA1IV)
      {
        case 0x0A :                             // TA1OVF przepełnienie
          if(play_sample == 1)
          {      
            one_byte = dong[buf_pointer++];     // odczytaj jeden bajt z bufora
            if(buf_pointer == DONGLEN) 
            { 
              buf_pointer = 0;
              play_sample = 0;
              TA0CCR1  = 0x00FF;                // zeruj przebieg z DAC
              TA0CCR2  = 0x0000;          
            }	
            one_byte = one_byte + 127;          // korekcja danych
            TA0CCR1  = one_byte;                // i do DAC
            TA0CCR2  = one_byte;
          }
          break;
      }
    }


    ps1. Próbkowanie jest 2kHz. Wydawać by się mogło, że to za mało, ale dźwięk składa się głównie z przebiegu 500Hz-600Hz - taki gong. Zatem te 2 kilo wystarcza w zupełności.
    ps2. Głośnik jest podpięty bezpośrednio do dwóch nóg procesora i sterowany jest przeciwsobnie.
  • #2 7599201
    kemot55
    Poziom 31  
    A czy częstotliwość PWM jest rzeczywiście równa 31kHz? Nie znam procesora, ale przy problemach z brakiem sprzętowe synchronizacji pomiędzy "update'em" PWM i chwilami przełączeń starałbym oba zdarzenia jakoś połączyć logicznie (choćby na zasadzie zapętlenia na zewnątrz i użycia przerwania-karkołomne, ale...) .
    Czy w AVR'ach też częstotliwość PWM wynosi 31KHz? Sprawdził bym też działanie tego układu ze stałym wsp. wypełnienia. Dostaniesz jeden ciągły "pisk" lub "pisk posiekany" co może świadczyć o innej przyczynie powstawania zakłóceń.
    A poza tym to raczej trzeba by spojrzeć na to na oscyloskopie.
  • #3 7599432
    ZbeeGin
    Poziom 39  
    kemot55 napisał:
    A czy częstotliwość PWM jest rzeczywiście równa 31kHz? Nie znam procesora, ale przy problemach z brakiem sprzętowe synchronizacji pomiędzy "update'em" PWM i chwilami przełączeń starałbym oba zdarzenia jakoś połączyć logicznie (choćby na zasadzie zapętlenia na zewnątrz i użycia przerwania-karkołomne, ale...) .

    Częstotliwość nośnej jest dokładna. Wypuściłem ją na pin i pomiar oscyloskopowy wskazuje piękny i stabilny przebieg. Oscyloskop wykazuje również idealnie wyliczone 31kHz z groszami.
    Dodałem drugie przerwanie z tajmera generującego DAC (w momencie przepełnienia), a w nim znajduje się tylko zapis do rejestrów porównania. Dźwięk jest lepszy ale trochę zakłóceń pozostało - w głównej mierze w głośniejszej partii. Na mowie to będzie bardziej przeszkadzać niż na sygnale typu gong.

    kemot55 napisał:
    Czy w AVR'ach też częstotliwość PWM wynosi 31KHz?

    Tak. Częstotliwość jest ta sama bo i w MSP, i w AVR taktowanie to 8MHz, a PWM ustawiony tak samo: FastPWM, 8bit, bez podziału częstotliwości.

    kemot55 napisał:
    Sprawdził bym też działanie tego układu ze stałym wsp. wypełnienia. Dostaniesz jeden ciągły "pisk" lub "pisk posiekany" co może świadczyć o innej przyczynie powstawania zakłóceń.

    Stałe wypełnienie to stałe wychylenie membrany. Pisku nie uświadczysz, gdyż nie tak to działa.

    kemot55 napisał:
    A poza tym to raczej trzeba by spojrzeć na to na oscyloskopie.

    To jest przebieg PWM. Zobaczysz sieczkę.

    Tak wygląda odtwarzana próbka.
  • #4 7600468
    kemot55
    Poziom 31  
    Wydaje mi się, że nie będzie do końca tak jak napisałeś. Przy cyklicznym wpisywaniu tej samej wartości współczynnika wypełnienia powinna być cisza, ale tylko w poprawnie działającym układzie. Jest tak? (co do określenia "piski" może źle się wyraziłem raczej powinno tu się pojawić określenie zgrzyt lub coś takiego oczywiście przy niewłaściwej pracy układu)
    A co do oscyloskopu. Wbrew pozorom przy złapaniu fragmentu fali powinno być widać ewentualne szpilki. Poza tym sprawdź czy oscyloskop przy generowaniu dzwięku da sie synchronizować?
    Zawsze też możesz podać znany, krótki wzorzec (kilka wsp. PWM powtarzających się cyklicznie) i wtedy na oscyloskopie zobaczysz wynik.
    Osobiście kiedyś też zrobiłem coś takiego na 8052 z tym, że na wyjściu był filtr RC. Ponieważ nie wychodziło rewelacyjnie całość skończyła się na układzie ISD.
  • #5 7601643
    ZbeeGin
    Poziom 39  
    kemot55 napisał:
    Wydaje mi się, że nie będzie do końca tak jak napisałeś. Przy cyklicznym wpisywaniu tej samej wartości współczynnika wypełnienia powinna być cisza, ale tylko w poprawnie działającym układzie. Jest tak?

    I niestety taka cisza występuje. Na zdjęciu (niestety jakość mocno komórkowa) widać dwa przebiegi z wyjść P2.3 i P2.4 które pełnią teraz funkcję wyjść komparatorów z licznika. Oba rejestry załadowano wartością 128. Przebieg w kanale 2 jest nieco poszarpany, ale to wina sondy, która ma problemy z masą.

    [MSP430][CCS4] Kłopocik z PWM-em jako DAC

    kemot55 napisał:
    A co do oscyloskopu. Wbrew pozorom przy złapaniu fragmentu fali powinno być widać ewentualne szpilki. Poza tym sprawdź czy oscyloskop przy generowaniu dzwięku da sie synchronizować?

    Na oscyloskopie widać, że podczas generowania dźwięku wypełnienie zmienia się. Nie ma tam nic nadzwyczajnego w formie szpilek. Niestety aby wychwycić czy PWMy chodzą synchronicznie i dokładnie tak samo ale symetrycznie, musiałbym nagrać obraz z oscyloskopu podczas odtwarzania próbki i później analizować go poklatkowo. "Na oko" wydaje mi się, że czasem przeleci jakieś fałszywe wypełnienie.

    ----

    kemot55 napisał:
    Osobiście kiedyś też zrobiłem coś takiego na 8052 z tym, że na wyjściu był filtr RC. Ponieważ nie wychodziło rewelacyjnie całość skończyła się na układzie ISD.

    Nagrałem krótką sentencję mowy próbkowaną 11kHz i puściłem z AVR-ka metodą jak wyżej. Brzmi rewelacyjnie nawet bez filtrowania. Patrz załącznik. Jedno nagranie to próbka męska 6kHz, drugie to próbka żeńska 11kHz.
  • #6 7601863
    kemot55
    Poziom 31  
    Zaraz zaraz. Napisałeś,że oba rejestry są załadowane i już. A co się dzieje jak te rejestry są załadowywane z określoną częśtotliwością (tak jakby szły kolejne próbki tylko zawsze z tą samą wartością współczynnika)?
  • #7 7601896
    ZbeeGin
    Poziom 39  
    One są właśnie cyklicznie w przerwaniu ładowane tą samą wartością. Fakt. Miałem napisać "ładowano". Sorry.

    Tak jak pisałem wcześniej dodano drugie przerwanie z licznika pracującego jako DAC
    
    // #######################################################################
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer0_A1(void)
    {
      switch(TA0IV)
      {
        case 0x0A :                             // TA0OVF przepełnienie
          TA0CCR1  = one_byte;                  // rejestr danych DAC
          TA0CCR2  = one_byte;
          break;
      } // koniec switch

    a zmienna one_byte posiada teraz status volatile.
  • #8 7603226
    kemot55
    Poziom 31  
    Na tym oscyloskopie możesz robić sumowanie kanałów (Math). To w kwestii porównania obu portów on-line.
    Czy to co pokazałeś na zdjęciu z oscyloskopu to były przebiegi z portów z dołączonym głośnikiem?
    Ponieważ zastanawiam się jeszcze nad wydajnością (i możliwością pracy) portów. Nie znalazłem na ten temat nic w dokumentacji od MSP. Porty w AVR'ach są dość wydajne prądowo. Może pojawia się jakieś ograniczenie.
    I ostatnia "abstrakcja".Przez chwilę pomyślałem, że może problemem może być obciążenie indukcyjne dla portu tego procesora . Ale to jest mało prawdopodobne.
  • #9 7603505
    Konto nie istnieje
    Poziom 1  
  • #10 7604098
    ZbeeGin
    Poziom 39  
    kemot55 napisał:
    Czy to co pokazałeś na zdjęciu z oscyloskopu to były przebiegi z portów z dołączonym głośnikiem?

    kemot55 napisał:
    I ostatnia "abstrakcja".Przez chwilę pomyślałem, że może problemem może być obciążenie indukcyjne dla portu tego procesora . Ale to jest mało prawdopodobne.

    Nie był podpięty. Jak głośnik jest podpięty to przebieg wygląda inaczej. Zbocza narastające są podniesione w górę - indukcja dodaje. A podczas stabilnego stanu napięcie opada krzywą paraboliczną (jakbyś ją przerzucił na oś X).

    kemot55 napisał:
    Ponieważ zastanawiam się jeszcze nad wydajnością (i możliwością pracy) portów. Nie znalazłem na ten temat nic w dokumentacji od MSP. Porty w AVR'ach są dość wydajne prądowo. Może pojawia się jakieś ograniczenie.

    No niestety nie jest ona dobra, z membraną piezo - obciążenie pojemnościowe -przebieg jest tylko nieco pofałdowany. Wiadomo inaczej niż to przedstawiłem wyżej i bardzo łagodnie. Przy głośniku 50R jest to tak jak opisałem. Przy głośniku 8R (mocne przeciążenie) to z PWMa robią się tylko krótkie impulsy. Ale pomimo to efekty "zakłóceniowe" się subiektywnie nie pogarszają. Dlatego dalej obstawiam, że to jednak błąd glitch. Albo oba efekty naraz...??

    Dodano po 9 [minuty]:

    atom1477 napisał:
    Spróbuj dać prosty filtr RC (10k 100nF) i podłącz się do jakiegoś wzmacniacza audio. Oczywiście w takim przypadku podłącz się pod jeden kanał.

    Prościej będzie nagrać przez line-in w laptopie. Jakoś w pracy nie mamy na półce żadnego audio. Nie ta branża.

    atom1477 napisał:
    A to to co?

    A to jest właśnie ustawienie przy, którym oba PWMy generują taki sam stan. Zauważ jaka jest konfiguracja: jeden jest inwersyjny.

    atom1477 napisał:
    Po za tym. Ustawiasz zmienną play_sample na 0. Ale zatrzymanie odtwarzania nastąpi dopiero w kolejnym cyklu.

    Wiem, ale to co tu jest to dopiero 1/10 programu jaki muszę stworzyć. Zatem gdy ta głosowa funkcja będzie już działać poprawnie to dopiero będę ją próbował "dopieścić".
  • #11 7604731
    kemot55
    Poziom 31  
    Cytat:
    Jak głośnik jest podpięty to przebieg wygląda inaczej. Zbocza narastające są podniesione w górę - indukcja dodaje. A podczas stabilnego stanu napięcie opada krzywą paraboliczną (jakbyś ją przerzucił na oś X).

    A czy przebiegi przy zboczu narastającym i opadającym są symetryczne?
    Możesz odczytać coś z TDS'a? Np. ściągnąć możliwie najdłuższą próbkę dźwięku z zakłóceniem i podesłać mi? (dwa przebiegi, podłączenie w tych samych punktach: jeden z podpiętym głośnikiem, drugi bez, zapisane w CSV albo w innym formacie, ale tekstowo. Przy czym nie istotne jest czy będą to dokładnie te same fragmenty dźwięku).
    Myślę o zrobieniu na szybko FFT. Jeżeli w obu przypadkach widmo będzie podobne to jednak trzeba będzie szukać bardziej w oprogramowaniu (a właściwie nie tyle w programie co w konfiguracji procesora).
    Tak a'propos słonia - mam wrażenie, że korzystasz z IAR'a. A masz włączoną w kompilatorze optymalizację kodu? Dla pewności wyłączyłbym to w czasie prób.
  • #12 7604893
    Konto nie istnieje
    Poziom 1  
  • #13 7607135
    ZbeeGin
    Poziom 39  
    kemot55 napisał:
    A czy przebiegi przy zboczu narastającym i opadającym są symetryczne?

    Kiedy dokładnie?

    kemot55 napisał:
    Możesz odczytać coś z TDS'a? Np. ściągnąć możliwie najdłuższą próbkę dźwięku z zakłóceniem i podesłać mi?

    Niestety nie mamy modułu rejestratora do niego. :cry:

    kemot55 napisał:
    Tak a'propos słonia - mam wrażenie, że korzystasz z IAR'a. A masz włączoną w kompilatorze optymalizację kodu? Dla pewności wyłączyłbym to w czasie prób.

    Nie korzystam z IAR-a. Nie przypada mi do gustu to środowisko. Używam Code Composera v4 w najnowszej edycji i FET-a z USB który też zasila układ podczas prób.

    Dodano po 6 [minuty]:

    atom1477 napisał:
    Tak, ale to powoduje skok z wartości średniej do GND albo do VCC co da trzask. Lepiej by było zamrozić próbki na 1/2 VCC czyli na wartości 128.

    On będzie nieistotny gdyż będzie tylko jeden na początku i na końcu odtworzenia próbki. Mnie chodzi o dziwne trzaski w trakcie trwania odtwarzania.

    Ponadto jak ustawisz wartość 128 w obu kanałach to dostaniesz taki przebieg jak na zdjęciu. Zatem głośnik niepotrzebnie będzie próbował odtwarzać nośną 31250Hz!
  • #14 7607460
    Konto nie istnieje
    Poziom 1  
  • #15 7607871
    ZbeeGin
    Poziom 39  
    atom1477 napisał:
    Chm, no właśnie. Chyba masz zły przebieg. Bo w takim układzie nie da się uzyskać normalnego poziomu „zero”. Ja rozumiem że podczas zatrzymania odtwarzania brak poziomu „zero” Ci nie przeszkadza, ale podczas normalnego odtwarzania takie „zero” też musi czasami występować. Po prostu sygnał czasami powinien przechodzić przez zero i tyle.

    I przez to zero przechodzi! Jak byś zobaczył przebieg na oscyloskopie to wypełnienie oscyluje wokół 50% podczas odtwarzania próbki.

    atom1477 napisał:
    Chyba trzeba to zrobić inaczej. Bo ustawienie obydwu kanałów na noninvet i programowe odwracanie wypełnienia da inny efekt niż ustawienie jednego kanału na noninvert a drugiego na invert.

    Przeczytaj komentarze w programie, zobacz screen z TDSa i treść Moich wypowiedzi. Jeszcze raz powtórzę: Oba kanały PWM chodzą przeciwsobnie. Sprzętowo!
  • #16 7607889
    Konto nie istnieje
    Poziom 1  
  • #17 7608642
    ZbeeGin
    Poziom 39  
    atom1477 napisał:
    Dodano po 54 [minuty]:

    Wszystko co napisałeś po 54 minucie myślę, że dałoby się obalić jednym zdaniem (Uwaga! Długie i zawiłe):
    Procesor AVR ATmega32L taktowany 8MHz, gdzie przerwanie z Timer0 odpowiada za podawanie kolejnych próbek do OCR1A i OCR1B w równych odstępach czasu; gdzie Timer1 jest podwójnym synchronicznym generatorem PWM o f=31250Hz, w którym to jeden kanał jest normalny, a drugi inwersyjny; odtwarza próbki przygotowane tą samą metodą i za pomocą dwóch portów OC1A i OC1B prawidłowo, a dowód na to znajduje się w nagraniach z mikrofonu przyłożonego do głośnika, które to nagrania jako archiwum ZIP możesz pobrać i odtworzyć za pomocą systemowego odtwarzacza audio.
    Jedno zasadnicze pytanie jest takie: Dlaczego ten sposób nie działa tak samo w MSP430?

    Odpowiedź Moja: Nie wiem dokładnie, szukam 100% odpowiedzi.
    Odpowiedź Twoja: [......................................] (wpisać maszynowo lub ręcznie)

    Moje przypuszczenie: Brak opcji glitch free w MSP430, wypełnienie się rozjeżdża.
    Twoje przypuszczenie: Masz nośne w przeciwfazach.

    ps. Sorry za tą ironię, ale właśnie obejrzałem House-a. Mogę go z premedytacją naśladować.

    ----

    Ok. Żeby nie było. Program dla AVR dla próbki męskiej 6kHz:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    #include <util/delay.h>
    
    uint8_t  volatile play    = 0;
    uint16_t volatile pointer = 0;
    uint16_t volatile counter = 0;
    
    #include "isospeak.h"
    
    // dane początków i rozmiarów próbek w isospeak.h
    const uint16_t wavetab[][2] = {
        {     0,  6060 },
        {  2125,  7105 }, 
        {  9369,  5469 },    // słaba bateria
        { 12295,  5538 }, 
    	{ 18634,  3045 }     // spadaj
    };
    
    //==================================================
    ISR(INT0_vect)
    {
      if(bit_is_set(PIND, 2))
      {
        cli();
    	pointer = wavetab[0][0];
    	counter = wavetab[0][1];
    	play = 1;
    	sei();
      }
      else
      {
        cli();
    	pointer = wavetab[1][0];
    	counter = wavetab[1][1];
    	play = 1;
    	sei();
      }
    }
    
    //==================================================
    ISR(INT2_vect)
    {
       cli();
       pointer = wavetab[2][0];
       counter = wavetab[2][1];
       play = 1;
       sei();
    }
    	
    //==================================================
    ISR(INT1_vect)
    {
        cli();
    	pointer = wavetab[4][0];
    	counter = wavetab[4][1];
    	play = 1;
    	sei();
    }
    
    //==================================================
    ISR(TIMER0_COMP_vect)
    {
       uint8_t temp;                                      // zmienna tymczasowa
       
       if(play)                                           // jak play = 1
       {
          if(counter--)                                   // i counter nie wyzerowany
    	  {
    		 temp = pgm_read_byte(&wave[pointer++]);      // odczytaj bajt z próbki pod adresem pointer
    		 temp = temp + 127;                           // korekcja próbki
    		 OCR1A = temp;                                // niech DAC przetworzy
    		 OCR1B = temp;
          }
    	  else
    	  {
            OCR1A = 255;                                    // DAC wygaś
    		OCR1B = 0;
    		play = 0;                                     // i koniec gadania
    	  }
    	}
    }
    
    //----------------------------------------------------
    void config(void)
    {
       // konfiguruj porty
       //
       DDRD  = (1<<PD5)|(1<<PD4);
               // OC1A/OC1B outputs
       PORTD = (1<<PD2)|(1<<PD3);
               // INT0/1 inputs high
       PORTB = (1<<PB2);
               // INT2 input high
     
       // konfiguracja PWMa (Timer1) nośna 30kHz
       //
       OCR1A = 255;
       OCR1B = 0;
       TCCR1A = (1<<WGM10)|(1<<COM1A1)|(0<<COM1A0)|(1<<COM1B1)|(1<<COM1B0);
       TCCR1B = (0<<WGM12)|(1<<CS10);
                // mode 1 fastpwm 8bit | oc1a clear | oc1b set | prescaler 1
       
       // konfiguracja licznika
       // generuj przerwania o częstotliwości 6kHz (160us)
       //
       OCR0 = 20;
       TCCR0 = (1<<WGM01)|(1<<CS01)|(1<<CS00);
       TIMSK = (1<<OCIE0);
               // mode 2 ctc | prescaler 64 | 20*8us | int enable
       
       // konfiguracja przerwań
       //
       MCUCR = (1<<ISC10)|(1<<ISC00);
               // int any change
       GICR  = (1<<INT1)|(1<<INT0)|(1<<INT2);
               // INT0/INT1/INT2 enable
    }
    
    //----------------------------------------------------
    int main(void)
    {
       config();
       sei();
       
       while(1);
      
       return 0;
    }
  • #18 7608731
    Konto nie istnieje
    Poziom 1  
  • #19 7608763
    ZbeeGin
    Poziom 39  
    atom1477 napisał:
    No właśnie myślałem że na AVR zrobiłeś to inaczej. Wiem, pisałeś że tak samo, ale nie podałeś kodu.
    No trudno, bo gdyby to była prawda to miał byś rozwiązany problem, a tak nie masz.

    Kod dla AVR nie jest istotą problemu, dlatego jego podanie nie miało sensu. Teraz postawiłeś "zarzut", zatem Ja wystawiłem "świadka koronnego". :P

    A ha! (C) Copyright by Zbigniew "ZbeeGin" G. 2010
  • Pomocny post
    #20 7608801
    Konto nie istnieje
    Poziom 1  
  • #21 7655866
    ZbeeGin
    Poziom 39  
    atom1477 napisał:
    A próbowałeś wszystko wrzucić do przerwania od Timera0?

    Tak. Była taka próba po podpowiedziach osoby, która z MSP430 jest dobrze obeznana.
    Niestety efekt jest ten sam. Próbkę wzorcową już przedstawiłem na forum, teraz przedstawię nagranie z głośnika podłączonego do MSP430 dla aktualnego programu z jednym przerwaniem.

    http://zbeegin.republika.pl/mspplay.wav

    Co więcej. Znalazłem też film, w którym odtwarzanie próbki z karty SD przez MSP430 też jest obarczone "śmieciami" z PWMa. Jest ich mniej, gdyż to tylko jeden kanał. Tam problem może być jednak rozwiązany przez filtrację, gdyż wyjście jest podłączone do wzmacniacza. Pokazuje on jednak, że coś nie pozwala cieszyć się dobrą jakością dźwięku jaką można uzyskać z AVRa. :(

    http://www.youtube.com/watch?v=uf82rc57YCA (Program 3)

    atom1477 napisał:
    Nie wiem jak Tobie, ale mi w 99% zdarza się pomyłka o 1 przy wyznaczaniu okresu Timera i zawsze muszę to później sprawdzać ;) Pewnie Ty policzyłeś dobrze, ale nie zaszkodzi sprawdzić.

    Zmiana częstości przerwań podsyłania próbek wpływa tylko na prędkość ich odtwarzania. Zaśmiecanie jest ciągle w takim samym stopniu.

    atom1477 napisał:
    Dodatkowo spróbuj zmniejszyć głośność dźwięku. Powiedzmy do 50%. Czyli próbki mają mieć wartości od 64 do 192. Dzięki temu ewentualny glitch nie wystąpi nawet jak by chciał wystąpić, bo wartość PWMa będzie zawsze aktualizowana przy stabilnym stanie na pinie (zanim Timer zdąży doliczyć do 64). Jaką próbkę byś nie wpisywał do TA0CCRx, to będzie ona zawsze większa od 64 a więc stan na pinie nie zmieni się. Zmieni się dopiero później, ale już w prawidłowym momencie bez wytwarzania impulsu glitch.

    Niestety ma to działać głośno tak jak tylko potrafi. :cry: I taka opcja nie przejdzie.
  • #22 7656399
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #23 7660632
    kemot55
    Poziom 31  
    Rzeczywiście sieć zniekształca znacznie przebieg. Prążki wyższych harmonicznych znacząco występują dla 734Hz (maksymalnie) i 2106Hz (37% 50Hz, 100% 734Hz, 95% 2106Hz, 24% 2800Hz, 37% 3573Hz oraz 41% 4946Hz (przy czym udział procentowy jest odniesiony do harmonicznej 734Hz)). Ma się to nijak do częstotliwości nośnej PWM'a. Można to ewentualnie nałożyć na źródło.
    W przebiegu WAV widać wyraźnie oscylacje po przełączeniu i pewnie z tego wynika cały kłopot. Możesz ta samą próbkę zarejestrować dla AVR'a?
    A to co teraz usłyszałem jest podobne z tym co sam robiłem. Teraz rozumiesz dlaczego mnie to nie zachwyciło. Ja próbowałem się z takim generatorem jakieś 6 lat temu na 89S8252 (zauważ, że wydajność portu tego procesora też jest słaba dla wysokiego poziomu logicznego)
  • #24 7660655
    Konto nie istnieje
    Poziom 1  
  • #25 7660899
    tek-no-logical
    Poziom 16  
    Przydatna by była informacja którego dokładnie procesora kolega używa, stawiam na MSP430F2131 lub MSP430F2132.
    
      TA0CCTL1 = CM_0 | CCIS_2 | OUTMOD_2;      // ustaw PWM - wysoki->niski
      TA0CCTL2 = CM_0 | CCIS_2 | OUTMOD_6;      //             niski->wysoki 
    

    Użyłbym raczej odpowiednio:
    OUTMOD_3 i OUTMOD_7 tj. set/reset i reset/set
    (zamiast OUTMOD_2,OUTMOD_6 toggle/reset toggle/set.)

    Przydatna też bywa errata dla tych układów: http://focus.ti.com/lit/er/slaz041c/slaz041c.pdf moduły timerów mają kilka problemów.
  • #26 7661639
    ZbeeGin
    Poziom 39  
    tek-no-logical napisał:
    Przydatna by była informacja którego dokładnie procesora kolega używa, stawiam na MSP430F2131 lub MSP430F2132.

    MCU to MSP430F2132.
    Tak jak się spodziewałem zmiana trybu wyjść nie miała znaczenia, z przebiegów z noty katalogowej wynika, że akurat w tym trybie są one tożsame.


    Próbkę z AVR zarejestruje dziś wieczorem po powrocie do domu.

    p.s. Wczoraj podłączyłem bezpośrednio pod AVR-a GDN20/40 8Ohm w obudowie zamkniętej i było dobrze, a zarazem głośno. Na szczęście sąsiedzi byli wyrozumiali. :D

    --edit later--

    A oto i nagrana próbka z AVR. Ten sam mikrofon, ten sam głośnik, tylko procesor i eval board inny.

    http://zbeegin.republika.pl/avrplay.wav
  • #27 7663936
    tek-no-logical
    Poziom 16  
    Sugestia odnośnie uproszczenia sobie życia - zamiast dość skomplikowanego przebiegu jakim jest gong - użyć sinusoidy lub piły o stałej znanej częstotliwości.

    Jeszcze ciekawi mnie dlaczego :
    unsigned int  volatile play_sample = 0;           // stan odgrywania 


    a już
    unsigned char one_byte;                           // próbka do obróbki 


    Rejestry CCRx są 16-sto bitowe - wypadałoby użyć:
    unsigned int one_byte;                           // próbka do obróbki 


    Wspomniane buforowanie z AVR w rodzinie MSP430 też występuje - można wczytywać nowe wartości synchronicznie z przepełnieniem licznika, wybrać długość licznika itp., jednak to wszystko w modułach TimerB, niedostępnych w użytym układzie. Mam jakąś płytkę z MSP430F2274, spróbuję w wolnej chwili przetestować podany program.
    Może dałoby się w ramach testu uaktualniać rejestry PWM po każdym cyklu? ( nawet, jeżeli wartość się nie zmienia )
  • #28 7664242
    ZbeeGin
    Poziom 39  
    tek-no-logical napisał:
    Sugestia odnośnie uproszczenia sobie życia - zamiast dość skomplikowanego przebiegu jakim jest gong - użyć sinusoidy lub piły o stałej znanej częstotliwości.

    Taki wymóg. Nic nie poradzę.

    tek-no-logical napisał:
    Jeszcze ciekawi mnie dlaczego :
    unsigned int  volatile play_sample = 0;           // stan odgrywania 

    Chodzi ci o typ zmiennej czy to, że ma status ulotnej zmienianej też w przerwaniu?

    tek-no-logical napisał:
    a już
    unsigned char one_byte;                           // próbka do obróbki 


    Rejestry CCRx są 16-sto bitowe - wypadałoby użyć:
    unsigned int one_byte;                           // próbka do obróbki 

    Próbki dźwiękowe są 8-bitowe. Poza tym jak zauważysz licznik jest skracany do 8 bitów.

    tek-no-logical napisał:
    Może dałoby się w ramach testu uaktualniać rejestry PWM po każdym cyklu? (nawet, jeżeli wartość się nie zmienia)

    Też to przerabiałem. Poprawy żadnej, a nawet gorzej.
  • #29 7664370
    kemot55
    Poziom 31  
    Wynik dla dźwięku z AVR'a. (50Hz) 3%!, (549Hz) 100%, (1575, 2673, 3700Hz) 20% oraz (4800Hz) <10%
    A zasilanie sprawdzałeś (oscyloskopem)? Jakoś ta duża zawartość harmonicznych sieci jest mocno zastanawiająca (dla MSP oczywiście). Nie obciąża ci się całość za bardzo?
  • #30 7664377
    Konto nie istnieje
    Poziom 1  
REKLAMA