こんにちは!や~べ~です。
今回は、モーター制御にも通じる!Arduino(アルディーノ、アルドゥイーノ?、アルデュイーノ?)とエンコーダーを使ったオモシロIoT工作&プログラムまとめ、ということで記事を書いていきたいと思います。
本格的にモーターを制御する為には、エンコーダー以外にも電流値などをセンシングする必要があると思いますが、今回はエンコーダーに焦点を当てて記事を作成していきたいと思います。
エンコーダーの情報を使えば、回転しているものの回転角度や回転数、速度、接地している紙などの長さ、車輪などが転がった距離など、を算出することができます。(>∀<)ノ☆
例えば、ラジコンの駆動モーターにエンコーダーが付属してるモーターを使用すれば、Arduino(アルドゥイーノ)にその情報を入力することで、モーターの回転数、速度などを算出することができます。(クルマの車速なども同じような考え方で検出&算出しています!)
※モーターの制御には、「PWM制御」などの、モーター制御方法の理解も必要だと思いますが、今回は割愛させていただきます。すみません。。。<(_ _)>
まずは、先日見つけた、ロータリーエンコーダーを使ったちょっと面白いIoTガジェット工作例の話から行きたいと思います。
1.Arduino(アルドゥイーノ)とロータリーエンコーダーを使ったちょっと面白いIoTガジェット工作例
先日、Arduino(アルドゥイーノ)関連の記事を漁っていると。。。
Arduinoを使って、「かなり攻めたIoTガジェット」を自作している記事を発見しましたぁ!!(∩´∀`)∩
その名も。。。
「トイレットペーパー使用量報告bot」
ネーミングセンスも去ることながら、精神年齢が大人になりきれてない自分にとっては、どんな動作をするのか期待感しかありませんっ!(>∀<)ノ☆
内容を見てみると、
「Arduino UNO」に「Ethernet Shield」を追加し、
マウスから入手した「ロータリエンコーダ」をトイレに設置、
その「ロータリエンコーダ」のセンサー信号をキャプチャし、
トイレットペーパーの使用量を検出、
さらに検出した数値をもとに、ツイッターbotから全世界へ向けて発信していくと言う、
シンプルな構成でありながら、面白IoTガジェットとして、発想をしっかりと具現化できている代物でした。。。(*^▽^*)
個人で自作してしまうあたり、かなりのツワモノだと思います。。。(*´ω`*)
こちらの記事↓
ただ現在(2018年3月時点)では、Arduino UNO用の「Ethernet Shield」の販売が終了してしまっているようなので、他の汎用Wi-Fiモジュール↓を使って、ネット接続&無線化を行っていく方が現実的のようです。
1-1.日本国内の技適も取得している汎用Wi-Fiモジュール「ESP-WROOM-02」について
汎用Wi-Fiモジュール『ESP-WROOM-02 (ESP8266 を内蔵)』
日本国内の技適も取得しており安心して使用できます。しかも、数百円とリーズナブル!
「ESP-WROOM-02」の接続方法や通信に関するプログラミング方法は、↓の記事を参考にして下さい。
電子工作でインターネットに無線接続して通信を行う (Arduino)
1-2.ロータリーエンコーダーの入手方法
ロータリーエンコーダーは、使い古したマウスか、リサイクルショップなどでジャンク扱いになってるマウスを分解して準備すれば、充分だと思います。
※光学式や無線マウスにもついている、マウス上方の、指で動かすホイール部分を使用します!
マウスの分解・組み立て関連の記事はこちら↓
分解後、ロータリーエンコーダーからの「A相」、「B相」、「GND」の3本の配線をはんだづけなどで延長する必要があると思います。
1-3.ロータリーエンコーダーからArduinoへの配線方法
ロータリーエンコーダーからの「A相」「B相」の2つのパルス信号は、いつも決まって「90°ずれて」それぞれ出力されるので、どちらのパルスが先に出力されたかを検出することによって、回転方向をセンシングすることができます。(↓図参照方)
(※↑ここでは簡単に説明してますが、厳密にはもう少し複雑な説明が必要かもしれません。。。)
出典:おもちゃラボ 「【Arduino】マウスホイール(ロータリーエンコーダ)の回転量を取得する」より
http://nn-hokuson.hatenablog.com/entry/2017/03/26/102145
↑エンコーダー逆転時はB相が90°早いタイミングで出力される構造になっています!
さらに「A相」「B相」それぞれのパルスは、出力する間隔(角度)が決まっているので、パルスの数を数えることによって、回転量(今回は、トイレットペーパーに密着させるので、引き出したペーパーの長さ)をセンシングすることができます。
このエンコーダーのパルスをArduinoで検出・計算させる為には、「attachInterrupt」という、「外部割り込み」機能を使用して、プログラミングする必要があります。
「Arduino UNO」で、この「外部割り込み」機能に使用できるピンは、「デジタル2番、3番」になるので、そこへロータリーエンコーダーからの「A相」、「B相」の配線を接続します。
「A相」⇒「デジタル2番ピン」
「B相」⇒「デジタル3番ピン」
「GND」⇒「GND」
※エンコーダーのピン配置ですが、メーカによって異なりますが、エンコーダーの端子が出ている方の面を手前にして、
左から「A相」、「B相」、「GND」となっているようです。
手順としては、机上でホイールを指で動かして、エンコーダーの動きとArduinoのプログラミング動作の確認ができたら、最後に、ホイールの表面がトイレットペーパーの表面に当たるように固定すると良いと思います。
Wi-Fi接続関連のハードルが少し高いかもしれませんが、エンコーダー部分の配線等に関しては結構簡単にできてしまいそうですよね!(*^▽^*)
ここまでは、「トイレットペーパー使用量報告bot」のエンコーダ入手方法や配線の解説をさせていただきました。
続いて、肝心のプログラミング内容の解説を少ししていきたいと思います。
2.「トイレットペーパー使用量報告bot」のArduino(アルドゥイーノ)プログラミング解説
まずは、プログラムの全体です。
//Copyright 2012 bildr //Released under the MIT License - Please reuse change and share //modified by Kei.Y - Additional portions license is CC0 #include <SPI.h> #include <Ethernet.h> #include <Twitter.h> byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Ethernet ShieldのMACアドレス byte ip[] = { 192, 168, 1, 123 }; //IPアドレス Twitter twitter("/* 取得したトークン */"); char msg[256]; int encoderPin1 = 2; int encoderPin2 = 3; volatile int lastEncoded = 0; volatile long encoderValue = 0; long lastencoderValue = 0; long encoderValueTemp = 0; long lastUse = 0; int stopCount = 0; int lastMSB = 0; int lastLSB = 0; void setup() { Ethernet.begin(mac, ip); Serial.begin (9600); pinMode(encoderPin1, INPUT); pinMode(encoderPin2, INPUT); digitalWrite(encoderPin1, HIGH); digitalWrite(encoderPin2, HIGH); attachInterrupt(0, updateEncoder, CHANGE); attachInterrupt(1, updateEncoder, CHANGE); } void loop(){ if(encoderValue > lastUse && (encoderValue - lastUse)>5){ if(encoderValue == encoderValueTemp){ stopCount++; if(stopCount > 3 ){ sprintf(msg,"おしりを拭きました(´ε`;)フキフキ 長さ%dcm",(int)((encoderValue - lastUse)/5.4)); postTweet(); lastUse = encoderValue; stopCount = 0; } } encoderValueTemp = encoderValue; } delay(1000); } void updateEncoder(){ int MSB = digitalRead(encoderPin1); int LSB = digitalRead(encoderPin2); int encoded = (MSB << 1) |LSB; int sum = (lastEncoded << 2) | encoded; if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; } void postTweet(){ Serial.println("connecting ..."); if (twitter.post(msg)) { int status = twitter.wait(); if (status == 200) { Serial.println("OK."); } else { Serial.print("failed : code "); Serial.println(status); } } else { Serial.println("connection failed."); } }
続いて、個別に解説していきます!
//Copyright 2012 bildr //Released under the MIT License - Please reuse change and share //modified by Kei.Y - Additional portions license is CC0 #include <SPI.h> #include <Ethernet.h> #include <Twitter.h>
↑ヘッダーファイル(.h)という、 Arduinoのプログラミングを補助してくれる初期設定ファイルを読み込む命令が書いてあります。
使用する機能や関数によって、必要なものを選んで読み込みます。
byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Ethernet ShieldのMACアドレス byte ip[] = { 192, 168, 1, 123 }; //IPアドレス Twitter twitter("/* 取得したトークン */"); char msg[256]; int encoderPin1 = 2; int encoderPin2 = 3; volatile int lastEncoded = 0; volatile long encoderValue = 0; long lastencoderValue = 0; long encoderValueTemp = 0; long lastUse = 0; int stopCount = 0; int lastMSB = 0; int lastLSB = 0;
↑変数の初期設定をしています。
変数というのは、センサ情報などのデータを忘れないように保存しておく「バケツ」のようなものです。
「int」「long」という最初のアルファベットの文字列でデータのサイズを決めていて、続いて変数の名前を登録しています。
初期値が定まっていないと、プログラムスタート時にプログラムが暴走して、意図しない動きをする可能性があるので、すべての変数に初期値を設定しています。
void setup() { Ethernet.begin(mac, ip); Serial.begin (9600); pinMode(encoderPin1, INPUT); pinMode(encoderPin2, INPUT); digitalWrite(encoderPin1, HIGH); digitalWrite(encoderPin2, HIGH); attachInterrupt(0, updateEncoder, CHANGE); attachInterrupt(1, updateEncoder, CHANGE); }
↑プログラムがスタートしたら1度だけ実行される「セットアップ」を行う関数です。
(プログラムは、基本、書いたプログラムの上から順番に下に向かって1行づつ実行していきます。)
ピンの入出力の選択、ピンのプルアップ設定、外部割込みの設定などを行っています。
void loop(){ if(encoderValue > lastUse && (encoderValue - lastUse)>5){ if(encoderValue == encoderValueTemp){ stopCount++; if(stopCount > 3 ){ sprintf(msg,"おしりを拭きました(´ε`;)フキフキ 長さ%dcm",(int)((encoderValue - lastUse)/5.4)); postTweet(); lastUse = encoderValue; stopCount = 0; } } encoderValueTemp = encoderValue; } delay(1000); }
↑このループ(loop)関数に書いてあるプログラムがメインとなるプログラムになります。
この関数内に書いてあるプログラムを、上から順番に1行づつ実行して、一番下まで行ったら、また再度一番上に戻って、電源が切れるまで実行しつづけます。
内容としては、
エンコーダーの信号から計算して、ある長さ以上トイレットペーパーが引き出されて、ペーパーの動きが止まったら、使用した長さをツイートする、という内容です。
void updateEncoder(){ int MSB = digitalRead(encoderPin1); int LSB = digitalRead(encoderPin2); int encoded = (MSB << 1) |LSB; int sum = (lastEncoded << 2) | encoded; if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; }
↑この関数では、エンコーダーの正転、逆転を判断し、パルスをカウントします。
※エンコーダー出力に変化があった時に、割り込んで、他のプログラムよりも優先して処理されます。(処理後は、再度もとの行に戻って、プログラムを実行します。)
※追記)↑のプログラムでも動くと思いますが、正確にエンコーダーパルスをカウントする為には、カウント動作の部分で割り込みが発生しないような記述が必要になるようです。理由としては、8ビットマイコンの場合、1バイトづつ数値を格納するのですが、例えば2バイト以上の変数へ数値を格納する際、上位1バイトと下位1バイトを2回に分けて格納する動作をするのですが、その2回の格納動作の間で割り込みが起こってしまうと、割り込み関数が作動してしてしまい、格納されるデータを意図せずアップデートしてしまうので、格納される数値が間違ったモノになってしまうからです。(intは2バイトの変数になります。)
詳しくは、↓サイトの情報が有用だと思います。(※居酒屋ガレージ店主(JH3DBO)様、ご指摘ありがとうございます!!<(_ _)>)
Arduino-UNO 割り込み処理のミスあれこれ:ロータリーエンコーダー
http://igarage.cocolog-nifty.com/blog/2022/03/post-fbb7ad.html
void postTweet(){ Serial.println("connecting ..."); if (twitter.post(msg)) { int status = twitter.wait(); if (status == 200) { Serial.println("OK."); } else { Serial.print("failed : code "); Serial.println(status); } } else { Serial.println("connection failed."); } }
↑ツイートを実行するプログラムです。ループ関数の中で、呼び出されています。
このように、プログラムは機能によって分けて書いておくと分かりやすいですね!(´∀`*)
Arduinoのプログラミングをする場合には、基本的には、この順番(ヘッダー呼び出し⇒変数の初期設定⇒セットアップ⇒ループ関数、その他の関数)で書いておくと良いと思います。
※C言語を使ったマイコンプログラミングでも、ほぼ同じような順番でプログラムを書いていきます。
※インターネット接続に、「Ethernet Shield」ではなく、「ESP-WROOM-02」を使用することになると思うので、初期設定やツイートを実行する関数などは、参考にできない部分があると思います。
※全文英語ですが、こちらの記事↓でもエンコーダーを使ったプログラミング方法が解説されています!
最後に、ロータリーエンコーダーの原理と構造、上手な使い方についてまとめていきたと思います。
3.ロータリーエンコーダーの原理と構造、上手な使い方について
ロータリーエンコーダーには、大きく分けると「インクリメンタル型」と「アブソリュート型」の2種類があります。
どちらの型も、片側から光を投射して、規則的にスリット(穴)の開いた回転する円盤を通過して検出される、光のON・OFF信号を利用したものが主流になっています。
※使用環境の厳しいクルマの車輪などには、ABSなどの高度な制御を行う為のセンサとして、光学的ではなく磁力を使ったメカ的なエンコーダーが使われることもあります。
3-1.「インクリメンタル型」ロータリーエンコーダーの原理と構造
「インクリメンタル型」は、発光ダイオードなどで発光した光が、円盤のスリットを通過して、フォトトランジスタで検出される単純な構造となっています。
出典:オムロン制御機器 「ロータリーエンコーダー編(原理と構造)」より
http://www.fa.omron.co.jp/guide/special/knowledge/re/principle_structure.html
実際に、プログラミングする際には、先ほどの「トイレットペーパー使用量報告bot」での使用方法と同様に、パルスを検出するプログラムを記述する必要があります。
※↑void updateEncoder()の部分。
3-2.「アブソリュート型」ロータリーエンコーダーの原理と構造
スリットを透過させた光のON・OFF信号を利用する基本的な考え方は「インクリメンタル型」と同様ですが、構造的に、光源、センサ、スリットがそれぞれ複数存在することが大きな違いになります。
複数のスリットを透過した光が、複数のセンサで検出されると、エンコーダーの回転角度(現在位置)を「グレイコード」と呼ばれる「2進数」の一種で表現できるようになっています。
「インクリメンタル型」で必要だったArduinoでのパルスカウントが不要で、エンコーダーからの情報がそのまま角度情報として使えます。(「グレイコード」の変換は必要だと思います。)
エンコーダーのスリット盤面に、直に、数字で「角度」情報が書かれているようなものなので、それを常に監視すれば、いつでもエンコーダーの絶対角度を検出することができます。
出典:オムロン制御機器 「ロータリーエンコーダー編(原理と構造)」より
http://www.fa.omron.co.jp/guide/special/knowledge/re/principle_structure.html
エンコーダーパルスをカウントするプログラムを記述する必要はありませんが、回転数などの情報が必要となる場合には、エンコーダーの情報をカウントアップ、またはダウンしていく関数が必要だと思います。
3-3.ロータリーエンコーダーの上手な使い方について(駆動、伝達、結合、カップリング方法)
回転運動しているものにローターリーエンコーダーを結合・接続する方法は、「直接駆動」、「段付きベルトによる伝達」、「歯車による伝達」、「フレキシブルカップリングによる駆動」の4つの方法が主に使われます。
今回紹介した「トイレットペーパー使用量報告bot」では、「直接駆動」でローターリーエンコーダーを使用しています。
出典:オムロン制御機器 「ロータリエンコーダ編(上手な使い方)」より
http://www.fa.omron.co.jp/guide/special/knowledge/re/good_usage.html
その他、参考にさせていただいた「Arduino&エンコーダー」関連の記事です。↓
【Arduino】マウスホイール(ロータリーエンコーダ)の回転量を取得する
RSコンポーネンツでは、汎用のロータリエンコーダを購入できますよ!
まとめ
モーター制御にも通じる!Arduino(アルディーノ、アルドゥイーノ?、アルデュイーノ?)とエンコーダーを使ったオモシロIoT工作&プログラムまとめ、ということで記事を書かせていただきましたが、いかがでしたでしょうか?
Wi-Fi接続部分の配線・設定・プログラミングの作業ボリュームが未知数なので、なんとも言えない部分もありますが、「ちょっと面白いかもなぁ~!」なんて思ったそこのあなた!ぜひ「トイレットペーパー使用量報告bot」自作してみてはいかがでしょうか?(>∀<)ノ☆
少し話が飛躍してしまうかもしれませんが、
昨今問題になっている、「老人の一人暮らしの安否確認」の手段の一つとしても、「使えるIoTガジェット」になり得るのではないかと思います。
遠方に高齢の親御さんがいて一人で生活している場合など、普通に日常生活で行っていることが、特別な操作をしなくても安否の情報として受け取ることができれば、心配な気持ちが少しでも和らぐのではないかと思います。(#^.^#)
(もちろん、この仕様のままではプライバシーに関わってしまう部分もあると思うので、色々と試行錯誤は必要だと思いますが。。。)
後半のエンコーダーの原理・構造については、モーターや回転体を使った装置を作る際に必要になる知識だと思うので、忘れてしまった時には、また読み返してみてくださいね~!(`∇´)
PWM制御などのモーター駆動・制御についての記事も、また次回以降書いていきたいと思いますので乞うご期待を!(>∀<)ノ☆
じゃあ、今回はここまでっ!!
ではではっ!(´∀`*)ノシ
おすすめArduino(アルドゥイーノ)関連記事
巷で流行っているArduinoですが、まずどのタイプのものを選んだらいいか迷ってしまうと思います。
そんな時に、参考にしたい記事がこちら↓
徹底比較。Arduino(アルディーノ)シリーズ23種類の価格、スペック、まとめ一覧表
これからArduino(アルディーノ)を使ってみようと考えてる方、既に使っていて他に便利な使い方がないかと思っている方はこちらの記事もどうぞ↓
こんな使い方があった!Arduino(アルディーノ)完全攻略。選び方から使用方法のまとめ
ランキング
ランキングに参加しています!
もしこの記事を気に入っていただけたなら、↓クリックで応援していただけると、とても嬉しいです! (∩´∀`)∩
※クリックで「みなラボ」へ1票&「みなラボ」のランキング状況を確認いただけます!
どうぞ、よろしくお願いいたします!m(_ _)m
↓こちらもお願いしますっ!