Menjalankan machine learning di mikrokontroler: konsep TinyML, batasan memori dan komputasi MCU, kuantisasi model, TensorFlow Lite Micro, serta praktik melatih, mengonversi, dan menjalankan model inferensi di ESP32.

Di episode 12 kita mendeteksi anomali dengan aturan statistik. Episode ini menaikkan level: membuat perangkat belajar sendiri pola normal dan mendeteksi penyimpangan — tanpa mengirim data ke cloud, tanpa menunggu internet. Ini adalah TinyML.
Mengapa TinyML adalah track tercepat di 2026? Karena menempatkan kecerdasan di perangkat memangkas latensi, bandwidth, dan biaya — plus menjaga privasi (data tidak keluar dari perangkat). Sensor yang bisa mendeteksi suara aneh, getaran mesin rusak, atau gestur — hanya dengan MCU hemat daya — adalah fondasi produk-produk baru yang sedang booming.
TinyML adalah menjalankan model machine learning pada MCU — perangkat dengan RAM ratusan KB dan flash beberapa MB. Bandingkan dengan ML biasa:
| Aspek | ML Cloud | TinyML |
|---|---|---|
| RAM | GB | 100–500 KB |
| Flash | Bisa puluhan GB | 1–4 MB |
| Model | Jutaan parameter | Ratusan ribu parameter |
| Latensi | Detik (jaringan) | Milidetik (lokal) |
| Daya | Watt | mW |
| Koneksi | Wajib | Tidak diperlukan |
Model TinyML harus kecil, cepat, dan hemat daya — tetapi kelebihannya luar biasa: inferensi berjalan di perangkat, offline, tanpa biaya per request.
Ekosistem utama TinyML adalah TensorFlow Lite Micro (TFLM): runtime C++ yang menjalankan model TFLite di MCU. Prosesnya:
Data → latih model (Python/TensorFlow)
→ konversi ke .tflite → kuantisasi ke int8
→ embed sebagai C array → inferensi di ESP32 (TFLM)Kuantisasi adalah kunci: mengubah bobot model dari float32 ke int8. Dampaknya dramatis:
| Representasi | Ukuran | Kecepatan |
|---|---|---|
| float32 | 4 byte/param | Lambat di MCU tanpa FPU |
| int8 | 1 byte/param | 4x lebih kecil, jauh lebih cepat |
Model 400 KB float bisa menyusut ke 100 KB setelah kuantisasi int8 — dengan penurunan akurasi kecil (1–3% untuk model sederhana). Ini trade-off yang hampir selalu layak untuk perangkat.
Mari buat contoh nyata: model mendeteksi apakah nilai sensor normal, anomali, atau kritis — klasifikasi tiga kelas dari satu fitur. Latih di Python:
import tensorflow as tf
import numpy as np
# Data sintetis: suhu normal 20-40, anomali 40-60, kritis 60-80
x = np.concatenate([
np.random.uniform(20, 40, 200),
np.random.uniform(40, 60, 200),
np.random.uniform(60, 80, 200)
]).astype(np.float32)
y = np.concatenate([
np.zeros(200), np.ones(200), np.full(200, 2)
]).astype(np.int32)
model = tf.keras.Sequential([
tf.keras.layers.Dense(8, activation="relu", input_shape=(1,)),
tf.keras.layers.Dense(3, activation="softmax")
])
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
model.fit(x, y, epochs=20, verbose=0)
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()
# Output C array untuk di-embed ke firmware
with open("model.tflite", "wb") as f:
f.write(tflite_model)
print("model.tflite:", len(tflite_model), "bytes")Hasilnya file model.tflite — konverter dengan Optimize.DEFAULT melakukan kuantisasi otomatis.
Konversi file .tflite ke C array:
xxd -i model.tflite > model_data.h#include <Arduino.h>
#include <tensorflow/lite/micro/all_ops_resolver.h>
#include <tensorflow/lite/micro/micro_interpreter.h>
#include "model_data.h" // hasil xxd
static tflite::MicroInterpreter *interpreter;
void setup() {
Serial.begin(115200);
static tflite::AllOpsResolver resolver;
static tflite::MicroInterpreter static_interpreter(
tflite::GetModel(model_data),
resolver,
/* tensor arena */ arena, /* ukuran arena */ ARENA_SIZE);
interpreter = &static_interpreter;
interpreter->AllocateTensors();
}
void loop() {
float t = readSensor();
// isi input tensor, jalankan inferensi
interpreter->input(0)->data.f[0] = t;
interpreter->Invoke();
// baca probabilitas tiap kelas
float *out = interpreter->output(0)->data.f;
Serial.printf("suhu=%.1f normal=%.2f anomali=%.2f kritis=%.2f\n",
t, out[0], out[1], out[2]);
delay(2000);
}Note
Tensor arena adalah buffer statis yang dialokasikan sekali di setup. Ukurannya dihitung saat build (tool dapat melaporkan ukuran yang dibutuhkan). Ini alasan TinyML memakai arena statis: tidak ada malloc runtime di jalur kritis sehingga latensi deterministik.
Mulai dari masalah sederhana: satu fitur, beberapa kelas, data bisa dilabeli. Contoh yang bagus untuk pemula: klasifikasi gestur dari accelerometer, deteksi suara kata sederhana, atau level baterai/suhu. Contoh yang terlalu ambisius di MCU: pengenalan gambar kompleks atau NLP.
Jangan percaya akurasi di dataset training — uji dengan data yang tidak pernah dilihat model. Kuantisasi int8 bisa menurunkan akurasi; selalu evaluasi model kuantisasi di data test sebelum deploy.
interpreter = tf.lite.Interpreter(model_path="model.tflite")
interpreter.allocate_tensors()
# ... evaluasi di data test, bandingkan akurasi float vs int8Jika penurunan akurasi melebihi toleransi, pertimbangkan: model lebih besar, teknik quantization-aware training, atau hybrid (kuantisasi sebagian lapisan).
Warning
TinyML adalah alat terakhir, bukan alat pertama. Mulailah dengan aturan sederhana (threshold, statistik episode 12); baru naik ke ML jika polanya terlalu kompleks untuk aturan. Produk yang hemat biaya adalah yang memakai solusi sesederhana mungkin — ML menambah kompleksitas testing, resource, dan maintenance.
Inti yang harus dibawa pulang:
.tflite → kuantisasi int8 → embed C array → inferensi TFLM.Di episode 14 selanjutnya, kita akan memperkuat tulang punggung komunikasi: IoT networking & gateway — arsitektur gateway, translasi protokol, dan buffering — plus praktik membangun gateway yang menghubungkan banyak perangkat ke cloud. Jaringan kalian mulai "terstruktur"!