#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <SD.h>
#include <SPI.h>
#include <RTClib.h>
#define I2C_SDA 21 // OLED and DS3231: SDA --> GPIO21
#define I2C_SCL 22 // OLED and DS3231: SCL --> GPIO22
#define OLED_I2C_ADDRESS 0x3c // OLED I2C Address
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // QT-PY / XIAO
#define LED_Pin 2 // On board LED --> GPIO2
Adafruit_SH1106G OLEDdisplay = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RTC_DS3231 rtc;
//String iniContent;
String iniContent =
"[FirstMed]\n"
"Name = Paracetamol\n"
"Notif_time = 07:00:00, 13:00:00, 17:00:00, 20:00:00\n"
"When = Before Meal\n"
"[SecondMed]\n"
"Name = Vitamin C\n"
"Notif_time = 20:00:00\n"
"When = Before Bed\n"
"[ThirdMed]\n"
"Name = Star\n"
"Notif_time = 17:00:00, 20:00:00\n"
"When = After Meal\n";
// Variable to keep track of med info
String FirstMedName;
String SecondMedName;
String ThirdMedName;
String FirstMedWhen;
String SecondMedWhen;
String ThirdMedWhen;
// Arrays to keep track of notification time for each med
String notif1[4];
String notif2[4];
String notif3[4];
void setup() {
Serial.begin(115200);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
parseIni(iniContent); // Save Config file contents into arrays and vars
printMedications();
pinMode(LED_Pin, OUTPUT);
Serial.println("Start OLED Display...");
OLEDdisplay.begin(OLED_I2C_ADDRESS, true);
OLEDdisplay.setContrast(0); // dim display
OLEDdisplay.display();
Wire.begin(I2C_SDA, I2C_SCL);
OLEDdisplay.clearDisplay();
OLEDdisplay.setTextSize(1);
OLEDdisplay.setTextColor(SH110X_WHITE);
OLEDdisplay.setCursor(0, 0);
displayMedication(FirstMedName, FirstMedWhen, notif1);
delay(1000);
displayMedication(SecondMedName, SecondMedWhen, notif2);
delay(1000);
displayMedication(ThirdMedName, ThirdMedWhen, notif3);
delay(1000);
displayReminder();
}
void loop() {
displayCurrentTime();
drawAnalogClock();
delay(1000);
}
void parseIni(String ini) {
String lines[12]; // Adjust size based on expected lines
int lineCount = 0;
// Split the string by newline characters
int startIndex = 0;
int endIndex = ini.indexOf('\n');
while (endIndex != -1) {
lines[lineCount++] = ini.substring(startIndex, endIndex);
startIndex = endIndex + 1;
endIndex = ini.indexOf('\n', startIndex);
}
lines[lineCount++] = ini.substring(startIndex); // Last line
// Process each section
for (int i = 0; i < lineCount; i++) {
if (lines[i].startsWith("[FirstMed]")) {
FirstMedName = getValue(lines[++i]); // Get name
fillNotifArray(notif1, lines[++i]); // Get notif_time
FirstMedWhen = getValue(lines[++i]); // Get when
} else if (lines[i].startsWith("[SecondMed]")) {
SecondMedName = getValue(lines[++i]); // Get name
fillNotifArray(notif2, lines[++i]); // Get notif_time
SecondMedWhen = getValue(lines[++i]); // Get when
} else if (lines[i].startsWith("[ThirdMed]")) {
ThirdMedName = getValue(lines[++i]); // Get name
fillNotifArray(notif3, lines[++i]); // Get notif_time
ThirdMedWhen = getValue(lines[++i]); // Get when
}
}
}
// Function to extract the value after '='
String getValue(String line) {
return line.substring(line.indexOf('=') + 2, line.length());
}
// Function to fill notification time arrays
void fillNotifArray(String notif[], String line) {
// Initialize the array with empty strings
for (int i = 0; i < 4; i++) {
notif[i] = "";
}
// Split the notif_time string by commas
int startIndex = line.indexOf('=') + 2; // Start after '='
int endIndex = line.indexOf(',', startIndex);
int index = 0;
while (endIndex != -1 && index < 4) {
notif[index++] = line.substring(startIndex, endIndex); // Extract time
startIndex = endIndex + 2; // Move past the comma and space
endIndex = line.indexOf(',', startIndex);
}
// Add the last time (if exists)
if (startIndex < line.length() && index < 4) {
notif[index] = line.substring(startIndex); // Add the last one
}
}
void printMedications() {
// Print FirstMed
Serial.println("First Medication:");
Serial.print("Name: ");
Serial.println(FirstMedName);
Serial.print("When: ");
Serial.println(FirstMedWhen);
Serial.print("Notification Times: ");
for (int i = 0; i < 4; i++) {
Serial.print(notif1[i]);
if (i < 3) Serial.print(", "); // Print comma between times
}
Serial.println("\n");
// Print SecondMed
Serial.println("Second Medication:");
Serial.print("Name: ");
Serial.println(SecondMedName);
Serial.print("When: ");
Serial.println(SecondMedWhen);
Serial.print("Notification Times: ");
for (int i = 0; i < 4; i++) {
Serial.print(notif2[i]);
if (i < 3) Serial.print(", "); // Print comma between times
}
Serial.println("\n");
// Print ThirdMed
Serial.println("Third Medication:");
Serial.print("Name: ");
Serial.println(ThirdMedName);
Serial.print("When: ");
Serial.println(ThirdMedWhen);
Serial.print("Notification Times: ");
for (int i = 0; i < 4; i++) {
Serial.print(notif3[i]);
if (i < 3) Serial.print(", "); // Print comma between times
}
Serial.println("\n");
}
void displayMedication(String medName, String medWhen, String notif[]) {
OLEDdisplay.clearDisplay();
OLEDdisplay.setCursor(0, 0);
OLEDdisplay.setTextSize(0.75);
OLEDdisplay.setTextColor(SH110X_WHITE);
OLEDdisplay.print("Pill: ");
OLEDdisplay.println(medName);
OLEDdisplay.print("Time: ");
for (int i = 0; i < 4; i++) {
if (notif[i] != "") { // Check if the current element is not empty
OLEDdisplay.print(notif[i]); // Print the current element
// Check if the next element is not empty and within bounds
if (i < 3 && notif[i + 1] != "") {
OLEDdisplay.print(",\n "); // Add a comma and new line with indentation if the next element is not empty
}
}
}
OLEDdisplay.print("\nWhen: ");
OLEDdisplay.println(medWhen);
OLEDdisplay.display();
}
void displayReminder() {
OLEDdisplay.clearDisplay();
OLEDdisplay.setCursor(0, 0);
OLEDdisplay.setTextSize(1);
OLEDdisplay.setTextColor(SH110X_WHITE);
OLEDdisplay.println(" Medicine reminder");
OLEDdisplay.println(" system");
OLEDdisplay.display();
displayCurrentTime();
}
void displayCurrentTime() {
DateTime now = rtc.now();
OLEDdisplay.setCursor(0, 50);
OLEDdisplay.setTextSize(1);
OLEDdisplay.setTextColor(SH110X_WHITE);
OLEDdisplay.fillRect(0, 50, SCREEN_WIDTH, 14, SH110X_BLACK); // Clear previous time
OLEDdisplay.setCursor((SCREEN_WIDTH - 6 * 8) / 2, 50); // Center time horizontally
OLEDdisplay.printf("%02d:%02d:%02d", now.hour(), now.minute(), now.second());
OLEDdisplay.display();
}
void drawAnalogClock() {
int clockCenterX = 62; // Center of the screen horizontally
int clockCenterY = 33; // Positioned lower to avoid overlapping with text
// Clear the analog clock area
OLEDdisplay.fillRect(clockCenterX - 12, clockCenterY - 12, 24, 24, SH110X_BLACK);
// Draw clock face
for (int i = 0; i < 2; i++) {
OLEDdisplay.drawCircle(clockCenterX, clockCenterY, 11 - i, SH110X_WHITE);
}
DateTime now = rtc.now();
int hour = now.hour();
int minute = now.minute();
int second = now.second();
// Draw hour, minute, and second hands
drawHand(clockCenterX, clockCenterY, hour * 30 + minute / 2, 5, SH110X_WHITE); // Hour hand
drawHand(clockCenterX, clockCenterY, minute * 6, 10, SH110X_WHITE); // Minute hand
drawHand(clockCenterX, clockCenterY, second * 6, 11, SH110X_WHITE); // Second hand
OLEDdisplay.display();
}
void drawHand(int cx, int cy, int angle, int length, uint16_t color) {
float radian = (angle - 90) * 0.0174533;
int x = cx + cos(radian) * length;
int y = cy + sin(radian) * length;
OLEDdisplay.drawLine(cx, cy, x, y, color);
}