VR空間移動用いす型デバイスを作成する⑦椅子の回転を読み取る（小型化）

⑤で説明したエンコーダの小型化してみました。
歯車を小型化します。また、歯の有無は赤外LEDとフォトダイオード（PD）の組み合わせで検出を行います。

#目次
１．エンコーダと回転検知について
２．歯車・センサ取付冶具を作る
３．センサ部分の回路を組む
４．組み立てる
５．ArduinoUNOのプログラム

#１．エンコーダと回転検知について
⑤と基本的に同じで、歯の有無を光センサで検出して回転しているかをみます。二つのセンサを使うことで回転方向がわかります。
歯車側が固定され、検出するセンサ側が回転します。ただし、センサには2つの赤外線LEDと一つのPDを使用します。
<img width=50% src=https://qiita-image-store.s3.amazonaws.com/0/184089/39af6901-772c-460d-4aaa-abe663f3ea8e.png>
（右写真は撮影しやすいように上の座面を外してある）
歯車を軸の回転しない側、センサを回転する側に固定します。
歯車及びセンサ取付用の冶具は3Dプリンタで作成しています。
<img width=50% src=https://qiita-image-store.s3.amazonaws.com/0/184089/3670b716-d090-9162-5c55-3216960bb09e.png>
センサ側の基板です。（撮影しやすいように歯車は下に動かした）
LEDを片方ずつ光らせます。LEDの前に物体があればPDに光が物体に反射して戻ってきます。

#2．歯車・センサ取付冶具を作る
歯車・センサ取付冶具を設計します。3DCADソフト（Fusion360）でモデルを作成し、3Dプリンタで出力します（DMM.MAKEに発注）。
まず、設置場所の寸法を確認します。（いすはニトリで買った「ワークチェア(ウェイビー2 BK)」）
<img width=30% src=https://qiita-image-store.s3.amazonaws.com/0/184089/e2760a76-5146-1718-d4be-a43549c4a568.png>
歯車をつける軸（黒）が直径50㎜、センサをつける軸（銀）が直径25㎜でした。
取り付けに余裕を持たすため、歯車の内径は55㎜とします。
二つに分割してあり、軸（黒）を挟み込んだ後、ねじ（M3）止めすることで固定できます。
歯と隙間が10度毎に来るようにするため、歯の数が18とします。
また、使用するLEDの直径が3㎜であり、2個分のサイズが入る（2個分のLEDの光が歯の間を透過または歯に反射する）ようにしたいと思います。
歯の横幅および歯の間の隙間が6㎜以上になるように外径を80㎜とします。歯車部分の厚さは2.5㎜としたので、歯の横幅および歯の間の隙間が6.5㎜になります（LED二個分6㎜に対して0.5㎜の余裕あり）。
<img width=50% src=https://qiita-image-store.s3.amazonaws.com/0/184089/d4a2765b-1568-71bf-e144-3ba88f672951.png>

<img width=40% src=https://qiita-image-store.s3.amazonaws.com/0/184089/10da827d-7406-6cbb-3b5a-8a5da1735fe0.png>

センサ基板の取付用冶具も余裕を見て内径を30㎜とします。
これも軸（銀）を挟んでねじ（M3）でねじ止めできます。
冶具には穴（間隔20㎜）があり、基板をねじ止めできるようにしてあります。
<img width=50% src=https://qiita-image-store.s3.amazonaws.com/0/184089/a1868af6-c98b-95ea-5208-93025439bbf5.png>
LEDと歯車をできる限り近づけたため、LEDの寸法と基板厚さを考慮し、LED-歯車間5㎜になるように作成してみました。
<img width=50% src=https://qiita-image-store.s3.amazonaws.com/0/184089/d1d482ba-06a1-0296-2ffb-1e684f90fc11.png>
出力した実物の写真です。
<img width=50% src=https://qiita-image-store.s3.amazonaws.com/0/184089/5b595494-743d-3e29-1e45-44570017d76a.png>

以下のサイト「3D CAD DATA.com」に投稿してみました。
STLファイル用のビュワーがあれば見れるはず。
【センサ基板取付冶具】
http://www.3d-caddata.com/3d_print_designs/view/567
http://www.3d-caddata.com/3d_print_designs/view/568
【歯車】
http://www.3d-caddata.com/3d_print_designs/view/569
http://www.3d-caddata.com/3d_print_designs/view/570

#3.センサ部分の回路を組む
以下のように回路を組みます。
<img width=40% src=https://qiita-image-store.s3.amazonaws.com/0/184089/a2882b7a-038b-6ca0-b3e8-ef6e58770427.png>
LEDは光が広がらないように（歯の誤検知や余計な反射光を減らす。）半減値が小さいものを使いました。
センサの感度を変更できるように可変抵抗をLEDに直列に入れてあります。
LEDの光量を可変抵抗で変更できれば、センサの感度を変えられます（光量大→感度大）。
なお、200Ωの抵抗も直列に入れることで20mA以上の電流が流れることを防いでいます。（ArduinoUNOの出力PINは20mAくらいまでしか流せない・・・）
PDは直列に300kΩの抵抗を入れてあります。PDに光が入るとPDに電流が流れ300kΩ抵抗とPD接続部の電圧値が降下します。
コンパレータで電圧値を比較します。PDが一定以上電流を流すと電圧値が降下、コンパレータ出力がLOW → HIGHに変化します。
NJM2903はコンパレータが二つ入っているため、片方が余ります。これをヒステリシスを作るために使います（チャタリング等が防げます）。
入光なし→入光あり（コンパレータ出力LOW→HIGH）の場合、300kΩ抵抗とPD接続部の電圧しきい値は1.5Vですが、入光あり→入光なし（出力HIGH→LOW）では3.3Vに変化します。

