リモートワークで患った腰痛をPythonと1000円くらいで改善した話

f:id:mukiebikun:20220307183810p:plain:w400

はじめに

こんにちは。 開発部の川上です。

突然ですが皆さん、腰の調子大丈夫ですか?
私はリモートワークを一昨年から始めていますが、明らかに昔と比べて腰の不調が増えています。
そこで今回の記事では、リモートワークで酷使された腰を技術の力で改善した話について紹介します。

腰痛対策案の検討

デスクワークが起因する腰痛の改善についてネットで調べると、改善方法はいくつかあるみたいで、

  • 定期的に体を動かす
  • 座っているときの姿勢に気をつける
  • 自分にあった椅子を見つける

ことが改善方法の一例みたいです。

1番目の対応は簡単ですが、2番目の対応は常に自分の姿勢に気をつけなければいけなく、大変そうです。
コードを読む際に猫背になっていることも多いので、今回はこの点を重点的に改善していきます。
3番目ができるならこんな記事書いてませんね。

改善方法

猫背が悪い姿勢の一環のようなので、改善方法をシンプルに考えると、
「猫背になってしまったら、猫背を治すよう促せばいい」
と判断しました。

また、猫背になっているときってどんなときだ?とも考えると
「背もたれに寄りかかっていない時、つまり、背もたれが傾いていない時」
とも判断できました。

もうここまでくればあとは簡単です。
「背もたれが傾いていない時、ユーザーは猫背になっていると判断する。その場合、画面に何らかの警告を出し、猫背を治すために、背もたれに寄りかかってもらうことを促す」
これを改善方法とすることとします。

どうやって背もたれの傾きを検知するか

背もたれの傾き検知ですが、ハードウェアの力を借りて傾きを検知したいと思います。
利用するハードウェアは以下の通りです。

仕組みとしては椅子に貼り付けたArduino+加速度計(GY-521)で重力加速度を検知し、椅子が傾いているかの検知を行います。
ハードウェアの価格はAliexpress直販なのでかなり安価ですが、日本で買い揃えても1000円位でまかなえるでしょう。

ハードウェア開発

やることはArduinoとGY-521を配線するだけです。
こんな感じに配線しています。

開発に必要なライブラリ等はこちらのREADME.mdから確認できます。
キャリブレーションについての解説も書いてありますが、傾き検知できればいいので行っていません。
https://github.com/ki-ui/ESP32_GY-521

あとは以下のコードをArduinoに書き込むだけです。
やっていることはZ軸の重力加速度を500ms毎に出力しているだけです。

#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

MPU6050 accelgyro;
int16_t XAccel, YAccel, ZAccel, XGyro, YGyro, ZGyro;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  
  accelgyro.initialize();
}

void loop() {
  accelgyro.getMotion6(&XAccel, &YAccel, &ZAccel, &XGyro, &YGyro, &ZGyro);
  
  Serial.println(ZAccel);
  delay(500);
}

ハードウェアは椅子の背もたれにこんな感じにぶら下げてます。
f:id:mukiebikun:20220307102526j:plain

ソフトウェア開発

傾きがArduinoから送られてくるので、Macで受け取って表示するソフトウェアを作ります。
ただ、受け取った値をターミナルに出力するだけだとターミナルがバックグラウンドに行ってしまったときに分かりづらいです。
そこで、常時全面に配置されているメニューバーに値を表示させつつ、しきい値以上に傾いていないときは警告をメニューバーに出すようにします。
しきい値についてはセンサの特性に左右されるので、動的に変えれるようにしておきます。

ハードウェアからの値を受け取る

ハードウェアとMacはシリアル通信で値のやり取りをしているので、pythonもシリアル通信を行うことで値の取得を行います。
利用するライブラリはpyserialで、さらに、ハードウェアが接続されているシリアルポートの情報が必要です。

接続されているハードウェアの情報はls /dev/tty*で雑に確認できるので、ハードウェアを抜き差ししつつ、上記コマンドを叩くことで、接続されているシリアルポートの情報が取得できます。
今回は/dev/tty.usbserial-0001のシリアルポートを利用しているようでした。

