AD変換によるステッピングモーターの速度制御をあきらめて
ましたが、割り込みとの組み合わせて、なんとか、
240hz~1300hz
のパルスの生成ができるようになりました。
ステッピングモーターに接続して回してみると、見事、かなり低速
から、結構高速、まで、制御できました。プログラムのソースコード
を掲載します。参考になるかは、わかりませんが。
デバック用につけているLCDのモジュールとヘッダーファイルも
掲載しますが、ここのHPを参考にさせていただきました。
速度変更----------main.c
デバック用LCD表示----- lcd.c
LCD表示用ヘッダーファイル--lcd.h
このHPに出会わなかったら、ここまではできませんでした。
実際にステッピングモーターを回してみると、加速や減速の
過程で、昔の地下鉄電車の様な音がでます。
あまりよく見えないのですが、ステッピングモーターのコントロール
に入れている周波数もオシロで同時に映してみました。
高速になるにつれて、パルスの幅が狭くなり、周波数が高く
なるのが、なんとなく分かります。
スピードコントロールのめどと、シュミットトリガーを入れたスイッチ
の調整ができましたので、正転と反転のコントロールと、スタート
ストップのコントロールのプログラムの
作成に移ります。
--「PIC」プログラミング再び (10)---
===TMR0の罠===
はまりました。TMR0の設定で、まるまる2日間。初期設定が
プログラムに反映されませんでした。
他の設定がだめなのか、制約があるのかネットで検索しま
くりましたが、ヒットなし。お助け掲示板に書き込みました。
しつこく検索続けていると、問い合わせのHPの過去記事に、
「TMR0」の設定は、一回オーバーフローするともとに戻る。
1回だけ有効の記事。目からうろこでした。
プログラムを書き換えると、見事思った動作。思わず、
「やった」と叫びたくなりました。
丸二日間、悩みました。
--「PIC」プログラミング再び (9)---
--「PIC」プログラミング再び (8)---
昨日作ったプログラムを変更して、AD変換で、周波数を変える
プログラムを作って、オシロで見てみました。
結果、AD変換は、だめでした。処理速度が遅くて、使えません。
残念。Cではなくて、アセンブラーで組めば、可能性あるのかも
しれませんが、難しいです。
方針を変えて、低、中、高、ぐらいの3段階ぐらいになるように、
してみようと思います。
割り込みで、キー入力をチェックして、作成していたテーブルに
従って、速度を変更する、というプログラムにして見ようと思います。
割り込みにどのくらいの時間がかかるのか、やっていないとわかり
ません。
まあ、最悪、PICを速度の分だけ用意して、それを切り替えれば、
いいので、のんびりとやります。
--「PIC」プログラミング再び (7)---
ステッピングモーターをPICでコントロールするにあたって、
スピードをボリュームでコントロールするためにはAD変換が
必要になります。
例のHPと参考書を見ながら、試作の回路でトライです。
やっと、AD変換のめどがつきました。
スピードをコントロールするのに、周波数を可変する必要
があります。AD変換で、PICの生成周波数を1500hzか
ら100hzぐらいまで、可変できるめどがつきました。
プログラムでは、AD変換で取り込んだ値を5倍して、ミリボルト
の表示をしてあります。この変数を多少変更すると、周波数
の変更に使えると思います。
テストに使ったプログラムです。
ボルトの表示に使ったLCDも思った動作をさせることができず、
やっとバックライトの配線を含め、正常動作するようになりました。
テストに使ってるボードは、例の教科書の付属品です。
いろいろ試作をするのには便利です。ブレッドボードもありますが、
ある程度作ってあった方がいいのかもしれません。
--「PIC」プログラミング再び (6)---
現在使用しているフリーのコンパイラで、__delay_μs()
という単なる待ち時間の関数が使える。以前から使えたのか、
あるヴァージョンかから使えるようになったのかは、分から
ないが、前述の教科書のように自分で関数をつくらなくて
いいので便利だし、結構使う関数だと思う。
ただ、実際のところ、どのぐらい時間なのか、あれこれやって
いるプログラムで簡易的に測定してみた。
PICで
for(;;){
RA1=1;
__delay_us(1);
RA1=0;
__delay_us(1);
}
のプログラムを実行すると、矩形波が生成できるので、
__delay_us(1)と__delay_us(2)と赤の部分を変更して、両者
の差を見てみると、たぶん、実際の待ち時間が分かる。
Cの場合は、1命令の実行時間がわからないので、命令
の実行時間を相殺しないと、実待ち時間が分からないよう
に思う。
__delay_us(1)のオシロの画面で、Hの時間は、約40μs。
__delay_us(2)のオシロの画面で、Hの時間は、約56μs。
56-40で、__delay_us(1)の実時間は、16μsということになる。
約16倍の待ち時間である。ちなみに、__delay_us(3)にしてみると、
Hの時間が約72μsなので、16μsずつ増えている。
やはり、細かい制御をするには、命令のクロック数の分かって
いるアセンブラー。でも、アセンブラーは、私には、超難解。
Cが似合ってる。
--「PIC」プログラミング再び (5)---
PICのプログラミングを再開するにあたって、困ったののが、
コンパイラと呼ばれるソフトです。教科書についていたCDに
入っていましたが、なくしてしまいました。
有料のを使えばいいのでしょうが、そこまで本格的でないので、
FREEのソフトを使いたかったのですが、時間の経過とともに、
便利に使ってたソフトは、バージョンアップしてしまい、HPから
すぐにはDLできませんでした。
現在は、すぐDLできるのはMPLAB® X IDEという最新のもの
でした。いろいろ探すと、古いソフトをためたアーカイブという
ところに以前のものがありました。
Cのコンパイラも同梱されている8.84をインストールしました。
さらに、このバージョンを使ってる方のHPがありました。
やりたいことのプログラムのサンプルがあり、同じ開発環境
なので、そのまま使わせてもらいました。
以前から使っていた教科書も引っ張り出しました。
この本についていたCD(どっかにしまい忘れ)がほしくて
同じものを購入しましたが、なんと、新しい本には、CDが同梱
されてなくて発売元のHPから、DLするようになってました。
これなら、同じも買わなくてもよかったです。
ジェジェジェです。
---「PIC」プログラミング再び (4)---
==PWMモード==
理屈の理解がいまいちでしたが、サンプルプログラムの変数
を変えて、PWMモードで、パルスを発生させてみました。
/*****************************
STEP20_PWMMode.c
*****************************/
#define _LEGACY_HEADERS//以前のヘッダーファイルにするための宣言これがないと古いのではエラーに
// インクルードファイルの読み込み
#include
__CONFIG(UNPROTECT & LVPDIS & BOREN & MCLRDIS & PWRTEN & WDTDIS & INTIO);
//#pragma config CPD=OFF , LVP=OFF , BOREN=ON , MCLRE=ON , PWRTE=ON , WDTE=OFF , FOSC=INTOSCIO
(この宣言は、新しいコンパイラ用。古いのでは、エラーになるので、コメントアウト)
// プロトタイプ宣言
void InitPWM (void);
void InitTimer2 (void);
// メイン関数
void main (void)
{
// 1,2,17,18端子を入出力端子に設定
CMCON = 0x07;
// 電圧レベルの初期設定
PORTA = 0xFF;
PORTB = 0xFF;
// 入出力設定
TRISA = 0x20;
TRISB = 0x00;
// PWMモード設定関数の呼び出し
InitPWM();
// タイマ2設定関数の呼び出し
InitTimer2();
// 永久ループ(これがないとプログラムが終わって
パルスが持続しない。)
while(1)
{
}
}
// PWMモード設定関数
void InitPWM (void)
{
// RB3端子を出力端子に設定
TRISB3 = 0;
// CCPのモードをPWMモードに設定
CCP1M3 = 1;
CCP1M2 = 1;
CCP1M1 = 0;
CCP1M0 = 0;
// 周期を100μ秒に設定(99 + 1μ秒)
//PR2 = 0b01100011;//99μ+ 1μ秒(10khz)
//PR2 = 0b11000111;//199μ+ 1μ秒(5khz)
PR2 = 0b11111110;//254μ+ 1μ秒(985hz プリスケラー4)
// Hの時間を99μ秒に設定(396 × 0.25μ秒)
//CCPR1L = 0b01100011;99μ
//CCPR1L = 0b00110010;//50μ
//CCPR1L = 0b000011001;//25μ
//CCPR1L = 0b000000101;//10μ
CCPR1L = 0b00000101;//5μ
CCP1X = 0;
CCP1Y = 0;
}
// タイマ2設定関数
void InitTimer2 (void)
{
// プリスケーラ値を1に設定
//T2CKPS1 = 0;
//T2CKPS0 = 0;
// プリスケーラ値を4に設定
T2CKPS1 = 0;
T2CKPS0 = 1;
// TMR2レジスタをクリア
TMR2 = 0;
// タイマ2起動
TMR2ON = 1;
}
パルス幅5μsにして、周期を変えてみました。
PR2レジスタ・・・・・・・周期(周波数)の設定
CCPR1Lレジスタ・・・・・・・・パルスの時間を設定
目的の周波数にするのに、段階的にPR2レジスタの数値
を大きくしていきましたが、すんなりと周波数を大きくは
できませんでした。「255」の壁がありました。256にする
とこのまでは不具合が起きます。このままでは分からない
のですが、2進数にすると一目瞭然です。
255・・・・・ 11111111
256・・・・・ 100000000
10進数で、9から10に変わるのとおなじように、桁数が
ふえてしまうのです。PR2レジスタは、8桁の2進数しか
収納できないので、これだけでは、256以上の数値は、
収納できません。しかし、便利な機能があって、プリスケラ-
という数え方を何分の一かにする機能があります。
これと組み合わせると、周期(周波数)をさらに何分の一
かにできます。
PR2に254(実際は+1されるので、255を格納)
CCPR1Lで5μs幅のパルスに設定
T2CKPS1 = 0;T2CKPS0 = 1;でプリスケラ-を4に設定
プリスケラ-は1,4,16の設定しかないようですので、4
に設定して、数え方を1/4にして、
やっと目的が果たせます。
---「PIC」プログラミング再び (3)---
パルスを作るのにPICで、自分でプログラムを組みましたが、
自分でプログラム作らなくても、CCPモードというのがあって、
このなかにPWMモードという機能があって、パラメーター
さえ設定してやれば、パルスの生成ができるようです。
ただ、その設定のパラメーターの与え方は、私には複雑で、
まだ、よく理解できません。いずれ、マスターしたいと思いますが、
とりあえず、自作のプログラムでも動いたので、今日もあれこれ
やりました。
今日は、
の赤矢印(LOWの時間)の時間を変えることで、パルスの周波数を
変えてモーターの動きを試してみました。
2000HZのパルスで回転させていたときは、回転中にモーターの
軸を指で持つと、回転をストップすることができました。
このモーター壊れているのかのかなと思いましたが、
約1500HZぐらいに落とすと、手で止められないくらいのトルク
がでました。どうやら、設定があってなかったようです。
1500HZから200HZぐらいまで、段階的に変えてみましたが、
うまく動いたようです。
この間で、周波数を変更できれば、スピードのコントロール
ができそうです。
PICで可変抵抗を使うには、AD変換が必要なので、
次なる課題は、AD変換のプログラムです。
---「PIC」プログラミング再び (2)---
PICのプログラムについて、少しずつ思い出してきました。
とはいっても、完全にマスターなどしている訳ではないので、
何年か前の水準にもどっただけです。
今日は、PICで、ステッピングモーターのパルスを発生さて、
中古のステッピングモーターを回してみました。
UDK2120の取説には、必要なパルスの要件は、
とありました。アセンブラでプログラムを組むと、命令に必要な
クロック数から細かい設計もできるのでしょうが、Cからは、
ちょと面倒で、私にはできません。ということで、実際にプログラム
しては、動かしてみて、オシロデ確認して組みました。
/******************************************
2014-10-15
PULSE SEISEI
********************************************/
#include
void WaitTime1 (void);
void WaitTime2 (void);
int dummy;
void main(void){
PORTA=0x00;//PORTAをLOWに
PORTB=0x00;//PORTBをLOWに
TRISA=0x08;//0000 1000 PORTAを出力に(RA3は入力に)
TRISB=0x00;//0000 0000 PORTBを出力に
CMCON=0x07; //1,2,17,18コンパレーターオフ 汎用端子を入出力へ
//パルスの生成
for(;;){
RA1=1;
dummy=1;//待ち時間だけHIGHに
dummy=1;
RA1=0;
WaitTime2();//待ち時間だけLOWに
}
}
// 待ち時間関数の呼び出し
void WaitTime1 (void){
int cnt1=1;
while(cnt1 > 0){
cnt1--;}
}
void WaitTime2 (void){
int cnt2=20;
while(cnt2 > 0){
cnt2--;}
}
やってることは単純なことで、一つの端子の出力を、オン、オフ
をしているだけです。ただ、当初予定していた二つの待ち時間
の関数を使おうとしましたが、この関数を使うと、パルスの幅
が50μsぐらいになるので、dummy=1という数字を代入すると
いう意味のない命令を一つ実行するだけで、だいたい、取説
にあった5μsの幅になりました。
WaitTime2()の関数で、待ち時間のカウンターを20にすること
で、パルスの周波数が約2kHになりました。
2kHだと約240rpm/mの早さで回るようです。
これで、目的にまた一歩近づきました。