[戻る]
一括表示

PWMでDuty=0が実行されない 投稿者:Qman 投稿日:2017/03/29(Wed) 10:47:38 No.860

PIC16F1827 で CCSC でPWMのプログラムを作りました。
CPU: PIC16F1827 32MHz(x4 PLL)
PWMの周期:100uS 分解能: 800

下記の「PWM繰返し」部において
PWMの100周期ごとにTMR2割込みを発生させて@ABを実行させます。
(@の実行前はBの続きでDuty=400になっています。)

@の実行後、(100uS後の)次のPWM周期にDuty=N1になります。
Aの実行後、(100uS後の)次のPWM周期にDuty=0になります。
Bの実行後、(100uS後の)次のPWM周期にDuty=400になり、それが続きます。

しかし、N1=35,43,67・・・(10進数)のときだけ (N1は変数ではなく定数です。)
Aの実行後、(100uS後の)次のPWM周期に
Duty=0 にならず Duty=800(100%)になります。
これらの数値を16進数にすると下位2bitが"11"になる場合ということがわかりました。
しかし、その理由がわかりません?。
ご教授をお願いします。

CCPTMRS = 0x00; // CCP1 にTMR2を使用
CCP1CON = 0b00001100; // CCP1=PWMモード

struct {
int CCP1M :4; // b3-0
int dat :2; // b5.4 PWM 下位2bitデータ
int P1M :2; // b7.6
} CCP1CON;
#byteCCP1CON = 0x293

void pwm_duty_set(signed long x)
{
if (x > 0)
{
CCP1CON.dat = x & 0b00000011; // 下位2bit
CCPR1L = x >> 2; // 上位8bit
}
else
{
CCP1CON.dat = 0; // 下位2bit
CCPR1L = 0; // 上位8bit
}
}

