046466
48時間以内の記事は New Mark で表示されます
大晦日のご挨拶

今年もいよいよ終わりですね。
大変お世話になりました。

今年は例年になく、あっという間に終わったって感じがします。
お陰様で、病気や怪我もなく過ごせました。

今日は、最後の大掃除、適当にやって、後は好きな事でもやります。

それから、モーターのPWM制御ですが、写真がそれです。一応、完成としました。
以前のものは、秋月のPWMキットと、SEC基板からの信号を受けるボードの2枚が必要で、大きなものでしたが、
PICにより、便利になり且つ、小さくなりました。
これも、皆様方のお陰です。
来年も宜しくお願いします。

TR 2018/12/31(Mon) 08:13 No.1406  記事編集
Re: 大晦日のご挨拶
私の疑似手パの方は、一応、完成目前です。
あと残るのは
・若干のコードの書き換え
・表示シール
・USBケーブル(1.5mのケーブルだとちょっと短かったので3mのを発注)
位になりました。

動作確認をしたのですけど、例えば1クリックあたり1mmや0.1mmだと
速く回すとバッファに溜まった分が、ダイヤル停止後もマシンが動きます

この辺りがやりにくいように感じました。
というか、1mmのレンジは逆に誤動作に繋がりやすいので付けない方が賢明でした。
MABOさんの手パはその辺りはどうなっているのでしょうか?

私はその位置(1mmのレンジを予定していたスライドスイッチ位置)は疑似パワーオフ=操作不可にしようかと思っています。


それと、ダイヤルを回すと↑→などのキーを送っているのですけど、STEP指定は送っていません。
デフォルトでSTEPにしているからです。
でも、途中で、PC画面上でCONTに切り替えた場合に、切り替えた事を、疑似手パが判っていないのでCONTモードに
なってしまっています。
そのあたりの、例えば
・前回動作から1秒以上経過していてダイヤルが回ったらSTEP指定のコードを入れる&誤動作防止の為に
 1クリック目は回さない
 つまり、前回から1秒経過していたら、最初のクリックはSTEP指定を入れて、経過していなければ動かすキーコードをいれる
という対処にしようと思います。
ていうか、その部分のコードは既に書き換えました。疑似パワーオフの方は全体を見なければならないのでまだです。

もう一つ残念な点は、おもちゃエンコーダなので、ダイヤルを付けると径が大きくてクリック感が少なくなります。
そうなると、回りやすくなってしまい、誤動作に繋がりやすいと思います。
なので、自分で割りを入れて、停止位置を作るかもしれません。でも、それは後に置いといて、取りあえずそのまま使おうと思います。


いやー、実は新PCの方なのですけど、使っていたら何故かMACHが立ちあがらなくなってしまって、
「MACH3を起動すると同時にPCが再起動する」、という現象に見舞われました。
PCとしては何の異常も感じられずサクサク動きます。
で、パラレルドライバやMACHの再インストール等をしてなんとかMACHを起動させるところまで行っても、
何故か軸は動かない(けれども、リミットスイッチ等は反応している)という状況でした。
で、パラレルドライバ?を違う設定に変えたら、またPCの再起動になったり…と、堂々巡りです。
結局、OSのリカバリーから始めて、前のPCに付いていたグラフィックボードを取り付けたら安定しました。

その後に、手パの基板切削やダイヤル部の加工などを、テストを兼ねてしていたのですけど、その間は何も問題無しです。


プログラム上で一番困難だったのは、文字コード→キーコード変換でした。
送った2バイトのコードはMACH3に付いているSCREEN4で、ホットキー入力の時に確認できるのですけど、
実際に、マイコンから送られるコードが、ちょくちょくそれと一致しないんですよね。
特にCtrl+Altを使うと全然違うキーコードが生成されたりします。
ALTだけでも、例えばMACH3の停止(STOP)はALT+Sキーですけど、
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press('s');
とSが小文字の方じゃないと駄目だったりです。
マイコンからは、コードを書いてマイコンに書き込んで、SCREEN4のその画面で試して同じ数字になるかを確認、
みたいなことをしないと何番を実際に送っているのか判らないので大変でした。
また、WINDOWSやMACH3自体に使われているショートカットキーがはっきりしないので、どのキーに割り当てていいのか?という部分が
思いのほか手間取りました。

探せばどこかに一覧表みたいなものがあるのでしょうか?

まぁ、思わぬ所に落とし穴はあるものです。

猛牛ロック   2018/12/31(Mon) 10:06 No.1407 記事編集
Re: 大晦日のご挨拶
完成まじかまで来てよかったですね。
猛牛ロックさんならできるのでしょうけど、凄いですよ。

ちょっとだけ教えてください。

No.1386で、
>実際は前の数行の内の50→50.0と「.0」を付けてほしい、と言う事です。
と言っていますが、どうして0を付けないといけないのでしょうか?
宜しくお願いします。


追記
ネットで「浮動小数点」で検索したら、ありました。
コンピューターの世界のことのようですね。
桁数あふれを起こさないように、小数点以下第1位の0を付けて計算させた訳ですね。
TR   2018/12/31(Mon) 11:50 No.1408 記事編集
Re: 大晦日のご挨拶
これにはintが何ビットなのか、つまり何ビットを標準にしているコンパイラなのか?という問題があります。
ウィンドウズのCコンパイラなら大抵は32bitですけど、8ビットマイコンのコンパイラは大抵は、16bitがint=基準となる
整数の型です。XC8もintは16bitです。

で、計算する過程は標準で16bitまでの計算になります。つまり計算用に16bitのメモリが用意されます。
例えば
unsigned char a=256*256/512;
とした場合、通常の計算なら128ですけど、256*256の計算ですでに0x10000(65536)なので、0x「1」0000の
1はメモリ範囲外になるので消えて0になります。つまり0/512でaが0になります。
※ただしこの式の場合は、マイコンには計算式は入らす、コンパイル過程で、すでに「256*256/512」を計算して
元々unsigned char a=128;と書かれているプログラムとして、コンパイルされると思います。256が変数として考えてください。

long a=
とした場合は最初から32bitが計算用のメモリとしてあてがわれます。

計算順序は四則演算はおおよそ普通の計算と同じです。
()カッコが付いている部分が優先され、次に*/%が優先され、次に+-で最後は=です。
そして、x/%+-は左から右に計算されます。=は右から左です。

num=(num-50)*(1023-500)/(1023-50)+500;
は、ちょっと変形(計算)すると
num=(num-50)*523/973+500;
なので、最初の(num-50)*523の段階で、numが175程度の段階で桁が溢れます。

あとは暗黙の型変換、というものを理解する必要があります。
charとintとの計算ではintとして計算されます。
intとlongではlongとして計算されます。
charやintやlongとfloatの計算ではfloatとして計算されます。
つまり範囲の広い方で計算されます。

なので、50ならばintとして16bitの整数ですけど、50.0と「.0」を付けるとそれはfloat型の浮動小数のメモリに配置されます。
で、(num-50.0)はfloatとして計算され、次に*523もまたfloat×intなのでfloatとして計算され、…となり、桁あふれにはなりません。
そして、最期の「num=」の時にそのfloat値がintとして変換されて代入されます。
猛牛ロック   2018/12/31(Mon) 13:17 No.1409 記事編集
Re: 大晦日のご挨拶
猛牛ロックさん早速にありがとうございます。

しかし、猛牛ロックさんが今回作った品は、お値段によると思いますが、
興味のある人に売れるんじゃないですか?
USB対応のようですが、自分のスムースステッパーに差し込んで使えるかな〜。
今の手パは、配線が凄いんです。
それと、作品は、自作の基板ですか?
いいですね〜。
自分はユニバーサルですよ。
流石です。
USB接続OKなら、すっきりとしますね。きっと。
TR   2018/12/31(Mon) 14:53 No.1410 記事編集
Re: 大晦日のご挨拶
猛牛ロックさん,TRさん,こんばんは。

===================
今年もおしせまりましたね。

いろいろありがとうございました。

勉強になりました。

来年もよろしくお願いいたします。
=================


*************************
猛牛ロックさん,

>というか、1mmのレンジは逆に誤動作に繋がりやすいので付けない方が賢明でした。
>MABOさんの手パはその辺りはどうなっているのでしょうか?

これ,すみません。私の環境では,確認していません。

というか,CNC等,を含めて,工房が実家の方にあるので,

このところ,いじってないのです。

という訳で,なんともいえないので,申し訳ありません。

それと,

>結局、OSのリカバリーから始めて、前のPCに付いていたグラフィックボードを取り付けたら安定しました。

は,原因はグラフィックボードだったんでしょうかね。

