[戻る]
新着表示

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^11: USART受信プログラム 投稿者:n 投稿日:2017/03/28(Tue) 23:34:52 No.859

radioさん
nです。

@加速度センサを送信モジュールの基板からケーブルで離し、
送受信モジュールを適当な間隔で固定してください。
目的は、加速度センサのみを傾けて動作確認することです。

AUSARTをリセットできる関数があれば良いのですが。
(closeしてopenしなおせばリセットになるかもしれません)

B誤りの少ない通信には、Xbeeのほうが適しています。
(目的が異なれば、何が適するかも異なります)
(今回は「なぜそれではうまくいかないか」を学べたと思います)

トラブルはチャンスと考え、楽しみながら力をつけてください。

> nさま
>
> 返信ありがとうございます。
> 2400bau/有線の条件はまったく問題ありません。
> (1200bau/有線はまだ試しておりません。)
>
> 加速度センサの値の変化は、「送信基板を少しでも傾けたら」という表現となります。
> 受信側 PICマイコンのRX端子の信号をモニタ(オシロスコープ)していると、
> たまにノイズが重畳しています。これが原因なのでしょうか?
>
> いただいた回答から何点か教えていただきたいことがあります。
>
> @送信機と受信機のアンテナの結合状態はどのように調べることができるのでしょうか?
>
> Aノイズが入るたびにUSARTのエラーをリセットするプログラムを組むことは可能でしょうか?
> 今は、一度エラーになると、ハードリセット(PICマイコン1pinをリセット)しなければ、
> 通信を再開することができません。
>
> B参考サイトをまねてAM送受信モジュールを使ってみましたが、nさまがおっしゃるように
>  リモコンとして使うには難しい(または不向き)なのでしょうか?
> Xbeeの方が適していますか?
>
>
>
> [受信側]
> http://www.picfun.com/Sensor/equipj78.html

Re^10: USART受信プログラム 投稿者:radio 投稿日:2017/03/28(Tue) 17:03:05 No.858

nさま

返信ありがとうございます。
2400bau/有線の条件はまったく問題ありません。
(1200bau/有線はまだ試しておりません。)

加速度センサの値の変化は、「送信基板を少しでも傾けたら」という表現となります。
受信側 PICマイコンのRX端子の信号をモニタ(オシロスコープ)していると、
たまにノイズが重畳しています。これが原因なのでしょうか?

いただいた回答から何点か教えていただきたいことがあります。

@送信機と受信機のアンテナの結合状態はどのように調べることができるのでしょうか?

Aノイズが入るたびにUSARTのエラーをリセットするプログラムを組むことは可能でしょうか?
今は、一度エラーになると、ハードリセット(PICマイコン1pinをリセット)しなければ、
通信を再開することができません。

B参考サイトをまねてAM送受信モジュールを使ってみましたが、nさまがおっしゃるように
 リモコンとして使うには難しい(または不向き)なのでしょうか?
Xbeeの方が適していますか?



[受信側]
http://www.picfun.com/Sensor/equipj78.html

Re^9: USART受信プログラム 投稿者:n 投稿日:2017/03/28(Tue) 11:22:13 No.857

radioさん
nです。

2400baudで、有線だとどうなりますか?

1200baudではどうですか?
(25を51、103を207に変更)

「加速度センサの値の変化」とは、「送信基板の移動や振動」ですか?
そうならば、「電波の強さの変化」が主因かもしれません。
送信機と受信機のアンテナの結合状況を確認してください。
(A AMでは、電波の強さの変化はUSARTへの信号の変化です)

AM送信モジュールの採用自体が、リモコンの送信に適さないのでは?
(信号にノイズが含まれることを前提としたアルゴリズムが必要)
(ノイズが入るたびにUSARTのエラーをリセットする必要あり)
(@ 最初の1文字の誤りは、パワーON時のノイズの可能性あり)

