🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

2回答

3300閲覧

ステッピングモータートルク保持休憩(リミットスイッチで原点復帰)

fukufuku999

総合スコア10

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

1クリップ

投稿2021/03/18 10:15

2相ステッピングモーターをL6470ドライバーとarduinoで動かしています。
arduinoは初めてで、いろんなところから拾って書いてみました。
動きとしては、電源ON→ステッピングモーターが正転→リミットスイッチに当たる(switch ON)→モーターが550秒100のスピードで逆転→トルク保持のまま100ミリ秒休憩→モーターが550秒100のスピードで正転→トルク保持のまま100ミリ秒休憩→の繰り返し

スイッチONからモーター正転逆転はできたのですが、「トルク保持のまま休憩」ができません。
delayを使うとスイッチの反応を邪魔してしまうので、このような書き方をしました。
どうかお助けください。。。

/*********************** 回転 ************************/ #include <Arduino.h> #include <SPI.h> /************* 設定の部 */ long max_speed = 7000;// 70000 固定 long int dd = 200;// 微増・微減の量 400 int dt = 10; // 微増・微減にかける時間 ミリ秒 int t_interval = 10;// (休止する時間 みり秒) int t_hold = 170; // 最高速を維持する時間 ミリ秒) int steps; /* 設定 終わり ************** ****/ // ピン定義。 #define PIN_SPI_MOSI 11 #define PIN_SPI_MISO 12 #define PIN_SPI_SCK 13 #define PIN_SPI_SS 10 #define PIN_L6470_SS PIN_SPI_SS // 関数プロトタイプ void L6470_write(unsigned char data); void L6470_init(void); void L6470_run(long speed); /*********************** 動作に関わる変数。 ************************/ long speed = 1000; // スピード初期値 long int n_dir = 0 ;// カウントアップ 奇数で正回転 偶数で逆回転 long offTime; int c_step = max_speed / dd; const int limit_sw = 7; bool switchState = false; int counter = 0; int milsec = 0; bool speedSwitch = false; void setup() { // ピン設定。 pinMode(PIN_SPI_MOSI, OUTPUT); pinMode(PIN_SPI_MISO, INPUT); pinMode(PIN_SPI_SCK, OUTPUT); pinMode(PIN_L6470_SS, OUTPUT); // りみとすいっち pinMode(limit_sw, INPUT_PULLUP ); digitalWrite(PIN_L6470_SS, HIGH); // SPI開始。 SPI.begin(); // シリアル通信。 Serial.begin(9600); // L6470の初期化。 L6470_init(); Serial.println("Start..."); } void loop() { int value = digitalRead(limit_sw); if(value == 0){ counter ++; if(counter > 50){ switchState = true; counter = 50; } } if (switchState == true){ milsec++; Serial.println(milsec); if(milsec > 550){ speedSwitch = !speedSwitch; milsec = 0; } int speed; if(speedSwitch == true){ speed = 100; } else{ speed = -100; } L6470_run( speed ); } else{ L6470_run( 400 );//速度 } } void L6470_write(unsigned char data) { // ~SSイネーブル。 digitalWrite(PIN_L6470_SS, LOW); // SPI転送。 SPI.transfer(data); // ~SSディスエーブル。 digitalWrite(PIN_L6470_SS, HIGH); } void L6470_init() { // MAX_SPEED設定。 /// レジスタアドレス。 L6470_write(0x07); // 最大回転スピード値(10bit) 0020 L6470_write(0x00); L6470_write(0x90); // KVAL_HOLD設定。 /// レジスタアドレス。 L6470_write(0x09); // モータ停止中の電圧設定(8bit) L6470_write(0xFF); // KVAL_RUN設定。 /// レジスタアドレス。 L6470_write(0x0A); // モータ定速回転中の電圧設定(8bit) //L6470_write(0xFF); L6470_write(0x64); // KVAL_ACC設定。 /// レジスタアドレス。 L6470_write(0x0B); // モータ加速中の電圧設定(8bit) L6470_write(0xFF); // KVAL_DEC設定。 /// レジスタアドレス。 L6470_write(0x0C); // モータ減速中の電圧設定(8bit) L6470_write(0xFF); // OCD_TH設定。 /// レジスタアドレス。 L6470_write(0x13); // オーバーカレントスレッショルド設定(4bit) L6470_write(0x0F); // STALL_TH設定。 /// レジスタアドレス。 L6470_write(0x14); // ストール電流スレッショルド設定(4bit) L6470_write(0x7F); } void L6470_run(long speed) { unsigned short dir; unsigned long spd; unsigned char spd_h; unsigned char spd_m; unsigned char spd_l; //spd = speed; // 方向検出。 if (speed < 0) { dir = 0x50; spd = -1 * speed; } else { dir = 0x51; spd = speed; } // 送信バイトデータ生成。 spd_h = (unsigned char)((0x0F0000 & spd) >> 16); spd_m = (unsigned char)((0x00FF00 & spd) >> 8); spd_l = (unsigned char)(0x00FF & spd); // コマンド(レジスタアドレス)送信。 L6470_write(dir); // データ送信。 L6470_write(spd_h); L6470_write(spd_m); L6470_write(spd_l); Serial.print( " current spd = "); Serial.println( spd ); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2021/03/18 10:21