私も,念のためCNC用のPCには,ONボードのグラフィック外して,安いグラフィックボード挿してます。

もう一つ,

>マイコンからは、コードを書いてマイコンに書き込んで、SCREEN4のその画面で試して同じ数字になるかを確認、
みたいなことをしないと何番を実際に送っているのか判らないので大変でした。

察するに,猛牛ロックさんでも,ご苦労なさるんですから,難しいのかなあと思ってます。

ちなみに,くぐってみると,

http://blog-imgs-70-origin.fc2.com/g/a/r/garagejb/mkp13.jpg
http://blog-imgs-70-origin.fc2.com/g/a/r/garagejb/mkp14.jpg
https://blogs.yahoo.co.jp/borog_602/19815995.html

がヒットしました。
****************************


////////////////////////////////////////////////////////
TRさん,完成おめでとうございます。

ご自分で考えられて,それ,実用にしてしまうのですから,

いつも感心させられます。

私は,いつも,発想はいいのですが,途中挫折,

なんていうパターンが多いので,困ります。
mabo   2018/12/31(Mon) 19:50 No.1411 記事編集
PWM/ADリレー無し SWもなし全てプログラム
替えるのは 以下の1行でよろしいですか?

num=(num-50.0)*(1023-500)/(1023-50)+500;
TR 2018/12/29(Sat) 06:47 No.1385  記事編集
Re: PWM/ADリレー
> MABOさん
音量調整以外ではBカーブが良いんじゃないですか?
音量でも、直接のアナログ制御ではなく、マイコンなどに入れるのなら
やはりBカーブが良いと思います。


で、疑似手パですけど、現在、添付画像のようなところまで来ています。
で、見れば解るようにPRO MICROにしました。
でも、作っていて気付いたのですけど、STM32でもピンヘッダを逆向き、つまり、
ブートジャンパーと同じ側に付ければ差し込んだ時に下を向いて何も問題が無い事に気づきました。
いやー、そんな単純な事に気づかなかったとは…(;'∀')

プログラムも初期的な動作は確認しました。
幾つかの点で当初の予定から変更になりそうです。


>TRさん
前の数行の内のその行を差し替えてください。
式は正しかった?のですが、桁あふれが起こったのでしょう。
実際は前の数行の内の50→50.0と「.0」を付けてほしい、と言う事です。

猛牛ロック   2018/12/29(Sat) 07:02 No.1386 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
>前の数行の内のその行を差し替えてください。

確認させてください。
以下でいいのでしょうか?


良い品ができましたね。



while (1) {
if(RB7==0){__delay_ms(10);break;}
LATA0=LATA1=RB7;//SEC基板ポート2のSL-13の1番ピン
num= adconv(); // RB3→RB4から半固定抵抗の値を読み込む
if(num<50){
CCPR1L = 0;
CCP1CONbits.DC1B = 0;
}else{
num=(num-50.0)*(1023-500)/(1023-50)+500;
CCPR1L =num>>2 ;
CCP1CONbits.DC1B = num&3;
}

CCPR1L = num / 4; // アナログ値からのデータでデューティ値を設定
CCP1CONbits.DC1B = num & 0b11;
__delay_ms(10);
}
TR   2018/12/29(Sat) 12:05 No.1387 記事編集
Re: PWM/ADリレー無し
既にif〜else〜でduty比を入れているのですから、もう一度

CCPR1L = num / 4;
CCP1CONbits.DC1B = num & 0b11;

と入れるわけないでしょ。つまり、この部分は不要です。

追伸
とはいえ、もう一度入れてもそれほど大きな影響はないような気がします。
駄目そうなら、
unsigned int num;

long num;
に変えてください。その場合は50.0じゃなくて50が良いです。
ていうか、こちらの対処の方が良いです。


if〜else〜文で添付図のようにしています。
num=(num-50)*(1023-500)/(1023-50)+500;
がなぜ駄目だったのかは、ちゃんと理解した方が良いです。
最初の(num-50)*(1023-500)の計算で、桁あふれ=65535以上になる、
という事です。
なので、32ビットで計算させるか、浮動小数点(float)で計算させるか、をしなければなりません。

猛牛ロック   2018/12/29(Sat) 12:29 No.1388 記事編集
PWM/ADリレー無し S全てプログラム
今やってみました。
完成したばかりの基板です。
VRを絞った状態が凄く不安定です。


CCP1CONbits.DC1B = num & 3;
マスク処理ですか?
この書き方は初めて見た感じです。
でも、2桁だけじゃないのかな〜。


グラフ有難うございます。
良く分かります。

TR   2018/12/29(Sat) 14:01 No.1390 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
> VRを絞った状態が凄く不安定です。
それなら、止める部分はPWMのduty比が0では無く、デジタルにして止めないと駄目かもしれません。

取り敢えずは、if〜else〜では無くelseの部分だけにした方が良いかもしれません。
つまり、

num= adconv();
num=(num-50.0)*(1023-500)/(1023-50)+500;
CCPR1L =num>>2 ;
CCP1CONbits.DC1B = num&3;
__delay_ms(10);

です。

3と0b11と0x3は全く同じです。表記法が違うだけ=人が数えやすい形をそれぞれ作っただけです。
コンピュータにとってはどれも同じです。
猛牛ロック   2018/12/29(Sat) 15:17 No.1391 記事編集
PWM/ADリレー無し S全てプログラム
駄目です。
不安定です。