> n様
>
> USARTの設定情報をお送りさせていただきます。
>
> [送信側]
> Clock=4MHz
>
> OpenUSART(USART_TX_INT_OFF&USART_RX_INT_OFF&USART_ASYNCH_MODE&USART_EIGHT_BIT&USART_CONT_RX&USART_BRGH_LOW,25 );
>
> [受信側]
> Clock=16MHz
>
> OpenUSART(USART_TX_INT_OFF&USART_RX_INT_OFF&USART_ASYNCH_MODE&USART_EIGHT_BIT&USART_CONT_RX&USART_BRGH_LOW,103 );
>
>
> 今の状況について説明させていただきます。
> 送信側で間隔を開けたり(↓のプログラムでdelay時間を調整)したりして試しています。
>
> ↓に掲載する送信プログラムで、ある程度※1通信し続けることを確認しました。
>
>
> 2つ分かったことがあります。
>
> @最初の文字'S'を受信できない。
> ↓の送信プログラムで、最初に'X'を送信しています。
> 'X'でなくても、最初に何らかの文字を送らないと、1文字目の'S'を受信してくれません。
>
> A※1
> ある程度というのは、送信側の加速度センサが少しでも変化してしまうと、通信が途切れます。
> 送信側で、送信間隔をあけてしまうと、加速度センサの変化に通信速度が追従できず…エラーになるのでしょうか?
>
> 私が今試しているのは、AM送信モジュールを使用して、2400bps通信ですが、
> 安定した通信を行うことができません。
>
> 何かアドバイスをいただけたらと思います。
> 少し手詰まりな感じがしてきました。
>
> [送信プログラム]
> //USART送信
> //delay_ms(100);
> WriteUSART('X');//putsUSART("S");同等
> delay_ms(15);
> WriteUSART('S');
> delay_ms(15);
> WriteUSART('S');
> delay_ms(5);
> WriteUSART(Direction);
> delay_ms(5);
> WriteUSART(MLdata >> 8);
> delay_ms(5);
> WriteUSART(MLdata & 0x00FF);
> delay_ms(5);
> WriteUSART(MRdata >> 8);
> delay_ms(5);
> WriteUSART(MRdata & 0x00FF);
> //delay_ms(5);
> WriteUSART(~Direction);
> delay_ms(5);
> WriteUSART(~(MLdata >> 8));
> delay_ms(5);
> WriteUSART(~(MLdata & 0x00FF));
> delay_ms(5);
> WriteUSART(~(MRdata >> 8));
> delay_ms(5);
> WriteUSART(~(MRdata & 0x00FF));
> delay_ms(5);
> WriteUSART('E');
> //delay_ms(1);

Re^8: USART受信プログラム 投稿者:radio 投稿日:2017/03/27(Mon) 13:05:10 No.856

n様

USARTの設定情報をお送りさせていただきます。

[送信側]
Clock=4MHz

OpenUSART(USART_TX_INT_OFF&USART_RX_INT_OFF&USART_ASYNCH_MODE&USART_EIGHT_BIT&USART_CONT_RX&USART_BRGH_LOW,25 );

[受信側]
Clock=16MHz

OpenUSART(USART_TX_INT_OFF&USART_RX_INT_OFF&USART_ASYNCH_MODE&USART_EIGHT_BIT&USART_CONT_RX&USART_BRGH_LOW,103 );


今の状況について説明させていただきます。
送信側で間隔を開けたり(↓のプログラムでdelay時間を調整)したりして試しています。

↓に掲載する送信プログラムで、ある程度※1通信し続けることを確認しました。


2つ分かったことがあります。

@最初の文字'S'を受信できない。
↓の送信プログラムで、最初に'X'を送信しています。
'X'でなくても、最初に何らかの文字を送らないと、1文字目の'S'を受信してくれません。

A※1
ある程度というのは、送信側の加速度センサが少しでも変化してしまうと、通信が途切れます。
送信側で、送信間隔をあけてしまうと、加速度センサの変化に通信速度が追従できず…エラーになるのでしょうか?

私が今試しているのは、AM送信モジュールを使用して、2400bps通信ですが、
安定した通信を行うことができません。

何かアドバイスをいただけたらと思います。
少し手詰まりな感じがしてきました。

