Smart Coaster

Smart Coaster: An IoT-powered hydration tracker that seamlessly monitors water intake, promoting better health & focus for office workers.

IntermediateFull instructions provided6 hours178
Smart Coaster

Things used in this project

Hardware components

ESP32
Espressif ESP32
×1
LED (generic)
LED (generic)
×1
SparkFun Load Cell Amplifier - HX711
SparkFun Load Cell Amplifier - HX711
×1
Load Cell, Industrial
Load Cell, Industrial
×1

Software apps and online services

Microsoft Azure
Microsoft Azure

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Code

Arduino Code

C/C++
The code for the Arduino
#include <Arduino.h>
#include "HX711.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <time.h> // Fr den Timestamp

// NTP-Server und Zeitzone
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 0; // GMT+1 (z. B. Deutschland im Winter)
const int daylightOffset_sec = 3600; // Sommerzeit (1 Stunde)


#define WIFI_TIMEOUT_MS 20000
#define WIFI_NETWORK "WIFI_NETWORK" 
#define WIFI_PASSWORD "WIFI_PASSWORD"
#define LED_PIN 19

WiFiClient client;

// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 16; // Daten-Pin
const int LOADCELL_SCK_PIN = 4;  // Clock-Pin

HX711 scale;

// Kalibrierungsfaktor
float calibration_factor = -373.91; // Beispielwert, passe ihn an

float zahl1 = 0;         // Erstes stabil gemessenes Gewicht
float zahl2 = 0;         // Zweites stabil gemessenes Gewicht
float getrunkeneMenge = 0; // Gesamt getrunkene Menge (Tageswert)

unsigned long lastStableTime = 0; // Zeit, wann das Gewicht zuletzt stabil war
bool isFirstMeasurement = true;  // Ob die erste Messung (Zahl1) gemacht wurde
bool isMeasuring = false;        // Ob gerade eine stabile Messung erfolgt


// Funktion zur Initialisierung der Zeit
void initializeTime() {
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  Serial.println("Synchronisiere Zeit mit NTP-Server...");
  
  // Warten, bis die Zeit synchronisiert ist
  struct tm timeinfo;
  while (!getLocalTime(&timeinfo)) {
    Serial.println("Warte auf Zeitdaten...");
    delay(1000);
  }
  Serial.println("Zeit synchronisiert!");
}


void connectToWifi(){
  Serial.print("Connecting to Wifi");
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_NETWORK, WIFI_PASSWORD);

  unsigned long startAttemptTime = millis();

  //repeating to establish connection until timeout
  while(WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < WIFI_TIMEOUT_MS){
    Serial.print(".");
    delay(100);
  }

  if(WiFi.status() != WL_CONNECTED){
    Serial.println("Failed");
  }
  else{
    Serial.print("Connected");
    Serial.println(WiFi.localIP());
  }
}


// Funktion, um die getrunkeneMenge und den Timestamp per PATCH zu senden
void sendPatchRequest(float getrunkeneMenge, float differenz) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;

    String url = "https://thankful-ocean-0345cfc1e.4.azurestaticapps.net/api/sensor/liveStatus";
    http.begin(url); // URL setzen
    http.addHeader("Content-Type", "application/json"); // JSON-Header

    // Timestamp im ISO 8601-Format generieren
    char timestamp[25];
    struct tm timeinfo;
    if (getLocalTime(&timeinfo)) {
      strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%SZ", &timeinfo); // ISO 8601 Format
    } else {
      Serial.println("Fehler: Keine aktuelle Zeit verfgbar.");
      snprintf(timestamp, sizeof(timestamp), "1970-01-01T00:00:00Z"); // Fallback
    }

    // JSON-String erstellen
    String jsonPayload = "{";
    jsonPayload += "\"getrunken\": " + String(getrunkeneMenge, 2) + ",";
    jsonPayload += "\"differenz\": " + String(differenz, 2) + ",";
    jsonPayload += "\"timestamp\": \"" + String(timestamp) + "\"";
    jsonPayload += "}";

    // PATCH-Request senden
    int httpResponseCode = http.PATCH(jsonPayload);

    // Debug-Ausgabe
    if (httpResponseCode > 0) {
      Serial.print("PATCH Response code: ");
      Serial.println(httpResponseCode);
    } else {
      Serial.print("Error on sending PATCH: ");
      Serial.println(http.errorToString(httpResponseCode).c_str());
    }

    http.end(); // Verbindung schlieen
  } else {
    Serial.println("WiFi disconnected. Unable to send PATCH.");
  }
}



