Tutorial Project Smart Sun-Safety & Skin Health Tracker Berbasis ESP32-C3


Matahari memancarkan radiasi sinar Ultraviolet (UV) yang memiliki dampak ganda bagi tubuh manusia. Di satu sisi, paparan matahari pagi memicu produksi Vitamin D yang esensial bagi tulang dan imunitas. Di sisi lain, paparan berlebih pada siang hari dapat merusak jaringan kulit, memicu penuaan dini, hingga meningkatkan risiko kanker kulit.
Sayangnya, mata manusia tidak dapat melihat radiasi ini. Untuk menjembatani kebutuhan tersebut, proyek Smart Sun-Safety & Skin Health Tracker ini dikembangkan. Alat portabel berbasis IoT ini bertindak sebagai asisten kesehatan kulit kontekstual yang tahu kapan matahari harus disambut sebagai nutrisi, dan kapan harus dihindari sebagai ancaman.
1. Penjelasan Projek
Proyek ini berfokus pada pembuatan perangkat wearable atau gadget portabel pintar yang mampu memantau indeks UV secara real-time. Keunggulan utama dari proyek ini adalah Sistem Logika Kontekstual Medis yang diintegrasikan dengan waktu lokal (RTC):
- Sesi Panen Vitamin D (08.00 – 10.00 WIB): Alat akan memberikan waktu toleransi selama 15 menit bagi pengguna untuk berjemur tanpa perlindungan (sunscreen). Perangkat akan menghitung durasi (timer) secara mundur dan menampilkan status “EMAS VITAMIN D”. Setelah batas 15 menit habis, buzzer akan berbunyi selama 10 detik sebagai pengingat untuk segera memakai perlindungan atau berteduh.
- Sesi Perlindungan Total (10.00 – 16.00 WIB): Perangkat langsung mendeteksi radiasi berbahaya sejak menit pertama dan menyarankan penggunaan sunscreen SPF 30+. Terdapat pula fitur timer otomatis 2 jam sekali untuk mengingatkan pengguna melakukan reapply sunscreen (pemakaian ulang).
2. Penjelasan Produk & Komponen
Sistem ini didukung oleh kombinasi komponen berspesifikasi tinggi yang ringkas dan efisien:
- ESP32-C3 SuperMini: Mikrokontroler berbasis arsitektur RISC-V berukuran mikro. Meskipun ukurannya sangat kecil, board ini memiliki performa tinggi serta dilengkapi konektivitas Wi-Fi dan Bluetooth, serta RTC internal yang dioptimalkan untuk perangkat wearable.
- Sensor UV GUVA-S12SD: Sensor analog yang sangat sensitif terhadap spektrum sinar UV-A dan UV-B (240-370nm). Berfungsi mengubah intensitas radiasi matahari menjadi output tegangan listrik linear.
- Sensor Spektral AS7341: Sensor analitis tingkat lanjut 11-channel. Di dalam proyek ini, channel Clear digunakan untuk membaca intensitas cahaya tampak (Ambient Light) sekitar sebagai validasi apakah pengguna benar-benar berada di bawah terik matahari (outdoor) atau sekadar di dalam ruangan.
- LCD MCUDEV TFT 1.44″: Layar warna berbasis driver ST7735 beresolusi kompak. Digunakan untuk menampilkan GUI (Graphic User Interface) adaptif yang presentable (Font angka jumbo dan warna latar belakang yang berubah otomatis sesuai tingkat bahaya).
- Buzzer Aktif: Komponen indikator suara (audio alert) untuk memberikan alarm tanda bahaya atau pengingat durasi waktu tanpa harus pengguna melihat layar.
- Body Case DIY: Berfungsi untuk melindungi komponen jika dibuat portable Opsional
3. Wiring Diagram (Skema Perkabelan)
Karena ESP32-C3 SuperMini memiliki jumlah pin yang sangat terbatas, konfigurasi pin dikondisikan menggunakan Hardware I2C dan Software SPI secara efisien agar semua komponen bekerja bersamaan tanpa bentrok:


