/**
* @file main.cpp
* @author Sachin Kushawaha
* @date January 2024
* @brief Medical device for automatic measurement and control of glucose drip.
*
*/
#include <Arduino.h>
#define BLYNK_TEMPLATE_ID "TMPL3KJtiTRlf"
#define BLYNK_TEMPLATE_NAME "Glucose meter"
#define BLYNK_AUTH_TOKEN "jn3N3R7_P7zj4KaLDLKDBWLQKC_n8kdY"
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
char ssid[] = "Glucose Monitor";
char pass[] = "12345678";
#include <HX711_ADC.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include "OneButton.h"
#include <ESP32Servo.h>
/*
Cunstructer builder For Operating modes For device
@note This device has three different modes.
*/
enum OperatingMode
{
NORMAL_MODE,
TASK_MODE,
TASK_SETUP_MODE
};
/*
Button1 press Function.
If in normal mode, change the operating mode to task setup mode.
if in Task setup mode, cycle through bottle types.
*/
void setMode();
/*
Button2 press Function.
If in task mode, press to pause/resume task.
if in Task setup mode, Task start.
*/
void taskPauseandesume();
/*
Button2 press Function.
If in task mode, press to cancel the task and return to normal mode.
*/
void taskCancel();
/*
Task function for calculating the gram to ml and alarms.
@param currentWeight The Current weight for calculations.
*/
void handleTask(float);
/*
Tare weight in normal mode.
*/
void tare();
/*
Checks for connections to blynk cloud every three second
*/
void checkBlynkStatus();
/*
Load Cell initalization function and statup tare.
*/
void loadcelSetup();
/*
Setup all the pins
*/
void pinSetup();
/*
Display the new weight on the OLED display if weight changes 1 gram or ml.
@param currentWeight The Current weight for display.
@param str "g" or "ml"
*/
void displayWeight(float, String);
/*
Task Status Displayed on Oled
@param str Staus of the task
*/
void displayTask(String);
/*
Cycle through types of bottles and calculate the three thresholds and ratio between gram and ml.
*/
void modeCycle();
const unsigned char myBitmap[1024] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x30, 0x06, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x7f, 0x30, 0x06, 0x7f, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, 0xf0, 0x07, 0xf0, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xfe, 0x0e, 0x03, 0xf8, 0x0f, 0xe0, 0x38, 0x3f, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x03, 0xef, 0xfb, 0xe0, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xf7, 0xff, 0xef, 0x03, 0xf7, 0x37, 0xe0, 0x79, 0xff, 0xf7, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x9f, 0xfe, 0x3d, 0xf8, 0xf6, 0x37, 0x8f, 0xde, 0x3f, 0xfc, 0x7e, 0x00, 0x00,
0x00, 0x03, 0xff, 0x9f, 0x31, 0xe1, 0xee, 0x3e, 0x3e, 0x3b, 0xc3, 0xc6, 0x7c, 0xff, 0xe0, 0x00,
0x00, 0xff, 0xfe, 0xfe, 0x0f, 0x87, 0x87, 0x8e, 0x38, 0xf0, 0xf0, 0xf8, 0x3f, 0xbf, 0xff, 0x80,
0x1f, 0xef, 0x87, 0xff, 0xfe, 0x1e, 0x1f, 0xfe, 0x3f, 0xfc, 0x1c, 0x3f, 0xff, 0xf0, 0xff, 0xfc,
0x07, 0xf8, 0x7d, 0xf3, 0xe7, 0xf8, 0x78, 0xe6, 0x33, 0x8f, 0x0f, 0xf3, 0xe7, 0xff, 0x07, 0xf0,
0x00, 0xff, 0xc7, 0x1f, 0x01, 0xff, 0xff, 0xce, 0x39, 0xff, 0xff, 0xc0, 0x7c, 0x71, 0xff, 0x80,
0x00, 0x1f, 0x30, 0xf0, 0x07, 0x9f, 0x9f, 0xfe, 0x3f, 0xfc, 0xfc, 0xf0, 0x07, 0xc6, 0x7c, 0x00,
0x00, 0x07, 0xef, 0x80, 0x1c, 0x0e, 0x0e, 0x3e, 0x3e, 0x38, 0x38, 0x1e, 0x00, 0xfb, 0xf0, 0x00,
0x00, 0x00, 0xfe, 0x00, 0xf0, 0x38, 0x1c, 0x7e, 0x3b, 0x1c, 0x0e, 0x07, 0x80, 0x3f, 0x80, 0x00,
0x00, 0x00, 0x1f, 0x83, 0xc0, 0xf0, 0x78, 0xee, 0x3b, 0xcf, 0x07, 0x81, 0xe0, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x03, 0xff, 0x01, 0xc0, 0xff, 0xfe, 0x3f, 0xff, 0x81, 0xc0, 0x3f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x07, 0x03, 0xc0, 0x06, 0x38, 0x00, 0xe0, 0x70, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xfe, 0x06, 0x30, 0x3e, 0x3e, 0x06, 0x30, 0x3f, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x7f, 0xfe, 0x3f, 0xff, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0xfe, 0x3f, 0xff, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3f, 0xfe, 0x3f, 0xfe, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0f, 0xfe, 0x3f, 0xf8, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x3f, 0xfe, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x3f, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x3f, 0xf0, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xfe, 0x3f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xfe, 0x3f, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xfe, 0x3f, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xfe, 0x3f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3f, 0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0xf8, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0f, 0xf0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1f, 0x7c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1f, 0x7c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1f, 0x7c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0xf8, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0xf1, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x71, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x71, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char myBitlogo[1024] PROGMEM = {
0x00, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x03, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x01, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff,
0xff, 0xf7, 0xdf, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xef, 0xfe, 0x7f, 0xff, 0x00, 0x7f,
0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff,
0x00, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xfe, 0xff, 0xff,
0xff, 0xff, 0x80, 0xff, 0xbd, 0xe5, 0xd5, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xdf, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0xf8, 0x5f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf9, 0xd8,
0xc2, 0x23, 0xff, 0xfe, 0x36, 0xc7, 0x80, 0xf8, 0x52, 0x5a, 0x67, 0xff, 0xfc, 0xb6, 0x97, 0x80,
0xf9, 0xd2, 0x5e, 0x6f, 0xff, 0xfc, 0xf6, 0xc7, 0x80, 0xf9, 0xda, 0x42, 0x6f, 0xff, 0xfc, 0xb0,
0xd7, 0x80, 0xf8, 0x58, 0xe7, 0x2f, 0xff, 0xfe, 0x30, 0xc7, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfb, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0x80, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff,
0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xf7, 0xff, 0xff,
0xff, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00};
#define FIRST_BUTTON 15 // First button pin
#define SECOND_BUTTON 14 // Second button pin
#define THIRD_BUTTON 13 // Third Button pin
#define FIRST_LED 2 // First LED pin
#define SECOND_LED 19 // Second LED pin
#define THIRD_LED 18 // Third LED pin
#define BUZZER 23 // Buzzer pin
#define SERVO_PIN 4 // Servo pin
#define HX711_dout 25 // MCU > HX711 dout pin
#define HX711_sck 26 // MCU > HX711 sck pin
#define TONE_D 50 // Buzzer delay for button press
#define SCREEN_WIDTH 128 // Oled Screen Width
#define SCREEN_HEIGHT 64 // Oled Screen Height
#define OLED_RESET -1
const int calVal_eepromAdress = 0; // EEPROM address for saving calibration value.
bool taskPaused = false; // Task pause and resume indicator.
bool blynkSet = false;
int count1 = 0;
int count2 = 0;
int bottleCount = 0;
int ope = 70; // Servo open angle.
int clos = 120; // Servo close angle.
float bottleWeights[] = {500, 200, 100}; // Predefined bottles type in ml.
float emptyWeights[] = {26, 15, 9}; // Predefined empty bottle weights in grams
float bottleWeight = 0.0; // Bottletype stored in variable used in current running task.
float emptyWeight = 0.0; // Empty weight stored in variable used in current running task.
float thresholdWeight[3]; // Three points in ml to be stored for three alrms/reminder.
float taskRatioWeight = 0; // Weight ratio between ml and grams.
float lastDisplayedWeight = 0.0; // Store the last displayed weight
float currentWeight = 0.0; // Store the current weight
unsigned long previousMillis = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long t = 0;
OneButton button1(FIRST_BUTTON, true);
OneButton button2(SECOND_BUTTON, true);
OneButton button3(THIRD_BUTTON, true);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // Display costructor
HX711_ADC LoadCell(HX711_dout, HX711_sck); // LoadCell Costructor
OperatingMode mode = NORMAL_MODE; // Normal mode initialization
WidgetTerminal terminal(V3); // Terminal initialization
BlynkTimer timer; // Timer initilization
Servo servo; // Servo initilization
void setup()
{
Serial.begin(57600);
delay(10);
Serial.println();
Serial.println("Starting...");
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
{
Serial.println(F("SSD1306 allocation failed"));
for (;;)
;
}
display.clearDisplay();
display.drawBitmap(0, 0, myBitmap, 128, 64, 1);
display.display();
delay(2500);
pinSetup();
delay(100);
loadcelSetup();
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println("Connecting to wifi");
display.display();
WiFi.begin(ssid, pass);
Blynk.config(BLYNK_AUTH_TOKEN);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println("Connected");
display.display();
timer.setInterval(3000UL, checkBlynkStatus);
button1.attachClick(setMode);
button1.attachLongPressStart(tare);
button2.attachClick(taskPauseandesume);
button3.attachClick(taskCancel);
terminal.clear();
terminal.flush();
mode = NORMAL_MODE;
}
void loop()
{
Blynk.run();
timer.run();
button1.tick();
button2.tick();
button3.tick();
static boolean newDataReady = 0;
const int serialPrintInterval = 250;
if (!blynkSet && Blynk.connected())
{
Blynk.virtualWrite(V2, 0); // Task Not Running
digitalWrite(SECOND_LED, LOW);
digitalWrite(THIRD_LED, LOW);
Blynk.virtualWrite(V4, 0);
Blynk.virtualWrite(V6, 0);
blynkSet = true;
}
if (LoadCell.update())
newDataReady = true;
if (millis() > t + serialPrintInterval)
{
currentWeight = LoadCell.getData();
// Serial.print("Load_cell output val: ");
// Serial.println(currentWeight);
t = millis();
}
if (mode == NORMAL_MODE && newDataReady)
{
if (currentWeight < 5)
{
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println(" Put the glucose\nbottle into the hook\n and press first\n button to start.");
display.display();
}
else
{
displayWeight(currentWeight, " g");
}
}
else if (mode == TASK_MODE)
{
handleTask(currentWeight);
}
if (LoadCell.getTareStatus() == true)
{
Serial.println("Tare complete");
digitalWrite(BUZZER, LOW);
}
}
void modeCycle()
{
emptyWeight = emptyWeights[bottleCount];
bottleWeight = bottleWeights[bottleCount]; // Full liquid
taskRatioWeight = (currentWeight - emptyWeight) / bottleWeight;
thresholdWeight[0] = (currentWeight - emptyWeight) * 0.05; // Third point at 5% of liquid for third alarm and stoping the task.
thresholdWeight[1] = (currentWeight - emptyWeight) * 0.10; // Second point at 10% of liquid for second alarm.
thresholdWeight[2] = (currentWeight - emptyWeight) * 0.20; // First point at 20% of liquid for first alarm.
// Serial print the current weight and threshold selected for task.
Serial.println();
Serial.print("BottleType ");
Serial.print(bottleWeight);
Serial.print("\tRatio: ");
Serial.print(taskRatioWeight);
Serial.print("\t 5% : ");
Serial.print(thresholdWeight[0]);
Serial.print("\t 10% : ");
Serial.print(thresholdWeight[1]);
Serial.print("\t 20% : ");
Serial.print(thresholdWeight[2]);
// Blynk terminal print the current weight and threshold selected for task.
terminal.clear();
terminal.print("BottleType ");
terminal.print(bottleWeight);
terminal.print("\t\t 5% : ");
terminal.print(thresholdWeight[0]);
terminal.print("\t 10% : ");
terminal.print(thresholdWeight[1]);
terminal.print("\t 20% : ");
terminal.print(thresholdWeight[2]);
terminal.flush();
// Oled display print the current weight and threshold selected for task.
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(10, 10);
display.print("Bottle Weight");
display.setTextSize(2);
display.setCursor(0, 30);
display.print(String(bottleWeight));
display.print("ml");
display.display();
bottleCount++;
if (bottleCount == 3)
{
bottleCount = 0;
}
}
void displayTask(String str)
{
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Bottle Type: ");
display.print(int(bottleWeight));
display.print(" ml");
display.setTextSize(2);
display.setCursor(10, 10);
display.print(" TASK");
display.setTextSize(2);
display.setCursor(0, 30);
display.println(str);
display.display();
delay(1000);
}
void displayWeight(float currentWeight, String str)
{
if (abs(currentWeight - lastDisplayedWeight) > 1.0)
{
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
if (mode == TASK_MODE)
{
display.setCursor(0, 0);
display.print("Bottle Type: ");
display.print(int(bottleWeight));
display.print(" ml");
}
display.setTextSize(2);
display.setCursor(0, 20);
display.print(" Weight ");
display.setCursor(0, 40);
display.print(" ");
display.print(currentWeight, 1);
display.println(str);
display.display();
lastDisplayedWeight = currentWeight;
}
}
void pinSetup()
{
pinMode(FIRST_LED, OUTPUT);
pinMode(SECOND_LED, OUTPUT);
pinMode(THIRD_LED, OUTPUT);
pinMode(BUZZER, OUTPUT);
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
servo.setPeriodHertz(50); // Standard 50hz servo
servo.attach(SERVO_PIN, 500, 2400);
servo.write(ope);
}
void checkBlynkStatus()
{
bool isconnected = Blynk.connected();
if (isconnected == false)
{
digitalWrite(FIRST_LED, LOW); // Turn off WiFi LED
}
if (isconnected == true)
{
digitalWrite(FIRST_LED, HIGH); // Turn on WiFi LED
}
}
void loadcelSetup()
{
LoadCell.begin();
float calibrationValue;
// calibrationValue = -467.24;
#if defined(ESP8266) || defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.get(calVal_eepromAdress, calibrationValue);
unsigned long stabilizingtime = 2000;
boolean _tare = true;
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag())
{
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println("Load Cell Error");
display.display();
while (1)
;
}
else
{
LoadCell.setCalFactor(calibrationValue);
Serial.println("Startup is complete");
}
delay(1000);
}
void tare()
{
if (mode == NORMAL_MODE)
{
LoadCell.tareNoDelay();
digitalWrite(BUZZER, HIGH);
}
}
void handleTask(float currentWeight)
{
float netweight = currentWeight - emptyWeight;
float weight = netweight / taskRatioWeight;
displayWeight(weight, " ml");
unsigned long currentMillis3 = millis();
if (currentMillis3 - previousMillis2 >= 500UL)
{
previousMillis2 = currentMillis3;
Blynk.virtualWrite(V0, weight); // Blynk data sending
}
if (netweight < thresholdWeight[0])
{
Blynk.virtualWrite(V5, 3); // Task completed
bottleCount = 0;
taskPaused = false;
servo.write(clos); // Rotate servo to 0 degrees
mode = NORMAL_MODE; // Switch back to normal mode
Serial.println("Task Completed");
displayTask(" Complete");
Blynk.virtualWrite(V2, 0); // Task completed
Blynk.virtualWrite(V5, 3); // Task completed
digitalWrite(SECOND_LED, LOW);
digitalWrite(BUZZER, HIGH);
delay(5000);
digitalWrite(BUZZER, LOW);
}
else if (netweight < thresholdWeight[1])
{
Blynk.virtualWrite(V5, 2);
unsigned long currentMillis1 = millis();
if (currentMillis1 - previousMillis >= 1000UL)
{
previousMillis = currentMillis1;
if (count1 < 10)
{
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
count1++;
}
}
}
else if (netweight < thresholdWeight[2])
{
Blynk.virtualWrite(V5, 1);
unsigned long currentMillis2 = millis();
if (currentMillis2 - previousMillis1 >= 1000UL)
{
previousMillis1 = currentMillis2;
if (count2 < 10)
{
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
count2++;
}
}
}
}
// Button Fuctions
void setMode()
{
digitalWrite(BUZZER, HIGH);
delay(TONE_D);
digitalWrite(BUZZER, LOW);
if (mode == NORMAL_MODE && currentWeight > 25)
{
mode = TASK_SETUP_MODE;
modeCycle();
}
else if (mode = TASK_SETUP_MODE)
{
modeCycle();
}
}
void taskPauseandesume()
{
digitalWrite(BUZZER, HIGH);
delay(TONE_D);
digitalWrite(BUZZER, LOW);
if (mode == TASK_MODE)
{
if (taskPaused)
{
digitalWrite(THIRD_LED, LOW);
Blynk.virtualWrite(V4, 0); // Task Resumed
taskPaused = false;
servo.write(ope); // Rotate servo to 30 degrees (resume)
Serial.println("Task Resumed");
displayTask(" Resumed");
}
else
{
digitalWrite(THIRD_LED, HIGH);
Blynk.virtualWrite(V4, 1); // Task Paused
taskPaused = true;
servo.write(clos); // Rotate servo to 0 degrees (pause)
Serial.println("Task Paused");
displayTask(" Paused");
}
}
else if (mode == TASK_SETUP_MODE)
{
count1 = 0;
count2 = 0;
mode = TASK_MODE;
digitalWrite(SECOND_LED, HIGH);
Blynk.virtualWrite(V2, 1); // Task Started
servo.write(ope); // Rotate servo to 30 degrees
Serial.println("Task Started");
displayTask(" Started");
}
else if (mode == NORMAL_MODE)
{
servo.write(ope);
}
}
void taskCancel()
{
digitalWrite(BUZZER, HIGH);
delay(TONE_D);
digitalWrite(BUZZER, LOW);
if (mode == TASK_MODE || mode == TASK_SETUP_MODE)
{
bottleCount = 0;
taskPaused = false;
servo.write(clos); // Rotate servo to 0 degrees
mode = NORMAL_MODE; // Switch back to normal mode
digitalWrite(SECOND_LED, LOW);
digitalWrite(THIRD_LED, LOW);
Serial.println("Task Cancelled");
displayTask("Cancelled");
Blynk.virtualWrite(V6, 1); // Task Cancelled
Blynk.virtualWrite(V2, 0); // Task Cancelled
}
else if (mode == NORMAL_MODE)
{
servo.write(clos);
}
}
// Blynk buttons
BLYNK_WRITE(V1)
{
if (param.asInt() == 1)
{
setMode();
}
}
BLYNK_WRITE(V7)
{
if (param.asInt() == 1)
{
taskPauseandesume();
}
}
BLYNK_WRITE(V8)
{
if (param.asInt() == 1)
{
taskCancel();
}
}
BLYNK_WRITE(V9)
{
if (param.asInt() == 1)
{
tare();
}
}
Loading
esp32-devkit-v1
esp32-devkit-v1