ページ 11

Hブリッジ制御について

Posted: 2015年10月20日(火) 17:05
by C素人
Hブリッジ回路の制御について質問です。
回路構成は次の通りです。
Vcc Vcc
| |
| |
| |
FET1 FET2
| |
| |
| |
-------MOT-------
| |
| |
| |
| |
| |
FET3 FET4
| |
| |
| |
GND GND

4つのポートでマイコンから各FETを制御します。
//MOTリセット
LATCbits.LATC0= 0 or 1; FET1
LATCbits.LATC1= 0 or 1; FET2
LATCbits.LATC2= 0 or 1; FET3
LATCbits.LATC3= 0 or 1; FET4


2つのSwitchの状態に応じて、次の通り動作させようとしています。
SW両方がON: ブレーキ
SW1がON、SW2がOFF: CW回転
SW1がOFF、SW2がON: CCW回転
SW両方がOFF: 前の状態を保持

このコードでSWに対応した動作を行うことはできますが、次の課題があります。
swの状態が切り替わるタイミングで、一度各FETを0に設定したい。(理由は、FET1/3及びFET2/4の同時ONを防ぎたいため)
次のコードをcase分の中に書くと、MOTリセットも無限ループで繰り返されてしまいます。
一度だけ、MOTをリセットして、swの状態に応じたモータ動作を行うためにはどうすれば良いのでしょうか。

//MOTリセット
LATCbits.LATC0= 0; FET1 OFF
LATCbits.LATC1= 0; FET2 OFF
LATCbits.LATC2= 0; FET3 OFF
LATCbits.LATC3= 0; FET4 OFF

コード:

st=0;
left=0;
right=0;
delay_ms(100);

 while(1){	  
	sw = PORTB & 0x03;
	switch(sw){
		case 0:	
			LATCbits.LATC0= 1;  //FET1 ON
			LATCbits.LATC1= 1;  //FET2 ON
			LATCbits.LATC2= 0;  //FET3 OFF
			LATCbits.LATC3= 0;  //FET4 OFF
			st=1;
			left=0;
			right=0;
			delay_ms(30);
			break;
		case 1:	
			LATCbits.LATC0= 1;  //FET1 ON
			LATCbits.LATC1= 0;  //FET2 OFF
			LATCbits.LATC2= 0;  //FET3 OFF
			LATCbits.LATC3= 1;  //FET4 ON
			left=1;
			delay_ms(30);
			break;
		case 2:	
			LATCbits.LATC0= 0;  //FET1 OFF
			LATCbits.LATC1= 1;  //FET2 ON
			LATCbits.LATC2= 1;  //FET3 ON
			LATCbits.LATC3= 0;  //FET4 OFF
			right=1;
			delay_ms(30);
			break;
		case 3:	
			if (st==1){
			LATCbits.LATC0= 1;  //FET1 ON
			LATCbits.LATC1= 1;  //FET2 ON
			LATCbits.LATC2= 0;  //FET3 OFF
			LATCbits.LATC3= 0;  //FET4 OFF
				st=0;
			}
			else if (left==1){
			LATCbits.LATC0= 1;  //FET1 ON
			LATCbits.LATC1= 0;  //FET2 OFF
			LATCbits.LATC2= 0;  //FET3 OFF
			LATCbits.LATC3= 1;  //FET4 ON
				left=0;
			}
			else if (right==1){
			LATCbits.LATC0= 0;  //FET1 OFF
			LATCbits.LATC1= 1;  //FET2 ON
			LATCbits.LATC2= 1;  //FET3 ON
			LATCbits.LATC3= 0;  //FET4 OFF
				right=0;
			}
				break;
		default:break;
          }
    }

Re: Hブリッジ制御について

Posted: 2015年10月20日(火) 17:27
by みけCAT
スイッチの状態が変化した時だけ切り替えを行えばいいでしょう。

コード:

prev_sw=4;
delay_ms(100);