回路を組みます。基板を分割した後、キリやペンチで穴をあけ固定用冶具につけられるようにします。
<img width=40% src=https://qiita-image-store.s3.amazonaws.com/0/184089/e333182b-176c-4c9a-5971-1140e886a797.png>

<img width=40% src=https://qiita-image-store.s3.amazonaws.com/0/184089/fcdcdc7a-1d7c-8874-ac76-040b55260569.png>

LEDはできるだけ密着するようにし（少し縁をやすりで削った）、高さを揃えます。
LEDが少しでも傾いているとうまく歯車を検知できなくなるので注意です。
また、LEDとPDの間にはAL板（マジックで黒く塗ってある）をしきりとして接着剤ほかでつけています。LEDの光が直接PDに入ってこないためです。

#4．組み立てる
内側にスポンジ（厚さ3㎜）をつけ、ずれ落ちないようにします。
<img width=40% src=https://qiita-image-store.s3.amazonaws.com/0/184089/7b39f357-bce5-3292-af1a-bd3227758b65.png>
基板を冶具にねじ（M3）とナットでつけます。
<img width=30% src=https://qiita-image-store.s3.amazonaws.com/0/184089/d5a266d7-6943-1971-21d3-650e2455d299.png>
いすに組み付けます。
できるだけLEDと歯車の歯が近づくようにします（5㎜くらい？）。
また、人が座ると少し沈むため、センサは少し上目につけます。
<img width=40% src=https://qiita-image-store.s3.amazonaws.com/0/184089/86a0385e-b6f4-9b29-ecf3-a6094df7622e.png>


#5．ArduinoUNOのプログラム
センサ部分をArduinoにつなげた後、Arduno側のプログラムを組み込み、PCに角度を表示します。
以下のようにプログラムをArduinoに書き込んでみました。

```arduino:PDandLED.ino
#define	PD				5
#define	IRRight			6
#define	IRLeft			9
#define	DelayTime		5

int rPD,lPD,pdStatus,transStatus,prePdStatus,angle;
void setup() {
	Serial.begin(9600);
	pinMode(IRRight,OUTPUT);
	pinMode(IRLeft,OUTPUT);
	digitalWrite(IRRight,LOW);
	digitalWrite(IRLeft,LOW);
}
void loop() {
	delay(DelayTime);
	
	digitalWrite(IRRight,HIGH);
	delayMicroseconds(500);
	rPD = digitalRead(PD);
	digitalWrite(IRRight,LOW);
	delayMicroseconds(500);
	digitalWrite(IRLeft,HIGH);
	delayMicroseconds(500);
	lPD = digitalRead(PD);
	digitalWrite(IRLeft,LOW);
	delayMicroseconds(500);
	
	if(rPD==0){
		if(lPD==0) pdStatus = 0;
		else pdStatus = 3;
	}
	else{
		if(lPD==0) pdStatus = 1;
		else pdStatus = 2;
	}
	
	transStatus=pdStatus-prePdStatus;
	if(transStatus == 3) transStatus = -1;
	else if(transStatus == -3) transStatus = 1;
	prePdStatus=pdStatus;
	
	if(transStatus==0) angle=angle;
	else if(transStatus==-1||transStatus==1) angle=angle+transStatus;
	if(angle<0) angle=72+angle;
	if(angle>71) angle=angle-72;
	Serial.println(angle*5);
}
```
Arduinoのツール→シリアルモニタを起動し結果を見てみます。
いすを回転させると角度が変化するのがわかります。
<img width=30% src=https://qiita-image-store.s3.amazonaws.com/0/184089/b11294c9-28fa-c6e1-82f2-fbf959b9b8c1.png>

ちょっと解説です。
<font color="DeepSkyBlue">ⅰ．Arduinoのプログラムについて</font>
・setup以下
LEDにつながっているPINを出力に指定し、一旦LEDを消灯します。
・loop以下
LEDを交互に点灯させ、PDの出力を確認します。
LEDもPDもすぐ反応するわけではないので、500us待ってからPD出力を確認しています。確認後はLEDを消灯します。
各LEDが光った時のPDの出力が0（歯無）、1（歯有）かにより、下表のように状態を0~3に振り分けています。これで状態が一つ増えるごと（3から0をのぞく）に右回り５度増加、一つ減るごと（0から3をのぞく）に右回り5度減少となります。

|LED（右）点灯時のPD|LED（左）点灯時のPD| 状態 |
|:-----------:|:------------:|:----:|
|0            |0             |0     |
|1            |0             |1     |
|1            |1             |2     |
|0            |1             |3     |
その後、3から0または0から3に変化した場合には変化量がおかしくなってしまいますので、3の場合は-1に-3の場合は1にもどしています。10度刻みで歯が入っているため、どちらかのセンサの値が変化すると5度の変化です。PCに出力する際に5をかけて角度にしています。
（00→11または11→00で10度の変化なので、その半分の変化は約5度となる。）

<font color="DeepSkyBlue">ⅱ．結果について</font>
Arduinoに電源投入した位置が原点（0度）です。
右に回してみました。５度ずつ値が大きくなっていくのがわかります。

以上になります。