18. Moottorin kierrosnopeuden säätäminen

Julkaistu: sunnuntai 12.2.2017

Sulautetuissa järjestelmissä, olivatpa ne monimutkaisia taikka vähemmän monimutkaisia, on yleistä se, että mikrokontrollerin avulla säädetään jotain prosessia.

Tällä kertaa tulemme säätämään moottorin kierrosnopeutta PWM-ohjauksen ja potentiometrin avulla ja tämän osan perusteella jokainen halukas voikin jo rakentaa itselleen esimerkiksi säädettävän tuulettimen tai vaikkapa himmennettävän valon. Toki säätää voi mitä mieleen tulee, mutta edellä oli vain pari esimerkkiä.

Mikäli eksyit tälle sivulle Googlen tai jonkun muun linkin kautta, eikä PWM-ohjaus tai AD-muuntimen käyttö ole vielä tuttua, niin kannattaa lukea osat 15, 16 ja 17, sillä ne liittyvät oleellisesti läpi käytävään asiaan ja niissä on sovelluksen kannalta tärkeää teoriaa. Tämän vuoksi teoriaosuus on tässä osassa lyhkäinen, koska itsensä toistaminen on hieman puuduttavaa toimintaa ;).

Sovelluksen kytkennät

Koska haluamme ohjata moottoria potentiometrin avulla, tarvitsemme potentiometrin joka kytketään yhteen MSP430G2231 mikrokontrollerin analogia-tuloon. Käytetään tässä tapauksessa aiemmin tutuksi tullutta kytkentää, joka löytyy edellisestä osasta. Kytkentäkuva löytyy alta.

PWM-ohjauskytkentä on tässä tapauksessa sama kuin osassa 15, joten kytkennän kuva on alla.

Lopuksi vielä kuva koekytkentäalustasta sekä launchpadiin liitetyistä osista.

Moottorin akseliin on kiinnitetty pieni pala teippiä, jonka kuvan ottamisen jälkeen värjäsin tussilla siniseksi helpottamaan pyörimisnopeuden muutoksen havainnointia. Mutta ei tästä tämän enempää joten siirrytäänpä pidemmittä puheitta sovelluksen tekoon.

Esimerkki 1: Kierrosnopeuden säätö-ohjelma

Aluksi tehdään alustukset ja luodaan tarvittavat makrot sekä otetaan käyttöön tutut kirjastot (engl. header, .h).

#include <msp430g2231.h>
// Ohjelman koko tavuina (byte) Flash/RAM = 450/2
// apumakroja käytetään helpottamaan koodin kirjoitusta 
#define INIT_LAUNCHPAD_LEDS (P1DIR |= BIT0+BIT6)
#define INIT_PWM_OUTPUT (P1DIR |= BIT2)
#define LED_OFF (P1OUT = 0)
#define LED_P_ON (P1OUT = BIT0)
#define LED_V_ON (P1OUT = BIT6)

void main(void)
{
     unsigned int pwm_speed = 0; // moottorin pyörimisnopeus
     WDTCTL = WDTPW + WDTHOLD; // watchdog pysäytys 
     INIT_LAUNCHPAD_LEDS; // Ledien alustus 
     INIT_PWM_OUTPUT; // PWM-lähdön alustus 
     P1SEL |= BIT2; // porttipinnin tila timerin ohjaamaksi 
     LED_OFF; // LED1 ja LED2 pois päältä 

     // alustetaan CPU:n kello 1 Mhz 
     BCSCTL1 = CALBC1_1MHZ;
     DCOCTL = CALDCO_1MHZ;

     // kiteen alustus 
     BCSCTL3 = XCAP_3;

     // asetetaan P1.1 analog 1 -kanavaksi 
     ADC10AE0 = BIT1;
     // Asetetaan kanava 1, valitaan kellosignaaliksi MCLK (1 Mhz) ja asetetaan yksi muunnos
     ADC10CTL1 = INCH_1 + ADC10SSEL_2 + CONSEQ_0;

     // Timerin asetus: 
     CCTL0 = OUTMOD_4; // asetetaan moodi toggle 
     CCTL1 = OUTMOD_7; // asetetaan moodi Reset/Set, huomaa että rekisteri on CCTL1 
     TACTL |= ID_0 + TASSEL_1; // asetetaan jakaja 0, laskentamoodi vertaileva ja ACLK-kello.
     CCR0 = 327; // ladataan 100 hertsin arvo 
     CCR1 = pwm_speed; // ladataan pulssisuhteen arvo, aluksi 0 ettei moottori pyöri 
     TACTL |= MC_1; // käynnistetään timer

     while(1)
     {
          // Oletuksena referenssijännitteet ovat Vcc (1) ja Vss (14)
          // Asetetaan näytteistysaika 64 kellojaksoa ja laitetaan ydin ja muunnos päälle 
          ADC10CTL0 = ENC + ADC10SC + ADC10SHT_3 + ADC10ON;

          while( ! (ADC10CTL0 & ADC10IFG)); // odotetaan että muunnos valmis 

          ADC10CTL0 &= ~ADC10IFG; // nollataan lippu 

           // lukua täytyy skaalata, jotta voidaan käyttää koko jännitealuetta 
          pwm_speed = ADC10MEM / 3.12;
          CCR1 = pwm_speed; // nopeuden päivitys 

          if(pwm_speed > 163)
          {
               LED_P_ON; // asetetaan yli 50% tehon huomiovalo 
          }
          else
          {
               LED_V_ON; // asetetaan alle 50% tehon huomiovalo 
          }
     }
}

