« ラズピコのPWM。 なんかおかしいような | トップページ | ラズピコのPWM。 やっぱしanalogWriteは捨てちゃえ »

2023年2月20日 (月)

ラズピコの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
Cap108_20230220112701

微妙に変動の周期が異なります。
n/256にしても半値の128で差が生じました。
128/256で50.000%になるはずが、実測値49.950%
で、-0.050%の差です。

そして、試したのがn/100、n/105、n/200、n/250の4つ。

Cap109
10^0桁が0の100、200、250は右下がりの直線になりましたが、
n/105が「なんじゃこれは」に。

デューティ比の設定がfloatなのが問題なのかなぁ。
「pwm->write」の中味を調べなくっちゃというところ
でしょうね。

|

« ラズピコのPWM。 なんかおかしいような | トップページ | ラズピコのPWM。 やっぱしanalogWriteは捨てちゃえ »

ラズパイ・ピコ」カテゴリの記事

1023 vs 1024」カテゴリの記事

コメント

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分

コメントを書く



(ウェブ上には掲載しません)




« ラズピコのPWM。 なんかおかしいような | トップページ | ラズピコのPWM。 やっぱしanalogWriteは捨てちゃえ »