#include <Wire.h>
#define DHTPIN 2
#define DHTTYPE DHT22
#define PULSE_PIN A0
#define SLOT1_BTN 3
#define SLOT2_BTN 4
#define BUZZER_PIN 5
#define LCD_ADDR 0x27
#define LCD_BACKLIGHT 0x08
#define LCD_ENABLE 0x04
#define LCD_RS 0x01
const unsigned long DOSE_INTERVAL = 20000;
const unsigned long RESPONSE_WINDOW = 8000;
const unsigned long VITALS_CHECK_INTERVAL = 5000;
unsigned long lastDoseTime = 0;
unsigned long doseWindowStart = 0;
bool doseWindowActive = false;
unsigned long lastVitalsCheck = 0;
const int TEMP_HIGH = 38;
const int HR_LOW = 60;
const int HR_HIGH = 100;
bool readDHT22(int &tempC) {
uint8_t data[5] = {0, 0, 0, 0, 0};
pinMode(DHTPIN, OUTPUT);
digitalWrite(DHTPIN, LOW);
delay(2);
digitalWrite(DHTPIN, HIGH);
delayMicroseconds(30);
pinMode(DHTPIN, INPUT_PULLUP);
unsigned long t = micros();
while (digitalRead(DHTPIN) == HIGH) { if (micros() - t > 100) return false; }
t = micros();
while (digitalRead(DHTPIN) == LOW) { if (micros() - t > 100) return false; }
t = micros();
while (digitalRead(DHTPIN) == HIGH) { if (micros() - t > 100) return false; }
for (int i = 0; i < 40; i++) {
t = micros();
while (digitalRead(DHTPIN) == LOW) { if (micros() - t > 100) return false; }
t = micros();
while (digitalRead(DHTPIN) == HIGH) { if (micros() - t > 100) return false; }
unsigned long len = micros() - t;
data[i / 8] <<= 1;
if (len > 40) data[i / 8] |= 1;
}
uint8_t checksum = data[0] + data[1] + data[2] + data[3];
if (checksum != data[4]) return false;
int rawTemp = ((data[2] & 0x7F) << 8) | data[3];
tempC = rawTemp / 10;
if (data[2] & 0x80) tempC = -tempC;
return true;
}
void lcdWrite4(uint8_t nibble, uint8_t rs) {
uint8_t data = (nibble & 0xF0) | LCD_BACKLIGHT | (rs ? LCD_RS : 0);
Wire.beginTransmission(LCD_ADDR);
Wire.write(data | LCD_ENABLE);
Wire.endTransmission();
delayMicroseconds(1);
Wire.beginTransmission(LCD_ADDR);
Wire.write(data & ~LCD_ENABLE);
Wire.endTransmission();
delayMicroseconds(50);
}
void lcdSend(uint8_t value, uint8_t rs) {
lcdWrite4(value & 0xF0, rs);
lcdWrite4((value << 4) & 0xF0, rs);
}
void lcdCommand(uint8_t cmd) { lcdSend(cmd, 0); }
void lcdChar(uint8_t c) { lcdSend(c, 1); }
void lcdInit() {
delay(50);
lcdWrite4(0x30, 0); delay(5);
lcdWrite4(0x30, 0); delayMicroseconds(150);
lcdWrite4(0x30, 0);
lcdWrite4(0x20, 0);
lcdCommand(0x28);
lcdCommand(0x0C);
lcdCommand(0x06);
lcdCommand(0x01);
delay(2);
}
void lcdClear() { lcdCommand(0x01); delay(2); }
void lcdSetCursor(uint8_t col, uint8_t row) {
uint8_t rowOffsets[] = {0x00, 0x40};
lcdCommand(0x80 | (col + rowOffsets[row]));
}
void lcdPrint(const char* str) {
while (*str) lcdChar(*str++);
}
void beep(int freqHz, int durationMs) {
unsigned long periodUs = 1000000UL / freqHz;
unsigned long halfPeriodUs = periodUs / 2;
unsigned long cycles = (unsigned long)durationMs * 1000UL / periodUs;
for (unsigned long i = 0; i < cycles; i++) {
digitalWrite(BUZZER_PIN, HIGH);
delayMicroseconds(halfPeriodUs);
digitalWrite(BUZZER_PIN, LOW);
delayMicroseconds(halfPeriodUs);
}
}
void setup() {
Wire.setSDA(PB7);
Wire.setSCL(PB6);
Wire.begin();
lcdInit();
pinMode(SLOT1_BTN, INPUT_PULLUP);
pinMode(SLOT2_BTN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
lcdSetCursor(0, 0);
lcdPrint("System ready");
delay(1000);
lcdClear();
}
void loop() {
unsigned long now = millis();
if (now - lastVitalsCheck >= VITALS_CHECK_INTERVAL) {
lastVitalsCheck = now;
checkVitals();
}
if (!doseWindowActive && (now - lastDoseTime >= DOSE_INTERVAL)) {
startDoseReminder();
}
if (doseWindowActive) {
handleDoseWindow(now);
}
}
void checkVitals() {
int temp = 25;
readDHT22(temp);
int hrRaw = analogRead(PULSE_PIN);
int heartRate = map(hrRaw, 0, 4095, 50, 130);
bool abnormal = false;
if (temp > TEMP_HIGH) abnormal = true;
if (heartRate < HR_LOW || heartRate > HR_HIGH) abnormal = true;
if (abnormal) {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Abnormal vitals!");
lcdSetCursor(0, 1);
lcdPrint("Alerting caregvr");
triggerAlertTone();
}
sendData(temp, heartRate, -1);
}
void startDoseReminder() {
lastDoseTime = millis();
doseWindowStart = millis();
doseWindowActive = true;
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Time for meds!");
lcdSetCursor(0, 1);
lcdPrint("Remove pill now");
beep(1000, 300);
}
void handleDoseWindow(unsigned long now) {
bool slot1Taken = (digitalRead(SLOT1_BTN) == LOW);
bool slot2Taken = (digitalRead(SLOT2_BTN) == LOW);
if (slot1Taken || slot2Taken) {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Dose confirmed");
beep(1500, 200);
doseWindowActive = false;
sendData(-1, -1, 1);
delay(1000);
lcdClear();
return;
}
if (now - doseWindowStart >= RESPONSE_WINDOW) {
lcdClear();
lcdSetCursor(0, 0);
lcdPrint("Missed dose!");
lcdSetCursor(0, 1);
lcdPrint("Caregiver alert");
triggerAlertTone();
doseWindowActive = false;
sendData(-1, -1, 0);
}
}
void triggerAlertTone() {
for (int i = 0; i < 3; i++) {
beep(2000, 200);
delay(300);
}
}
void sendData(int temp, int hr, int doseStatus) {
(void)temp; (void)hr; (void)doseStatus;
}Loading
st-nucleo-c031c6
st-nucleo-c031c6