質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Arduino

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

Q&A

解決済

4回答

2113閲覧

【Arduino】ロータリーエンコーダの使い方

Alyn

総合スコア50

Arduino

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

0グッド

0クリップ

投稿2018/11/02 13:23

編集2018/11/18 01:14

実現したいこと

ロータリーエンコーダから来る値を読み取ってシリアル通信で表示する。
下記プログラムを実行するとロータリーエンコーダを触っていないにも関わらずA,Bの値が変化してしまいます。
ロータリーエンコーダを動かした時だけ、A,Bの値が変化するようにするにはどうしたらよいでしょうか?

ソースコード1

Arduino

1int EnPinA = 3; 2int EnPinB = 4; 3int ledPin12 = 12; 4int ledPin13 = 13; 5 6void setup() 7{ 8 pinMode(EnPinA, INPUT); 9 pinMode(EnPinB, INPUT); 10 pinMode(ledPin12, OUTPUT); 11 pinMode(ledPin13, OUTPUT); 12 Serial.begin(9600); 13} 14 15void loop() 16{ 17 int A = 0; 18 int B = 0; 19 20 A = digitalRead(EnPinA); 21 B = digitalRead(EnPinB); 22 23 Serial.print("A : "); 24 Serial.print(A); 25 Serial.print(" / "); 26 Serial.print("B : "); 27 Serial.println(B); 28 29 digitalWrite(ledPin12, A); 30 digitalWrite(ledPin13, B); 31 delay(100); 32}

回路

ロータリーエンコーダはD3,D4,GNDと繋がっている。
LEDは2つあり、1つ目はD12とGND、2つ目はD13とGNDと繋がっている(間に抵抗器あり)。

.【ロータリーエンコーダ】
.  A   B   G
.  │  │  │
.  D3  D4  GND
.【   Arduino   】
.  D12 GND D13 GND
.  │  │ │  │
.  抵抗 │ 抵抗 │
.  │  │ │  │
. 【LED 1】【LED 2】

追記1

申し訳ありません。実機が手元になくて動作確認できていません。

シリアル通信の速度は9600で大丈夫なのでしょうか?

追記2

ソースコードを改良致しました。
0,1の値が操作なしに変化することはなくなりました。
ありがとうございました。

ソースコード2

Arduino