void main()
{
// ----- PWM繰返し -----
pwm_duty_set(N1); //@
delay_us(100);
pwm_duty_set(0); //A
delay_us(100);
pwm_duty_set(400); //B

Re: PWMでDuty=0が実行されない 投稿者:PWM 投稿日:2017/03/30(Thu) 12:22:58 No.861

PWMのduty=0の出力は、保障外だと思いますが。
PWMをOFFにすればいいのでは

PWMでDuty=0が実行されない 投稿者:Qman 投稿日:2017/03/30(Thu) 13:44:27 No.863

回答ありがとうございます。

> PWMのduty=0の出力は、保障外だと思いますが。
マニュアルに書いてありますか?
英語が苦手なのでその箇所を教えていただければ幸いです。

いままで、このプログラムでPWMは何度か使ってきましたが、
今回初めて気が付いた次第です。

1.@が下位2bitが"11"以外ではduty=0になります。
2.Aの実行後200uS待てばduty=800の次の周期にduty=0になります。
3.duty=0が保障外のPWMって、使い物になりますか?

> PWMをOFFにすればいいのでは

Re: PWMでDuty=0が実行されない 投稿者:PWM^2 投稿日:2017/03/30(Thu) 17:40:57 No.865

横から失礼します。
詳しくマニュアルを誰も親切には見ないでしょう。
PWMを単にOFFでいいものを、原因を知りたいというご意見でしたので、回答を控えていました。
8ビットの場合で考えてみれば、0が設定値としてOKなら最大値は255まで、0が値としてNGなら、値は1からなので最大値は256です。
どちらかで出来ているはずです。
前者の場合、ビットの基準が0=256の最大値を意味することも有り得るので、原因を知りたいのなら、0、1、255、256の値をそれぞれ代入してみて、結果がどう変わるか確認して下さい。
おそらく、255の時にPWMはOFF(duty=0)になるはずです。
8ビットの場合で説明しているので、16ビットであれば当てはめて考えて下さい。
もうひとつ、duty=0は厳密にはならないはずなので、きちんとオシロスコープで出力を解析されることをお勧めします。


> 回答ありがとうございます。
>
> > PWMのduty=0の出力は、保障外だと思いますが。
> マニュアルに書いてありますか?
> 英語が苦手なのでその箇所を教えていただければ幸いです。
>
> いままで、このプログラムでPWMは何度か使ってきましたが、
> 今回初めて気が付いた次第です。
>
> 1.@が下位2bitが"11"以外ではduty=0になります。
> 2.Aの実行後200uS待てばduty=800の次の周期にduty=0になります。
> 3.duty=0が保障外のPWMって、使い物になりますか?
>
> > PWMをOFFにすればいいのでは

PWMでDut=0が実行されない 投稿者:Qman 投稿日:2017/03/30(Thu) 19:41:45 No.866


>きちんとオシロスコープで出力を解析されることをお勧めします。

当然、しています。
本質問に関しては、
デジタルオシロスコープで波形観測をして確認したうえでなければ質問自体が
無意味であるということは誰でもわかることです。

8bitとしての使い方はしていません。
プログラムリストをみればわかるとおり10bitで使用していますし
動作も10bitで動作していることは質問および返信に書いたとうりです。

いままで経験した、機械系のような低速応答の閉ループ制御においては
本質問のとおりでもほとんど問題はないことはおわかりのことと思います。
それで、いままで気が付かなかったと思います。


> 横から失礼します。
> 詳しくマニュアルを誰も親切には見ないでしょう。
> PWMを単にOFFでいいものを、原因を知りたいというご意見でしたので、回答を控えていました。
> 8ビットの場合で考えてみれば、0が設定値としてOKなら最大値は255まで、0が値としてNGなら、値は1からなので最大値は256です。
> どちらかで出来ているはずです。
> 前者の場合、ビットの基準が0=256の最大値を意味することも有り得るので、原因を知りたいのなら、0、1、255、256の値をそれぞれ代入してみて、結果がどう変わるか確認して下さい。
> おそらく、255の時にPWMはOFF(duty=0)になるはずです。
> 8ビットの場合で説明しているので、16ビットであれば当てはめて考えて下さい。
> もうひとつ、duty=0は厳密にはならないはずなので、きちんとオシロスコープで出力を解析されることをお勧めします。
>
>
> > 回答ありがとうございます。
> >
> > > PWMのduty=0の出力は、保障外だと思いますが。
> > マニュアルに書いてありますか?
> > 英語が苦手なのでその箇所を教えていただければ幸いです。
> >
> > いままで、このプログラムでPWMは何度か使ってきましたが、
> > 今回初めて気が付いた次第です。
> >
> > 1.@が下位2bitが"11"以外ではduty=0になります。
> > 2.Aの実行後200uS待てばduty=800の次の周期にduty=0になります。
> > 3.duty=0が保障外のPWMって、使い物になりますか?
> >
> > > PWMをOFFにすればいいのでは

: PWMでDuty=0が実行されない 投稿者:Qman 投稿日:2017/04/02(Sun) 09:52:00 No.873


> duty=0は厳密にはならないはずなので、
それが「PWM2さん」の作ったプログラムで言われてことならば
見直されたらいかがですか?
確実に duty=0 になります。
>きちんとオシロスコープで出力を解析されることをお勧めします。

「PWM」、「duty」で検索してみたらいかがですか?
身近なところでは後閑さんのpicfun にもduty=0は使われています。

PS.
質問した件は、プログラムを変更して全て解決しました。

2: PWMでDuty=0が実行されない 投稿者:Qman 投稿日:2017/04/02(Sun) 09:26:54 No.872

>PWMのduty=0の出力は、保障外だと思いますが。
H/W(CPU)はduty=0が可能な機能を有しています。
したがって、問題はCPUを動作させるS/Wにあります。
「PWMさん」が、確実に、そして保証できるプログラミングを
すればいいだけの話だと思いますが。

>PWMをOFFにすればいいのでは
言葉のあやですね。
PICのPWMは10bitです。
通常はduty=0h〜3ffhとしてONとかOFFという言葉は使いません。

PS.
質問した件は、プログラムを変更して全て解決しました。

Re: PWMでDuty=0が実行されない 投稿者:n 投稿日:2017/03/31(Fri) 01:12:30 No.867

Qmanさん

はじめましてnです。

データシートを読んだだけなので実際には試していません。
以下の仮説をご検証ください。

データが35のとき、カウンタ?は「0b00100000.11」でコンペアされ、
PWM出力用のFFがリセットされます。
このとき、カウンタの上位8bitはクリヤされますが、下位の2bitは、
クロックOSCの信号を参照しているだけなので、変化しません。

つまり、10ビットカウンタ?の値は「0b00000000.11」です。
これを捕まえるためには、データも「0b00000000.11」と指定します。

0b00000000.00になるのは、0b11111111.11の次です。
0b00000000.11→0b00000001.00→0b00000001.01→…0b11111111.11
このため、約1周期リセットが遅延します。

void pwm_duty_set(signed long x)
{
if (x > 0){
CCP1CON.dat = x & 0b00000011; // 下位2bit
CCPR1L = x >> 2; // 上位8bit
}else{
CCP1CON.dat = CCP1CON.dat; // 下位2bit(保存)
CCPR1L = 0; // 上位8bit
}
}

> PIC16F1827 で CCSC でPWMのプログラムを作りました。
> CPU: PIC16F1827 32MHz(x4 PLL)
> PWMの周期:100uS 分解能: 800
>
> 下記の「PWM繰返し」部において
> PWMの100周期ごとにTMR2割込みを発生させて@ABを実行させます。
> (@の実行前はBの続きでDuty=400になっています。)
>
> @の実行後、(100uS後の)次のPWM周期にDuty=N1になります。
> Aの実行後、(100uS後の)次のPWM周期にDuty=0になります。
> Bの実行後、(100uS後の)次のPWM周期にDuty=400になり、それが続きます。
>
> しかし、N1=35,43,67・・・(10進数)のときだけ (N1は変数ではなく定数です。)
> Aの実行後、(100uS後の)次のPWM周期に
> Duty=0 にならず Duty=800(100%)になります。
> これらの数値を16進数にすると下位2bitが"11"になる場合ということがわかりました。
> しかし、その理由がわかりません?。
> ご教授をお願いします。
>
> CCPTMRS = 0x00; // CCP1 にTMR2を使用
> CCP1CON = 0b00001100; // CCP1=PWMモード
>
> struct {
> int CCP1M :4; // b3-0
> int dat :2; // b5.4 PWM 下位2bitデータ
> int P1M :2; // b7.6
> } CCP1CON;
> #byteCCP1CON = 0x293
>
> void pwm_duty_set(signed long x)
> {
> if (x > 0)
> {
> CCP1CON.dat = x & 0b00000011; // 下位2bit
> CCPR1L = x >> 2; // 上位8bit
> }
> else
> {
> CCP1CON.dat = 0; // 下位2bit
> CCPR1L = 0; // 上位8bit
> }
> }
>
> void main()
> {
> // ----- PWM繰返し -----
> pwm_duty_set(N1); //@
> delay_us(100);
> pwm_duty_set(0); //A
> delay_us(100);
> pwm_duty_set(400); //B

2: PWMでDuty=0が実行されない 投稿者:Qman 投稿日:2017/04/02(Sun) 10:28:40 No.874


nさん、回答ありがとうございます。

>以下の仮説をご検証ください。
すみません。
検証する前に気が付いた事があり、質問した件は、プログラムを変更して全て解決しました。

> Qmanさん
>
> はじめましてnです。
>
> データシートを読んだだけなので実際には試していません。
> 以下の仮説をご検証ください。
>
> データが35のとき、カウンタ?は「0b00100000.11」でコンペアされ、
> PWM出力用のFFがリセットされます。
> このとき、カウンタの上位8bitはクリヤされますが、下位の2bitは、
> クロックOSCの信号を参照しているだけなので、変化しません。
>
> つまり、10ビットカウンタ?の値は「0b00000000.11」です。
> これを捕まえるためには、データも「0b00000000.11」と指定します。
>
> 0b00000000.00になるのは、0b11111111.11の次です。
> 0b00000000.11→0b00000001.00→0b00000001.01→…0b11111111.11
> このため、約1周期リセットが遅延します。
>
> void pwm_duty_set(signed long x)
> {
> if (x > 0){
> CCP1CON.dat = x & 0b00000011; // 下位2bit
> CCPR1L = x >> 2; // 上位8bit
> }else{
> CCP1CON.dat = CCP1CON.dat; // 下位2bit(保存)
> CCPR1L = 0; // 上位8bit
> }
> }
>

役立ちましたか? 投稿者:n 投稿日:2017/04/02(Sun) 13:01:34 No.875

Qmanさん
nです。

私の回答は役立ちましたか?
(10bitデータの下位2bitの扱い等)
さしつかえなければ、参考までにお聞かせください。

>
> nさん、回答ありがとうございます。
>
> >以下の仮説をご検証ください。
> すみません。
> 検証する前に気が付いた事があり、質問した件は、プログラムを変更して全て解決しました。

Re: 役立ちましたか? 投稿者:Qman 投稿日:2017/04/02(Sun) 13:50:00 No.876


回答があったことは知っていました。
まず、自分の考えでプログラムしてダメだったら
nさんの回答をじっくり読んでトライしてみようと思っていました。

オシロでも確認した結果、OKだったのでトライしていません。
せっかく、貴重な時間をいただき回答いただいたのに
すみませんでした。

> Qmanさん
> nです。
>
> 私の回答は役立ちましたか?
> (10bitデータの下位2bitの扱い等)
> さしつかえなければ、参考までにお聞かせください。
>
> >
> > nさん、回答ありがとうございます。
> >
> > >以下の仮説をご検証ください。
> > すみません。
> > 検証する前に気が付いた事があり、質問した件は、プログラムを変更して全て解決しました。

- WebForum -