ラズピコのPWM。 なんかおかしいような #2
ラズピコのPWM。 なんかおかしいような
これの続きです。
analogWrite()を処理しているソースを探し出すと
どうやらこれのようです。
void analogWrite(pin_size_t pin, int val)
{
if (pin >= PINS_COUNT) {
return;
}
float percent = (float)val/(float)((1 << write_resolution)-1); // ★1
mbed::PwmOut* pwm = digitalPinToPwm(pin);
if (pwm == NULL) {
pwm = new mbed::PwmOut(digitalPinToPinName(pin));
digitalPinToPwm(pin) = pwm;
pwm->period_ms(2); //500Hz
}
if (percent < 0) {
delete pwm;
digitalPinToPwm(pin) = NULL;
} else {
pwm->write(percent);
}
}
★1のところで、write_resolutionが
8bitなら255に、
10bitにしたら1023に。
これがデューティ100%での浮動小数点除算の
除数になります。
つまりPWMの出力が出力がHに固定される値です。
得られた「percent」値がデューティ比でそれを
pwm->write(percent);
でPWM出力しています。
※「pwm->write」の中味はまだ追いかけてません
このanalogWriteをこんなふうに書き換えました。
(1 << m) - 1
をやめて、「write_resolution」を任意の値に設定でき
るようにします。
/***** PWM出力 *****/
// analogWiteの代替
// フルスケールはpwm_range -1
// 元々は (1 << write_resolution)-1 で8bitなら255に
void pwmWrite(pin_size_t pin, int val, int range)
{
float percent; // デューティサイクル
if(pin >= PINS_COUNT){
return;
}
percent = (float)val / (float)range; // デューティ比を計算
mbed::PwmOut* pwm = digitalPinToPwm(pin);
if(pwm == NULL){
pwm = new mbed::PwmOut(digitalPinToPinName(pin));
digitalPinToPwm(pin) = pwm;
pwm->period_ms(2); // 500Hz PWM周波数
}
if(percent < 0){
delete pwm;
digitalPinToPwm(pin) = NULL;
}
else{
pwm->write(percent); // デューティ指定でPWM出力
}
}
これで、フルスケール値(デューティ100%)を任意に書き換え
できます。
で、試してみました。
デューティ計算値と実測値の差をグラフにします。
まず、n/255 と n/256。
微妙に変動の周期が異なります。
n/256にしても半値の128で差が生じました。
128/256で50.000%になるはずが、実測値49.950%
で、-0.050%の差です。
そして、試したのがn/100、n/105、n/200、n/250の4つ。
10^0桁が0の100、200、250は右下がりの直線になりましたが、
n/105が「なんじゃこれは」に。
デューティ比の設定がfloatなのが問題なのかなぁ。
「pwm->write」の中味を調べなくっちゃというところ
でしょうね。
| 固定リンク
「ラズパイ・ピコ」カテゴリの記事
- トラ技2024年5月号に「3.3/65535」(2024.04.07)
- ラズピコだと1/65535が出現(2024.03.30)
- Help me! ラズピコ、Philhower版だとスケッチをアップロードできない(2023.04.12)
- Arduino IDEでのラズピコ開発環境 Philhower版が正解でしょう(2023.04.04)
- ラズピコのピン:自由になりそうだけど定義で固定されている(2023.04.03)
「1023 vs 1024」カテゴリの記事
- おっと。map関数の計算桁に注意(2024.10.06)
- サーミスタでの温度測定、「inf」の出現に耐えられるか?(2024.05.13)
- トラ技2024年5月号に「3.3/65535」(2024.04.07)
- ラズピコだと1/65535が出現(2024.03.30)
- Arduino UNO R4のDACサンプルに出てくるmap関数(2024.02.19)
コメント
ArduinoのanalogWriteの仕様が、0-255の設定に対して0-100%を出力するように定義されているのが話をややこしくしていますよね。計算する時に割り切れないので誤差が出るし、、
素直に0x00~0x100に対して0~100%が出力されるように定義し、上限は0xFFまでね。ということにしておけば良かったと思います。でも最大出力にしてもHighに張り付かないのがいやだったんでしょうか?
投稿: ラジオペンチ | 2023年2月20日 (月) 17時04分
Arduino UNOのanalogWrite、ここ↓で述べたことがすべてかと思うんですよ。
2020年8月13日:Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう
http://igarage.cocolog-nifty.com/blog/2020/08/post-0d2777.html
Arduinoが初心者用のツールだとしても、原理的におかしいものはおかしいわけで・・・
ラズピコでそれを引き継いだのはちょっとなぁ、でっす。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2023年2月21日 (火) 09時23分
続き。
http://igarage.cocolog-nifty.com/blog/2023/02/post-f8baae.html
ラズピコでもanalogWriteは捨てましょう。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2023年2月21日 (火) 10時15分