Arduino UNOのPWM出力を(ちょっと精密に)確かめる
Arduino UNOが装備する、6つのPWM出力を確かめる
プログラムを書いてみました。
シリアルモニターでval値を入力するとその値(0~255)で
6つのPWMを出力します。
※プログラム:ダウンロード - test_analog_wr1.c
(ファイルタイプを.cとしています)
現状、このようにATmega328Pが内蔵する3つのタイマーで
6つのPWM出力が得られます。
・タイマー0 OC0AとOC0B出力
8bit高速PWM動作でイニシャルされている。
val=0でL固定、255でH固定。
1でデューティ 2/256。 2でデューティ 3/256。
127でデューティ128/256。128でデューティ129/256。
254でデューティ255/256。
▼問題点
val=1~254で欲しいデューティ値から1ずれる。
・タイマー1 OC1AとOC1B出力
・タイマー2 OC2AとOC2B出力
8bit位相基準PWM動作でイニシャルされている。
val=0でL固定、255でH固定。
1でデューティ 1/255。 2でデューティ 2/255。
127でデューティ127/255。128でデューティ128/255。
254でデューティ254/255。
▼問題点
ベースが1/255なので、127あるいは128とセット
してもデューティ50%が得られない。
■確認
タイマー1のインプットキャプチャー機能を使って、
ICP1に入力されたパルスのデューティー比と周波数を
計ってみました。
プログラム:ダウンロード - duty_checker1.c
(ファイルタイプを.cとしています)
1秒ごとにデューティ、周波数、H区間とL区間のパルス数
(Arduino unoの16MHzクロック数)をシリアル出力します。
パルスが無ければ「No pulse」。
↑↓パルスが接近して割り込み処理が間に合わないと
「Overlap pulse」と警告メッセージを出します。
Arduino基板を2枚用意して、PWM出力とICP1入力をつなぎ替えながら
↑の問題点を実際に見てみます。
(ICPクロック同期の関係で1~2発のズレが出ます)
・タイマー0
val=1
0.78% 0.977kHz 128 16255
val=2
1.17% 0.977kHz 192 16191
val=127
50.00% 0.977kHz 8191 8192
val=128
50.39% 0.977kHz 8255 8128
val=254
99.61% 0.977kHz 16319 64
このように、val値と実値が1/256ずれています。
1/2デューティのつもりで128をセットすると129/256
になってしまいます。
※もう一度言います。
0.4%の誤差が勝手に発生するのです。
・タイマー1と2
val=1
0.39% 0.490kHz 128 32510
val=2
0.78% 0.490kHz 256 32382
val=127
49.80% 0.490kHz 16255 16383
val=128
50.20% 0.490kHz 16384 16255
val=254
99.61% 0.490kHz 32510 128
1/255が設定単位で、1周期のベースが
64*2*255=32640クロックです。
そのため1/2デューティが設定できません。
127でも128でも0.5/255ずれてしまいます。
●改善方法
・タイマー0
前記事に書きましたように「反転動作」「255-val」と
することで、val=0~255で正しいデューティー比が
得られます。
また、val=0の時も0判定無しで0/256=L固定が得られます。
その確認
val=1
0.39% 0.977kHz 64 16319
val=128
50.00% 0.977kHz 8192 8192
val=255
99.61% 0.977kHz 16319 64
※プログラム例
analogWrite( 5, val); // PD5 OC0B
のかわりに
b = TCCR0A & 0b11001111; // COM0B
TCCR0A = b | 0b00110000; // 反転出力
OCR0B = 255 - val; // top値255からの差で
・タイマー1、タイマー2
残念ながら「8bit位相基準PWM動作」を使う限り
改善できません。
タイマー0と同じように「8bit高速PWM動作」にイニシャルし
直しでしょう。
あるいは、タイマー1は「TOP値=ICR1による高速PWM動作」が
使えます。
高分解能なPWMを得ることができますので、この利用をおすす
めします。
※関連
・2020年8月13日:Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう
・2020年2月10日:ArduinoのanalogWrite 1/255なの?
・2020年2月 4日:Arduinoのタイマー OCRレジスタは「n」じゃなく「n - 1」の値を設定せよ
| 固定リンク
「Arduino」カテゴリの記事
- おっと。map関数の計算桁に注意(2024.10.06)
- DDS方式の2相パルス発生回路、周波数スキャン機能を付ける(2024.10.05)
- 1クロックでも速くしたい 割込を「ISR_NAKED」で(2024.09.30)
- 1クロックでも速くしたい DDS方式の2相パルス発生器(2024.09.27)
- 秋月のI2C接続液晶 AQM1602XAを基板に直付け(2024.09.24)
コメント
・2020年8月18日:Arduino デューティー計測のためのインプットキャプチャータイミング
http://igarage.cocolog-nifty.com/blog/2020/08/post-21a70b.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年8月18日 (火) 11時22分