【Contacts IoT】コンタクトレンズの着脱を検知するケースを作ってみた

はじめに

テントの中から失礼します、CX事業本部のてんとタカハシです!

コンタクトレンズ使用者を眼障害から守ることを目的として、コンタクトレンズの着脱管理を行う IoT プロジェクトを進めています。 プロジェクトの概要については、下記の記事をご参照ください。

本プロジェクトに関する記事の一覧は下記のページにまとまっています。

概要

下記の記事に記載した、コンタクトレンズ着脱検知方法のボタン案を試してみました。

まず、コンタクトケースを格納する検知用ケースを作ります。コンタクトケースを格納する際、コンタクトケースの端をボタンに当て、押下させる仕組みによって状態を検知します。

検知用ケースにコンタクトケースが格納されていれば未着用の状態。逆であれば着用中と判定します。コンタクトレンズ着用時は、コンタクトケースを洗浄して自然乾燥させる必要があるため、検知用ケースにはコンタクトケースを格納しないという使い方になります。

検知用ケースを作りますとは言っても、見た目がカッコイイ感じではなく、とりあえず想定通りに動くそれっぽいものになります。部品はそれぞれマスキングテープで止めたりします。カッコイイちゃんとしたケースの作成は将来的な話になります。

デモ

コンタクトケースの押し込みによってボタンが押下されると、サーボモータの羽によりコンタクトケースが固定され、LED が光ります。この状態が「未着用」となります。

再度、ボタンを押下すると、サーボモータによる固定が解除され、LED の光が消えます。この状態が「着用中」となります。

検知用ケースの作り方

使用する部品

サーボモータは、格納したコンタクトケースを固定するために使用しています。SDカードリーダーなどに採用されているプッシュイン/プッシュアウト方式(差し込み/取り出し時に押し込んでカチッと音が鳴るやつ)を実現したかったのですが、仕組みがよくわからず、とりあえずサーボモータで固定する案にしました。

LED はコンタクトレンズの着脱に応じて光らせます。

使用する工具

穴あけ用のドリルやらヤスリやらビニル電線を剥ぐやつなどです。

ケースに穴を開けて部品を埋め込む

プラスチックケースのサイズはW48×D74×H28mmです。

ケースの蓋を取り外し、コンタクトケースが入る幅の穴を開けます。他にもっと良いやり方があるかもですが、ドリルで穴を開けまくって、ひたすらヤスリました。

反対側にも穴を開けます。左側はサーボモータのリード線を通す用、右側はタクトスイッチを埋め込む用の穴です。タクトスイッチ用の穴は大きく開けすぎると上手く埋め込めなくなっちゃうので、テーパーリーマーを使って穴の大きさを確認しながら開けました。

タクトスイッチを埋め込みます。

後ろから見るとこんな感じで、マスキングテープで固定します。

タクトスイッチのピンに IC クリップを挟みます。

IC クリップのキャップを外して、ビニル電線を先端に巻き付けます。本当は半田付けした方が良いかもですが、とりあえずの対応です。

サーボモータの羽が、丁度コンタクトケースの真ん中に来るように設置します。リード線は穴に通します。

ケースの入り口に無駄なスペースが残っているので、スポンジで埋めます。

配線

下記の配線図を参考にして、それぞれの部品とラズパイを繋げます。

こんな感じになります。

ラズパイ側の実装

環境

Raspberry Pi の環境は下記の通りです。

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

$ python3 --version
Python 3.7.3

$ pip3 --version
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)

準備

サーボモータを良い感じに制御するため、wiringpiをインストールします。

$ pip3 install wiringpi

実装

ボタンが押下されたら、LED を光らせ、サーボモータの羽でコンタクトケースを固定します。再度ボタンが押下されたら、LED の光を消して、サーボモータの羽による固定を解除します。

import RPi.GPIO as GPIO
from time import sleep

import wiringpi

LED_PIN = 25
BTN_PIN = 24
SERVO_PIN = 18
OPEN = 36
CLOSE = 80

on_off = GPIO.LOW


def callback(ch):
    global on_off
    if ch == BTN_PIN:
        on_off = not on_off
        GPIO.output(LED_PIN, on_off)
        if on_off == GPIO.HIGH:
            wiringpi.pwmWrite(SERVO_PIN, CLOSE)
        else:
            wiringpi.pwmWrite(SERVO_PIN, OPEN)


GPIO.setmode(GPIO.BCM)
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(BTN_PIN, GPIO.RISING, callback=callback, bouncetime=200)

wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(SERVO_PIN, wiringpi.GPIO.PWM_OUTPUT)
wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS)
wiringpi.pwmSetClock(375)
wiringpi.pwmWrite(SERVO_PIN, OPEN)

try:
    print('start...')
    while True:
        sleep(0.01)

except KeyboardInterrupt:
    pass

print('end...')

GPIO.cleanup()

実行

$ python3 main.py

これでデモ動画の動作を確認できます。

次回予告

今回作った検知用ケースをバックエンドに繋げて、着脱した時間をデータベース上に保存できるようにします。

おわりに

3D プリンターを使ったケース作りができるようになりたいなあと思いました。引き続き頑張ります。

今回は以上になります。最後まで読んで頂きありがとうございました!