[送信プログラム]
//USART送信
//delay_ms(100);
WriteUSART('X');//putsUSART("S");同等
delay_ms(15);
WriteUSART('S');
delay_ms(15);
WriteUSART('S');
delay_ms(5);
WriteUSART(Direction);
delay_ms(5);
WriteUSART(MLdata >> 8);
delay_ms(5);
WriteUSART(MLdata & 0x00FF);
delay_ms(5);
WriteUSART(MRdata >> 8);
delay_ms(5);
WriteUSART(MRdata & 0x00FF);
//delay_ms(5);
WriteUSART(~Direction);
delay_ms(5);
WriteUSART(~(MLdata >> 8));
delay_ms(5);
WriteUSART(~(MLdata & 0x00FF));
delay_ms(5);
WriteUSART(~(MRdata >> 8));
delay_ms(5);
WriteUSART(~(MRdata & 0x00FF));
delay_ms(5);
WriteUSART('E');
//delay_ms(1);

Re^7: USART受信プログラム 投稿者:n 投稿日:2017/03/24(Fri) 21:48:49 No.855

radioさん
nです。

"SS"だけでなく、他の文字も試してください。
("AB"等が透過するか、透過しないコードは何か)

送信側で、間隔をあけて送信してみてください。
(「'A'しばらく待って'B'しばらく待って'C'」等)

USARTの初期設定の情報を教えてください。
例:
OpenUSART( USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH,25 );

Re^6: USART受信プログラム 投稿者:radio 投稿日:2017/03/24(Fri) 09:41:01 No.854

nさま

n様のお陰で、だいぶゴールに近くなりました。
今の状況を説明します。

送信側PICマイコン⇒ 受信側PICマイコン
USART通信(有線)で動作を確認しています。
Bau Rateは、9600bpsに設定しています。
この状態で、送信側からのデータに応じて受信側のマイコンが動作できています。

次の目標として、無線通信を試みています。
2つのデバイスを使用してテストしています。

@AM送受信モジュール
送信側PICマイコン=>AM送信モジュール ⇔ AM受信モジュール=>受信側PICマイコン

AXbee
送信側PICマイコン=>Xbee Coordinator ⇔ Xbee Router=>受信側PICマイコン

@に関しては、データシートやメーカの情報から、2400bpsに設定してテストしています。
しかし、受信側で'S'、'S'受信まで行っているのですが、LCDに5バイトのデータが受信されません。



Aに関しては、まだあまり詳しくテストしていませんが、
9600bpsで動作確認をおおなったところ、連続して5回程データを受信した後、データを受信しなくなってしまいます。
こちらは、「RO Packetization Timeout」の設定が影響しているのではと考えています。


[ご質問]
まずは、@の環境で、有線と同じレベルまで持っていきたいと考えていますが、
5バイトデータが受信できない理由が分かりません。
考えられる原因についてアドバイスいただけると助かります。

Re^5: USART受信プログラム 投稿者:n 投稿日:2017/03/23(Thu) 22:36:57 No.853

radioさん
nです。

質問が明確なので、回答が楽です。

@ 動作にdelay時間を設けてしまうと、受信できないのは何故でしょうか?

 調歩同期式の通信では、受信側がデータを取りこぼすからです。

A Buf1[]内のデータが"ffff"や"ffe8"になってしまうのは何故でしょうか?

 char型データは、sprintf関数へint型に変換されて渡されます。
 char型の"ff"が負の数(-1)として扱われ、"ffff"になります。
 回避するには、unsigned char型へのキャストを行います。
 (unsigned char)Buf1[1]

B LCDにBuf1[]の5バイト分を1行に表示させる場合、どのように記述すれば良いのでしょうか?

 sprintf関数のbuff1へのポインタを2文字進めながら繰り返します。
 buff1のサイズは、11文字以上必要です。

for(i = 0 ; i < 5 ; i++){
sprintf(buff1+2*i,(const far rom char *)"%02x",(unsigned char)Buf1[i]);
}

