LoginSignup
3
3

More than 5 years have passed since last update.

VR空間移動用いす型デバイスを作成する⑤いすの回転を光センサで読み取ってみる

Posted at

続けて椅子の回転を読み取ってみます。

目次

1.エンコーダと回転検知について
2.歯車を作ってみる
3.センサ部分を組み立てる
4.ArduinoUNOのプログラム

1.エンコーダと回転検知について

回転を検知するには、エンコーダというものが使われます。世の中にあるのは小型になっているので同じサイズは難しいのですが、大きくても良ければ自作できます。
エンコーダは歯車の歯を検知することにより、歯車が回転したかを検出します
さらにセンサを二つ使用する(他にもいろいろやり方あります)と回転の方向までわかります。

通常のエンコーダは歯車が回転し、歯をセンサや電気的接触等で検知しますが、今回はセンサが回転し、歯車は固定となります。いすは上部の座る部分が回転しますが、こちらにArduinoはじめ回路部分が存在するため、センサもこっち側になりました。

センサには反射型の光センサを使用しています。秋月電子で売ってる「反射型フォトインタラプタ GP2A200LCS」というやつです。
近赤外線の光を照射し、物がる場合、反射してきた光を検知するというセンサです。

センサを二つ使うと、センサのON・OFFする順番が歯車の右回りと左回りで異なりますので、回転方向もわかります。

2.歯車を作ってみる

歯車を作ります。

歯の数は18です。とりあえず勘で歯の数は決めてます。歯の数が多くなるほど細かく角度を検知できまが、歯車のサイズは大きくなるでしょう。作った歯車の直径240㎜です、反射型光センサの横幅が二つで18㎜あるので、歯の横幅および歯のない部分の幅も18㎜なるようにしました(狭すぎるとセンサが二つともにOFFまたはONにならない。)。
歯車はカラーボードで作成しました。100均で売っています。カッターで加工できるので便利です。

ネット上にある分度器の絵を当該サイズに拡大して裏面になる側に貼っておくとうまく切れます。色は黒だと赤外線が反射しにくいため検知距離が短い、白だと逆に反射しすぎるてチャタリングが発生するので青にしました(本当は灰色が良かったのだが、売ってなかった。)。青でも少しチャタリングするのですが・・・。
これをいすに取り付けます。適当なものが見当たらなかったので、サドルバンド(塩ビ管の固定に使うやつね)を使った。内径が合わないので、内側にゴム巻いてサイズを合わせた。

