トピック関連記事
48時間以内の記事は New Mark で表示されます
制御分について
皆さんこんばんは。

maboさん、以前、
セレクターSWを使って、3軸の選択や、1/10mm、1/100mmの選択をできるプログラムを頂きまして、
感謝申し上げます。
当時の頂いたプログラムは、抜粋ですが、以下の通りです。

プログラムを眺めていて思った点があります。
IF文の条件式についてです。

条件式を判断した結果を真偽値というのだそうです。
答えは、1か0のどちらかで、1が真、0が偽だそうです。

そう思って、プログラムを見ると、
maboさんのプログラムは、
if (条件式1) {
処理1
} else if (条件式2) {
これが使われています。

セレクターSWの場合、ここまで、複雑にしなくてもいいと思うのですがいかがでしょうか?

1か0だけであれば、
もっと単純に
if (条件式) {
条件が成立するときの処理A
} else {
条件が成立しないときの処理B
}
このような感じでもいいと思うのですが、如何でしょうか?
ご気分を悪くしないでください。
自分のレベルを上げたい一心です。
宜しくお願いします。


当時、いただいたプログラムは今も大活躍をしています。

// メイン関数
void main (void){

// 1,2,17,18端子を入出力端子に設定
CMCON = 0x07;

// 電圧レベルの初期設定
PORTA = 0x00;
PORTB = 0x00;

// 入出力設定
TRISA = 0b11111111;//全部入力
TRISB = 0b10000000;//全部出力

//int 型の sw という変数を宣言
int sw0;
int sw1;
int sw2;
int sw3;
int sw4;
int sw5;
int sw6;

// 永久ループ
while(1){
//RA0*****************************
if(RA0 == 0){
WaitTime (500);// 待ち時間関数の呼び出
if(RA0 == 0){//もう一度確認する。
//PORTB=0x00;
RB0 = 1;// LED1点灯
sw0=1;//スイッチがおされた
}
}
else {
WaitTime (500);// 待ち時間関数の呼び出し(約10m秒:チャタリング対策)
if(sw0==1 && RB0==1){
RB0 = 0;// LED1消灯
sw0=0;
}
}
以下、上記と同じようにRA1、PR2〜 ず〜っと、制御文が並んでいます。
TR 2018/12/20(Thu) 20:13 No.1352
Re: 制御分について
TRさん,こんばんは。

>セレクターSWの場合、ここまで、複雑にしなくてもいいと思うのですがいかがでしょうか?

なぜそんなプログラムにしたのか,忘れている部分もあるのですが,

while(1)のなかで,条件判断と処理をしてますので,

同じ処理を2回しないためとチャタリング対策のためかな,

と思い出してます。



elseのなかで,

if(sw0==1 && RB0==1){
RB0 = 0;// LED1消灯
sw0=0;

としているのは,スイッチが押されてない時に,

何回もLEDを消す動作をするのを避けるためだと思います。

LEDを消す動作は,LEDがONの時だけすればいいので,

こんな表現したのかもしれませせん。

ただ,else のなかでの処理ですので,

if(sw0==1 && RB0==1)

じゃなくて,

if(RB0==1)

でも,十分だったかもですね。

私のなかでは,電灯を消すのに,消えているにもかかわらず,

何回もOFFのスイッチを押すのが,好みでないようです。

多分,結果的には,あまり変わらないと思います。


それと,私の思考が堅いせいなのか,

考えられる条件の組み合わせを,

列挙しないと気が済まないようなところがあります。

そのくせ,肝心のところが抜けたりで,苦労するのですが・・・・・・(笑)。



ただ,TRさんのおっしゃるように,あまりいいプログラムでは,ないですね。

猛牛ロックさんにも多分,ご指摘受けたと思いますけど,

WaitTime (500);を使ってチャタリングを防止しようとしてますので,

その間,何もできないことになります。

割り込み等を使って,判断した方がよかったかもしれませんね。
mabo   2018/12/20(Thu) 23:55 No.1353
Re: 制御分について
> そう思って、プログラムを見ると、
> maboさんのプログラムは、
> if (条件式1) {
> 処理1
> } else if (条件式2) {
> これが使われています。

どう見ても、使われていないのですけど、後半部のプログラムは、TRさんが変更した後のものでしょうか?


> セレクターSWの場合、ここまで、複雑にしなくてもいいと思うのですがいかがでしょうか?
>
> 1か0だけであれば、
> もっと単純に
> if (条件式) {
> 条件が成立するときの処理A
> } else {
> 条件が成立しないときの処理B
> }。

セレクタスイッチならば駄目です。

if(1番がONなら)選択番号=1;
else if(2番がONなら)選択番号=2;
else if(3番がONなら)選択番号=3;
else if(4番がONなら)選択番号=4;

のような処理になります。条件式は真か偽で判断されますけど、行いたい事が2択で判断できるわけではありません。
勿論、「スイッチが押されたら」の逆は「スイッチが押されていない」なので、そういった「それ以外」という判断で充分なら
「else」のみになります。


で、このプログラムの内容的には、ポートAがSW、ポートBがLEDで、押されている時は〜、というプログラムですね。
となると、基本的にはチャタリング対策は不要です。
一番シンプルなのが

while(1){
PORTB=(PORTB&0x80)|(~PORTA&0x7F);
__delay_ms(1);//無くても良い
}

です。処理的には一番早く、合理的です。ただし、慣れていないと使いにくいです。
なので、

while(1){
RB0=!RA0;
RB1=!RA1;
RB2=!RA2;
RB3=!RA3;
RB4=!RA4;
RB5=!RA5;
RB6=!RA6;
}

と並べた方が良いかもしれません。
ただし、LATレジスタを使わないと誤動作するかもしれません。
猛牛ロック   2018/12/21(Fri) 12:41 No.1354
Re: 制御分について
原文の方、失礼をしました。

変えようとしている途中のものでした。

正しくは以下の通りです。

// 永久ループ
while(1){
//RA0*****************************
if(RA0 == 0){
WaitTime (500);// 待ち時間関数の呼び出
if(RA0 == 0){//もう一度確認する。
//PORTB=0x00;
RB0 = 1;// LED1点灯
sw0=1;//スイッチがおされた
}
}
else {
WaitTime (500);// 待ち時間関数の呼び出し(約10m秒:チャタリング対策)
if(sw0==1 && RB0==1){
RB0 = 0;// LED1消灯
sw0=0;
}
}



猛牛ロックさんの変えたプログラムですが、
過日、教えて下さったですね。思い出しました。

Bを反転しAに代入する意味でした。
これはいいですね!
でもよく見ると、似た記号がありますね。
比較演算子
A!=B
AとBは等しくない。

猛牛ロックさんのプログラムを記録しておいて、現行プログラム済みPIC16F627Aの不慮の出来事に備えたいと思います。

実は、なんで、こういった事をしていたかというと、
1/100mmのモニター用LEDが点灯しなくなりました。
で、基盤を見たんですよ、勿論、プログラム済みPICも動作を確認しました。
ま〜、原因は、断線でした。
でも、自作して正解でしたと、つくづく思いました。
既製品でしたら、自分レベルでは、買い替えです。
でも、自作なので、原因を調べられますからね。


写真は、実機に使用中のセレクターSWです。


追記
16F88の場合、LATAだと、エラーを起こします。
ANS0という記載ならOKですが、如何でしょうか?

TR   2018/12/21(Fri) 18:44 No.1355
Re: 制御分について
88はLATレジスタがなさそうですね。
TR   2018/12/21(Fri) 21:30 No.1356
Re: 制御分について
TRさん,猛牛ロックさん,こんばんは。

猛牛ロックさん,相変わらず,適切なアドバイスありがとうございます。

TRさん,16F88は,LATレジスタないと思います。

ですので,もしエラーになるようなら,間にアセンブラで,

nopをいれてやればいいようです。

 asm("nop");→何もしない休みの時間です。

間に,

 __delay_ms(1);

でもいいかもですね。




それと以前ポートをそれぞれに操作して,

思った結果がでないことがありました。

 RA0=1;

はまともにうごかなくて,

 PORTA=0b00000001;

のように書いたらまともに動いたことがあります。
mabo   2018/12/21(Fri) 23:33 No.1357
Re: 制御分について
maboさん、猛牛ロックさんこんばんは。

>__delay_ms(1);


気持ちって感じなんでしょうか?


で、素人考えですが、
セレクタSWの場合、チャタリング対策不要ということ。

88に、デジタル用出力として、LATレジスタがないとしたら、
RB6とかしてもいいんじゃないかと思います。
それだけ、88の動作速度が、最新型にあるLATレジスタを必要とするほど、早くないっていうことだと推測します。

ネット検索してもまだ、はっきりとはしません。
TR   2018/12/22(Sat) 18:30 No.1358
Re: 制御分について
TRさん,猛牛ロックさんこんばんは。

私もよく分からないところあるのですが,

要は,レジスターの連続した操作をした場合,不具合が起きる可能性がある,ということだと思います。

>RB6とかしてもいいんじゃないかと思います。

16F88の場合,LATレジスタありませんので,今までのレジスタを使うことになりますけど,

while(1){
RB0=!RA0;
RB1=!RA1;
RB2=!RA2;
RB3=!RA3;
RB4=!RA4;
RB5=!RA5;
RB6=!RA6;
}

のように,連続して,レジスタを使うとだめな場合がある,
ということだと思います。

内部クロック等を使用の場合は,影響は,少ないかもしれませんが,

外部クロック等を使って,クロックをあげるとその可能性大だと思います。

その際は,

while(1){
RB0=!RA0;
asm("nop");(4MHzの場合1μs)
RB1=!RA1;
asm("nop");
RB2=!RA2;
asm("nop");
RB3=!RA3;
asm("nop");
RB4=!RA4;
asm("nop");
RB5=!RA5;
asm("nop");
RB6=!RA6;
}

のようにしただけで,うまくいったということ経験してます。

asm("nop");

は,ワンクロック待つということですの,

(これ正確には間違いですね。NOPは何もしないという命令ですので。)******追記

 __delay_ms(1);

より遙かに短い時間です。
mabo   2018/12/22(Sat) 22:56 No.1359
Re: 制御分について
> セレクタSWの場合、チャタリング対策不要ということ

いえいえ、セレクタSW自体にはチャタリング以外に、ショーティング/ノーショーティングタイプの問題もありますから
難しいです。
但し、「ボタンを押している間は〜」という理屈も成り立ちます。

LEDレベルの切り替えなら、ノイズによる誤動作も気づかないうちに通り過ぎて元に戻りますから対策は不要です。
けれども、そのセレクタスイッチが大きなシステムの変更ならば、ちゃんと対策すべきです。


> 88の動作速度が、最新型にあるLATレジスタを必要とするほど、早くないっていうことだと推測します。

どの位の速度から誤動作をするのかは判りませんけど、どのデバイスでも遅く動かせば問題は発生しません。
また、LATレジスタが存在しないデバイスでもその問題は起こり得ます。

最近の電子工作も、それなりの能力が無いとデバイスを制御出来ません。
例えば、最近人気のマイコン入りLED(ネオピクセル)WS2812B等の制御はF88あたりでは無理です。
F1827でもかなりきついと思います(でも、最適な値を見つければ多分動く)。UNOやPIC18(16MIPS)でなんとか(勘でプログラムすれば動く)、というレベルだと思います。
勿論、F88やF1827でも大多数のものは制御可能ですけど、時代が進むにつれ、周辺デバイスも変化していきますから、
だんだんと扱えないものの割合も増えることになります。

> __delay_ms(1);

__delay_us(1)で充分でしょうね。
前述のLEDは下の感じの制御になります。
この範囲に制御するのはある程度、速度のあるマイコンじゃなくては無理です。
そして、__deley_us(1)なんてしていたら、全く制御出来ません。
何クロック休むか(asm("nop"))、です。
(でも、実際には分岐命令が入りこみますから、そこが難しい所なのです)

T0H 0 code ,high voltage time 0.4us ±150ns
T1H 1 code ,high voltage time 0.8us ±150ns
T0L 0 code , low voltage time 0.85us ±150ns
T1L 1 code ,low voltage time 0.45us ±150ns
(WS2812のデータシートより)
猛牛ロック   2018/12/23(Sun) 02:29 No.1360
Re: 制御分について
皆さんおはようございます。

>asm("nop");

この意味を調べて分かりました。
使い方は、ICの応答待ちというのが狙いなんですね。
ワンクロック待ちというというので、飽くまでも、決まった時間を待つのかと思っていましたが、
ICの動作を待つという意味だったんですね。

>、「ノンショーティングタイプ」
すっかりと忘れていた言葉です。(笑

調べて思い出しました。
maboさんが以前に言っていたと思い出しました。


追記
早速 OSCCONレジスタも弄って4MHZに設定しました。
TR   2018/12/23(Sun) 07:35 No.1361
Re: 制御分について
> ICの動作を待つという意味だったんですね。

いいえ、違います。16Fなら1サイクル=4クロック消費します。
単に何もするな、という命令です。
表には出なくても、よく使われる命令です。
__delay_ms()や__delay_us()はこのnop命令を指定時間行います。
で、何回すれば、その指定時間かはコンパイラが解らないので、F_CPUや_XTAL_FREQなど、
どの位の駆動クロックかを記述しないとdelay命令が出来ません。


ICの動作を待つ、ということではありません。
猛牛ロック   2018/12/23(Sun) 10:20 No.1362

処理 記事No 暗証キー

- JoyfulNote v6.02 -
++ Edited by Hamel ++