Ohjelman kulku

Kun ohjelma käynnistyy, mikrokontrolleri alustaa portit, ledit, timerin ja AD-muuntimen kuten koodissa on kommentoitu. Ohjelman pääsilmukassa otetaan koko ajan muunnostietoja talteen mikrokontrollerin AD-muuntimelta ja saatua lukua skaalataan, jotta moottorin nopeuden säätö tapahtuu maltillisemmin. Punainen LED sytytetään silloin, kun PWM-pulssisuhde ylittää 50 %:a (noin puolet 327:stä) ja vastaavasti vihreä LED silloin kun pulssisuhde on alle edellä mainitun.

AD-muuntimelta saatua muunnoslukua myös skaalataan, kuten varmaan huomasitkin. Seuraavassa selitän miksi ja miten luku on saatu.

Jos AD-muuntimelta saatua lukua ei skaalattaisi, niin hyvin pieni muutos potentiometrillä vastaisi kovin äkillistä muutosta moottorin kierrosluvussa ja säätäminen olisi hankalaa.

Mikrokontrollerin ohjaaman PWM-pulssin leveys, eli pulssisuhde määräytyy CCR1 rekisterin mukaan. Jos arvo on yli tai yhtä suuri kuin 327, niin pulssisuhde on 100%. Koska AD-muuntimelta otetaan arvoja, jotka voivat olla väliltä 0 - 1023, niin ilman skaalausta jo 1,15 voltin jännite AD-muuntimen tulossa aiheuttaisi sen, että moottori pyörisi täysillä (327 vastaa tässä tapauksessa 1,15 voltin jännitettä, kun referenssinä on 3,6 volttia. Katso AD-muunnin jos menee yli hilseen).

Koska haluamme, että moottori pyörii täydellä teholla vasta kun potentiometrikin on ns. "täysillä", niin AD-muuntimen arvoa täytyy skaalata. Skaalausarvo saadaan kun AD-muuntimen täyden skaalan arvo (engl. Full-Scale) eli 1023 jaetaan PWM-pulssisuhteen 100 %:n täydellä arvolla eli 327:llä. Näin ollen tulokseksi saadaan:

1023/327 = 3,128440367 --> 3,12

Jos et heti ymmärtänyt selitystä, niin älä huoli. Ajan kanssa teksti käy varmasti selkeämmäksi ja saat punaisesta langasta kiinni. Kopioi siis koodi rauhassa CCS:n editoriin ja kokeile vaikkapa muuttaa skaalaus-arvoa joksikin toiseksi ja tutki kuinka moottorin kierrosluku muuttuu nyt.

Alla vielä lyhyt esittelyvideo kytkennän ja ohjelman toiminnasta:

Seuraavassa osassa perehdytään siihen, miten tietokone ja Launchpad saadaan kommunikoimaan keskenään. Asia voi kuulostaa vaikealta, mutta jos olet päässyt jo näin pitkälle, niin uskoisin senkin asian onnistuvan - ei se nyt niin vaikeaa ole 😉