NephroSense is my most ambitious project to date — an IoT-based real-time kidney health monitoring system that combines ESP32 microcontrollers, health sensors, AWS IoT Core, and a machine learning model to predict Chronic Kidney Disease (CKD) risk. Here's the full technical breakdown.

The Problem We're Solving

CKD affects over 850 million people worldwide, but 90% don't know they have it until it's in advanced stages because early symptoms are silent. Traditional monitoring requires frequent hospital visits and lab tests. NephroSense aims to bring non-invasive, continuous monitoring to the home.

"Early detection saves lives. If IoT can make that detection accessible, we have a responsibility to build it."

Hardware Architecture

Components used:

  • ESP32 DevKit v1 — main microcontroller (WiFi + Bluetooth built-in)
  • MAX30102 — Pulse oximetry + heart rate sensor (I2C)
  • DS18B20 — Body temperature sensor (OneWire protocol)
  • AD8232 — ECG signal measurement module
  • OLED 0.96" display (SSD1306) — local readout via I2C
  • 18650 LiPo battery + TP4056 charging module — portable power

Firmware: ESP32 + Arduino Framework

The ESP32 reads sensor data every 5 seconds and publishes to AWS IoT Core via MQTT over TLS:

#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <MAX3010x.h>
#include <DallasTemperature.h>

// Publish sensor payload to MQTT
void publishReading(float heartRate, float spo2, float temp) {
    char payload[256];
    snprintf(payload, sizeof(payload),
        "{\"device\":\"nephrosense-01\",\"hr\":%.1f,\"spo2\":%.1f,\"temp\":%.2f,\"ts\":%lu}",
        heartRate, spo2, temp, millis()
    );
    mqttClient.publish("nephrosense/readings", payload);
}
Tip: Store AWS IoT certificates as binary arrays in firmware rather than SPIFFS — it reduces boot time from ~2s to ~200ms and eliminates filesystem corruption risk.

AWS IoT Pipeline

The cloud backend processes readings in real-time:

  • AWS IoT Core — MQTT broker with TLS mutual auth (X.509 device certs)
  • IoT Rules Engine → routes messages to Lambda and DynamoDB
  • Lambda function — runs CKD risk scoring on each reading batch
  • DynamoDB — stores time-series readings with TTL for 90-day retention
  • SNS — sends SMS/email alert if risk score exceeds threshold

The ML Model

The CKD prediction model was trained on the UCI CKD dataset (400 patients, 24 features). We used Random Forest (best accuracy: 98.3%) deployed as a Lambda layer:

import joblib, json

model = joblib.load('/opt/ckd_model.pkl')
scaler = joblib.load('/opt/scaler.pkl')

def handler(event, context):
    features = [event['hr'], event['spo2'], event['temp'], ...]
    scaled = scaler.transform([features])
    risk_prob = model.predict_proba(scaled)[0][1]
    risk_level = 'HIGH' if risk_prob > 0.7 else 'MEDIUM' if risk_prob > 0.4 else 'LOW'
    return {'risk_level': risk_level, 'probability': round(risk_prob, 3)}

Mobile Dashboard

The mobile dashboard (built with React Native) shows:

  • Live heart rate and SpO2 gauge charts (update every 5s)
  • 24-hour trend graphs with anomaly markers
  • CKD risk indicator with color coding (green/yellow/red)
  • Push notifications for threshold breaches

Key Takeaways

Building NephroSense taught me that IoT projects are harder than they look — but also more rewarding. The biggest challenges were sensor calibration drift, WiFi reconnection handling, and keeping AWS Lambda cold-start times under 500ms. All solvable with persistence and good architecture.

Share this article: