LoginSignup
0
2

ATtiny202のPWM機能を試す

Last updated at Posted at 2024-02-15

はじめに

本記事ではATtiny202のPWM機能について、自分なりに使い方をまとめてみました。非常に安価なAVRマイコンとして秋月電子通商より1個70円から購入できるATtiny202ですが、意外と日本語の資料は少ない印象なので少しでも参考になりましたら幸いです。
picture.jpg

開発環境

ATtinyシリーズはArduino開発環境が使えます。

  • Windows 11 Home 22H2
  • Arduino IDE 1.8.19
  • megaTinyCore 2.6.10

以下のURLをボード設定に追加し、インストールすることで導入できます。
http://drazzy.com/package_drazzy.com_index.json

ATtiny202

ピン配置は以下の通りです。
pinout.png
また、各ピンの機能は以下の通りです。
port_function.png
ATtiny202は2個のタイマを内蔵しています。TCA0とTCB0です。TCA0のチャンネルはWO0、WO1、WO2、WO3の4個、TCB0のチャンネルはWO0の1個です。対応するピンはそれぞれPA7、PA1、PA2、PA3の4本、そして、PA6の1本となります。

データシートより抜粋しました。
https://akizukidenshi.com/goodsaffix/attiny202-402.pdf

書き込み

ATtiny202は新しい世代のAVRマイコンとなるため、書き込み方式としてはUPDIが採用されています。従来から採用されているICSPとは異なり単線式なので配線が楽です。また、下図のように簡単な回路を組むだけで汎用的なUSBシリアル変換モジュールが書き込み装置として利用できます。専用品は不要なので便利です。
schematic.png
クロック周波数は20MHzと設定しています。ただし、設定したらブートローダの書き込みも併せて実行しておく必要があります。ATtinyシリーズはブートローダが不要なので実際に書き込まれる訳ではないものの、ヒューズビットが書き換えられるため、設定した内容を反映できます。また、書き込み装置はSerial UPDIを選択します。書き込み速度はSLOWを選んでおくと失敗しにくいです。
screenshot.png
プログラムは動いている最中でも書き込み可能です。書き込みに成功したらプログラムがそのまま動き始めます。

回路構成

PA6に緑色LED、PA2に赤色LEDを接続しています。書き込み回路も配線してあります。
breadboard.png

Arduino言語の場合

関数analogWriteを使い、PWM信号を出力します。なお、関数pinModeは不要です。内部的にはTCA0を利用しているようなのでPA6からは出力できません。今回はPA2から出力しました。また、ピン番号は予め定義されているピン名で指定しました。赤色LEDがじんわり点滅します。

pwm_standard.ino
void setup() {
}

void loop() {
  static unsigned int duty = 255;
  
  analogWrite(PIN_PA2, duty--); //change the duty cycle
  if (!duty) {
    duty = 255;
  }
  delay(10);
}

TCA0のレジスタを叩く場合

まずはType-Aのタイマを使い、PWM信号を出力します。

公式の資料がダウンロードできます。
https://www.microchip.com/en-us/application-notes/tb3217

クロック周波数$f_{MAIN}$が20MHzの場合、ペリフェラルに供給されるクロック周波数$f_{PER}$はデフォルトだと6分周されるため、約3.33MHzとなります。タイマに供給されるクロック周波数はさらに$N$分周されます。また、$PER$はカウンタが生成する波形の高さに当たりPWM分解能、つまりはPWM周期を表します。最小値は2ビットの4、最大値は16ビットの65536です。ただし、実際には0から数えるため、1だけ小さい値を指定します。まとめるとPWM周波数$f_{PWM}$は次式より求まります。今回は分周比を2、PWM分解能を8ビットに指定したので約6.51kHzと求まりました。

f_{PWM} = \frac{f_{PER}}{N(PER + 1)}