この情報をpyserialで指定することで値の取得ができます。

メニューバーに値を表示させる

macのメニューバーに情報を表示させるのにはrumpsライブラリを利用することで簡単に表示できます。
数行でかなり自由度の高いUIが作れますが、最終リリースが2019年らしいので、もっといいライブラリがあるかもしれないですね。知ってる方教えて下さい!

pythonコード

前述のライブラリを利用したソースが以下となります。

import rumps 
import serial 

app = None

def initesp(baudrate=115200, port='/dev/tty.usbserial-0001'):
    ser = serial.Serial()

    ser.baudrate = baudrate
    ser.port = port

    ser.parity = serial.PARITY_ODD
    ser.open()
    ser.close()
    ser.parity = serial.PARITY_NONE
    ser.open()

    return ser

def readesp(esp) -> int:
    read = int(esp.readline())
    esp.flush()
    return read

class ChairTiltApp(rumps.App):
    def __init__(self):
        super(ChairTiltApp, self).__init__("Chair Tilt")
        
        self.esp_serial = initesp()
        self.threshold = -3000
        self.normal_icon_path = "normal.png"
        self.alert_icon_path = "alert.png"

    @rumps.clicked("calibrate")
    def calibrate(self, _):
        self.threshold = readesp(self.esp_serial) - 500

    @rumps.timer(0.1)
    def updatestatus(self, _):
        line = readesp(self.esp_serial)

        app.title = str(self.threshold) + " : " + str(line)
        if line <= self.threshold:
            app.icon = self.normal_icon_path
        else:            
            app.icon = self.alert_icon_path

if __name__ == "__main__":
    app = ChairTiltApp()
    app.menu = [("calibrate")]
    app.run()

ごちゃごちゃと書いているが、def updatestatus(self, _):内が毎秒呼び出されるメソッドで、この中で傾きの値を読み込みつつ、しきい値以上に傾いていないなら警告を出す処理を実施しています。
def calibrate(self, _):ではユーザーがメニューを操作することで、しきい値を変更できる仕組みを導入しています。
文字だと分かりづらいので、実際に上記を起動したときの動作を確認します。

動作確認

ハードウェアとMacを接続し、上記.pyを実行するとメニューバーにこのようなアイコンが表示されます。

f:id:mukiebikun:20220307102532g:plain

なにやらエラーっぽい赤いアイコンと-3000 : 動的な数値が表示されていますね。
それぞれ表している情報は

  • エラーっぽい赤いアイコンは椅子の傾きがしきい値未満を表している。
  • -3000は現在の傾きの判定しきい値
  • 動的な数値は現在の傾き値

を示しています。
今回は-3000以下の傾き値のときに椅子が傾いていると判定しているため、
動的な数値が6000〜7000の現在はエラーっぽいアイコンが表示され、猫背をやめるように促されています。

そこで、椅子に深く腰掛けてみてしきい値以上の傾きを示すようにしてみると...

f:id:mukiebikun:20220307102600g:plain

深く傾けてみましたが、動的な数値は3000程度までにしか下がらないみたいですね。
これはしきい値の設定が不適切なので、しきい値を設定し直す必要がありますね。
しきい値再設定機能は実装しているので、メニューバーをクリックし、椅子を傾けていない状態で「calibration」ボタンをクリックしてみましょう。

f:id:mukiebikun:20220307102631g:plain

しきい値-3000から椅子を傾けていないときの6788に変更されました。
この状態で椅子を傾けてみると、

f:id:mukiebikun:20220307102650g:plain

椅子の傾きが無事しきい値以下になりました。
エラーっぽい赤いアイコンも緑色に変わり、猫背気味でないことがひと目で分かりますね。

最後に

腰痛が気になった日曜夜に勢いだけで作りましたが、今後の寿命が伸びそうで良かったです。
今後技術が発展し、ソフトウェアだけで猫背状態やストレス状態がわかる世界が来てほしいですね。