> nさま
>
> 度々すみません。
> 少しずつ原因らしきものが見えてきました。
>
>
> 原因を解析するために、状態確認用のLEDを点灯させています。
> 最初の'S'を受信: 白色LED点滅
> 次の'S'を受信:  黄色LED点滅
>
> この点滅をわざと、delay時間を設けて行ってみました。
> 50msecに設定して点滅させてみたところ、'S'、'S'の後の、5バイトデータを受信することができませんでした。
> ⇒LCDに何も表示されない + 5バイトデータの一致判定プログラム(Errorなら赤色LED、Errorが無ければ緑色LED)で確認
>
> この時間を5msecに変更したところ、5バイトデータの一致判定プログラムまで進み、
> Errorが無い(緑色LEDが500msecで点滅する)ことを確認することができました。
>
> ただ、データを連続して受信することができません。
> 次の'S'、'S'受信まで行っているのですが、再びLEDに5バイトのデータが受信されません。
>
> そこで、Errorが無いときに確認していた緑色のLEDの点滅周期を5msecに変更しました。
> そしたら、連続してデータを受信することができ、送信側のデータに応じた動作(LED点灯)を行うことができました。
>
>
> 以上を踏まえて、何点か質問をさせてください。
>
> @今の状態では根本的な解決になっておらず、送信側のデータに応じた動作(今はLEDを点灯するだけ)の時間が長くなると、同じような不具合(連続してデータを受信できない)が発生してしまいます。
>  動作にdelay時間を設けてしまうと、受信できないのは何故でしょうか?
>
>
> ABuf1[]内のでーたが"ffff"や"ffe8"になってしまうのは何故でしょうか?
> 先程の投稿でもお伝えしましたが、Xbeeを接続して、XCTUで送信データを確認してみると、送信側は02 00 00 00 00 の5バイトのはずですが、
> LCDに表示されるデータが違ってしまいます。
> (ただ、この表示のデータでも、送信側のデータに応じた動作はできていますので、私のLCD表示プログラムがおかしいのでしょうか。)
> //Buf1[]内の数字を0〜4まで変更してLCDにデータを表示させました。
> //Buf1[0]=02
> //Buf1[1]=ffff
> //Buf1[2]=ffe9 or ffea or ffe8
> //Buf1[3]=00
> //Buf1[4]=17
>
>
> B初歩的な質問ですみません。
>  LCDにBuf1[]の5バイト分を1行に表示させる場合、どのように記述すれば良いのでしょうか?  
> 今は、↓のように[]内の数字を変えて1つずつ確認しています。
> sprintf(buff1,(const far rom char *)"Data=%02x",Buf1[1]);
> lcd_cmd(0x80); //1行目へ移動
> lcd_str(buff1);
>
>
>
> 5バイトデータ受信後のプログラムです。
> 照合一致(3 緑LED点灯、消灯)はコメントアウトしました。
>
>
> void MotorControl(void)
> {
>
>
> /*** 2連送照合比較一致の場合のみ制御実行***/
> Error = 0; // エラーフラグリセット
> for(i=0; i<5; i++){
> if(Buf1[i] != Buf2[i]) // 比較実行
> {
> Error = 0xFF; // エラーフラグオン
> LED_R ^= 1; // 赤LED点滅
> delay_ms(100);
> }
> }
> if((Error == 0) && (RcvData == 'E')) // 照合一致か?
> {
> //LED_G = 1; // 3 緑LED点灯
> //delay_ms(500);
> //LED_G = 0; // 3 緑LED消灯
> //delay_ms(500);
>
>
> Direction = (int)Buf1[0]; // 方向セット
> MLdata = (int)Buf1[1] * 256 + (int)Buf1[2];
> MRdata = (int)Buf1[3] * 256 + (int)Buf1[4];
> // 制御実行
> switch(Direction) // 方向チェック
> {
> case 0:
> //MLReverse(MLdata); // 後進の場合
> //MRReverse(MRdata);
> LED_G=1;
> delay_ms(5);
> //LED_G=0;
> //delay_ms(500);
> break;
> case 1:
> //MLFeed(MLdata); // 前進の場合
> //MRFeed(MRdata);
> LED_W=1;
> delay_ms(5);
> //LED_W=0;
> //delay_ms(500);
> break;
> case 2:
> MLStop(); // 停止の場合
> MRStop();
> LED_R=1; //4 赤LED点灯
> delay_ms(5);
> //LED_R=0; //4 赤LED消灯
> //delay_ms(500);
> break;
> default: break;
> }
> }
> }

Re^4: USART受信プログラム 投稿者:radio 投稿日:2017/03/23(Thu) 11:13:47 No.852

nさま