いまいちよーわかりませんが、トルク保持休憩、ってモータを停止させるってことでしょうか
fukufuku999

2021/03/18 10:38 編集

早速ありがとうございます!ひとまず、停止させたいです。
guest

回答2

0

状態マシンって考え方を知っておくとよいかと思います。

例えば、

Arduino

1//プログラム① 2const int LED1=4; 3const int LED2=5; 4void setup(){ 5 pinMode(LED1,OUTPUT); 6 pinMode(LED2,OUTPUT); 7} 8 9int state=0; 10//あるいは 11//int state =1; 12void loop(){ 13 if( state == 0 ){ 14 digitalWrite(LED1,HIGH); 15 }else if(state == 1){ 16 digitalWrite(LED2,HIGH); 17 } 18}

というプログラム、なにが起こるかわかりますね? stateが0のときには、if文はstate==0が真のときの動きしかしませんから、

Arduino

1void loop(){ 2 digitalWrite(LED1,HIGH); 3}

と同じこと。多分LED1が点灯するのでしょう。一方、state=1の方を生かせば

Arduino

1//int state=0; 2//あるいは 3int state =1; 4void loop(){ 5 digitalWrite(LED2,HIGH); 6}

と同じ。LED2が点灯。

では、ちょっと変えて、

Arduino

1//プログラム② 2const int LED1=4; 3const int LED2=5; 4unsigned long t0; 5void setup(){ 6 pinMode(LED1,OUTPUT); 7 pinMode(LED2,OUTPUT); 8 t0=millis(); 9} 10 11int state=0; 12void loop(){ 13 unsigned long t=millis(); 14 if( state == 0 ){ 15 digitalWrite(LED1,HIGH); 16 if(t-t0>500){ 17 digitalWrite(LED1,LOW); 18 t0=t; 19 state=1; 20 } 21 }else if(state == 1){ 22 digitalWrite(LED2,HIGH); 23 if(t-t0>300){ 24 digitalWrite(LED2,LOW); 25 t0=t; 26 state=0; 27 } 28 } 29}

としたらどうでしょう。なんだかプログラムが長くなった気もしますが、stateが0の間は

Arduino

1void loop(){ 2 unsigned long t=millis(); 3 digitalWrite(LED1,HIGH); 4 if(t-t0>500){ 5 digitalWrite(LED1,LOW); 6 t0=t; 7 state=1; 8 } 9}

だけ考えれば良くて、LED1を点灯しておいて前回t0を更新した時間から500m秒経ったらLED1を消す。その時間をt0に記録して、stateを1にするという動作です。stateが1になったら今度は

Arduino

1void loop(){ 2 unsigned long t=millis(); 3 digitalWrite(LED2,HIGH); 4 if(t-t0>300){ 5 digitalWrite(LED2,LOW); 6 t0=t; 7 state=0; 8 } 9}