| Komponen | Pin Komponen | Sambungkan ke ESP32-C3 | Fungsi / Keterangan |
| LCD TFT 1.44″ | VCC | 3V3 (atau 5V jika backlight kurang cerah) | Daya Utama LCD |
| GND | GND | Ground | |
| DI (MOSI) | GPIO 6 | Jalur Data Jalur SPI | |
| SC (CLK) | GPIO 4 | Jalur Clock SPI | |
| CS | GPIO 7 | Chip Select Layar | |
| RST | GPIO 10 | Reset Pin | |
| RS (DC) | GPIO 5 | Data / Command Selection | |
| BLK | 3V3 | Backlight (Lampu Latar Selalu Hidup) | |
| Sensor AS7341 | VIN / GND | 3V3 / GND | Daya Sensor Spektral |
| SDA | GPIO 1 | Jalur Data I2C Kustom | |
| SCL | GPIO 2 | Jalur Clock I2C Kustom | |
| Sensor UV GUVA | VCC / GND | 3V3 / GND | Daya Sensor UV (Wajib 3.3V) |
| SIO / SIG | GPIO 0 | Input Analog ADC murni | |
| Buzzer Aktif | Positif (+) | GPIO 8 | Kontrol Pemicu Suara Alert |
| Negatif (-) | GND | Ground |
4. Kodingan Lengkap (Source Code Arduino IDE)
Berikut adalah source code final yang sudah dikalibrasi (multi-sampling 20x rata-rata) untuk meredam noise ADC, lengkap dengan sistem operasi mini berbasis RTC internal ESP32-C3:
#include <Wire.h>
#include <Adafruit_AS7341.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <time.h> // Library bawaan untuk RTC internal
// ==========================================
// CONFIGURASI PIN LCD TFT ST7735
// ==========================================
#define TFT_CS 7
#define TFT_RST 10
#define TFT_DC 5
#define TFT_MOSI 6
#define TFT_SCLK 4
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
#define ST77XX_GREY 0x8410
// ==========================================
// CONFIGURASI PIN SENSOR & BUZZER
// ==========================================
Adafruit_AS7341 as7341;
const int UV_PIN = 0;
#define BUZZER_PIN 8
// Variabel Pelacak Waktu & Timer
unsigned long outdoorStartTime = 0;
unsigned long lastReapplyTime = 0;
bool isOutdoorBefore = false;
unsigned long buzzerAlertStart = 0;
bool isBuzzerActive = false;
uint16_t lastBgColor = ST77XX_BLACK;
void setup() {
Serial.begin(115200);
Wire.begin(1, 2);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
tft.initR(INITR_144GREENTAB);
tft.setRotation(1);
tft.fillScreen(ST77XX_BLACK);
// Setting Waktu RTC Internal Manual awal (Simulasi jam 09:00 pagi)
struct tm tm_skrg;
tm_skrg.tm_year = 2026 - 1900;
tm_skrg.tm_mon = 4;
tm_skrg.tm_mday = 19;
tm_skrg.tm_hour = 9; // Silakan ubah angka jam di sini untuk pengujian beralih mode
tm_skrg.tm_min = 0;
tm_skrg.tm_sec = 0;
time_t t = mktime(&tm_skrg);
struct timeval tv = { .tv_sec = t, .tv_usec = 0 };
settimeofday(&tv, NULL);
if (!as7341.begin()) {
Serial.println("Sensor AS7341 tidak ditemukan!");
} else {
as7341.setATIME(100);
as7341.setASTEP(999);
as7341.setGain(AS7341_GAIN_256X);
}
tft.fillScreen(ST77XX_BLACK);
}
void loop() {
// 1. Ambil Waktu Terkini dari RTC Internal
time_t now;
struct tm *timeinfo;
time(&now);
timeinfo = localtime(&now);
int jamAktif = timeinfo->tm_hour;
int menitAktif = timeinfo->tm_min;
// 2. Membaca Sensor UV (20x Multi-sampling anti-flicker)
long totalADC = 0;
for(int i = 0; i < 20; i++) { totalADC += analogRead(UV_PIN); delay(2); }
float rawADC = totalADC / 20.0;
float voltage = (rawADC * 3300.0) / 4095.0;
float uvIndex = 0;
if (voltage > 50.0) uvIndex = (voltage - 50.0) / 110.0;
if (uvIndex < 0) uvIndex = 0;
// 3. Membaca Kecerahan Lingkungan (AS7341)
uint16_t lightAmbient = 0;
uint16_t readings[12];
if (as7341.readAllChannels(readings)) {
lightAmbient = readings[AS7341_CHANNEL_CLEAR];
}
// Parameter penentu apakah pengguna berada di luar ruangan terik
bool isCurrentlyOutdoor = (lightAmbient > 2500 && uvIndex > 0.5);
// 4. State Machine Analisis Kontekstual Medis
uint16_t bgColor = ST77XX_GREEN;
uint16_t txtColor = ST77XX_BLACK;
String riskStatus = "AMAN / INDOOR";
String rec1 = "Kondisi aman di ";
String rec2 = "dalam ruangan. ";
bool triggerBuzzerPendek = false;
if (isCurrentlyOutdoor) {
// A. MODE BERJEMUR PAGI (08.00 - 10.00 WIB)
if (jamAktif >= 8 && jamAktif < 10) {
if (!isOutdoorBefore) {
outdoorStartTime = millis();
isOutdoorBefore = true;
}
unsigned long durasiTerpaparMenit = (millis() - outdoorStartTime) / 60000;
if (durasiTerpaparMenit < 15) {
bgColor = ST77XX_GREEN; txtColor = ST77XX_BLACK;
riskStatus = "EMAS VITAMIN D";
rec1 = "Waktu emas sehat! ";
rec2 = "Durasi:" + String(durasiTerpaparMenit) + " mnt/15mnt ";
} else {
bgColor = ST77XX_YELLOW; txtColor = ST77XX_BLACK;
riskStatus = "BATAS JEMUR HABIS";
rec1 = "Segera pakai SPF /";
rec2 = "masuk ruangan! ";
if (durasiTerpaparMenit == 15 && !isBuzzerActive && buzzerAlertStart == 0) {
isBuzzerActive = true;
buzzerAlertStart = millis();
}
}
}
// B. MODE PROTEKSI SIANG TERIK (10.00 - 16.00 WIB)
else if (jamAktif >= 10 && jamAktif < 16) {
if (!isOutdoorBefore) {
lastReapplyTime = millis();
isOutdoorBefore = true;
}
unsigned long durasiReapplyMenit = (millis() - lastReapplyTime) / 60000;
if (uvIndex >= 7.5) {
bgColor = ST77XX_RED; txtColor = ST77XX_WHITE;
riskStatus = "BAHAYA EKSTREM!";
rec1 = "Matahari membakar!";
rec2 = "Cari tempat teduh!";
triggerBuzzerPendek = true;
} else {
bgColor = 0xFD20; txtColor = ST77XX_WHITE; // Oranye
riskStatus = "WAJIB SUNSCREEN";
if (durasiReapplyMenit >= 120) {
rec1 = "WAKTUNYA REAPPLY ";
rec2 = "Ulangi Sunscreen! ";
triggerBuzzerPendek = true;
} else {
rec1 = "Gunakan SPF 30+ ";
rec2 = "Reapply dlm " + String(120 - durasiReapplyMenit) + " mnt ";
}
}
}
// C. SORE HARI LUAR JENDELA TERIK
else {
bgColor = ST77XX_GREEN; txtColor = ST77XX_BLACK;
riskStatus = "MATAHARI TEDUH";
rec1 = "Radiasi rendah. ";
rec2 = "Aman beraktivitas.";
}
} else {
isOutdoorBefore = false;
outdoorStartTime = 0;
lastReapplyTime = 0;
}
// 5. Manajemen Pola Bunyi Suara Alarm Buzzer
if (isBuzzerActive) {
if (millis() - buzzerAlertStart < 10000) {
digitalWrite(BUZZER_PIN, (millis() / 300) % 2);
} else {
digitalWrite(BUZZER_PIN, LOW);
isBuzzerActive = false;
}
} else if (triggerBuzzerPendek) {
digitalWrite(BUZZER_PIN, (millis() / 500) % 2);
} else {
digitalWrite(BUZZER_PIN, LOW);
}
// 6. Merender ke Layar LCD (Presentable Layout)
if (bgColor != lastBgColor) { tft.fillScreen(bgColor); lastBgColor = bgColor; }
tft.setTextColor(txtColor, bgColor);
tft.setTextWrap(false);
// Baris Atas: Jam Digital
tft.setTextSize(1); tft.setCursor(6, 6);
tft.printf("JAM: %02d:%02d", jamAktif, menitAktif);
tft.drawFastHLine(0, 18, 128, txtColor);
// Baris Tengah: Font Jumbo Angka UV Index
tft.setCursor(6, 24); tft.setTextSize(4);
tft.print(uvIndex, 1); tft.print(" ");
// Kanan Atas: Info Intensitas Cahaya
tft.setTextSize(1); tft.setCursor(84, 24); tft.print("LIGHT:");
tft.setCursor(84, 36); tft.print(lightAmbient); tft.print(" ");
tft.drawFastHLine(0, 60, 128, txtColor);
// Baris Bawah: Status Alat
tft.setCursor(6, 66); tft.print("STATUS ALAT:");
tft.setCursor(6, 76);
String fStat = riskStatus + " ";
tft.print(fStat.substring(0, 19));
tft.drawFastHLine(0, 92, 128, txtColor);
// Baris Paling Bawah: Rekomendasi Tindakan Medis
tft.setCursor(6, 98); tft.print("REKOMENDASI OS:");
tft.setCursor(6, 109); tft.print(rec1);
tft.setCursor(6, 119); tft.print(rec2);
delay(200);
}
5. Kesimpulan Proyek
Melalui integrasi data sensor analog dan spektral digital yang dikendalikan oleh RTC internal ESP32-C3, alat Smart Sun-Safety & Skin Health Tracker berhasil membuktikan bahwa teknologi embedded system mampu diaplikasikan secara dinamis untuk mendukung gaya hidup sehat. Alat ini tidak hanya memberikan proteksi pasif dari ancaman kanker kulit pada siang hari, melainkan juga mengedukasi sekaligus menuntun penggunanya untuk mengoptimalkan penyerapan Vitamin D alami secara seimbang. Perangkat ini siap dikembangkan lebih lanjut menjadi produk komersial wearable mandiri berbasis baterai.












