User Tools

Site Tools


pwm_pulse_width_modulation

Taimerid

Taimer on väga populaarne mikrokontrollerite perifeeria, mis võimaldab lugeda aega, tekitada PWM signaale ja palju muud.

Oma olemuselt suurendavad taimerid loenduri väärtust ühe võrra iga kellasignaali tsükkliga. Tänu sellele saab taimeritega lugeda aega, täita mingit ülesannet iga teatud aja tagant ning PWM signaali genereerida.

Ekraanil olev juhend katab ainult PWM signaali genereerimist.

PWM

Teooria

PWM ehk Pulse Width Modulation on väga kasulik digitaalsignaal, mida saab kasutada erinevate andurite ja seadmetega suhtmeliseks ning analoogsignaalide emuleerimiseks.

PWM kasutusalad

  1. Mootorite kiiruse reguleerimine
  2. LED heleduse muutmine
  3. Buzzer’i helisageduse muutmine
  4. Kellasignaalid suhtlusprotokollidele

Oma olemuselt on PWM signaal hästi kiiresti 0V ja mingi loogikapinge vahel põrkav signaal.

PWM signaali üks tähtsamaid suuruseid on duty-cycle, mis näitab, mitu protsenti ajast on PWM signaal kõrge. Mida rohkem ajast on PWM signaal kõrge, seda suurem on duty-cycle ja vastupidi.

Duty-cycle on kasulik, et arvutada keskmine PWM signaali pinge. Kuna signaal põrkab pidevalt 0V ja loogikapinge (Nucleo F303K8 korral 3V3, Arduino-del 5V), siis on võimalik arvutada keskmine pinge. Selleks on valem Vavg = Vlogic * DT, kus DT on duty-cycle.

Näiteks, kui loogikgapinge on 3v3 ning duty-cycle on 25%, siis saame, et keskmine pinge on 3.3 * 0.25 = 0.825V.

Selle valemi abil ongi võimalik näha, kuidas saab emuleerida analogsignaale, näiteks LED-i põlema panemiseks või mootori kiiruse muutmiseks. Signaal on küll digitaalne, kuid muutes duty-cycle’t siis saame muuta keskmist pinget.

PWM – Kuidas seda tekitada

PWM signaali peamine tekitamisviis toimub taimerite abil. Taimeril on 3 väärtust, mis meid huvitavad. Nendeks on

  1. Prescaler – Näitab, mitu korda aeglasemaks tehakse taimer sisendkella. Tavaliselt kasutatakse sisendkellaks protsessori põhikella, mis on vahemikus 8MHz – 72MHz. Olenevalt ülesandest võib see olla liiga kiire ning prescaler aeglustab taimerit ilma protsessori kella aeglustamata.
  2. Period – Maksimaalne väärtus, milleni loendur lugeda saab. Jõudes selle arvuni, läheb loenduri väärtus tagasi nulli.
  3. Compare – Arv vahemikus 0 kuni period’i väärtus, mis otsutab millal PWM väljund langeb/tõuseb.

Põhitöötsükkel käib nii:

  1. Taimer alustab tööd, loenduri väärtus on null, väljundsignaal on kõrge.
  2. Iga kellatsükkli korral liidab taimer loenduri väärtuse ühe võrra suuremaks.
  3. Kui loenduri väärtus on võrdne compare väärtusega, läheb väljundsignaal madalaks.
  4. Kui taimeri väärtus jõuab period väärtuseni, läheb väljundsignaal tagasi kõrgeks ning taimeri väärtus läheb nulli.

Selleks, et teemat veidi paremini visualiseerida, on olemas Desmose graafik. (Kui see link on maas, pekske Kevinit) https://www.desmos.com/calculator/gwlvicnnpf

Sellel graafikul ülemine “saehamba signaal” näitab loenduri väärtust. See kasvab ajas lineaarselt, kuni jõuab maksimumi ning siis läheb tagasi nulli.

Alumine signaal on väljund PWM signaal, on näha, et kui loenduri väärtus jõuab compare väärtuseni, läheb PWM signaal madalaks. Kui loenduri väärtus ennast nullib, läheb PWM signaal kõrgeks.

Kui liigutada Desmos graafikul PWM Period Slider’i, siis on näha, kuidas PWM signaali duty-cycle muutub.

PWM – Valemid

Tähised

f_sys – Süsteemi põhikella sagedus

f_pwm – PWM signaali sagedus

DT - Duty cycle

Valemid

f_pwm = f_sys / (prescaler * period)

DT = 100% * compare / period

Lisainfo

Selleks, et saada sama signaal Nucleo mikrokontrolleritel, mis on Arduinodel, kasutada väärtuseid prescaler = 625 - 1 ning period = 256 - 1. Nende numbrite eelduseks on see, et Nucleo põhikell töötab tavakiirusel 8MHz. Need arvutavad tekitavad PWM signaali sagedusega 50Hz, mille vahemiku on 0 - 255.

CubeIDE – Taimeri seadistamine PWM jaoks

Täpselt nagu kõikide teiste liidestega, saab taimereid konfigureerida CubeIDE-s. Selle eelis on see, et kõik sätted saab valida GUI-s ning programm genereerib selle koodi sinu eest.

Kõiki taimereid ja nende sätteid näeb .ioc failist

CubeIDE-st näeme, et Nucleo F303K8-l on kokku 8 taimerit, mida kasutadas saab. Kõik taimerid ei ole võrdsed, uurides näed lähemalt näeme, et esimesel taimeril on 6 väljundkanalit, teisel taimeril 4 väljundkanalit ning seitsmendal timeril polegi väljundeid.

