
皆さんは毎日の薬って飲んでいますか? 今は飲んでいなくても、年取ってくると生きてるだけで何だか色々なところが調子悪くなって薬が必要になってきたりもします。私は尿酸値が高く、もうかれこれ15年ほど朝に薬を飲んでいます。で、この薬なのですが、ホント飲み忘れる。また、飲んだにも関わらず、びっくりするほど飲んだかどうかを覚えていません(私だけ??)。
今回は この飲み忘れを防止する機械をArduinoで作った話です。かれこれ1年近く使用していますが、これにしてから殆ど飲み忘れがありません。
薬の飲み忘れ防止の選択
服薬管理アプリ(スマートフォンアプリ)
まず直ぐに思いつくのが投薬管理のスマートフォンアプリ。無料のものも多く、私も最初はこれを使用しました。薬の残り個数管理や、リマインダー、スヌーズなど色々な機能があるのですが、
- スマホを探す→スマホの電源を入れる→ロック解除→飲んだボタンを押すのが面倒
- スマホが手元にあっても、朝食中など、まだ薬を飲まない時に微妙な操作性
- 飲んだかどうかが自分しか分からない&アプリを起動しないと分からない。
- (無料のものは)広告などの通知などが邪魔。個人情報もできれば取られたくない。
- クラウド連携等、多機能なのは正直設定などが面倒
→1週間程度で使わなくなりました。

飲み忘れも含め、薬管理関連は沢山出てる
スマートスピーカ
- Google Home、IFTTT、Googleスプレッドシートを使って独自音声コマンドでログをとる@Qiita
https://qiita.com/miso_develop/items/be562d8a823ad2639d94
上記の記事を読み「スマホを探さなくて済む!」と参考にしながら同じようなシステムを作りました。googleスプレッドシートに記録がない場合は定期的にSlackとgoogle homeの音声で通知を繰り返し、「飲んだよ」って言うと通知が止まる的なもの。ただこれの問題点は…
- 通知が来た瞬間には飲めないが、もうちょっと後で…と思ってると忘れる
- 飲んだ時に「ok google 薬飲んだよ」って言わなければならない→面倒
- 飲んだかどうかパッと確認できない(確認にgoogle homeに聞く or スマホを見なければならない)
→結構飲みやすれが多い状態で2ヶ月ほど続けた。