1int EnPinA = 3; 2int EnPinB = 4; 3int pos = 0; 4void Position(int, int); 5 6void setup() 7{ 8 pinMode(EnPinA, INPUT_PULLUP); 9 pinMode(EnPinB, INPUT_PULLUP); 10 Serial.begin(57600); 11 Serial.print("pos : "); 12 Serial.println(pos); 13} 14 15void loop() 16{ 17 int A = 0; 18 int B = 0; 19 A = digitalRead(EnPinA); 20 B = digitalRead(EnPinB); 21 Position(A, B); 22} 23 24void Position(int A, int B) 25{ 26 static int bA = 1; 27 static int bB = 1; 28 static int bpos = 0; 29 30 if((bA == A) && (bB == B)) 31 { 32 // 何もしない 33 } 34 else 35 { 36 // bAbB == 00 or 11 37 if(bA == bB) 38 { 39 if((bA != A) && (bB == B)) 40 { 41 pos++; // 右 42 } 43 else if((bA == A) && (bB != B)) 44 { 45 pos--; // 左 46 } 47 } 48 // bAbB == 01 or 10 49 else 50 { 51 if((bA != A) && (bB == B)) 52 { 53 pos--; // 左 54 } 55 else if((bA == A) && (bB != B)) 56 { 57 pos++; // 右 58 } 59 } 60 61 if(bpos != pos) 62 { 63 Serial.print("pos : "); 64 Serial.print(pos); 65 if(bpos < pos) 66 { 67 Serial.println(" →"); 68 } 69 else 70 { 71 Serial.println(" ←"); 72 } 73 bpos = pos; 74 } 75 bA = A; 76 bB = B; 77 } 78}

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

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

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

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

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

YOshim

2018/11/03 15:02

エンコーダー信号のH/L切り替えの時間はどの程度でしょうか。エンコーダーの仕様がわかれば、シリアル通信の速度が十分かどうかが判断できます。1回転あたりのpulse数と1秒あたりの回転数から、1pulseの時間が算出できます。
guest

回答4

0

仕様書に一回転で24パルスと書いています。
これはご自身の手で回転させるつもりでしょうか。
そうであれば、仮に1秒最大1回転として、4逓倍エンコーダーであることを考慮し、
24 x 4パルス/秒 => 10ms/pulse。
シリアル通信の9600bpsのときの1charの通信速度はおおよそ1000回/s => 1ms/回なので、
9600でもエンコーダーの状態を取りこぼすことはないと思います。
エンコーダーを早く動かした際に値が狂うようならボーレート上げてみてください。

また仕様書の4.3のfig.2にテスト回路が記載されています。
この内容を真似してプルアップ抵抗10kohmを接続してください。
*5V(or 3.3V)電源ラインとエンコーダーのA/B端子間に接続してください。

投稿2018/11/05 01:22

YOshim

総合スコア1085

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

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

0

既に回答が付いていますが、実際の結線はどうなっているのでしょうか?
出力が安定しない件は、Pullupかな、という気もしますが、相手機器との接続が分かっていないと不明です。

検索したら、 意外と知られていない?INPUT_PULLUP とか、pinMode (pin, mode) とかありました。

あと、別の方も触れていますが、 ロータリエンコーダ出力を シリアル通信で取得するのは無理があるかもです。 (変化が早すぎる) LED点滅は、動いているが分かるレベルと思います。

参考情報として。

投稿2018/11/03 11:36

pepperleaf

総合スコア6383

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

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

0

ベストアンサー

A相、B相それぞれのレベルを覚えておいて、立ち上がり/立ち下がりのエッジを捉えてカウントしていく操作をする必要がありますね

右回転の検出でカウントUP、左回転でカウントDOWN、それをどう判断するか考えてみてください


なんかまだ解決してないようで、、
まず、
pinMode(EnPinA, INPUT_PULLUP);
pinMode(EnPinB, INPUT_PULLUP);
としてください。
これでレベルが勝手に変わる、ということはなくなります

で、ここで言うロータリエンコーダとはダイヤルタイプの接点出力のヤツだと思いますが、これをきちんと動かそうとするとちとめんどくさいです
こっちでやったのは、1msほどのタイマ割り込みでA相B相を取り込み、チャタリング処理&エッジ検出してカウントさせるってことをやってました。
これだとArduinoNanoでもきちんとカウント動作ができます

投稿2018/11/02 13:41

編集2018/11/03 12:34
y_waiwai

総合スコア87774

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

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

Alyn

2018/11/02 13:55

左右の識別はif文使えばできますけど、何もしてないのに値が変化すると左右の識別できないと思います…
y_waiwai

2018/11/02 13:58 編集

そっちのほうは別回答を参照しましょう ifをつかえば、、、できるといいねえw
Alyn

2018/11/02 13:59

具体的にどうしたら良いのでしょうか?
y_waiwai

2018/11/02 14:02

まずは別回答を実行して、ちゃんと値が出るようにしてください
YOshim

2018/11/02 15:16

ロータリーエンコーダーって結構なスピードで信号のH/Lが切り替わるので 回転スピードによってはArduinoでは難しいかも。 仕様書と回転速度から信号のH/Lの周期を確認してみてください。 とりあえずdelayはdelayMicrosecondsにしてみましょう。
guest

0

とりあえずINPUTをINPUT_PULLUP

投稿2018/11/02 13:28

ozwk

総合スコア13521

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

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

Alyn

2018/11/02 13:56

どう違うのですか?
ozwk

2018/11/02 14:00

入力が内部抵抗介してハイレベルに繋がるようになる
pepperleaf

2018/11/03 04:19

確かに定番エラーですね。 昔、それで失敗した。 Pull Upしておかないと、出力が不安定になるので、Hi/Lowも不安定となる。 回路が分からないので、なんともですが、可能性の一つ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問