if(ADRES > 500 ) {//ボリューム50%=500/1000μs
まだ始めて間もない自分なので、間違いかもしれないと思います。
先ず断ります。

自分はこう思いました。
上記が、シンプルでAD変換も早いですし、安定している感があります
この式を思いついたのは、ツールラボさんの AD変換の中で、以下の言葉使い
「さて、500を2進数に変換して、その上位8ビットや下位2ビットを求めるのは面倒ですので、楽な方法でプログラムを書くことにしましょう。」
https://tool-lab.com/make/pic-app-4/
上記ページの中ごろを過ぎたあたりにあります。

それと、PWMの制御ログラム %で制御しています。
https://tool-lab.com/make/pic-app-5/

この考えは、AD変換にも使えると思います。
10ビットには変わりないのでそう思いました。
%は、動作速度を1MHzにすれば、1μs 最大で1000μsの関係があるから、
50%は500と出来ると思いました。


500とすれば、50%×5V=2.5Vのところ、
実験の結果でも、約2.54Vを示しています。
勿論、いっぱい開けたら。約5.1Vです。

追記
スタートを、今からMOSFETのスレッショル電圧に変えます。
スレッショルドでしたっけ?」
TR   2018/12/29(Sat) 16:48 No.1392 記事編集
Re: PWM/ADリレー無し 
ちょっと状況が呑み込めません。

> VRを絞った状態が凄く不安定です。
これは私の書いたグラフで、最初の0のライン=停止部の事を言っているかと思ったのですが、違うのでしょうか?
動き出しの斜めの部分ですか?


> if(ADRES > 500 ) {//ボリューム50%=500/1000μs
おおよそ、「つまみの位置が半分以上なら」という意味合いになりますけど、
何を言っているのか、また言いたいのかは良く判りません。

ちょっとページ検索してみたら、No.1380 の
> @ if(ADRES > 300 ) {
> temp = ADRESH; //上位8bit
> temp = (temp << 8) + ADRESL; //RB3→RB4で読み込んだ値をtempに代入
> return temp;} //読み込んだtempをnumに返す
> }
これの事ですか?
これの意味合いとしては
「もしツマミの位置が約30%以上」ならもう一度つまみの位置を確認する、というコードに見えます。
何処にこのコードを入れるつもりなのでしょうか?


> 上記が、シンプルでAD変換も早いですし、安定している感があります
この「上記」とは「if(ADRES > 500 ) {」のことですか?
これは変換結果=つまみの位置に応じてなにかをしようとしているのではないのですか?
「変換が早い」も「安定」もどこにも要素自体がありませんけど。

また、それ以降も何を言いたいのかさっぱり解りません。

> 「さて、500を2進数に変換して、その上位8ビットや下位2ビットを求めるのは面倒ですので、楽な方法でプログラムを書くことにしましょう。」
なぜこんな言葉がここで出てきたのでしょうか?

> %は、動作速度を1MHzにすれば、1μs 最大で1000μsの関係があるから、
> 50%は500と出来ると思いました
これは10ビット=最大1023の分解能のPWMなので、50%は約500です。動作速度とは関係ありません。


追記します。
今気づきましたけど、No.1387の
> if(RB7==0){__delay_ms(10);break;}
> LATA0=LATA1=RB7;//SEC基板ポート2のSL-13の1番ピン

は、

RB7がLレベルなら再起動。
(それ以外なら、)RA0ピンとRA1ピンをHIGHにする。

という意味合いですけど、これでいいのでしょうか?
猛牛ロック   2018/12/29(Sat) 20:56 No.1393 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
TRさん,猛牛ロックさん,こんばんは。

プログラムの方は,混乱しないように,差し控えます。

プログラムではないのですが,以前,ADCのボリュームと

同じ役目させるのに,オシレーターの制御で,多回転のポテンショメーターを使ったことあります。

これ,どうなんでしょうね。

通常のボリュームより,正確な数値になるような気がしますが。

mabo   2018/12/29(Sat) 21:03 No.1394 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
> MABOさん

私も使った事はありますよ。それと回転数表示付きのツマミですね。
電圧としては安定していますよね。それに細かい制御が出来ます。
けれども多回転すぎるのは使いにくさもありますね。
微調整が利くのとトレードオフです。
私の場合は確か、インバータの外部ツマミとして使いました。
っていうか、元々それが付いていたのですけど、マシンが調子が悪くなって組み直したんです。
で、やはり前に付いていたそのタイプのボリュームが良いと言う事で使いました。

もっとも、今回の件はボリュームの性能とはあまり関係が無いと思っています。
「不安定」の原因がボリュームの読み取りなのか、プログラムの問題なのか、出力先の問題なのか不明です。

ボリュームの読み取りが不安定と言う事が解っていれば、その対処もあるんですけどね。
猛牛ロック   2018/12/29(Sat) 21:38 No.1395 記事編集
PWM/ADリレー無 全てプログラム
>動き出しの斜めの部分ですか?

不安定な部分は、スタートを始めるあたりでした。


>何を言っているのか、また言いたいのかは良く判りません。

私が見たページを見てください。その方が早いと思います。
それとも、見てくださったうえで聞いているのかな〜。
私が感じた点はすべて言いました。これ以上の説明はできません。
なので、紹介したページを見ていただいた方が早いと思います。
申し訳ないです。


> @ if(ADRES > 300 ) {
> temp = ADRESH; //上位8bit
> temp = (temp << 8) + ADRESL; //RB3→RB4で読み込んだ値をtempに代入
> return temp;} //読み込んだtempをnumに返す
> }

紹介したページに、%でプログラムが入っています。
見た方が早いともいます。

私の場合は、ADRESの値が30%以上だったら、読み込むと理解しました。
間違えかもしれませんよ。
でも、いい具合に動いています。

若し見ていないようでしたら、見てください。
拙い自分には、これ以上、猛牛ロックさんのようなレベルの高い人にはうまく説明できません。


>RB7がLレベルなら再起動。
(それ以外なら、)RA0ピンとRA1ピンをHIGHにする。

という意味合いですけど、これでいいのでしょうか?


再起動という表現が正しいのかどうかわかりません。
ただ、自分としては、
SEC基板からの信号とPICの動作が一体となれればいいなと思いました。
その結果が、
> if(RB7==0){__delay_ms(10);break;}
> LATA0=LATA1=RB7;//SEC基板ポート2のSL-13の1番ピン

これです。
実際、RB7に、信号がなければ、止まるし、信号が入れば、動作します。
今までもLEDとSWの関係のプログラムがありましたよね。
それと、猛牛ロックさんに教わったbreak文、これをミックス
したらどうだろうかと思った次第です。
今のところ、RB7とPWM、RA0、RA1は全て同調しています。
TR   2018/12/29(Sat) 22:03 No.1396 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
maboさんこんばんは。

今回、VRも考えました。
手持ちに東京コスモスのいい奴があったので、現在試作中のボードに使ってみました。
でも、思ったんです。
MOSFETの場合、電圧制御なんですよね。
なので、プログラムで、SWを作れるって、
FETのVgsでしたっけ、
調べると、1〜2Vでした。
現在は、目標2Vにしました。
あとは実機につけて、微調整します。
これで、リレーも要らないし、SW代わりのフォトカプラーも要らない。


それと、やっとわかったんですが、
SEC基板のOUTPUTには、信号とGNDがセットになっています。
それは、直接、リレーなどを操作するために、信号線とGNDがセットになっていたんですね。
今回は、SEC基板の端子からは、信号線だけをRB7に繋げます。 その辺、図面が誤っていました。
勿論、電源は、全て一緒。スムースステッパー、SEC基板、今回のボードはすべて同じ電源です。
TR   2018/12/29(Sat) 22:21 No.1397 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
> 不安定な部分は、スタートを始めるあたりでした。
というのは斜めの部分と言う事ですか?平らでは無くて?

> 私が見たページを見てください。その方が早いと思います。
勿論、両方のページを見ていますよ。

で、別にそのページでは%では書いてありませんよ。
っていうか、単に1023の23の部分を切り捨てて単純に考えたい、という意味ですか?

> @ if(ADRES > 300 ) {
> temp = ADRESH; //上位8bit
> temp = (temp << 8) + ADRESL; //RB3→RB4で読み込んだ値をtempに代入
> return temp;} //読み込んだtempをnumに返す
> }

このプログラムを解説すれば、

> @ if(ADRES > 300 ) {
「もしADRESが300より大きければ、」と言う事です。
ADRESレジスタが存在すればそれを読み込みます。
レジスタが無ければ、自分で作った変数でしょうから、前回ADCを読んだ値だと思います。

> temp = ADRESH; //上位8bit
> temp = (temp << 8) + ADRESL; //RB3→RB4で読み込んだ値をtempに代入
2行で、新たにADCの値10bitをtempに代入しています。

> return temp;} //読み込んだtempをnumに返す
問題はここです。そのADC値をリターンして「関数を終わらせます。」なので、どこでこのコードを使うのかが気になったのです。
普通に考えれば、ADCの読み取り関数の部分に書かれているのだと思いますけど、もしかしてここでも再起動させていませんか?
で、自分の作った変数なら、一度300以下になったら更新されないような気がするのですけど?

ちょっと全体のコードを見ないと判断が付きません。

例えば、私のコードで、__delay_ms(10);の部分を10000(10秒)にするとどうなりますか?
つまり、10秒おきに更新しますから、それでその10秒間が安定しないならハードの問題です。=動き出しの力が弱すぎて
モータが回るか止まるかが安定しないのでしょう。もう少し上の数値から行えばいいと思います。
それで、安定しているのなら、ADCの取得値がばらばらと言う事でしょう。


> MOSFETの場合、電圧制御なんですよね。
> なので、プログラムで、SWを作れるって、
> FETのVgsでしたっけ、
> 調べると、1〜2Vでした。
> 現在は、目標2Vにしました。

ちょっと良く判らないのですけど、「SW」とは何の意味でしょうか?
Vgsはゲートに入れる電圧の事です。1〜2Vとは?また、「目標」も何のことを差しているのですか?
もう少し略さずに書いてください。「SWを作れるって、」はどこに繋がるのですか?

「何が」「どうしたか」という部分が理解できません。


> 直接、リレーなどを操作するために、信号線とGNDがセットになっていたんですね。
直接リレーを駆動できるかは別問題です。GNDは必ず必要です。でないと信号線の電圧が解りません。
電圧計(テスター)も2本ありますよね?それと同じです。1本を繋いでも電圧は測れません。
あとはその出力にどの位の駆動能力があるかです。本当の信号のみなのか、LED程度は駆動できるのか、リレーも可能なのか?
ただ、普通はICの出力端子が繋いであるのでLED程度までです。トランジスタアレイあたりが繋がっていればリレーも大丈夫です。

※SEC基板やスムースステッパーの事はかなり忘れています。TRさんのポンプ制御も回路の方はすっかり忘れています。
猛牛ロック   2018/12/29(Sat) 23:11 No.1398 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
割合で書いてあった内容です。
ADCのプログラムでは、10ビット 0〜1023ですよね。
ADRESの判定を次のように記載してありました。