void setup() {
  
  Serial.begin(115200);
  connectToWifi();
  initializeTime();

  Serial.println("HX711 Getrnkemessung starten...");

  // HX711 initialisieren
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  
  pinMode(LED_PIN, OUTPUT);

  // Prfe, ob der HX711 bereit ist
  while (!scale.is_ready()) {
    Serial.println("HX711 nicht bereit. Versuche erneut...");
    delay(1000); // Warte 1 Sekunde
  }
  Serial.println("HX711 ist bereit.");

  // Kalibrierungsfaktor setzen
  scale.set_scale(calibration_factor);

  // Tare durchfhren (Null setzen)
  Serial.println("Tare... bitte alle Gewichte entfernen.");

  for (int i = 0; i < 10; i++) {  
    digitalWrite(LED_PIN, HIGH);  
    delay(250);                   
    digitalWrite(LED_PIN, LOW);   
    delay(250);                   
  }
  scale.tare();
  Serial.println("Tare abgeschlossen.");
}

void loop() {
  // Gewichtsmessung durchfhren
  int differenz = 0;
  int currentWeight = scale.get_units(10); // Durchschnitt von 10 Messungen
  Serial.print("Aktuelles Gewicht: ");
  Serial.println(currentWeight);

  // ist etwas auf der Waage?
  if (currentWeight > 10) { 
    if (!isMeasuring) {
      // Gewicht ist stabil, starte die Zeitmessung
      lastStableTime = millis();
      isMeasuring = true;
    } 

    else if (millis() - lastStableTime >= 5000 ) { // Stabil fr 5 Sekunden
      if (isFirstMeasurement) {
        // Erste stabile Messung (Zahl1)
        zahl1 = currentWeight;
        Serial.print("Zahl1 gespeichert: ");
        Serial.println(zahl1);
        isFirstMeasurement = false;
      } 
      else {
        // Zweite stabile Messung (Zahl2)
        zahl2 = currentWeight;
        Serial.print("Zahl2 gespeichert: ");
        Serial.println(zahl2);

        // Differenz berechnen und getrunkene Menge hinzufgen
        float differenz = zahl1 - zahl2; 

        if(differenz >= 5 ){
          getrunkeneMenge += differenz;
          Serial.print("Getrunkene Menge hinzugefgt: ");
          Serial.println(differenz);
          Serial.print("Gesamt getrunkene Menge: ");
          Serial.println(getrunkeneMenge);

          Serial.println(getrunkeneMenge);

          // Timestamp erstellen
          char timestamp[20];
          snprintf(timestamp, sizeof(timestamp), "%lu", millis());

          // PATCH-Request senden
          sendPatchRequest(getrunkeneMenge, differenz);


          // Zahl2 wird neue Zahl1 (fr nchste Runde)
          zahl1 = zahl2;
        }
        if(differenz < 0){
          isFirstMeasurement = true;
        }
        
        
      }
      isMeasuring = false; // Messung abgeschlossen
    }
  } else {
    // Gewicht unstabil, Messung abbrechen
    isMeasuring = false;
  }

  delay(500); // Kleine Pause zwischen den Messungen
}

Iot_Smarter_Becher

GitHub Repository

Credits

Tom Karaqi
1 project • 0 followers
Contact
kevinboehmisch
1 project • 0 followers
Contact
MarvinB
1 project • 2 followers
Contact
arturhoxha
1 project • 0 followers
Contact
Janfabian Fabriczek
7 projects • 7 followers
Embedded Software Expert @ Festo SE & Co. KG; Lecturer IoT Ecosystems @ Hochschule Esslingen
Contact

Comments

Please log in or sign up to comment.