while(1){	  
	sw = PORTB & 0x03;
	if(prev_sw != sw && sw != 3) {
		//MOTリセット
		LATCbits.LATC0= 0;  //FET1 OFF
		LATCbits.LATC1= 0;  //FET2 OFF
		LATCbits.LATC2= 0;  //FET3 OFF
		LATCbits.LATC3= 0;  //FET4 OFF
		switch(sw){
			case 0:	
				LATCbits.LATC0= 1;  //FET1 ON
				LATCbits.LATC1= 1;  //FET2 ON
				LATCbits.LATC2= 0;  //FET3 OFF
				LATCbits.LATC3= 0;  //FET4 OFF
				break;
			case 1:	
				LATCbits.LATC0= 1;  //FET1 ON
				LATCbits.LATC1= 0;  //FET2 OFF
				LATCbits.LATC2= 0;  //FET3 OFF
				LATCbits.LATC3= 1;  //FET4 ON
				break;
			case 2:	
				LATCbits.LATC0= 0;  //FET1 OFF
				LATCbits.LATC1= 1;  //FET2 ON
				LATCbits.LATC2= 1;  //FET3 ON
				LATCbits.LATC3= 0;  //FET4 OFF
				break;
			default:break;
		}
		delay_ms(30);
	}
	prev_sw = sw;
}
※テストしていません

Re: Hブリッジ制御について

Posted: 2015年10月20日(火) 17:52
by c素人
ありがとうございます。
理解が悪くてすみません。

次の部分をもう少し噛み砕いて教えていただけると助かります。


if(prev_sw != sw && sw != 3)

Re: Hブリッジ制御について

Posted: 2015年10月20日(火) 22:16
by みけCAT
「直前にチェックした時のスイッチの状態と今のスイッチの状態が違っていて、かつ今のスイッチの状態が3(前の状態を保持)でないなら」という意味です。

Re: Hブリッジ制御について

Posted: 2015年10月21日(水) 07:54
by c素人
みけCAT様

返信ありがとうございます。
2つ確認をさせてください。

①prev_sw=4; としているのは、
swの状態が0,1,2,3のいずれでもない状態、つまり4を初期値としておけば、最初に必ずリセットされるから。という理解で良いでしょうか。

②いただいたコードにcase3が含まれていませんでしたが、
次の通り、case3を含めたコードでも問題ないですよね。

コード:

st=0;
left=0;
right=0;
prev_sw=4;
delay_ms(100);
 
while(1){     
    sw = PORTB & 0x03;
    if(prev_sw != sw && sw != 3) {
        //MOTリセット
        LATCbits.LATC0= 0;  //FET1 OFF
        LATCbits.LATC1= 0;  //FET2 OFF
        LATCbits.LATC2= 0;  //FET3 OFF
        LATCbits.LATC3= 0;  //FET4 OFF
        switch(sw){
            case 0: 
                LATCbits.LATC0= 1;  //FET1 ON
                LATCbits.LATC1= 1;  //FET2 ON
                LATCbits.LATC2= 0;  //FET3 OFF
                LATCbits.LATC3= 0;  //FET4 OFF
                break;
            case 1: 
                LATCbits.LATC0= 1;  //FET1 ON
                LATCbits.LATC1= 0;  //FET2 OFF
                LATCbits.LATC2= 0;  //FET3 OFF
                LATCbits.LATC3= 1;  //FET4 ON
                break;
            case 2: 
                LATCbits.LATC0= 0;  //FET1 OFF
                LATCbits.LATC1= 1;  //FET2 ON
                LATCbits.LATC2= 1;  //FET3 ON
                LATCbits.LATC3= 0;  //FET4 OFF
                break;
	    case 3:	
		if (st==1){
		LATCbits.LATC0= 1;  //FET1 ON
		LATCbits.LATC1= 1;  //FET2 ON
		LATCbits.LATC2= 0;  //FET3 OFF
		LATCbits.LATC3= 0;  //FET4 OFF
		st=0;
		}
		else if (left==1){
		LATCbits.LATC0= 1;  //FET1 ON
		LATCbits.LATC1= 0;  //FET2 OFF
		LATCbits.LATC2= 0;  //FET3 OFF
		LATCbits.LATC3= 1;  //FET4 ON
		left=0;
		}
		else if (right==1){
		LATCbits.LATC0= 0;  //FET1 OFF
		LATCbits.LATC1= 1;  //FET2 ON
		LATCbits.LATC2= 1;  //FET3 ON
		LATCbits.LATC3= 0;  //FET4 OFF
		right=0;
		}
		break;
            default:break;
        }
        delay_ms(30);
    }
    prev_sw = sw;
}

Re: Hブリッジ制御について

Posted: 2015年10月21日(水) 08:59
by みけCAT
c素人 さんが書きました:①prev_sw=4; としているのは、
swの状態が0,1,2,3のいずれでもない状態、つまり4を初期値としておけば、最初に必ずリセットされるから。という理解で良いでしょうか。
はい。
ただし、最初のswが3かもしれないので、ループに入る前に出力を適切に設定した方がいいでしょう。
c素人 さんが書きました:②いただいたコードにcase3が含まれていませんでしたが、
次の通り、case3を含めたコードでも問題ないですよね。
  • sw != 3という条件が入っているので、case 3は(swが割り込みハンドラなどでちょうどif文を過ぎた後switch文に入る前に書き換えられなければ)実行されません
  • もしもcase 3が実行されても、st, left, rightは割り込みハンドラなどで書き換えられなければ常に0なので、case 3では実質何もしません