今回はカウンタの波形が鋸波となるモードを選択し、PWM信号を出力しています。三角波を生成するモードよりも高速なPWM信号を出力できる点が特徴です。
tca.png
ここで、$n$はチャンネル番号を表します。今回はWO2を有効化し、対応するPA2から出力しました。デューティ比$D_{WOn}$は次式より求まります。閾値$CMPn$を調整することでデューティ比が変わります。なお、複数のチャンネルを有効化しても各チャンネルで個別にデューティ比は設定できます。

D_{WOn} = \frac{CMPn}{PER + 1}

先述のプログラムと同様に赤色LEDがじんわり点滅します。

pwm_tca.ino
void setup() {
  pinMode(PIN_PA2, OUTPUT);
//  PORTMUX.CTRLC = PORTMUX_TCA00_DEFAULT_gc; //turn off the port multiplexer, assigning WO0 to PA3
//  PORTMUX.CTRLC = PORTMUX_TCA00_ALTERNATE_gc; //turn on the port multiplexer, assigning WO0 to PA7
  
  takeOverTCA0(); //disable and reset the timer
  TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm | TCA_SINGLE_CLKSEL_DIV2_gc; //start the timer, set the prescaler to 2
  TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP2EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc; //enable WO2, select the single slope PWM mode
  TCA0.SINGLE.PER = 255; //set the PWM resolution to 8 bits
  TCA0.SINGLE.CMP2 = 0; //set the duty cycle
}

void loop() {
  static unsigned int duty = 255;
  
  TCA0.SINGLE.CMP2 = duty--; //change the duty cycle
  if (!duty) {
    duty = 255;
  }
  delay(10);
}

補足ですが、WO0はデフォルトだとPA7に出力されるようです。PA3から出力したい場合は上記のコメントアウトを解除し、ピン配置を再設定する必要があります。ただし、同時には出力できません。関数analogWriteなら特に設定する手間もなく同時に出力できます。

TCB0のレジスタを叩く場合

次にType-Bのタイマを使い、PWM信号を出力します。

公式の資料がダウンロードできます。
https://www.microchip.com/en-us/application-notes/tb3214

PWM周波数$f_{PWM}$は次式より求まります。先述の式と似ていますが、レジスタ名は異なります。$CCMP$の上位8ビットを$CCMPH$、下位8ビットを$CCMPL$と別々に指定することが可能です。$CCMPL$はPWM分解能を表します。今回は分周比を1、PWM分解能は最大8ビットなので255を指定し、約13.02kHzと求まりました。

f_{PWM} = \frac{f_{PER}}{N(CCMPL + 1)}

PWM分解能を下げるとPWM周波数は上がります。また、カウンタの波形は鋸波です。
tcb.png
TCB0のチャンネルはWO0のみです。つまり、対応するPA6からしか出力できません。デューティ比$D_{WOn}$は次式より求まります。閾値$CCMPH$を調整することでデューティ比が変わります。

D_{WOn} = \frac{CCMPH}{CCMPL + 1}

先述のプログラムとは異なり緑色LEDがじんわり点滅します。

pwm_tcb.ino
void setup() {
  pinMode(PIN_PA6, OUTPUT);
  
  TCB0.CTRLA = TCB_ENABLE_bm | TCB_CLKSEL_CLKDIV1_gc; //start the timer, set the prescaler to 1
  TCB0.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_PWM8_gc; //enable WO0, select the 8 bits PWM mode
//  TCB0.CCMP = 0x00FF;
  TCB0.CCMPL = 255; //set the PWM resolution to 8 bits
  TCB0.CCMPH = 0; //set the duty cycle
}

void loop() {
  static unsigned int duty = 255;
  
  TCB0.CCMPH = duty--; //change the duty cycle
  if (!duty) {
    duty = 255;
  }
  delay(10);
}

おわりに

ATtiny202はプログラムメモリのサイズが2kBと控え目なので用途は限定されそうですが、Arduino開発環境が使えて機能もそこそこ豊富なので重宝しそうです。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2