// (ADコンバート値が250未満の場合)
if( ADRES < 250 ) {

一部抜粋
// (ADコンバート値が250未満の場合)
if( ADRES < 250 ) {
timerValue--; // タイマー時間を減らす
// タイマー時間をLEDの点滅回数で表現する
RA5 = 0; // いったんLEDを消して
__delay_ms(500);
// 設定時間分LEDを点滅して、
for(i=0; i<timerValue; i++) {
RA5 = 0;
__delay_ms(200);
RA5 = 1;
__delay_ms(200);
}
RA5 = 0; // ちょっとの間LEDを消して、
__delay_ms(800);
RA5 = 1; // LEDを点灯する
} else {
// タイマー時間を増やすスイッチの処理
// (ADコンバート値が250以上750未満)
if( 250 <= ADRES && ADRES < 750 ) {
timerValue++;// タイマー時間を増やす
// タイマー時間をLEDの点滅回数で表現する
// 点滅制御方法は減らす場合と同じ
RA5 = 0;
__delay_ms(800);
for(i=0; i<timerValue; i++) {
RA5 = 0;
__delay_ms(200);
RA5 = 1;
__delay_ms(200);
}
RA5 = 0;
__delay_ms(800);
RA5 = 1;
}
}
例のようにADRESを1023の内、0〜250としています。
なので、自分も
if(ADRES > 400 ) {//ボリューム40%=400/1000μs

としたんだけど、
//ボリューム40%=400/1000μs 正しくは、
400/1023かな。

でも、5Vからとスレッショルド電圧2Vを考えた場合
2/5V×1023=約400となるから、

仮に、例のような使い方ができるのであれば、
if(ADRES > 400 ) {//2/5V×1023=約400
でいいような。


>レジスタが無ければ、自分で作った変数でしょうから

自分で作るとは、変数宣言をすることですか?
だとすれば、変数宣言をしていませんので、自分では作っていませんよ。

>直接リレーを駆動できるかは別問題です。GNDは必ず必要です。でないと信号線の電圧が解りません。
電圧計(テスター)も2本ありますよね?それと同じです。1本を繋いでも電圧は測れません。
あとはその出力にどの位の駆動能力があるかです。本当の信号のみなのか、LED程度は駆動できるのか、リレーも可能なのか?
ただ、普通はICの出力端子が繋いであるのでLED程度までです。トランジスタアレイあたりが繋がっていればリレーも大丈夫です。

※SEC基板やスムースステッパーの事はかなり忘れています。TRさんのポンプ制御も回路の方はすっかり忘れています。


こういった込み入った話になると、やはり、誤解を招かないように、SECさんの以下のページを見ていただいた方が良いと思います。
http://sec-suzuki.com/PALA-CNC-V2.pdf

あとの事はもっと時間がかかりそうです。
なにせ、あちこち調べてプログラムを並べた状態ですから。
これ以上は、誤解を招く言動になりそうです。
TR   2018/12/30(Sun) 06:47 No.1399 記事編集
Re: PWM/ADリレー無し
ちょっと検索してみたのですけど、これは違うページの物ですね。

ただし、プログラムとしては、最大値1023のなかで、閾値として250と750を使っている、
というだけです。
私のプログラムのif(num==50)と閾値を50にしているのと何も変わりません。

そして、やはり%ではありません。
それは単にTRさんが簡単に理解しようと置き換えただけでしょう。


> 変数宣言をしていませんので、自分では作っていませんよ。
となるとレジスタを参照しているのですね。
で、御免なさい。No.1380 はADC読み取りのadconv関数自体が書いてあったのですね。
最期の}まで書いてありません。最後に付けただけの

unsigned int adconv() {
unsigned int temp;
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ

if(ADRES > 300 ) {
temp = ADRESH; //上位8bit
temp = (temp << 8) + ADRESL; //RB3→RB4で読み込んだ値をtempに代入
return temp;
} //読み
}

なのかと思いますけど、これはあまり良くありません。
↓のようにすべきです。

unsigned int adconv() {
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ

if(ADRES > 300 ) return ADRES;
else return 0;
}

まず、if(ADRES > 300 )の部分ですけど、
ADRES自体がコンパイラが、
ADRES=(ADRESH<<8)+ADRESL;
として、自動で値を取得してくれています。なので、もう一度同じ値を取得し直す必要はありません。
で、もっと重要な事はそれ以外の場合は0を返す(return 0;)、と言う事です。
※何も返さないのは、返す値が何でも良い場合のみにして下さい。「書かない場合は0を返す」と言う事ではありません。

それと、前にも言ったと思いますけど、こういった使いまわすような関数を弄るのはあまり良くありません。
つまり、ここで弄っているのでつまみの位置が約30%までがおかしくなっています。

なので、ここでは、
@
unsigned int adconv() {
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ
return ADRES;
}

として、メイン関数のループの方で、
num=adconv();//adcを読み込んで
if(num<=300)num=0;//300以下なら0にする。
とした方が間違いが無くなります。

で、私のプログラムでは上記の@で、ストレートにADCの値を取得した上で、
num=adconv();//adcを読み込んで
num=(num-50.0)*(1023-500)/(1023-50)+500;//変換式
CCPR1L =num>>2 ;
CCP1CONbits.DC1B = num&3;

です。


SEC基板の出力段は74HC540なので、直接制御ならLED程度ですよ。
猛牛ロック   2018/12/30(Sun) 12:37 No.1400 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
猛牛ロックさん、すでに実機に取り付けましたので、
いただいた改良案は、今後の参考にしたいと思います。
それで、色々と書いてあるので。
全て記載してください。
私のようなものには、間違って受け取る恐れがあるからです。


%の件ですがありますよ。
PWMのページです。私が紹介したページにあります。
最初自分はPWMの方で、何とかしたいと考えていましたので、何回か見ました。

それと、もう一言、耳が痛いかもしれません。
それは、「前にも言いましたが」という言い方を何度もするのは、止めた方が良いですよ。
まるで人の話を聞いていないだろうといわんばかりに聞こえます。
猛牛ロックさんが言われても理解できないでいたり、興味がなかったりして忘れてしまうとか、色々とありますので。
他にもありますが、この辺で辞めます。ともかく悪気があっての行動ではないのです。
なので、何度も言われると気分が良くないです。
TR   2018/12/30(Sun) 14:18 No.1401 記事編集
Re: PWM/ADリレー無し
> TRさんへ
私が「%とは何のことを言っているのか判らない」といったので、No.1399の例を載せたのですよね?

これを見ると
・if( ADRES < 250 ) {
・if( 250 <= ADRES && ADRES < 750 ) {

あたりを指しているのだと思ったのですが、閾値、つまり250や750辺りの事を言っているのだと思うのですが
違うのでしょうか?
正確には%というよりも、千分率とみなして考えた方が簡単、ということですよね?
で、数値としては千分率として250で比較しても、%として考えて250で比較しても、1023まであるとして250で比較しても
それは個人の頭の中の問題です。やっている事は
if( ADRES < 250 )
とADRESと250を比較していれば同じ事です。

私が
if(num<50){
としているのとどこに違いを感じるのかが解りません。

> 全て記載してください。
このあたりも、どこの部分を言っているのか、逆に記載してください。
私の中では、自分が同じ事をくどいように説明しているように感じています。

逆に、どの部分を言っているのか、範囲を絞って1つずつ消化する方がいいと思うのですけど。


> %の件ですがありますよ。
> PWMのページです。私が紹介したページにあります。
> 最初自分はPWMの方で、何とかしたいと考えていましたので、何回か見ました。

そのページのどの部分かを具体的に言ってください。
「そのページにあります」「何回か見ました」では判りません。
似たような部分は
> // 5% -> 100%の制御
> for(duty=50; duty<=1000; duty++) {
があります。これの事ですか?
これはduty比を1000までにして上の部分の23を切り捨てて簡単に考えています。

でも、既にNo.1398で、

> で、別にそのページでは%では書いてありませんよ。
> っていうか、単に1023の23の部分を切り捨てて単純に考えたい、という意味ですか?

と聞きました。でもそこでは無いような感じのNo.1399のレスを返されました。

なので、一体どの部分を言っているのか、全く不明です。


<<追記>>

普通、%で制御というのは、10ビットの場合は1023が上限なので、そこが100%にあたります。なので、
int percent_adc=ADRES*100.0/1023;
のようなことをして、100分率に直して使います。
なので、面倒なひと手間が入ります。
勿論、PWMへの出力なら逆に100(%)→1023変換になります
これは、表示器で入出力を%で表示したい場合によく使われる手法です。
猛牛ロック   2018/12/30(Sun) 16:25 No.1402 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
この話題は、一旦止めにしましょう。
本日のちょい試運転では、動作しましたので、
今後、様子を見ます。
TR   2018/12/30(Sun) 17:00 No.1403 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
それが良いですね。年末ですし(^^)/
猛牛ロック   2018/12/30(Sun) 17:55 No.1404 記事編集
Re: PWM/ADリレー無し SWもなし全てプログラム
猛牛ロックさん、こんばんは。
先ほど、寒かったけど、頑張ってフライス盤の部屋で、PICを交換しました。
猛牛ロックさんのプログラムです。
結果 OKでしたよ。
TR   2018/12/30(Sun) 20:34 No.1405 記事編集
疑似手パ,中間報告
手パの経過報告です。
幾つかの問題に直面しました。
部材(スライドスイッチ)が25日発送予定なので、どちらにしてもまだなのですけど、
プログラムとCADの部分はおおよそ作って、テストしています。

@一番大きな問題ですけど、「CTRL」+「ALT」+「X」が通用しません。
 試してみると、「CTRL」+「X」や「ALT」+「X」なら問題無さそうです。
 (STM32F103ボード、PRO MICRO共通)
 勿論、本物のキーボードからは「CTRL」+「ALT」+「X」で通用します。
 今の所、解決策は3つです。
 1.根本的に、プログラム(ライブラリ)を見直して、「CTRL」+「ALT」+が通用するものを作る
 2.ホットキーの割り当てを変える。
 3.今まで行っていたJoyToKeyというソフトを使うなら通用するでしょうから、
  ジョイパッドとして作って、JoyToKeyを通して作業するなら問題はすり抜けそうです。
 今の所、2番の割り当て変更になりそうです。ただ、元々どこに当てられているのかがはっきりしないんですよね。
 一覧とかがあれば、「それ以外」も決めれるのですけど。

ASTM32F103ボードにはBOOTジャンパが付いています。これで、起動を切り替えるのですけど、
 これが邪魔で予定ケースには入らないことが判明しました。ピンヘッダを削ってはんだ付けしちゃうか?ケースに
 穴をあけるか、それともピンヘッダの無いPRO MICROにするか?まぁ、ケースを変える、というのもありましたね。
 添付画像のように、PRO MICROは平らです。リセットボタンやISPピンも出てないのが今回は好結果になります。
 (勿論あった方が使いやすいですけど、この平べったさをみると意図的にしているようですね)
 これはちょっとPRO MICROに気持ちが傾いています。ジャンパを取ってもちょっと膨れる位なんですよね。

B以前MABOさんから、「フォルムさんの疑似手パは使いにくかった」というようなことを聞いたような気がするのですけど、
 それと同じような要因なのかと思います。
 CONTモードの時はボタンが直ぐに切り替わりません。0.5秒位は離さないと次の命令(ボタンを押す)を聞いてくれません。
 最初にこれに遭遇したので戸惑いました。
 (これはキーボードでも確認できます。→キーを押してX+方向にうごかしていて、直ぐに←キーに切り替えるとX-には動かずに停止します。
 また、同じキーの2度打ちでも停止します)
 
 ただし、stepモードの場合は
> for (i = 0; i < 100; i++) {
> BootKeyboard.press(KEY_PAGE_UP);
> delay(3);
> BootKeyboard.release(KEY_PAGE_UP);
> delay(3);
> }
 のコードで動くことを確認しました。(0.01mm×100回押す=1mm動作)
 エンコーダ自体は1周30パルスなので、早く回しても1秒間に3回転=90パルス/秒です。
 これで動いたと言う事は160パルス/秒でも問題ないことを意味しているので、STEPモードにすれば
 ちゃんと動きそうです。

猛牛ロック 2018/12/23(Sun) 10:23 No.1363  記事編集
Re: 疑似手パ,中間報告
猛牛ロックさん,TRさん,こんばんは。

猛牛ロックさん,着々とすすでますね。

ちょっと疑問点なんですが,



USB接続だと思うのですが,

USBまわりのライブラりーでもあるのでしょうか。

それと,

BootKeyboard.press(KEY_PAGE_UP)

のKEY_PAGE_UPは,猛牛ロックさんが別途作った,Define等で
の処理でしょうか。

それとも,一括で,ヘッダーフィアイルかんなんかにあるのでしょうか。
mabo   2018/12/23(Sun) 20:48 No.1364 記事編集
Re: 疑似手パ,中間報告
HIDデバイス絡みのライブラリです。
HIDデバイスなら、標準ドライバで動くのでドライバを作る必要もありません。
マウス、キーボード、ジョイパッドあたりのデバイスです。

数日前に参考プログラムを乗せたと思うのですけど。(No.1347です)
STM32F103ボードの方はコンポジットライブラリ(それらの複合)になっていて、
モードが幾つかあるので面倒です。でも基本は一緒で、

#include <USBComposite.h>
USBHID HID;
HIDKeyboard BootKeyboard(HID, 0);

void setup() {
HID.begin(HID_BOOT_KEYBOARD);
BootKeyboard.begin();

まで記述すれば、既に始める準備が出来ています。
後は
BootKeyboard.press('M');
BootKeyboard.release('M');
BootKeyboard.write('M');//押して離す複合
BootKeyboard.releaseAll();
の類の命令を状況に応じて書くだけです。
※「BootKeyboard」は自由に付けていいはずです。。
なので3行目は
HIDKeyboard TEPA(HID, 0);
とすれば、6行目は
TEPA.begin();
として、
TEPA.press('k');
のように使います。

PRO MICROは単独のHIDキーボードライブラリのなので、もっと簡単に

#include "Keyboard.h"

void setup() {
Keyboard.begin();
}
の2行を付けれるだけで準備OKです。

KEY_PAGE_UP
等は既に定義されています。
まともなマニュアルはありませんから、ライブラリ内を検索して、実際にはUSBHID.hというファイルに定義されていました。
(Arduinoの方はリファレンスサイトに載っています。勿論PICにも同様のライブラリはあると思います。
ただし、PRO MICRO(実際はLEONARDOのライブラリ)とSTM32ボードやPIC、その他のライブラリでそれぞれ違いはあります。
どれも、その仕様に沿って書くことになります。)
猛牛ロック   2018/12/23(Sun) 23:09 No.1365 記事編集
Re: 疑似手パ,中間報告
c言語 #include <USBComposite.h>

上記でネット検索しましたが、該当なし!
いや〜、難しいことやっていますね。


自分事ですが、最近、たてつづきに、制御関係のアクシデント
内、3件目は深刻です。

ポンプ制御に使っていた、秋月のPWMが壊れたようです。
出力端子から、全く電圧なし。

仕方がないので、とりあえず、写真の赤枠にある
秋月のPWMを買い替えます。

しかし、自分で作った赤枠以外のボードは、問題なし。

TR   2018/12/24(Mon) 08:08 No.1366 記事編集
Re: 疑似手パ,中間報告
直接関係なくてすみません。

仮配線で秋月PWMに使われている発信用のIC555を試しました。
結果、発光せず。
どうも、これが駄目らしい。
一応、買い替えに決定しました。

TR   2018/12/24(Mon) 12:31 No.1367 記事編集
Re: 疑似手パ,中間報告
使用マイコンの方はまだどちらにするか悩んでいます。

ホットキーについては、はっきりとしたことは判りません。
例えば、Ctrl+ALT+1(Qキーの上にある方)だとマイコンもキーボードも同一です。
しかし、特定のものはやはり違った値になります。
でも、まぁ、マイコンはどちらにしろ、この問題はあるようですし、対処できない訳でもないので
この部分で悩んでいる訳でもないのですけど。

・あまりADCは使いたくない→STM32ボードが良いかなぁ
・ピンヘッダが邪魔→PRO MICROの方がすっきりするかなぁ


今となっては使うか判らないSTM32ボード用の最初のスケッチです。
実際試した訳では無いので、多少変えないと動かないと思います。
大部分は、「押したボタンに対応するコードを送る」というだけです。
こっちはブートキーボードじゃなくて、単なるキーボードになっていますね。
(何が違うのかは把握していません。今回の件ではどちらのモードでも同じかも)


#include <USBComposite.h>

const uint32_t used_pin=0b11111111110110000011111111111;
uint16_t pin_old[29];
uint8_t pin_state[29];


volatile uint8_t axis,feed,step_unit;

USBHID HID;
HIDKeyboard TEPA(HID);

void read_mode(void) {
for(byte i=0; i<=2; i++) {
if(digitalRead(i)==0)axis=i;
}
for(byte i=19; i<=22; i++) {
if(digitalRead(i)==0)step_unit=i;
}
for(byte i=23; i<=25; i++) {
if(digitalRead(i)==0)feed=i;
}
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
TEPA.press('.'); //基本的に、STEPがデフォルト
if(step_unit==22)TEPA.write('K');
else if(step_unit==21)TEPA.write('L');
else if(step_unit==20)TEPA.write(';');
else if(step_unit==19)TEPA.write(':');
if(feed==25)TEPA.write('F');
else if(feed==24)TEPA.write('G');
else if(feed==23)TEPA.write('H');
TEPA.releaseAll();
}

void setup() {
HID.begin(HID_KEYBOARD);
TEPA.begin();
for(byte i=0; i<=28; i++) {
if((used_pin>>i)&1) {
pinMode(i,INPUT_PULLUP);
}
}
delay(1000);
read_mode();
}

void loop() {
byte enc;

for(byte i=0; i<=28; i++) { //16bit履歴を保存
if((used_pin>>i)&1) {
pin_old[i]<<=1;
if(digitalRead(i)==0) {//SW-ON
pin_old[i]++;
if(pin_old[i]=0xFFFF) {
if(i<=2 && i!=axis) {
axis=i;
} else if(i>=19 && i<=22 && i!=step_unit) {
step_unit=i;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
if(i==19)TEPA.press(':');
else if(i==20)TEPA.press(';');
else if(i==21)TEPA.press('L');
else if(i==22)TEPA.press('K');
TEPA.releaseAll();
} else if(i>=23 && i<=25 && i!=feed) {
feed=i;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
if(i==23)TEPA.press('H');
else if(i==24)TEPA.press('G');
else if(i==25)TEPA.press('F');
TEPA.releaseAll();
} else if(i==3 && pin_state[3]==0) { //1/2
pin_state[3]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
if(axis==0)TEPA.press('A');
else if(axis==1)TEPA.press('S');
else if(axis==2)TEPA.press('D');
TEPA.releaseAll();
} else if(i==4 && pin_state[i]==0) { //z1.02
pin_state[4]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
TEPA.press('/');
TEPA.releaseAll();
} else if(i==5 && pin_state[i]==0) { //DRO 0
pin_state[5]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
if(axis==0)TEPA.press('B');
else if(axis==1)TEPA.press('N');
else if(axis==2)TEPA.press('M');
TEPA.releaseAll();
} else if(i<=8 && pin_state[i]==0) { //g56,55,54
pin_state[i]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
if(i==8)TEPA.press('4');
else if(i==7)TEPA.press('5');
else if(i==6)TEPA.press('6');
TEPA.releaseAll();
} else if(i==26 && pin_state[i]==0) { //stop
pin_state[i]=1;
TEPA.press(KEY_RIGHT_ALT);
TEPA.press('S');
TEPA.releaseAll();
} else if(i==27 && pin_state[i]==0) {
pin_state[i]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
if(axis==0)TEPA.press('W');
else if(axis==1)TEPA.press('E');
else if(axis==2)TEPA.press('R');
TEPA.releaseAll();
} else if(i==28 && pin_state[i]==0) { //G0z1
pin_state[i]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
TEPA.press('Z');
TEPA.releaseAll();;
} else if(i==9 && pin_state[i]==0) { //+ ※releaseはしない
pin_state[i]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
TEPA.write(',');//CONT指定
if(axis==0)TEPA.press(KEY_RIGHT_ARROW);
else if(axis==1)TEPA.press(KEY_UP_ARROW);
else if(axis==2)TEPA.press(KEY_PAGE_UP);
} else if(i==10 && pin_state[i]==0) { //- ※releaseはしない
pin_state[i]=1;
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
TEPA.write(',');//CONT指定
if(axis==0)TEPA.press(KEY_LEFT_ARROW);
else if(axis==1)TEPA.press(KEY_DOWN_ARROW);
else if(axis==2)TEPA.press(KEY_PAGE_DOWN);
}
}
} else { //SW-OFF
if(pin_old[i]==0) {
if((i==9 || i==10)&& pin_state[i]==1) {
pin_state[i]=0;
TEPA.releaseAll();
TEPA.press(KEY_RIGHT_CTRL);
TEPA.press(KEY_RIGHT_ALT);
TEPA.press('.');//STEP指定
TEPA.releaseAll();
} else if(pin_state[i]==1)pin_state[i]=0;
}
}

enc=((pin_old[16]&0b11)<<2)|(pin_old[17]&0b11);//step-cont切替も
if(enc==1) {
if(axis==0)TEPA.write(KEY_RIGHT_ARROW);
else if(axis==1)TEPA.write(KEY_UP_ARROW);
else if(axis==2)TEPA.write(KEY_PAGE_UP);
} else if(enc==2) {
if(axis==0)TEPA.press(KEY_LEFT_ARROW);
else if(axis==1)TEPA.press(KEY_DOWN_ARROW);
else if(axis==2)TEPA.press(KEY_PAGE_DOWN);
}
}
}
delay(1);
}

猛牛ロック   2018/12/24(Mon) 19:00 No.1368 記事編集
Re: 疑似手パ,中間報告
猛牛ロックさん,TRさん,こんばんは。

猛牛ロックさん,疑問点への回答ありがとうございます。

arduino,ライブラリー等,充実してるんですね。

機種にもよるのでしょうけど,本当,親切ですね。

16系のPICだと,新しいものでないと,USBのインターフェース等,搭載してないようですね。

私がもっている,16ファミリーでの解説書でも,USBのインターフェ-スについては,載ってないです。

STM32F103のUSBのライブラリ-ちょっとみてみました。

https://github.com/arpruss/USBComposite_stm32f1

PICのこともよく分からないのですが,arduinoは,なんか充実しているような感じです。



PICだと16系では,16F1455がUSBのインターフェース搭載なのですね。

秋月での販売が2016年あたりですので,新しいですよね。

このあたりは。arduino の方が進んでるんでしょうかね。


TRさん,PWMのコントローラーの不具合,原因分かってよかったですね。

ICは,もしかして,中華製だったりして・・・・・・。

ICの交換より,全体の買い換えの方が安くつくんでしょうかね。
mabo   2018/12/25(Tue) 21:04 No.1370 記事編集
Re: 疑似手パ,中間報告
猛牛ロックさんのは、今はやりでしたか。
プログラムを見てもチンプンカンプンです。

IC555は秋月で。確か20円でした。
基板毎だと500円です。

一応、両方購入しました。

でも、FETとPICを使い、DCポンプを滑らかに回そうとしています。
でも、DC5V位から、一気に回ってしまう感じです。
ムズイ。
図面で一部誤り
GNDは、共通です。

TR   2018/12/25(Tue) 22:44 No.1371 記事編集
Re: 疑似手パ,中間報告
> MABOさん

基本的に、上位のマイコンほど複雑ですけど、逆に複雑な部分は捨て去って?、簡単になります。
PCは内部は複雑だけれども、それを知らなくてもすぐにインターネットやEXCELが出来るのと同じです。
まぁ、複雑な部分は他人に任せているのですけど。
基本的に、Arduinoもmbedなども同じ(WINDOWSとMACのようなもの)で、それに対応させれば、同じような操作で
GPIO等は操れます。(Arduinoに対応したデバイスはArduino流に書いて、mbedならmbed流に書く)

Arduino(UNO)なら、レジスタ操作からライブラリを使った、様々なデバイスも容易に纏められます。
つまり、入門から応用まで対応出来ます。
PICでそう言った事が出来るかは、良く判りません。(勿論、マイコン性能ではなく、開発環境の問題です)
USBもPIC16Fからありますし、品ぞろえ的にはPICは問題ないです。
だけど、設定が面倒なんですよね。だから、http://bit-trade-one.co.jp/product/assemblydisk/revive-usb/
のような物も発売されています。
でも、多少いじるなら、このコードを改変するよりも、https://garretlab.web.fc2.com/arduino_reference/language/functions/usb/index.html
を見て、Arduinoで組んだ方が楽で面白いかと思います。


> TRさん

プログラム自体は全然難しいものではありませんよ。
ボタンを押されたら1回点滅させる、というLチカと同じ類のものです。
それが、1回(そのボタンに対応する)キーコードを送る、となっているだけです。

で、その回路ですけど、
・FETは4V(或いは2.5V)駆動品を選ぶ
・プルダウン抵抗は高すぎです。数十kΩが良いです。
・3.5kΩの部分はプルダウン抵抗の1/10程度が良いかな?
・バリスタよりもダイオードが良いです。
 ※バリスタ27Vなら実際のバリスタ電圧?が30Vとして、42Vになった時にDC12V側に還流されます。
  つまり、42Vのサージが残ります。
  ダイオードなら12.6Vで還流されるので、ほぼサージが消えます。
猛牛ロック   2018/12/26(Wed) 12:37 No.1372 記事編集
Re: 疑似手パ,中間報告
猛牛ロックさんへ、
先ほど、バラックでテスト完了しました。
中華ポンプは、えらくいい加減です。
動作する電圧の範囲です。
表示はDC12Vですが、DC24でも行けそうです。


バリスタはどうって選ぶのか分かりませんでした。
以下のページを参考にして、出しました。
VE≦VA(1−α) …A
VE:回路電圧
VA:最大許容回路電圧
α:設計マージン(α=0.2)
http://www.koaglobal.com/product/basic/varistor


本当は違うのですか、よかったら、
詳しく教えてください。


MOSFETの1MΩは、自信があります。
続トランジスタ回路の設計から出しましたし、実験の結果、やはり1MΩじゃないと、
GND側に引っ張り切れなくて、ドレインから電流が流れてしまいました。
FET方向への3.9kΩは、実験の結果、一番安定していました。
ただ、参考文献でもハッキリとしませんでした。

バリスタは、高速ダイオードに変えます。


それから、教えていただいたPWMとADのプログラムは、理解できたので、
大活躍していますよ。


バラックでのテストは、安定電源でやったので、ポンプ無理なく滑らかに回っています。
ボリュームをいじっていると気分がいいです。
ただ、ポンプがいまいち、ボリュームを目いっぱいに絞っていないのに停止します。
これはプログラムじゃなくポンプです。
なにせ、DC18Vの電源だとパワフルに回ってくれますから、きっと、最適の電圧は12Vじゃなくもっと上だと思います。


言語は、MPLABの言語じゃないのですか?



写真は、バラックでのテスト風景です。

TR   2018/12/26(Wed) 14:36 No.1373 記事編集
Re: 疑似手パ,中間報告
皆さんこんばんは。

教えて欲しい事があります。

SEC基板のポート2 SL13の1 からの出力信号(これが、「-電圧」なんです、、、。)。
今まで、逆に繋いでいました。

話を戻します。

PWMをSL13の1からの信号をRB7に繋ぎ、RB7により全体を制御したいと思います。
そこで、プログラムの真ん中あたり、@のところに、break文を付けました。
これで、宜しいでしょうか?

動作
RB7のLoで、すべて停止、
Hiで、
・全体の動作モニター用のLED
・PWM信号をRB0端子で、DCモーターポンプを回転数制御
・RB3で回転数を電圧読み取り


/*PWM機能によりRB3可変抵抗で制御*/
//RB7がSEC基板ポート2のSL-13の1番ピン(出力端子)を入力端子として受けるその表示をLEDでRA1から発光させる
//RB0を出力端子LEDPIC16F1827 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
// クロック周波数指定
// (__delay_ms()関数が必要としているため)
#define _XTAL_FREQ 1000000

// プロトタイプ宣言
void InitPWM(void);
void InitTimer2(void);
unsigned int adconv(void);

// メイン関数
void main(void) {
OSCCON = 0b0110101; //クロック周波数を1MHzに設定
PORTA = 0x00; //全てLo
PORTB = 0x00; //全てLo
ANSELA = 0b00000000; //全てデジタルI/Oとする
ANSELB = 0b00001000; // 可変抵抗の電圧読み込み用にRB3のみアナログ
// 入出力設定
TRISA = 0b00000000; // RA全て出力
TRISB = 0b00001000; //RB3 可変抵抗用ADC用入力端子
// ADコンバータ設定
ADCON0 = 0b00100101; // アナログ変換情報設定(AN9 RB3から読込む)
ADCON1 = 0b10010000; // 読取値は右寄せ、A/D変換クロックはFOSC/8、VDDをリファレンスとする
__delay_us(5); // アナログ変換情報が設定されるまでとりあえず待つ
//変数宣言
unsigned int num;

// PWMモード設定関数の呼び出し
InitPWM();
// タイマ2設定関数の呼び出し
InitTimer2();

while (1) {
@ if(RB7==0){break;}
LATA1=RB7;//SEC基板ポート2のSL-13の1番ピン
num = adconv(); // RB3 9番ピン(AN9)から半固定抵抗の値を読み込む
CCPR1L = num / 4; // アナログ値からのデータでデューティ値を設定
CCP1CONbits.DC1B = num & 0b11;
__delay_ms(10);
}
}
// アナログ値の変換と読込み処理関数
unsigned int adconv() {
unsigned int temp;
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ
temp = ADRESH; //
temp = (temp << 8) + ADRESL; //RA3で読み込んだ値をtempに代入
return temp; //読み込んだtempをnumに返す
}
// PWMモード設定関数
void InitPWM(void) {
APFCON0bits.CCP1SEL = 1; // RB0端子を出力端子に設定
// CCPのモードをPWMモードに設定
CCP1CONbits.CCP1M3 = 1;
CCP1CONbits.CCP1M2 = 1;
CCP1CONbits.CCP1M1 = 0;
CCP1CONbits.CCP1M0 = 0;
// 周期を255μ秒に設定(PR2 + 1μ秒)×1/(動作処理速度÷4)
PR2 = 255; //PR2レジスタ8bit0~255
// デューティーサイクルを0msで初期化
CCPR1L = 0;
CCP1CONbits.DC1B = 0;
}
// タイマ2設定関数
void InitTimer2(void) {
// プリスケーラ値を1に設定
T2CONbits.T2CKPS1 = 0;
T2CONbits.T2CKPS0 = 0;
// TMR2レジスタをクリア
TMR2 = 0;
// タイマ2起動
T2CONbits.TMR2ON = 1;
}
TR   2018/12/26(Wed) 20:47 No.1374 記事編集
Re: 疑似手パ,中間報告
DCモータは電圧によって力(回転数)が変わります。
なので、電圧を上げれば上げるほど回ります。
ただし、壊れる危険性も上がります。
電圧を2倍にすれば電流も2倍流れ、消費電力は4倍になります。当然発熱も4倍ですから気を付けてください。


> GND側に引っ張り切れなくて
誤解があるようですけど、1MΩよりも10kΩの方が引っ張る力は100倍あります。
けれども、あまりFETは使っていないので、どの位が適切かは自信がありません。

バリスタは交流の方が良く使われます。
交流の場合は素子の両側が入れ替わりますから、両方対処する必要があります。
例えばAC12Vなら最大17V程度ですよね?その場合は実効20Vのバリスタを入れれば最大値の3Vオーバーの値までにとどめられます。
でも、今回のようにDC12Vの場合は、20Vだと逆電流の場合は20+12V=32V以上の時にVCC(12V)側に流れる事になります。
で、ダイオードなら0.6V程度で流れだすのでこちらの方をお薦めします。

プログラムの方ですけど、はっきりとは言えませんけど多分、再起動を繰り返すのだと思います。
で、そこまでのプログラムではPWMはLOW状態なので、大体、LOW出力あるいはアナログ入力になると思います。
私自身はプログラムが終わるコードを書いたことが無いので、当然、試したこともありません。
猛牛ロック   2018/12/26(Wed) 22:36 No.1375 記事編集
Re: 疑似手パ,中間報告
>プログラムの方ですけど、はっきりとは言えませんけど多分、再起動を繰り返すのだと思います。


今まで使っていた、秋月のPWMキットは、使っていて、感じた点があります。
それは、完全にON・OFFしない事。
その欠点とも思われる事は、秋月のPWMキット説明書にも、その旨の記載があります。

今回、自作、ま〜ガラクタですけど(笑い)

その辺の欠点を何とかと思った次第です。

それと、もう一点あります。
ボリュームの途中で、モーターが停止します。
これも何とかしたいのですが、何かいいアイデアありませんか?

PWMは、MACH3のボタン操作に伴い、SEC基板からの信号をPIC16F1827が受けて制御します。

AD変換する仕切り値といいうのかな〜、
仕切り値以上になったら、電圧の読み取り開始とか、
したらいいのでしょうか?

そうか、DUTYだ!


追記
Dutyを決めるCCPR1に最初から加算したら、どうかな?
+400 とか 500
動作速度から算出する。
TR   2018/12/27(Thu) 07:00 No.1376 記事編集
Re: 疑似手パ,中間報告
PWMの動作開始を50%から出来たらいいな〜と、考えました。

そこで、プログラム真ん中辺りに、@ Aを書き加えました。

50%は、内部クロック1Mhzにしたので、
1/1000000 → 1サイクル時間は、1μs=1000ms
50%なら、500ms
ここから推測なのですが、
50%にしたいなら、CCPR1Lが500でいいと思いました。

如何でしょうか?
ご指摘願います。
宜しくお願いします。


/*PWMによりRB3で可変抵抗制御し、RB0を出力端子*/
//RB7がSEC基板ポート2のSL-13の1番ピン(出力端子)を入力端子として受ける
//その表示を操作盤のLEDでRA1から発光させる、また、基盤でもRA0からLEDにより発光させる
//PIC16F1827 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
// クロック周波数指定
// (__delay_ms()関数が必要としているため)
#define _XTAL_FREQ 1000000

// プロトタイプ宣言
void InitPWM(void);
void InitTimer2(void);
unsigned int adconv(void);

// メイン関数
void main(void) {
OSCCON = 0b0110101; //クロック周波数を1MHzに設定
PORTA = 0x00; //全てLo
PORTB = 0x00; //全てLo
ANSELA = 0b00000000; //全てデジタルI/Oとする
ANSELB = 0b00001000; // 可変抵抗の電圧読み込み用にRB3のみアナログ
// 入出力設定
TRISA = 0b00000000; // RA全て出力
TRISB = 0b00001000; //RB3 可変抵抗用ADC用入力端子
// ADコンバータ設定
ADCON0 = 0b00100101; // アナログ変換情報設定(AN9 RB3から読込む)
ADCON1 = 0b10010000; // 読取値は右寄せ、A/D変換クロックはFOSC/8、VDDをリファレンスとする
__delay_us(5); // アナログ変換情報が設定されるまでとりあえず待つ
//変数宣言
unsigned int num;//ADRESHの値
unsigned int duty;

// PWMモード設定関数の呼び出し
InitPWM();
// タイマ2設定関数の呼び出し
InitTimer2();

while (1) {
if(RB7==0){__delay_ms(10);break;}
LATA0=LATA1=RB7;//SEC基板ポート2のSL-13の1番ピン

num = adconv(); // RB3 9番ピン(AN9)から半固定抵抗の値を読み込む
@ duty=500+num;//Duty比50%からスタート
A if(duty > 500){
CCPR1L = num / 4; // アナログ値からのデータでデューティ値を設定
CCP1CONbits.DC1B = num & 0b11;
__delay_ms(10);}
}
}
// アナログ値の変換と読込み処理関数
unsigned int adconv() {
unsigned int temp;
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ
temp = ADRESH; //
temp = (temp << 8) + ADRESL; //RA3で読み込んだ値をtempに代入
return temp; //読み込んだtempをnumに返す
}
// PWMモード設定関数
void InitPWM(void) {
APFCON0bits.CCP1SEL = 1; // RB0端子を出力端子に設定
// CCPのモードをPWMモードに設定
CCP1CONbits.CCP1M3 = 1;
CCP1CONbits.CCP1M2 = 1;
CCP1CONbits.CCP1M1 = 0;
CCP1CONbits.CCP1M0 = 0;
// 周期を255μ秒に設定(PR2 + 1μ秒)×1/(動作処理速度÷4)
PR2 = 255; //PR2レジスタ8bit0~255
// デューティーサイクルを0msで初期化
CCPR1L = 0;
CCP1CONbits.DC1B = 0;
}
// タイマ2設定関数
void InitTimer2(void) {
// プリスケーラ値を1に設定
T2CONbits.T2CKPS1 = 0;
T2CONbits.T2CKPS0 = 0;
// TMR2レジスタをクリア
TMR2 = 0;
// タイマ2起動
T2CONbits.TMR2ON = 1;
}
TR   2018/12/27(Thu) 21:33 No.1377 記事編集
Re: 疑似手パ,中間報告
> その辺の欠点を何とかと思った次第です。

そのように、気にくわない部分を直していくのも良いと思います。


> ボリュームの途中で、モーターが停止します

これは単純に動き出す位置の問題ですよね?
前にも言ったと思いますけど、ボリューム位置をADCで取得しているのです。duty比を取得しているのではありません。
で、そのボリューム位置へ自由にduty比を割りづければ良いです。ただし、最低付近はキッチリ止めた方が良いです。(duty比0もしくはPWM停止)
止めなければモータが動かなくても電流が流れて発熱します。なので、ボリュームの10%?とか停止範囲を作った方が良いと思います。

※読み取りは全範囲します。というか、読み取らなければどの位置か判りません。
ツマミ位置が0-10%で停止。ツマミ位置10〜100%の位置で、使用する最低のちょっと下ぐらいのPWM〜100%PWMみたいな感じの割り付けになると思います。
スイッチ付のボリュームならちょっと違うと思います。


> @ duty=500+num;//Duty比50%からスタート
> A if(duty > 500){
> CCPR1L = num / 4; // アナログ値からのデータでデューティ値を設定
> CCP1CONbits.DC1B = num & 0b11;
> __delay_ms(10);}
> }

Aがif文なのが判らないです。numが0の場合を除外したいのならもう少し範囲を確保した方が良いです。
テスターで電圧を測れば判ると思いますけど、一番下の桁はちょくちょく動きます。
そして、このコードだと上が切り取られる?(桁があふれる)のでちゃんと割合で合わせなければ駄目です。
猛牛ロック   2018/12/27(Thu) 22:14 No.1378 記事編集
Re: 疑似手パ,中間報告
猛牛ロックさん、有難うございます。

>※読み取りは全範囲します。というか、読み取らなければどの位置か判りません。
ツマミ位置が0-10%で停止。ツマミ位置10〜100%の位置で、使用する最低のちょっと下ぐらいのPWM〜100%PWMみたいな感じの割り付けになると思います。
スイッチ付のボリュームならちょっと違うと思います。

以下の部分が、電圧読み取りの部分ですが、@〜Fの間で細工するということでしょうか?
改善したい点は、現在、ボリュームが0〜50%に部分では動作しないので、
50%から動作開始としたいです。


// アナログ値の変換と読込み処理関数
@ unsigned int adconv() {
A unsigned int temp;
B GO_nDONE = 1; // アナログ値読取り開始指示
C while (GO_nDONE); // 読取り完了まで待つ
D temp = ADRESH; //
E temp = (temp << 8) + ADRESL; //RA3で読み込んだ値をtempに代入
F return temp; //読み込んだtempをnumに返す
}
TR   2018/12/28(Fri) 05:52 No.1379 記事編集
Re: 疑似手パ,中間報告
AD変換のプログラムの内、@を追加したら、
ボリューム0でも、いきなり電圧が出てよくなったのですが、
不安定です。3,2V
ボリュームが悪いのかな〜、プログラムかな〜、どこが悪いのか分かりませんか?
皆様方宜しくお願いします。

// アナログ値の変換と読込み処理関数
unsigned int adconv() {
unsigned int temp;
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ

@ if(ADRES > 300 ) {
temp = ADRESH; //上位8bit
temp = (temp << 8) + ADRESL; //RB3→RB4で読み込んだ値をtempに代入
return temp;} //読み込んだtempをnumに返す
}
TR   2018/12/28(Fri) 13:32 No.1380 記事編集
Re: 疑似手パ,中間報告
こんな感じじゃないこと思います。
No.1377の@Aの部分に入れてください。
※ADCの値が50以上で動作。出力500(/1023)から。

if(num<50){
CCPR1L = 0;
CCP1CONbits.DC1B = 0;
}else{
num=(num-50)*(1023-500)/(1023-50)+500;
CCPR1L =num>>2 ;
CCP1CONbits.DC1B = num&3;
}
猛牛ロック   2018/12/28(Fri) 21:27 No.1381 記事編集
Re: 疑似手パ,中間報告
猛牛ロックさん駄目です。
途中から2.2V位出てそのまま、ほぼ一定です。

まだ、No1380の方が良いです。
右肩上がりで、1.4V〜約4.2Vでます。
TR   2018/12/28(Fri) 22:10 No.1382 記事編集
Re: 疑似手パ,中間報告
> @ duty=500+num;//Duty比50%からスタート
> A if(duty > 500){
> CCPR1L = num / 4; // アナログ値からのデータでデューティ値を設定
> CCP1CONbits.DC1B = num & 0b11;

ちゃんと↑の4行をに変えましたか?

追伸
あぁ、多分桁あふれですね。
num=(num-50.0)*(1023-500)/(1023-50)+500;
でどうでしょう?
猛牛ロック   2018/12/28(Fri) 22:20 No.1383 記事編集
Re: 疑似手パ,中間報告
TRさん,猛牛ロックさん,こんばんは。

TRさん,いろいろがんばってられますね。

猛牛ロックさん,初歩的な質問ですけど,

PWMの制御に使う可変抵抗,AカーブとBカーブのもの,

どちらがいいのでしょうかね。

LEDの明るさとかではないので,普通Aカーブのもの

の方がいいのでしょうかね。


それとPWMの制御で,回転数を無段階に変更するよりも,

可変抵抗の読み取りを,あらかじめ作成しておいたテーブルに

したがって,振幅を決める,なんていう方法はどうなんでしょうか。

プログラムが煩雑になるかなあ・・・・・。
mabo   2018/12/29(Sat) 00:43 No.1384 記事編集
制御分について
皆さんこんばんは。

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 記事編集
ファイルの追加方法
皆さんおはようございます。
これも皆様にとっては今更なのかも。

MPLAB IDEの操作方法で、
mainファイルを作り、追加でファイルを増やす方法が、
やっと分かりました。 下のページの中頃にありました。
今までどうしていたかというと、
テキストファイルに保存したファイルを、
MPLAB IDEのエディタにコピペしていました。

http://www.picfun.com/mplabx/mpxlab01.html
TR 2018/12/19(Wed) 10:27 No.1351  記事編集

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