原文:https://circuitdigest.com/microcontroller-projects/arduino-medicine-reminder
使用Arduino的自动药物提醒
经过**阿比曼尤·潘迪(Abhiemanyu Pandit)** 2019年1月22日
使用Arduino的医学提醒
对于我们所爱的人,我们始终希望保持他们的健康和健康。但是,如果他们生病而忘记按时吃药,将会发生什么。我们会担心,对吗?在医院里,有很多病人,很难提醒每个病人准时吃药。传统方式需要人工来提醒他们按时服药。数字时代并没有随之而来,我们可以使用机器来做到这一点。Smart Medicine Reminder的应用范围非常广泛,可以被家庭患者,医院的医生以及许多其他地方使用。关于提醒,可以有多种提醒方法:
- 在显示器上显示
- 通过电子邮件或电话发送通知
- 使用行动应用程式
- 蜂鸣警报
- 使用蓝牙/ Wi-Fi
- 接电话
- 提醒下一次服药时间,同时提醒当前时间
我们可以根据需要结合多种方式。为了使事情简单,我们使用Arduino创建了一个简单的药品提醒,提醒我们每天服用1或2或3次药物。可以使用按钮选择时隙。此外,它还显示当前的日期和时间。我们将其进一步扩展到IoT项目传入的文章,在该文章中,电子邮件或SMS通知将发送给用户。该用药提醒也可以与患者监测系统集成。
使用Arduino的自动药物提醒所需的组件
- Arduino Uno(我们也可以使用其他Arduino开发板,例如Pro mini,Nano)
- RTC DS3231模块
- 16x2 LCD显示屏
- 蜂鸣器
- LED(任何颜色)
- 面包板
- 按按钮
- 10K电位器
- 10K,1K电阻器
- 跳线
使用Arduino Circuit的Arduino Medicine提醒
下面显示了 使用Arduino构建智能药箱的完整电路图
以下是Arduino与不同外设的引脚连接
Arduino****引脚外围引脚
- 2 -----------------------------> Dx的16x2 LCD显示屏
- 3 -----------------------------> D6的16x2 LCD显示屏
- 4 -----------------------------> D5的16x2 LCD显示屏
- 5 -----------------------------> D4的16x2 LCD显示屏
- 7 ----------------------------->第三个按钮
- 8 ----------------------------->第二个按钮
- 9 ----------------------------->第一个按钮
- 11 -----------------------------> 16x2 LCD显示屏的EN引脚
- 12 -----------------------------> 16x2 LCD显示器的RS引脚
- 13 -----------------------------> +蜂鸣器和LED的Ve引脚
- A0 ----------------------------->停止按钮
- A4 -----------------------------> DS3231的SDA
- A5 -----------------------------> DS3231的SCL
- 3.3V -----------------------------> DS3231的Vcc
- Gnd ----------------------------->Gnd
在此医学提醒项目中,RTC DS3231通过I2C协议与Arduino Uno接口。您还可以使用 RTC IC DS1307与Arduino读取时间。RTC DS3231还具有内置的32k存储器,可用于存储其他数据。RTC模块通过Arduino uno的3.3V引脚供电。甲16×2 LCD显示器使用SPI接口。一个buzze R用于警示和提醒,它的时间服药。四个按钮用于每个都有独特选择功能的地方。第一个按钮用于提醒每天服药一次。第二个按钮每天提醒两次,第三个按钮每天提醒三次。当用户听到警报时,第四个按钮用于停止蜂鸣器。
自动药品提示系统的工作
该丸提醒警报使用5V电源供电。当它第一次启动时,它会显示一个欢迎按摩,如" Welcome to Circuit Digest “。LCD屏幕设置为在三个屏幕之间循环。1个ST屏幕显示按摩为"保持健康,早日康复”。第二个屏幕是一个帮助屏幕,告诉您按选择按钮以选择任何一个要提醒的时间段(一天一次/两次/三次)。该时隙可在程序中更改,并可进行相应配置。现在,我们将其固定为三个时段,即上午8点,下午2点和晚上8点。
我们将时隙分为三种模式。模式1用于选择吃药一次/天在早上8时,用户按下1个ST按钮。当用户按下第二个按钮时,模式2选择每天两次在上午8点和晚上8点服药。模式3个选择吃药三次/天上午8点,下午2点和下午8点,如果用户按压3次按钮。
我们还可以添加一项功能,使蜂鸣器暂停10分钟(此项目不包括此功能)。当用户通过按下按钮选择所需的插槽时,将记录用户输入,并从RTC中获取时间。当时间与选定的时隙匹配时,蜂鸣器开始蜂鸣。用户可以通过按"停止"按钮来停止蜂鸣器。下一个插槽提醒将继续相同的过程。本节末尾的视频中显示了完整的过程。
编程Arduino UNO进行医学提醒
一旦想到了提醒服用药丸的方法,编写程序就非常容易。此处将在显示屏上显示提醒,对蜂鸣器进行蜂鸣并使用LED进行指示。它还具有选择三个时隙(每天一次/两次/三次)的选项,并且当时间到时将开始通过蜂鸣器的蜂鸣来提醒患者。然后整个系统将如下所示:
用户在显示屏上获得帮助说明>用户选择时隙(一次/天,两次/天,三次/天)>在显示屏上显示确认消息>计时开始>当时间与用户选择的时隙相匹配时蜂鸣器和LED响起>用户停止按下停止按钮>结束
如果要添加更多功能,我们可以更改程序和硬件。为了以更简单的方式理解,我们将程序分解为小功能。这些功能易于理解和实现。完整的程序在该项目的末尾给出。让我们从程序开始。
由于我们使用了其他外设,例如16x2 LCD显示器,RTC DS3231,因此我们首先必须包含库f或那个库。所需的库如下:
<LiquidCrystal.h>
<RTClib.h>(https://github.com/adafruit/RTClib)
<EEPROM.h>
<Wire.h>
如果未打开Arduino,则EEPROM库用于跟踪用户选择输入。而且,当用户打开Arduino电源时,它会使用EEPROM库获得按钮的先前状态。之所以使用Wire.h库,是因为RTC DS3231模块是使用I2C进行通信的。
始终检查RTC接线是否正确或是否已损坏,因为RTC在整个提醒系统的计时中将发挥重要作用。
if(!rtc.begin()){//检查rtc是否已连接
Serial.println("找不到RTC");
while(1);
}
if(rtc.lostPower()){
Serial.println(" RTC掉电,请设置时间!");
}
时间调整可以通过两种方式完成,要么自动使用系统编译时间,要么手动输入。设置时间后,除非您想再次更改RTC时间,否则请注释以下几行。
rtc.adjust(DateTime(F(__ DATE__),F(__ TIME__)));
//rtc.adjust(DateTime(2019,1,10,7,59,52));
该**switch语句用于读取按钮的先前保存状态,**并在适当和准确的提醒时间恢复该状态。
val2 = EEPROM.read(addr); //读取先前保存的按钮值,从先前保留的位置开始进行
switch(val2){
case 1:
Serial.println("Set for 1 / day");
push1state = 1;
push2state = 0;
push3state = 0;
pushVal = 01;
break;
case 2:
Serial.println(" Set for 2 / day");
push1state = 0;
push2state = 1;
push3state = 0;
pushVal = 10;
break;
case 3:
Serial.println(" Set for 3 / day")
push1state = 0;
push2state = 0;
push3state = 1;
pushVal = 11;
break;
}
此语句用于使毫秒数用于定时和控制已定义的间隔屏幕循环。
currentMillisLCD = millis(); //在定义的时间间隔内启动毫秒以进行LCD屏幕切换
开始读取连接到按钮的数字引脚。
push1state = digitalRead(push1pin);
push2state = digitalRead(push2pin);
push3state = digitalRead(push3pin);
stopinState = digitalRead(stopPin);
以下功能用于读取按钮状态并将其写入EEPROM。每当按下按钮时,状态就会写入EEPROM。它还在所选用户输入选项的LCD显示屏上打印消息。类似地,使用函数push2()和push3()。
void push1(){//
if(push1state == 1){
push1state = 0;
push2state = 0;
push3state = 0;
// pushPressed = true;
EEPROM.write(addr,1);
Serial.print(" Push1 Written:"); Serial.println(EEPROM.read(addr)); //用于调试
pushVal = 1; //保存按钮1的状态
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Reminder set");
lcd.setCursor(0,1);
lcd.print("每天一次!");
delay(1200);
lcd.clear();
}
}
以下功能用于停止蜂鸣器和指示灯。提出建议总是好的。在"用温水服药"显示屏上打印建议消息。
void stopPins(){//
if(stopinState == 1)
用户按下停止按钮时停止嗡嗡声的功能{ // stopinState = 0;
// pushPressed = true;
pushval= 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Take Medicine");
lcd.setCursor(0,1);
lcd.print("带温水");
delay(1200);
lcd.clear();
}
}
以下功能与计时无关,但始终在三个屏幕上循环,这对用户有帮助。由于我们一直在照顾患者,因此请打印问候语,因为我们知道情感支持对于更快地治愈患者非常有帮助。您可以选择自己的创意信息。让我们打印一条消息,“保持健康,早日康复”。
第二个屏幕用于向患者发出指示,例如"按提醒按钮…"。 第三个屏幕仅用于显示当前日期和时间。
void changeScreen() { //function for Screen Cycling
// Start switching screen every defined intervalLCD
if (currentMillisLCD - previousMillisLCD > intervalLCD) // save the last time you changed the display
{
previousMillisLCD = currentMillisLCD;
screens++;
if (screens > maxScreen) {
screens = 0; // all screens over -> start from 1st
}
isScreenChanged = true;
}
// Start displaying current screen
if (isScreenChanged) // only update the screen if the screen is changed.
{
isScreenChanged = false; // reset for next iteration
switch (screens)
{
case getWellsoon:
gwsMessege(); // get well soon message
break;
case HELP_SCREEN:
helpScreen(); // instruction screen
break;
case TIME_SCREEN:
timeScreen(); // to print date and time
break;
default:
//NOT SET.
break;
}
}
}
如果已达到所选时间,则此功能可用于同时开始蜂鸣和LED闪烁。
void startBuzz() { // function to start buzzing when time reaches to defined interval
// if (pushPressed == false) {
if (pushpressed == 0) {
Serial.println("pushpressed is false in blink");
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // save the last time you blinked the LED
Serial.println("Start Buzzing");
if (ledState == LOW) { // if the LED is off turn it on and vice-versa:
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
else if (pushpressed == 1) {
Serial.println("pushpressed is true");
ledState = LOW;
digitalWrite(ledPin, ledState);
}
}
*此功能用于比较用户在上午8点选择的时隙,并开始蜂鸣蜂鸣器并使LED闪烁,直到用户按下停止按钮为止。类似地,*void at2pm()* 和void at8pm的***功能用于启动蜂鸣器,并在2pm和8pm引导。
void at8am(){//函数从上午8点开始嗡嗡声
DateTime now = rtc.now();
if(int(now.hour())> = buzz8amHH){
if(int(now.minute())> = buzz8amMM){
if(int(now.second())> buzz8amSS){
// ///
startBuzz() ;
/ ///
}
}
}
}
这是您可以使用Arduino简单地制作自己的自动药品提醒的方法。您还可以将ESP8266与Arduino结合使用,使其成为一个IoT项目,该项目将能够向用户发送电子邮件警报。
完整的代码和演示视频如下。
代码
//Medicine Reminder using Arduino Uno
// Reminds to take medicine at 8am, 2pm, 8pm
/* The circuit:
LCD RS pin to digital pin 12
LCD Enable pin to digital pin 11
LCD D4 pin to digital pin 5
LCD D5 pin to digital pin 4
LCD D6 pin to digital pin 3
LCD D7 pin to digital pin 2
LCD R/W pin to ground
LCD VSS pin to ground
LCD VCC pin to 5V
10K resistor:
ends to +5V and ground
wiper to LCD VO pin (pin 3)*/
#include <LiquidCrystal.h>
#include <Wire.h>
#include <RTClib.h>
#include <EEPROM.h>
int pushVal = 0;
int val;
int val2;
int addr = 0;
RTC_DS3231 rtc;
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; // lcd pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
#define getWellsoon 0
#define HELP_SCREEN 1
#define TIME_SCREEN 2
//bool pushPressed; //flag to keep track of push button state
int pushpressed = 0;
const int ledPin = LED_BUILTIN; // buzzer and led pin
int ledState = LOW;
int Signal = 0;
int buzz = 13;
int push1state, push2state, push3state, stopinState = 0; //
int push1Flag, push2Flag, Push3Flag = false; // push button flags
int push1pin = 9;
int push2pin = 8;
int push3pin = 7;
int stopPin = A0;
int screens = 0; // screen to show
int maxScreen = 2; // screen count
bool isScreenChanged = true;
long previousMillis = 0;
long interval = 500; // buzzing interval
unsigned long currentMillis;
long previousMillisLCD = 0; // for LCD screen update
long intervalLCD = 2000; // Screen cycling interval
unsigned long currentMillisLCD;
// Set Reminder Change Time
int buzz8amHH = 8; // HH - hours ##Set these for reminder time in 24hr Format
int buzz8amMM = 00; // MM - Minute
int buzz8amSS = 00; // SS - Seconds
int buzz2pmHH = 14; // HH - hours
int buzz2pmMM = 00; // MM - Minute
int buzz2pmSS = 00; // SS - Seconds
int buzz8pmHH = 20; // HH - hours
int buzz8pmMM = 00; // MM - Minute
int buzz8pmSS = 00; // SS - Seconds
int nowHr, nowMin, nowSec; // to show current mm,hh,ss
// All messeges
void gwsMessege(){ // print get well soon messege
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Stay Healthy :)"); // Give some cheers
lcd.setCursor(0, 1);
lcd.print("Get Well Soon :)"); // wish
}
void helpScreen() { // function to display 1st screen in LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Press Buttons");
lcd.setCursor(0, 1);
lcd.print("for Reminder...!");
}
void timeScreen() { // function to display Date and time in LCD screen
DateTime now = rtc.now(); // take rtc time and print in display
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Time:");
lcd.setCursor(6, 0);
lcd.print(nowHr = now.hour(), DEC);
lcd.print(":");
lcd.print(nowMin = now.minute(), DEC);
lcd.print(":");
lcd.print(nowSec = now.second(), DEC);
lcd.setCursor(0, 1);
lcd.print("Date: ");
lcd.print(now.day(), DEC);
lcd.print("/");
lcd.print(now.month(), DEC);
lcd.print("/");
lcd.print(now.year(), DEC);
}
void setup() {
Serial.begin(9600); // start serial debugging
if (! rtc.begin()) { // check if rtc is connected
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
}
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // uncomment this to set the current time and then comment in next upload when u set the time
rtc.adjust(DateTime(2019, 1, 10, 7, 59, 30)); // manual time set
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Welcome To"); // print a messege at startup
lcd.setCursor(0, 1);
lcd.print("Circuit Digest");
delay(1000);
pinMode(push1pin, INPUT); // define push button pins type
pinMode(push2pin, INPUT);
pinMode(push3pin, INPUT);
pinMode(stopPin, INPUT);
pinMode(ledPin, OUTPUT);
delay(200);
Serial.println(EEPROM.read(addr));
val2 = EEPROM.read(addr); // read previosuly saved value of push button to start from where it was left previously
switch (val2) {
case 1:
Serial.println("Set for 1/day");
push1state = 1;
push2state = 0;
push3state = 0;
pushVal = 1;
break;
case 2:
Serial.println("Set for 2/day");
push1state = 0;
push2state = 1;
push3state = 0;
pushVal = 2;
break;
case 3:
Serial.println("Set for 3/day");
push1state = 0;
push2state = 0;
push3state = 1;
pushVal = 3;
break;
}
}
void loop() {
push1(); //call to set once/day
push2(); //call to set twice/day
push3(); //call to set thrice/day
if (pushVal == 1) { // if push button 1 pressed then remind at 8am
at8am(); //function to start uzzing at 8am
}
else if (pushVal == 2) { // if push button 2 pressed then remind at 8am and 8pm
at8am();
at8pm(); //function to start uzzing at 8mm
}
else if (pushVal == 3) { // if push button 3 pressed then remind at 8am and 8pm
at8am();
at2pm(); //function to start uzzing at 8mm
at8pm();
}
currentMillisLCD = millis(); // start millis for LCD screen switching at defined interval of time
push1state = digitalRead(push1pin); // start reading all push button pins
push2state = digitalRead(push2pin);
push3state = digitalRead(push3pin);
stopinState = digitalRead(stopPin);
stopPins(); // call to stop buzzing
changeScreen(); // screen cycle function
}
// push buttons
void push1() { // function to set reminder once/day
if (push1state == 1) {
push1state = 0;
push2state = 0;
push3state = 0;
// pushPressed = true;
EEPROM.write(addr, 1);
Serial.print("Push1 Written : "); Serial.println(EEPROM.read(addr)); // for debugging
pushVal = 1; //save the state of push button-1
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reminder set ");
lcd.setCursor(0, 1);
lcd.print("for Once/day !");
delay(1200);
lcd.clear();
}
}
void push2() { //function to set reminder twice/day
if (push2state == 1) {
push2state = 0;
push1state = 0;
push3state = 0;
// pushPressed = true;
EEPROM.write(addr, 2);
Serial.print("Push2 Written : "); Serial.println(EEPROM.read(addr));
pushVal = 2;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reminder set ");
lcd.setCursor(0, 1);
lcd.print("for Twice/day !");
delay(1200);
lcd.clear();
}
}
void push3() { //function to set reminder thrice/day
if (push3state == 1) {
push3state = 0;
push1state = 0;
push2state = 0;
// pushPressed = true;
EEPROM.write(addr, 3);
Serial.print("Push3 Written : "); Serial.println(EEPROM.read(addr));
pushVal = 3;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reminder set ");
lcd.setCursor(0, 1);
lcd.print("for Thrice/day !");
delay(1200);
lcd.clear();
}
}
void stopPins() { //function to stop buzzing when user pushes stop push button
if (stopinState == 1) {
// stopinState = 0;
// pushPressed = true;
pushpressed = 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Take Medicine ");
lcd.setCursor(0, 1);
lcd.print("with Warm Water");
delay(1200);
lcd.clear();
}
}
void startBuzz() { // function to start buzzing when time reaches to defined interval
// if (pushPressed == false) {
if (pushpressed == 0) {
Serial.println("pushpressed is false in blink");
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // save the last time you blinked the LED
Serial.println("Start Buzzing");
if (ledState == LOW) { // if the LED is off turn it on and vice-versa:
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
else if (pushpressed == 1) {
Serial.println("pushpressed is true");
ledState = LOW;
digitalWrite(ledPin, ledState);
}
}
void at8am() { // function to start buzzing at 8am
DateTime now = rtc.now();
if (int(now.hour()) >= buzz8amHH) {
if (int(now.minute()) >= buzz8amMM) {
if (int(now.second()) > buzz8amSS) {
/
startBuzz();
/
}
}
}
}
void at2pm() { // function to start buzzing at 2pm
DateTime now = rtc.now();
if (int(now.hour()) >= buzz2pmHH) {
if (int(now.minute()) >= buzz2pmMM) {
if (int(now.second()) > buzz2pmSS) {
///
startBuzz();
//
}
}
}
}
void at8pm() { // function to start buzzing at 8pm
DateTime now = rtc.now();
if (int(now.hour()) >= buzz8pmHH) {
if (int(now.minute()) >= buzz8pmMM) {
if (int(now.second()) > buzz8pmSS) {
/
startBuzz();
/
}
}
}
}
//Screen Cycling
void changeScreen() { //function for Screen Cycling
// Start switching screen every defined intervalLCD
if (currentMillisLCD - previousMillisLCD > intervalLCD) // save the last time you changed the display
{
previousMillisLCD = currentMillisLCD;
screens++;
if (screens > maxScreen) {
screens = 0; // all screens over -> start from 1st
}
isScreenChanged = true;
}
// Start displaying current screen
if (isScreenChanged) // only update the screen if the screen is changed.
{
isScreenChanged = false; // reset for next iteration
switch (screens)
{
case getWellsoon:
gwsMessege(); // get well soon message
break;
case HELP_SCREEN:
helpScreen(); // instruction screen
break;
case TIME_SCREEN:
timeScreen(); // to print date and time
break;
default:
//NOT SET.
break;
}
}
}