google homeは良い子
という事で…
- 視覚的に飲んだ / 飲んでいないが直ぐにわかる
- 飲んだ場合、飲んだ記録を直ぐに、簡単に付けられる
- できれば、見た目にも少し気を使いたい…
そんな商品は無かったので、作ってみました。
できたのがこれ
- 指定の時刻になると光る
- 頭をポチッと押すと光が消える
- 6時間、頭のボタンを押されなければ自動的に消える
- ちょっとかわいい
仕組みはすごく単純で、ハード系の一番最初に試す”Lチカ”とほぼ同じです。
でもこれ作ってからはホント飲み忘れなし! レガシーな物理スイッチの威力を感じます。
作り方
材料
Arduinoがおうちに転がっているような方であれば、既に持っているものばかりだと思われます。
- Arduino Nano
KKHMF Mini USB Nano V3.0 ATmega328P CH340G 5V 16M マイクロコントローラーボード モジュールArduinoと互換
- リアルタイムクロック(DS3231)
EasyWordMall DC 3.3-5.5V DS3231 AT24C32 高精度リアルタイムクロックモジュール [並行輸入品]
- LED×2
- 抵抗 150Ωくらい×2
- プッシュスイッチ
適当なものを。今回は http://akizukidenshi.com/catalog/g/gP-04586/ を使用。 - USB ACアダプタ(スマホに付いてきた、適当に余っているものを)
筐体のデータ
3Dプリンタのデータを置いておきます。
https://www.tinkercad.com/things/dQp2mWPZLOf-kusuribox
接続方法
スイッチはINPUT_PULLUPを使うのでプルアップ抵抗は使いません。電源は、余ってたスマホ用の5V USB充電器をArduinoのUSBポートに刺して使います。
プログラム(スケッチ)
このプログラムでは時刻がハードコードしてありますが、もう一つスイッチを作って、それを押したら設定できるようにしたり、電源コネクタをつなげた時の時刻などにすると汎用性が上がるのかなぁとも思いました。また、Arduinoのsleep機能を使えば電池でも動くのかなとも思いますが、面倒なのでやっていません。
#include <DS3232RTC.h> #include <MsTimer2.h> #include <Streaming.h> #define BUTTON_PIN 2 #define LED_PIN1 5 #define LED_PIN2 6 int buttonState = 0; void setup() { Serial.begin(115200); // ボタンを入力に pinMode(BUTTON_PIN, INPUT_PULLUP); // 割り込み(LED点滅用) MsTimer2::set(500, flashLED); // PCから時刻を持って来て、RTCに設定(初回のみ使用。2度めはコメントアウトして書き込む) //RTC.set(compileTime()); //アラーム自動開始。7:15(秒, 分, 時, 曜日) RTC.setAlarm(ALM1_MATCH_HOURS, 0, 15, 7, 0); RTC.alarm(ALARM_1); RTC.alarmInterrupt(ALARM_1, false); //アラーム自動停止。13:00(秒, 分, 時, 曜日) RTC.setAlarm(ALM2_MATCH_HOURS, 0, 0, 13, 0); RTC.alarm(ALARM_2); RTC.alarmInterrupt(ALARM_2, false); } void loop() { //アラーム開始 if ( RTC.alarm(ALARM_1) ) { Serial.print("アラーム開始"); MsTimer2::start(); } //アラーム自動停止 if ( RTC.alarm(ALARM_2) ) { Serial.print("アラーム停止"); //LED停止 MsTimer2::stop(); analogWrite(LED_PIN1, 0); analogWrite(LED_PIN2, 0); } buttonState = digitalRead(BUTTON_PIN); if (buttonState == LOW) { // ボタンが押されていたら、ピンの値はLOW Serial.print("アラーム停止"); //LED停止 MsTimer2::stop(); analogWrite(LED_PIN1, 0); analogWrite(LED_PIN2, 0); } //デバッグ用(現在の時刻を表示) printDateTime(); //ストップボタンの効きが甘いと思ったら短くする delay(1000); } // LEDを点滅させる void flashLED() { static boolean output = true; output = !output; if (output){ analogWrite(LED_PIN1, 5); analogWrite(LED_PIN2, 0); } else { analogWrite(LED_PIN1, 0); analogWrite(LED_PIN2, 5); } } // 時刻表示(デバッグ用) void printDateTime() { tmElements_t tm; RTC.read(tm); Serial.print(tm.Year + 1970, DEC); //年は1970年からの年数で記録されるので1970を足して表示 Serial.print("/"); Serial.print(tm.Month, DEC);//月を表示 Serial.print("/"); Serial.print(tm.Day, DEC);//日を表示 Serial.print(" "); Serial.print(tm.Hour, DEC);//時を表示 Serial.print(":"); Serial.print(tm.Minute, DEC);//分を表示 Serial.print(":"); Serial.println(tm.Second, DEC);//秒を表示して改行 } // コンパイルしたPCの時刻を返す // https://github.com/JChristensen/DS3232RTC/blob/master/examples/alarm_ex1/alarm_ex1.ino time_t compileTime() { const time_t FUDGE(10); //fudge factor to allow for upload time, etc. (seconds, YMMV) const char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec"; char compMon[3], *m; strncpy(compMon, compDate, 3); compMon[3] = '\0'; m = strstr(months, compMon); tmElements_t tm; tm.Month = ((m - months) / 3 + 1); tm.Day = atoi(compDate + 4); tm.Year = atoi(compDate + 7) - 1970; tm.Hour = atoi(compTime); tm.Minute = atoi(compTime + 3); tm.Second = atoi(compTime + 6); time_t t = makeTime(tm); return t + FUDGE; //add fudge factor to allow for compile time }
最後に
薬が1種類×1日1回なので これでちょうど良いのですが、増えてきたら 結局昔からある↓が一番一番有効なのかもしれません。シンプル、一覧性、保存場所など悔しいけどかなりわかりやすいです。ただ、もう少しシュッとした見た目のがあればいいのになぁ。
薬飲まないのが一番ですが、飲むことになったら思い出してもらえればと思います。あとは、作ってご両親にプレゼントとかでも楽しいかも。
![]() |
ナカバヤシ お薬カレンダー 1週間分 壁掛タイプ グレー IF-3010GY【送料無料】 |