という理由により意味の無いコードですが、プログラムメモリを無駄に消費する可能性がある以外は問題はないでしょう。

Re: Hブリッジ制御について

Posted: 2015年10月21日(水) 09:26
by c素人
みけCAT様

返信ありがとうございます。
度々すみません。2つ確認をさせてください。

[確認1]
実際に確認してみましたが、
sw != 3という条件が入ることで、前の状態が保持されていることに驚きました。
case3は、実質何も役をなしていないのですね。

この部分の理解ですが、

例えば、
case1 (SW1がON, SW2がOFF)の状態から、SW1, SW2が共にOFFとした場合、

sw=3の状態となるので、
MOTリセットは行われず、
switch文の中の処理も、
default: break; となっているので、何も処理されない(=つまり、case1の状態が保持される)

このような理解で正しいでしょうか。

[確認2]
次のコメントを頂きましたが
"ただし、最初のswが3かもしれないので、ループに入る前に出力を適切に設定した方がいいでしょう。"

これは、頂いたコードのように、
while(1)の前で、
prev_sw=4; と設定してあるので、最初のswが3でも問題ないですよね。

Re: Hブリッジ制御について

Posted: 2015年10月21日(水) 12:44
by みけCAT
c素人 さんが書きました:例えば、
case1 (SW1がON, SW2がOFF)の状態から、SW1, SW2が共にOFFとした場合、

sw=3の状態となるので、
MOTリセットは行われず、
switch文の中の処理も、
default: break; となっているので、何も処理されない(=つまり、case1の状態が保持される)

このような理解で正しいでしょうか。
惜しいです。
MOTリセットは行われないはずですが、そもそもsw != 3が偽なので、switch文自体が実行されません。
よって、「default: break; となっているので」は誤りです。
c素人 さんが書きました:次のコメントを頂きましたが
"ただし、最初のswが3かもしれないので、ループに入る前に出力を適切に設定した方がいいでしょう。"

これは、頂いたコードのように、
while(1)の前で、
prev_sw=4; と設定してあるので、最初のswが3でも問題ないですよね。
問題ないかは使用しているマイコンの仕様(リセット時のポートの初期値)やコードのこの部分より前の(初期化?)処理によります。
実際の回路で実行してみて壊れなければ問題ないと言えるかもしれません。
しかし、swが3の時はこのループ中ではポートの操作は行われないため、「while(1)の前で、prev_sw=4; と設定してあるので、最初のswが3でも問題ないですよね。」という理由付けは誤りです。
ループに入る前にポートの出力を適切(例えば全てのFETをOFF)に設定した方がいいでしょう。

Re: Hブリッジ制御について

Posted: 2015年10月21日(水) 15:13
by c素人
みけCAT様

返信ありがとうございます。
if文の範囲について、教えてください。

[その①]
if(prev_sw != sw && sw != 3) {
//MOTリセット
LATCbits.LATC0= 0; //FET1 OFF
LATCbits.LATC1= 0; //FET2 OFF
LATCbits.LATC2= 0; //FET3 OFF
LATCbits.LATC3= 0; //FET4 OFF
}

この範囲でif文を閉じてしまった場合、
保持される動作の考えとして、次の考えで正しいでしょうか。

例えば、
case1 (SW1がON, SW2がOFF)の状態から、SW1, SW2が共にOFFとした場合、

sw=3の状態となるので、
MOTリセットは行われず、
switch文の中の処理も、
default: break; となっているので、何も処理されない(=つまり、case1の状態が保持される)



[その②]
if文を閉じるところを、
次の場所にした場合(みけCAT様から教えていただいたコード)
この場合は、みけCAT様がおっしゃる通り、switch文の処理にすら入らないということが理解できました。

prev_sen = sen;
}
}

その①、②共に動作確認していますが、同じように動作できているように見えます。

Re: Hブリッジ制御について

Posted: 2015年10月21日(水) 18:26
by みけCAT
その①の考えは正しそうだと思います。

Re: Hブリッジ制御について

Posted: 2015年10月21日(水) 18:47
by c素人
みけCAT様

ありがとうございました。
大変勉強になりました。