目的
Arduinoを使い始めて、そろそろ10年超えそうです。
10年経っても結局Arudinoが安いし、使い勝手がいいですね。
ESPという選択もありますが、ESPほどの性能は必要ないときの方が多いので結局Arudinoを使ってしまいます。
PWMを100kHz単位で出す場合、タイマー関数では精度が全く出ません。多重割り込みを起こしている可能性もあります。16MHz動作クロックなので、大丈夫な気もしますが
ということで、レジスタで設定する方法を備忘録として残します。
作成途中に見つけたおすすめサイト(このサイト見れば全部解決してる気がする)
レジスタ設定 : Fast PWM : timer1
周波数可変Fast PWMモードを使うには、mode 15か14です。mode14の場合でやります。
WMG13 = 1
WMG12 = 1
WGM11 = 1
WGM10 = 0
コンペアマッチについて解説します。
OCR1A/OCR1Bとカウンターが同じ値になるとハードウェア的に下記の動作が発生します。
COM1*1/COM1*0 = 0/0 →不動作
COM1*1/COM1*0 = 0/1 →コンペアマッチでトグル
COM1*1/COM1*0 = 1/0 →下限で1、コンペアマッチで0
COM1*1/COM1*0 = 1/1 →下限で0、コンペアマッチで1
portは
OCR1A : pin9
OCR1B : pin10
プリスケーラの解説
CS12/11/10 = 0/0/0 → 不動作
CS12/11/10 = 0/0/1 → 16MHz:62.5ns
CS12/11/10 = 0/1/0 → 2MHz:500ns
CS12/11/10 = 0/1/1 → 250kHz:4us
CS12/11/10 = 1/0/0 → 62.5kHz:16us
CS12/11/10 = 1/0/1 → 15.625kHz:64us
設定例100kHzPWM
WMG13 = 1
WMG12 = 1
WGM11 = 1
WGM10 = 0
COM1A1/COM1A0 = 1/0 →下限で1、コンペアマッチで0
OCR1A : pin9
CS12/11/10 = 0/0/1 → 16MHz:62.5us
100kHz:10us → 10us/62.5ns = 160
ICR1 = 160-1
プログラム
void setup() {
Serial.begin(9600);
pinMode(9,OUTPUT);
digitalWrite(9,LOW);
/*タイマ1初期化*/
TCCR1A = 0;
TCCR1B = 0;
/* OC1A,OC1B 40kHz出力
* PWMモード:Fast PWM
* 分周比:1
* TOP:ICR1 = 160 - 1
* OCR1A:コンペアマッチLOW
* OCR1B:コンペアマッチLOW
*/
TCCR1A |= (1 << WGM11) | (1 << COM1A1);
TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
ICR1 = 160 - 1;
OCR1A = 10;
}
void loop() {
}
問題なさそうです。