LED2を点灯しておいて前回t0を更新した時間から300m秒経ったらLED2を消す。その時間をt0に記録して、stateを0にします。
結果として、プログラム②はLED1の点灯を500m秒、LED2の点灯を300m秒で交互に点灯するプログラムです。
もうちょっとひねって、以下はどうなるでしょう。

Arduino

1//プログラム③ 2const int LED1=4; 3const int LED2=5; 4const int SW1=8; 5unsigned long t0; 6void setup(){ 7 pinMode(LED1,OUTPUT); 8 pinMode(LED2,OUTPUT); 9 pinMode(SW1,INPUT_PULLUP);//追加 10 t0=millis(); 11} 12 13int state=0; 14void loop(){ 15 unsigned long t=millis(); 16 if( state == 0 ){ 17 //およそプログラム②と同じ 18 digitalWrite(LED1,HIGH); 19 if(t-t0>500){ 20 digitalWrite(LED1,LOW); 21 //t0=t; 22 state=1; 23 } 24 }else if(state == 1){ 25 digitalWrite(LED2,HIGH); 26 if(digitalRead(SW1)==LOW){//変えた 27 digitalWrite(LED2,LOW); 28 t0=t; 29 state=0; 30 } 31 } 32}

LED1が500m秒点灯して消灯/LED2点灯、LED2の点灯時にスイッチをON(スイッチはピンとGNDの間に入っているとして)にするとLED2が消灯してLED1が500m秒点灯する、ということになります。

このような構造を応用すると、

Arduino

1int state=0; //これを「状態変数」と呼ぶ 2void loop(){ 3 if(state==0){//状態0だったら 4 //処理0 5 if(他の処理に遷移する条件){ 6 //この状態の後始末 7 //次の状態への準備 8 //次の状態へ、状態変数の変更 9 } 10 } else if(state==1){//状態1だったら 11 //処理1 12 if(他の処理に遷移する条件){ 13 //この状態の後始末 14 //次の状態への準備 15 //次の状態へ、状態変数の変更 16 } 17 } else if(state==2){//状態2だったら 18 //処理2 19 if(他の処理に遷移する条件){ 20 //この状態の後始末 21 //次の状態への準備 22 //次の状態へ、状態変数の変更 23 } 24 } else if...(状態をいくつも繋げられる) 25}

という定形バターンで「次々と変わっていく状態」を記述できます。(switch文で書くことが多いのですが、知らない可能性を想定してif~else ifで書いています。知っているなら適宜置き換えてください)

今回であれば、

Arduino

1int state=0; 2void loop(){ 3 if(state==0){ 4 正転 5 if(リミットスイッチオン){ 6 時間取得 7 state=1; 8 } 9 }else if(state==1){ 10 逆転 11 if(550m秒経過){ 12 時間取得 13 state=2; 14 } 15 }else if(state==2){ 16 ブレーキ 17 if(100m秒経過){ 18 時間取得 19 state=3; 20 } 21 }else if(state==3){ 22 正転 23 if(550m秒経過){//もしかしたらif(550m秒経過 or リミットスイッチON)とした方がいいかも 24 時間取得 25 state=4; 26 } 27 }else if(state==4){ 28 ブレーキ 29 if(100m秒経過){ 30 時間取得 31 state=1; 32 } 33 } 34}

とすれば、とりあえず目的は達成出来るのではないでしょうか。
ブレーキの2箇所はそのつもりになれば一つにまとめられるでしょうが、とにかく動かす、ということで放置しています。

投稿2021/03/18 12:19

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ぐぐると出てくるページですが、

マイコンの実験:モータドライバ(L6470)の実験

L6470_Stop(mode)

  モータを停止させる処理関数です。
Hizはモータを停止させた後、モータの出力をOFF(ハイインピーダンス)にします。
mode:停止モードを指定します
0 = SoftStop 減速しながらモータを停止させます、保持トルク有り。
1 = HardStop 即時にモータを停止させます、保持トルク有り。
2 = SoftHiz 減速しながらモータを停止させます、保持トルク無し。
3 = HardHiz 即時にモータを停止させます、保持トルク無し。

ってな記述がありますが。

投稿2021/03/18 10:39

y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fukufuku999

2021/03/18 11:02

ありがとうございます。 これをどこに入れたらいいかわからりません。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問