度々すみません。
少しずつ原因らしきものが見えてきました。


原因を解析するために、状態確認用のLEDを点灯させています。
最初の'S'を受信: 白色LED点滅
次の'S'を受信:  黄色LED点滅

この点滅をわざと、delay時間を設けて行ってみました。
50msecに設定して点滅させてみたところ、'S'、'S'の後の、5バイトデータを受信することができませんでした。
⇒LCDに何も表示されない + 5バイトデータの一致判定プログラム(Errorなら赤色LED、Errorが無ければ緑色LED)で確認

この時間を5msecに変更したところ、5バイトデータの一致判定プログラムまで進み、
Errorが無い(緑色LEDが500msecで点滅する)ことを確認することができました。

ただ、データを連続して受信することができません。
次の'S'、'S'受信まで行っているのですが、再びLEDに5バイトのデータが受信されません。

そこで、Errorが無いときに確認していた緑色のLEDの点滅周期を5msecに変更しました。
そしたら、連続してデータを受信することができ、送信側のデータに応じた動作(LED点灯)を行うことができました。


以上を踏まえて、何点か質問をさせてください。

@今の状態では根本的な解決になっておらず、送信側のデータに応じた動作(今はLEDを点灯するだけ)の時間が長くなると、同じような不具合(連続してデータを受信できない)が発生してしまいます。
 動作にdelay時間を設けてしまうと、受信できないのは何故でしょうか?


ABuf1[]内のでーたが"ffff"や"ffe8"になってしまうのは何故でしょうか?
先程の投稿でもお伝えしましたが、Xbeeを接続して、XCTUで送信データを確認してみると、送信側は02 00 00 00 00 の5バイトのはずですが、
LCDに表示されるデータが違ってしまいます。
(ただ、この表示のデータでも、送信側のデータに応じた動作はできていますので、私のLCD表示プログラムがおかしいのでしょうか。)
//Buf1[]内の数字を0〜4まで変更してLCDにデータを表示させました。
//Buf1[0]=02
//Buf1[1]=ffff
//Buf1[2]=ffe9 or ffea or ffe8
//Buf1[3]=00
//Buf1[4]=17


B初歩的な質問ですみません。
 LCDにBuf1[]の5バイト分を1行に表示させる場合、どのように記述すれば良いのでしょうか?  
今は、↓のように[]内の数字を変えて1つずつ確認しています。
sprintf(buff1,(const far rom char *)"Data=%02x",Buf1[1]);
lcd_cmd(0x80); //1行目へ移動
lcd_str(buff1);



5バイトデータ受信後のプログラムです。
照合一致(3 緑LED点灯、消灯)はコメントアウトしました。


void MotorControl(void)
{


/*** 2連送照合比較一致の場合のみ制御実行***/
Error = 0; // エラーフラグリセット
for(i=0; i<5; i++){
if(Buf1[i] != Buf2[i]) // 比較実行
{
Error = 0xFF; // エラーフラグオン
LED_R ^= 1; // 赤LED点滅
delay_ms(100);
}
}
if((Error == 0) && (RcvData == 'E')) // 照合一致か?
{
//LED_G = 1; // 3 緑LED点灯
//delay_ms(500);
//LED_G = 0; // 3 緑LED消灯
//delay_ms(500);


Direction = (int)Buf1[0]; // 方向セット
MLdata = (int)Buf1[1] * 256 + (int)Buf1[2];
MRdata = (int)Buf1[3] * 256 + (int)Buf1[4];
// 制御実行
switch(Direction) // 方向チェック
{
case 0:
//MLReverse(MLdata); // 後進の場合
//MRReverse(MRdata);
LED_G=1;
delay_ms(5);
//LED_G=0;
//delay_ms(500);
break;
case 1:
//MLFeed(MLdata); // 前進の場合
//MRFeed(MRdata);
LED_W=1;
delay_ms(5);
//LED_W=0;
//delay_ms(500);
break;
case 2:
MLStop(); // 停止の場合
MRStop();
LED_R=1; //4 赤LED点灯
delay_ms(5);
//LED_R=0; //4 赤LED消灯
//delay_ms(500);
break;
default: break;
}
}
}

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |

- WebForum -