0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Arduino Nano Every (ATmega4809) PWM周波数変更メモ

Last updated at Posted at 2024-05-05

はじめに

色々調べた結果の自分用メモ。
人が見てもわかりやすいようにする。

使えるピン

Pin Timer CMPn
D9 A0 0
D10 A0 1
D5 A0 2
D6 B0 -
D3 B1 -

Timerの特徴

  • Timer A
    • 周波数を変更すると、Delay、Millis、Microsが狂う
      • 厳密には上記はTCB3で制御されているが、TCA0を参照しているため影響を受ける
  • Timer B
    • 周波数に柔軟性がない
    • Aとは制御の仕方がちょっと違う

ざっくりとした使い方

  • 決められた択から周波数を選ぶ形でよい場合
    • 周波数だけ高速化して、analogWriteで動かす
  • 同上、だがMillisとかが狂うと困る場合
    • 周波数の択は狭まるが、Timer B でやる
  • 周波数を自分で作りたい
    • 細かいところまで調整する
    • ただしanalogWriteだとDuty比の設定範囲に制限がでてしまうので、違う動かし方を使う
      • 入れたいDuty比が制限範囲内に収まるならanalogWriteも可

Timer A (TCA0)

Split Modeという分割モード(16bitの枠を8bit x2にするモード)もあるが、デフォルトのNormal Modeの話で進める。

周波数の計算式は以下のとおり。

fPWM_SS [Hz] = fCLK_PER / N(PER+1)

全部デフォルトだと下記のとおり。

fCLK_PER = クロック = 16MHz
N = TCAプリスケーラー = 64
PER = カウンター分解能 = 255

クロックジェネレータの選択

特別な事情がなければ変更不要。後の計算で使うので把握しておくだけ。

  • CLKCTRL.MCLKCTRLA
    • CPUクロック(デフォルト)
      • 弄ってなければ 16MHz。弄ったら20MHz
    • 内蔵水晶発振子
      • 32 KHz
    • 外部水晶発振子
      • 32.768 KHz

TCA 周波数選択(プリスケーラー選択)