いすの座面を外した後、上に歯車をつけられるようにL字の金具をはめて閉めています。反対側についているのはUSBケーブルを通すための冶具です(。USBケーブルはそのまま下に垂らすと歯車やセンサに絡まる可能性があるからです。3Dプリンターで作りました。

なお、USBケーブルを使用している理由は展示会等に出展するためです。展示会のような人の多い会場では電波が汚染されており、無線通信の使用はむずかしいです。もし、個人で使う場合ならBluetooth等を使用したほうが楽でしょう(この冶具だけで1800円・・・)。

3.センサ部分を組み立てる

センサ側を組みましょう。

同じように軸の回転する側にサドルバンドや金具をつけます。先端のセンサを取り付ける部分は3Dプリンタで作っています。センサの裏に凸部と先端に丸穴があるのでうまくはまるようにしています。できたものが思ってたより肉薄かったので裏をパテで補強しています。

歯車とセンサの距離は(自分が座って、少し沈み込んだ状態で)1㎝程度としました。重い人が乗るとさらに沈み込んで、歯車とセンサが接触する可能性があります。余裕を見ておいたほうが良いでしょう、一方で、遠すぎると赤外光が距離の分だけ広がりますので、センサの検知範囲が広くなります。凹部を検知しにくくなります。
以下のような回路でセンサの出力をArduinoにつなぎます。

センサの出力にLEDをつけているのは目視でセンサのON/OFFを確認するためです。なお、出力をいったんコンパレータで整形してArduinoに送付しています。おそらくこのコンパレータは不要と思うのですが、センサからArduinoまでの距離が長いので、波形がなまっていないか不安で入れました。オシロスコープとかあれば波形を確認できるのですが・・・。
また、TLP222Aはフォトモス(無接点スイッチ)です。このスイッチでセンサの電源をArduino側からON/OFFできます。センサは出力確認時のみ電源をつなぎます。下図のようなセンサ間の干渉を避けるためです。二つのセンサが同時に動作していると、隣のセンサからの赤外光が反射し入ってきてしまいます。

フォトモス使った理由は安いからです。リレーとかでも問題ありません。
実際の回路とか

4.ArduinoUNOのプログラム

Arduno側のプログラムを組みPCに角度っを表示してみましょう。

interrupter.ino
#define VddClock        7
#define VddAntiC        8
#define Clockwise       12
#define Anticlockwise   13
int pdClock,pdAntiC,pdStatus,prePdStatus,transStatus,angle;

void setup() {
    pinMode(VddClock,OUTPUT);
    pinMode(VddAntiC,OUTPUT);
    Serial.begin(9600);
    GetInterrupterStatus();
}
void loop() {
    GetInterrupterStatus();
    if(transStatus==0) angle=angle;
    else angle=angle+transStatus;
    if(angle<0) angle=355;
    if(angle>355) angle=0;
    Serial.print(" angle ");
    Serial.println(angle);
}
void GetInterrupterStatus(){
    //pdStatus=12output+13output 00=0 01=1 11=2 10=3
    //transStatus 0->1=5 1->2=5 2->3=5 3->0=5 0->3=-5 3->2=-5 2->1=-5 1->0=-5
    digitalWrite(VddClock,LOW);     //Vdd ON
    digitalWrite(VddAntiC,HIGH);    //Vdd OFF
    delayMicroseconds(3500);
    pdClock = digitalRead(Clockwise);
    digitalWrite(VddClock,HIGH);    //Vdd ON
    digitalWrite(VddAntiC,LOW);     //Vdd OFF
    delayMicroseconds(3500);
    pdAntiC = digitalRead(Anticlockwise);
    digitalWrite(VddClock,HIGH);    //Vdd OFF
    digitalWrite(VddAntiC,HIGH);    //Vdd OFF

    if(pdClock==0){
        if(pdAntiC==0) pdStatus=0;
        else pdStatus=1;
    }
    else{
        if(pdAntiC==0) pdStatus=3;
        else pdStatus=2;    
    }
    transStatus=5*(prePdStatus-pdStatus);
    if(transStatus==15||transStatus==-15) transStatus=-1*transStatus/3;
    prePdStatus=pdStatus;
}'

Arduinoのツール→シリアルモニタを起動し結果を見てみます。
いすを回転させると角度が変化するのがわかります。

ちょっと解説です。
ⅰ.Arduinoのプログラムについて
・ GetInterrupterStatus() 以下
干渉を避けるためセンサは片側ずつ電源ONにします。TLP222AのターンON時間が最大2ms、センサの応答時間が最大1msでした。500us余裕を見て、3500us後にセンサの出力を確認しています。
Arduinoの13pinにつながっているセンサと12pinにつながっているセンサについて、各センサの出力が0(凸部)、1(凹部)かにより、下表のように状態を0~3に振り分けています。これで状態が一つ増えるごと(3から0をのぞく)に右回り5度増加、一つ減るごと(0から3をのぞく)に右回り5度減少となります。

センサ_12pin センサ_13pin 状態
0 0 0
0 1 1
1 1 2
1 0 3


10度刻みで凹凸が入っているため、どちらかのセンサの値が変化すると5度の変化です。状態の差分に5をかけます。その後、3からまたは3に変化した場合には変化量が15度になってしまいますので、15の場合は-5にもどしています。
・void loop() のなか
変化量を角度に加算しています。なお、360度になる場合は0度、-5度になる場合には355度に変更します。

ⅱ.結果について
Arduinoに電源投入した位置が原点(0度)です。
右に回してみました。5度ずつ値が大きくなっていくのがわかります。

以上になります。
UnityとかのPCとのデータの受け渡しをどうするのかについては、ネット上にいろいろあるので説明しないです。
次は少し振動モーターの話をしてみたい。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3