Olenevalt taimerist, saab üks taimer tekitada mitu PWM signaali, kuid tuleb arvestada, et taimeri prescaler ja period väärtused kehtivad iga kanali kohta. See tähendab, et sa ei saa tekitada ühes taimeris kaks PWM signaali, millel on erinevad prescaler ja period.

Kasutame praeguses näites kõige võimsamat taimerit, milleks on taimer 1. Ütleme, et kasutame esimese taimeri esimest kanalit PWM signaali väljastamiseks.

Nüüd peaks tekkima uus jalg nimega TIM1_CH1. Seda jalga võib vabalt ümber nimetada, täpselt nagu GPIO jalgu. Pane tähele, et kui kanali valik on kollane või roosa, siis see tähendab, et selle kanali väljundjalg on juba kasutuses mingi teise asja jaoks. Näeme, et TIM1_CH1 väljundjalg on PA8.

Konfigureerime nüüd taimeri sätteid. Kõik olulised sätted on “Counter settings” kategooria all.

Kolm valikut, mis meid huvitavad on Prescaler – Siit saab valida prescaler väärtuse. Hoolikas tuleb olla sellega, et kui kui panna prescaler’i väärtuseks 0, siis jagatakse sisendkella väärtusega 1. Seega, kui tahetakse kella teha täpselt 16 korda aeglasemaks, peab prescaler olema tegelikult 15. Soovitav on kirjutada lahtrisse 16-1, et näidata teistele, sellega on arvestatud.

Counter Period – Siit saab valida period väärtuse. Kehtib täpselt sama reegel, et tegelik väärtus on ühe võrra väiksem, sest loendamine algab nullist.

Auto-reload – See valik tuleb panna “Enable”. Auto-reload tähendab seda, et kui loendur jõuab maksimum väärtuseni ning läheb nulli, jätkab kell lugemist. Ilma selle sätteda lõppeks PWM signaal pärast 1 tsükklit.

Koodi genereerimiseks tuleb kõigepealt .ioc fail salvestada ning siis vajutada üleval tööriista real kollast hammasratta pildiga nuppu.

STM32 HAL – PWM signaali kasutamine

Täpselt nagu GPIO HAL funktsioonid algavad kõik nimega “HAL_GPIO_”, algavad ka kõik taimeri funktsioonid liidesega “HAL_TIM_”.

HAL_TIM_Base_Start(htim)

Selleks, et PWM signaali tekitada, tuleb kõigepealt taimer käima panna. Selleks on olemas HAL funktsioon

See funktsioon võtab ühe argumendi, milleks on taimeri konfiguratsiooni struktuuri address. Selleks kirjutatakse argumendiks &htim ning taimeri number.

Näites kasutame taimer 1. Selleks, et taimer 1 käima panna, kirjutame. HAL_TIM_Base_Start(&htim1)

HAL_TIM_PWM_Start(htim, Channel)

Eelmine funktsioon pani käima terve taimeri, kuid meil on vaja veel käima panna meie valitud kanal, et ta hakkaks PWM signaali tekitama.

See funktsioon võtab kaks argumenti.

Esimene neist argumentidest on jälle taimeri konfiguratsiooni struktuuri address, milleks antud näites on &htim1.

Teine argument ütleb, millist taimeri kanalit käivitatakse. Selleks genereerib CubeIDE automaatsed C macrod, mis näevad välja kujul “TIM_CHANNEL_x”, kus x on kanali number. Hetkel kasutame kanalit 1, seega kirjutame “TIM_CHANNEL_1”

Selleks, et taimer 1 esimene kanal käivitada, kirjutame HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

Nüüd meie PWM generatsioon käib, kuid väljundiks on ikka tühi, sest algolekus on compare väärtus 0, mis tähendab, et PWM signaal on alati madal.

__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)

Compare väärtuse muutmiseks on olemas C macro funktsioon, mis muudab compare muutmise kergemaks.

See funktsioon võtab kolm argumenti. Esimesed kaks argumenti on juba lahti seletatud, kui need on siin välja toodud teise nimega.

HANDLE all mõeldakse argumenti htim

CHANNEL all mõeldakse argumenti Channel

COMPARE all mõeldakse soovitud compare väärtust

Kuna kasutame taimer 1 esimest kanalit, saame, et HANDLE on &htim1 ning CHANNEL on TIM_CHANNEL_1. Tekitame 50% duty-cycle-ga PWM signaali. Kuna teame, et period väärtus on 256, paneme compare väärtuseks 256 / 2 = 128.

Kirjutame

__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 128)

Nüüd on lõpuks näha väljundjalal 50% duty-cycle PWM signaali.

Koodinäide

  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start(&htim1);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	for (int i = 0; i < 256; i++) {
		__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, i);
		HAL_Delay(5);
	}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

See kood paneb alguses käima esimese taimer ning seejärel esimese taimeri esimese kanali. Seejärel läheb kood while(1) tsükklisse, kus ta suurendab PWM compare väärtust iga tsükkel, kuni see jõuab maksimumi ja alustab uuesti.

Tulemusena tekib PWM signaal, mille duty-cycle läheb järjest suuremaks, kuni see jõuab 100%-ni ning siis läheb tagasi 0%-ni.

pwm_pulse_width_modulation.txt · Last modified: 2022/04/28 20:24 by 127.0.0.1