択から周波数を選ぶだけでよいなら、これだけ変更すればOK

  • TCA0_SINGLE_CTRLA
    • 0b1011(デフォルト)
      • DIV64, enable
      • = 16,000,000 / (64 * (255 + 1)
      • = 976 Hz
    • 一番速いDIV1の場合で 62,500 Hz
    • 最下位ビットは有効フラグなので1にしておく
    • 以後のビットからの数値
    • 詳細はデータシートの 20.5.1 Control A を参照

TCA 周波数カスタマイズ(カウンター分解能調整)

択からの選択では物足りない場合に使用する。
analogWriteにも反映される。

  • TCA0.SINGLE.PER
    • 255(デフォルト)
    • 16bitなので、上限は 65535
    • 例えば 25000 Hz を作りたい場合は、DIV4の31250Hzをベースに以下の計算で作成する
      • 倍率 = 元になる周波数 / 作りたい周波数
      • 31250 / 25000 = 1.25
      • 255 * 1.25 = 318.75
      • ≓ 319

TCA Duty比の制限範囲を考える

  • analogWriteで入力できる値は255まで
    • 分解能調整でPERを255を超える値にした場合でも、変わらず255まで
      • 255を超えた分のDuty比を指定できなくなる
    • 例えば25000Hzを作るために 319 に変更した場合、analogWriteで設定できるDuty比の上限は以下のとおり
      • 255 / 319 ≓ 80%
    • この枠内を超えるDuty比を入れたい場合は次の項目に進む

TCA analogWriteとは違う形でDuty比設定&出力

  • Duty比設定
    • TCA0.SINGLE.CMPnBUF
      • CMP n BUF のnの部分は冒頭の表を参照
      • TCA0.SINGLE.PERを上限とした数値で指定する
      • 倍率指定で入れてOK。50%を指定するならこんな感じ
        • TCA0.SINGLE.CMP0BUF = TCA0.SINGLE.PER * 0.5;
        • loop内で随時変更可
  • pin出力開始
    • TCA0.SINGLE.CTRLB
      • 下位8bitで波形モード選択
        • PWMを作るならデフォルトの0x3をそのまま使用する
      • 上位8bitのうちの下位3bitでピンの有効化を行う
        • 0x40 D5
        • 0x20 D10
        • 0x10 D9
      • 厳密には有効化というよりはピン操作のオーバーライド
      • 詳細はデータシートの20.5.2 Control B - Normal Mode を参照
    • pinMode(pin, OUTPUT/INPUT)
      • CTRLBでピン有効化した場合は、この時点でPWM出力が始まる

TCA サンプルコード(pin9)

void setup() {
  Serial.begin(9600);
  delay(100);

  ////TCAプリスケーラーを64(0b1011)から2(0b11)に ⇒ fPWM_SS 16000000 / (2 * 256) = 31250 Hz
  TCA0.SINGLE.CTRLA = 0b011; 

  //目標値の25000 Hz にするためには、分解能(TOP)を調整する
  // 31250 / 25000 = 1.25
  // 255 * 1.25 = 318.75 ≓ 319
  TCA0.SINGLE.PER = 319;

  //Duty初期値設定(50%)
  TCA0.SINGLE.CMP0BUF = 158;

  //PWM出力設定(これて常時WriteされるためloopでのWriteは不要)
  //処理中にDutyを変更したい場合はCMPnBUFを 0~PER の範囲で変更する
  TCA0.SINGLE.CTRLB = 0x13; //Bit4 = CMP0 = pin9
  pinMode(9, OUTPUT);
}

void loop() {
}

Timer B (TCB0 / TCB1)

TCAとの違い

  • 周波数指定の範囲が狭い
    • クロック分解能(CLK_PER)の選択肢が以下の3つのみ
      • DIV1
      • DIV2
      • TCA0と同じ値
    • ピンの指定の仕方が異なる
      • TCAではTCA0のCMPnBUFの数値だったが、TCBではTCB0かTCB1かで指定
      • 続くレジスタ名はTCB0で記載する
    • bitモード選択がない
      • 元々使ってないからいいとして、レジスタの指定の仕方が異なる
      • TCBではSINGLE/SPLITがいらないので名前が短い
    • 生成できる波形の種類が少ない
      • 代わりに他の機能が設けられている
      • いずれにしても、PWMが欲しい場合には気にする必要なし
    • カウンター分解能が低い
      • TCAの16bit(65535)に対し、こちらは8bit(255)
        • カウンター分解能調整による周波数調整の仕方が

TCB 周波数選択(周波数の取得元選択)

択から周波数を選ぶだけでよいなら、これだけ変更すればOK。

  • TCB0_CTRLA
    • 先述のとおり以下の三択
      • DIV1
      • DIV2
      • TCA0_SINGLE_CTRLA で指定したのと同じ値
    • 最下位ビットは有効フラグなので1にしておく
    • 詳細はデータシートの 21.5.1 Control A を参照

TCB 周波数カスタマイズ(カウンター分解能調整)

択からの選択では物足りない場合に使用する。
analogWriteには反映されない。

  • TCB0.CCMPL
    • 255(デフォルト)
    • 8bitなので、上限は 255
      • 倍率 = 元になる周波数 / 作りたい周波数
      • デフォルトが上限値なので、倍率調整は下げる方(周波数が速くなるほう)しかできない

TCB analogWriteとは違う形でDuty比設定&出力

  • Duty比設定
    • TCB0.CCMPH
      • TCB0.CCMPLを上限とした数値で指定する
  • pin出力開始
    • TCB0.CTRLB
      • 下位4bitで波形モード選択
        • PWMを作るならデフォルトの0x3(0b111)をそのまま使用する
      • 上位4bitのうちの下位1bitでピンの有効化を行う
        • TCB0.CTRLB = 0b10111;
      • 厳密には有効化というよりはピン操作のオーバーライド
      • 詳細はデータシートの21.5.2 Control B を参照
      • CTRLBでピン有効化した場合は、この時点でPWM出力が始まる
        • pinModeはいらない

TCB サンプルコード(pin6)

void setup() {
  Serial.begin(9600);
  delay(100);

  //TCB0周波数を CLK_PER/2(31250Hz) に
  TCB0.CTRLA = 0b11; 

  //目標値を40000 Hzとして、分解能(TOP)を調整する
  // 31250 / 40000 = 0.78125
  // 255 * 0.78 = 199
  TCB0.CCMPL = 199;

  //Duty初期値設定(50%)
  TCB0.CCMPH = 100;

  //PWM出力設定(これて常時WriteされるためloopでのWriteは不要)
  //処理中にDutyを変更したい場合はCMPnBUFを 0~PER の範囲で変更する
  TCB0.CTRLB = 0b10111;
  //pinModeはいらない
}

void loop() {
}

参考文献

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?