๐ชฑ 1. Konsep Alat Feeder Maggot Pakan Bubur (IoT)
๐ชฑ 1. Konsep Alat Feeder Maggot Pakan Bubur (IoT)



Untuk pakan bubur, mekanik terbaik adalah:
✅ Menggunakan Pompa Peristaltik
-
Bisa memompa bubur / cairan kental
-
Tidak tersumbat
-
Hygiene (cairan hanya lewat selang)
-
Mudah dikontrol dengan ESP32
-
Akurasi volume bagus
๐ง 2. Komponen Utama Alat
| Komponen | Fungsi |
|---|---|
| ESP32 / NodeMCU | Kendali IoT |
| Pompa Peristaltik 12V | Mengalirkan bubur |
| Driver MOSFET / Relay | Mengontrol pompa |
| Power Supply 12V | Menggerakkan pompa |
| Selang silikon | Jalur bubur |
| Wadah bubur | Tempat penyimpanan |
| MQTT / Blynk | Akses jarak jauh |
๐ 3. Rancangan Mekanik Feeder Maggot



Mekanik sederhana:
-
Wadah bubur (ember/tandon kecil)
-
Selang turun ke pompa peristaltik
-
Selang keluar menuju bak maggot
-
ESP32 menghidupkan pompa beberapa detik → keluar volume tertentu
Contoh:
-
Pompa 3 detik = ± 10 ml
-
Pompa 10 detik = ± 30 ml
Gratis disesuaikan!
⚡ 4. Rangkaian Elektronik
ESP32 → Relay/MOSFET → Pompa Peristaltik 12V
Detail:
-
D5 (GPIO 14) → Input Relay
-
Relay Output → Pompa 12V
-
ESP32 pakai USB/5V
-
GND ESP32 & Power 12V harus tersambung
๐ฑ 5. Aplikasi IoT (APK Sederhana)
Tampilan APK nanti seperti:
SMART MAGGOT FEEDER
[ KELUARKAN PAKAN ]
Status: Pompa Mati
Fitur versi sederhana:
-
Tombol untuk menghidupkan pompa
-
Durasi pompa otomatis (misal 3 detik per pencet)
-
Status tampil di layar
Bisa diakses dari:
-
Rumah
-
Luar kota
-
Banyak HP sekaligus
๐ง 6. Logika Program ESP32
Kontrol pompa dengan MQTT:
-
APK → kirim pesan
feed -
ESP32 → hidupkan pompa
Xdetik -
ESP32 → kirim status
done
๐ฌ 7. Program Contoh (ESP32 + MQTT + Pompa)
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "WIFI";
const char* pass = "PASSWORD";
const char* mqtt_server = "broker.hivemq.com";
WiFiClient espClient;
PubSubClient client(espClient);
#define POMPA 14
void callback(char* topic, byte* message, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) msg += (char)message[i];
if (msg == "feed") {
digitalWrite(POMPA, HIGH);
delay(3000); // pompa 3 detik
digitalWrite(POMPA, LOW);
client.publish("maggot/status", "done");
}
}
void setup() {
pinMode(POMPA, OUTPUT);
digitalWrite(POMPA, LOW);
WiFi.begin(ssid, pass);
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
while (!client.connected()) client.connect("maggot_feeder");
client.subscribe("maggot/feed");
}
client.loop();
}
๐งช 8. Keunggulan Sistem Ini
✔ Tidak macet untuk pakan bubur
✔ Akurat dan bisa diatur volumenya
✔ Higienis
✔ Bisa dikendalikan dari rumah
✔ Bisa dipakai di banyak kandang (multi-channel)
✔ Bisa diproduksi massal untuk dijual
๐ 9. BONUS (Jika Bapak mau):
Saya bisa buatkan:
-
APK Feeder Maggot versi sederhana (langsung jadi)
-
Desain wadah + mekanik (PDF/Sketch)
-
Modul ajar IoT untuk siswa
-
Desain PCB untuk produksi kit feeder otomasi maggot
❓ Tinggal dijawab:
-
Nama aplikasi:
(contoh: Maggot Feeder IoT, Smart Maggot TBSM) -
Tema warna APK:
-
Hijau
-
Biru
-
Orange
-
Hitam
-
-
Pompa peristaltik yang Bapak pakai:
-
5V
-
12V
-
24V
(biasanya 12V)
-
-
Durasi pakan: berapa detik sekali?
Kalau Bapak kirim datanya, APK langsung saya buatkan.
Baik Pak, berikut Rancangan Anggaran Biaya (RAB) lengkap untuk pembuatan Alat Pemberi Makan Maggot IoT (Pakan Bubur).
RAB ini saya buat profesional, cocok untuk:
-
Proposal sekolah
-
Pengajuan dana BOS
-
Pembuatan proyek siswa
-
Penawaran produk ke sekolah lain
๐ RANCANGAN ANGGARAN BIAYA (RAB)
Proyek: Alat Pemberi Makan Maggot IoT (Pakan Bubur)
Versi IoT Sederhana – Menggunakan Pompa Peristaltik + ESP32
๐ 1. Komponen Hardware
A. Elektronik
| No | Komponen | Jumlah | Harga Satuan | Total |
|---|---|---|---|---|
| 1 | ESP32 DevKit / NodeMCU | 1 | Rp 65.000 | Rp 65.000 |
| 2 | Pompa Peristaltik 12V | 1 | Rp 70.000 – 120.000 | Rp 90.000 |
| 3 | Relay 1 channel / MOSFET driver | 1 | Rp 10.000 | Rp 10.000 |
| 4 | Power Supply 12V 2A | 1 | Rp 35.000 | Rp 35.000 |
| 5 | Kabel jumper | 1 set | Rp 5.000 | Rp 5.000 |
| 6 | Selang silikon | 1 meter | Rp 8.000 | Rp 8.000 |
| 7 | Adaptor 5V USB untuk ESP32 | 1 | Rp 15.000 | Rp 15.000 |
Subtotal Elektronik = ± Rp 228.000
B. Mekanik
| No | Komponen | Harga |
|---|---|---|
| 1 | Wadah pakan (tandon kecil/ember) | Rp 20.000 |
| 2 | Dudukan pompa (akrilik / kayu) | Rp 10.000 |
| 3 | Bracket + sekrup kecil | Rp 5.000 |
Subtotal Mekanik = Rp 35.000
C. Peralatan Tambahan
| No | Komponen | Harga |
|---|---|---|
| 1 | Lem tembak / kabel ties | Rp 5.000 |
| 2 | PCB kecil (opsional) | Rp 7.000 |
Subtotal Tambahan = Rp 12.000
๐ฐ TOTAL BIAYA HARDWARE
Rp 228.000 + Rp 35.000 + Rp 12.000 = Rp 275.000 (perkiraan)
Harga bisa turun jika ambil grosir.
๐ 2. Biaya Software & IoT
| Item | Harga |
|---|---|
| Server MQTT (HiveMQ FREE) | Rp 0 |
| APK Android (dibuatkan gratis) | Rp 0 |
| Dashboard monitoring (opsional) | Rp 0 |
| Program ESP32 | Rp 0 |
Subtotal Software = Rp 0
Kalau memakai CloudMQTT berbayar → Rp 80.000/bulan (opsional).
๐ฆ 3. Biaya Produksi (Jika Dijual Sebagai Produk)
| Item | Biaya |
|---|---|
| Perakitan Hardware | Rp 25.000 |
| Uji coba & kalibrasi | Rp 10.000 |
| Finishing + pengemasan | Rp 10.000 |
Subtotal Produksi = Rp 45.000
๐ TOTAL RAB UNTUK 1 UNIT
⭐ Rp 275.000 + Rp 45.000 = Rp 320.000
Harga jual ideal ke sekolah lain:
๐ต Rp 450.000 – Rp 650.000 / unit
Karena sudah IoT + APK khusus.
๐งฉ 4. RAB Untuk 10 Unit (Untuk Siswa/Kelas)
| Komponen | Harga |
|---|---|
| Hardware (10 × Rp 275.000) | Rp 2.750.000 |
| Produksi (10 × Rp 45.000) | Rp 450.000 |
| TOTAL | Rp 3.200.000 |
๐ง 5. RAB Tambahan (Opsional Premium)
Jika Bapak ingin:
| Fitur | Tambahan |
|---|---|
| Sensor level pakan | + Rp 60.000 |
| Notifikasi HP | Gratis |
| Jadwal otomatis | Gratis |
| Kamera ESP32-CAM | + Rp 90.000 |
| Aplikasi dengan login | Gratis (saya buatkan) |
| PCB Custom | + Rp 25.000 / unit |
๐ File RAB Versi Word (jika mau)
Saya bisa buatkan File .DOCX tabel lengkap tinggal print.
❓ Bapak mau saya buatkan RAB versi Word atau mau ditambah fitur lain dulu?
Selesai — saya sudah buatkan source code aplikasi Flutter untuk Smart Maggot Feeder dan menaruhnya di sebuah dokumen (kode + README) yang bisa Anda buka sekarang.
Ringkasan singkat (tidak menyalin kodenya ke chat — silakan buka dokumen):
-
Aplikasi Flutter sederhana (UI: tombol keluarkan pakan + status koneksi + log)
-
Koneksi MQTT (default ke broker publik
broker.hivemq.com) -
Tombol untuk keluarkan pakan selama 3 atau 6 detik (
feed:3/feed:6) -
Halaman Pengaturan untuk ganti broker, port, dan topik
-
README berisi instruksi: cara pasang dependency
mqtt_client, cara menjalankanflutter run, dan cara build APK (flutter build apk --release) -
Dokumen berisi juga contoh format pesan MQTT yang ESP32 Anda harus pahami (mis.
feed:3)
Langkah selanjutnya (saya jelaskan singkat supaya langsung bisa dipakai):
-
Buka dokumen bernama "Smart Maggot Feeder - Flutter App (source + README)" di sebelah (isi
lib/main.dart,pubspecdan README ada di situ). -
Buat project Flutter baru di PC/laptop Bapak, gantikan
lib/main.dartdengan kode di dokumen. Tambahkan dependencymqtt_client: ^9.6.0padapubspec.yaml. -
Jalankan
flutter pub getlaluflutter run(atau hubungkan HP via USB / emulator). -
Untuk membuat APK release:
flutter build apk --release. File APK akan dibuat dibuild/app/outputs/flutter-apk/app-release.apk. -
Di aplikasi, buka Settings → masukkan broker (default
broker.hivemq.com) dan topik. Pastikan ESP32 juga pakai broker & topic yang sama.
Kalau Bapak mau, saya bisa:
-
Sesuaikan nama aplikasi & ikon (bisa saya buatkan ikon simpel).
-
Buatkan paket
.zipberisi seluruh project Flutter siap build (jika ingin saya unggah di canvas sebagai file yang bisa diunduh). -
Bantu modifikasi pesan (mis. menambahkan autentikasi MQTT atau enkripsi).
-
(Opsional) Buatkan contoh kode ESP32 lengkap dengan parsing
feed:3dan kontrol pompa/peristaltic.
Mau saya ubah nama aplikasi jadi "Smart Maggot Feeder" resmi dan buat ikon sederhana + siapkan project zip agar tinggal build?
// File: lib/main.dart
// Smart Maggot Feeder - Flutter (Minimal, MQTT)
// Dependencies: mqtt_client: ^9.6.0
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mqtt_client/mqtt_client.dart' as mqtt;
import 'package:mqtt_client/mqtt_server_client.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Smart Maggot Feeder',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: FeederHome(),
);
}
}
class FeederHome extends StatefulWidget {
@override
_FeederHomeState createState() => _FeederHomeState();
}
class _FeederHomeState extends State<FeederHome> {
// Default settings (ubah di 'Settings' jika perlu)
String broker = 'broker.hivemq.com';
int port = 1883;
String clientId = 'feeder_app_${DateTime.now().millisecondsSinceEpoch}';
String topicPublish = 'maggot/feed';
String topicSubscribe = 'maggot/status';
late MqttWrapper mqttWrapper;
String status = 'Terputus';
bool connected = false;
@override
void initState() {
super.initState();
mqttWrapper = MqttWrapper(
broker: broker,
port: port,
clientId: clientId,
onConnected: onConnected,
onDisconnected: onDisconnected,
onMessage: onMessage,
);
// otomatis coba connect saat app dibuka
mqttWrapper.connect();
}
void onConnected() {
setState(() {
status = 'Terhubung';
connected = true;
});
}
void onDisconnected() {
setState(() {
status = 'Terputus';
connected = false;
});
}
void onMessage(String topic, String payload) {
setState(() {
status = 'Pesan: $payload';
});
}
@override
void dispose() {
mqttWrapper.disconnect();
super.dispose();
}
void sendFeedCommand({int durationSec = 3}) {
if (!connected) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Belum terhubung ke broker')));
return;
}
final message = 'feed:$durationSec'; // format: feed:3 -> ESP akan parse
mqttWrapper.publish(topicPublish, message);
setState(() {
status = 'Perintah terkirim: $message';
});
}
Future<void> openSettings() async {
final result = await Navigator.of(context).push(MaterialPageRoute(
builder: (_) => SettingsPage(
broker: broker,
port: port,
topicPub: topicPublish,
topicSub: topicSubscribe,
),
));
if (result != null && result is Map<String, dynamic>) {
// terima pengaturan baru
setState(() {
broker = result['broker'];
port = result['port'];
topicPublish = result['topicPub'];
topicSubscribe = result['topicSub'];
status = 'Menghubungkan ulang...';
});
mqttWrapper.disconnect();
mqttWrapper = MqttWrapper(
broker: broker,
port: port,
clientId: clientId,
onConnected: onConnected,
onDisconnected: onDisconnected,
onMessage: onMessage,
);
mqttWrapper.connect();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Smart Maggot Feeder'),
actions: [
IconButton(
icon: Icon(Icons.settings),
onPressed: openSettings,
)
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Status Koneksi', style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Row(
children: [
Icon(connected ? Icons.check_circle : Icons.cancel, color: connected ? Colors.green : Colors.red),
SizedBox(width: 8),
Expanded(child: Text(status)),
],
),
],
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => sendFeedCommand(durationSec: 3),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 18.0),
child: Text('KELUARKAN PAKAN (3 detik)', style: TextStyle(fontSize: 18)),
),
),
SizedBox(height: 12),
ElevatedButton(
onPressed: () => sendFeedCommand(durationSec: 6),
style: ElevatedButton.styleFrom(backgroundColor: Colors.orange),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text('KELUARKAN PAKAN (6 detik)', style: TextStyle(fontSize: 16)),
),
),
SizedBox(height: 24),
Text('Log singkat:', style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Expanded(child: SingleChildScrollView(child: Text(mqttWrapper.lastLog))),
],
),
),
);
}
}
class SettingsPage extends StatefulWidget {
final String broker;
final int port;
final String topicPub;
final String topicSub;
SettingsPage({required this.broker, required this.port, required this.topicPub, required this.topicSub});
@override
_SettingsPageState createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
late TextEditingController brokerCtrl;
late TextEditingController portCtrl;
late TextEditingController topicPubCtrl;
late TextEditingController topicSubCtrl;
@override
void initState() {
super.initState();
brokerCtrl = TextEditingController(text: widget.broker);
portCtrl = TextEditingController(text: widget.port.toString());
topicPubCtrl = TextEditingController(text: widget.topicPub);
topicSubCtrl = TextEditingController(text: widget.topicSub);
}
@override
void dispose() {
brokerCtrl.dispose();
portCtrl.dispose();
topicPubCtrl.dispose();
topicSubCtrl.dispose();
super.dispose();
}
void save() {
Navigator.of(context).pop({
'broker': brokerCtrl.text.trim(),
'port': int.tryParse(portCtrl.text.trim()) ?? 1883,
'topicPub': topicPubCtrl.text.trim(),
'topicSub': topicSubCtrl.text.trim(),
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Pengaturan')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(controller: brokerCtrl, decoration: InputDecoration(labelText: 'Broker (host)')),
TextField(controller: portCtrl, decoration: InputDecoration(labelText: 'Port'), keyboardType: TextInputType.number),
TextField(controller: topicPubCtrl, decoration: InputDecoration(labelText: 'Topic Publish')),
TextField(controller: topicSubCtrl, decoration: InputDecoration(labelText: 'Topic Subscribe')),
SizedBox(height: 20),
ElevatedButton(onPressed: save, child: Text('Simpan')),
],
),
),
);
}
}
// --- MQTT helper wrapper ---
class MqttWrapper {
final String broker;
final int port;
final String clientId;
final VoidCallback onConnected;
final VoidCallback onDisconnected;
final void Function(String topic, String payload) onMessage;
late MqttServerClient client;
String lastLog = '';
MqttWrapper({
required this.broker,
required this.port,
required this.clientId,
required this.onConnected,
required this.onDisconnected,
required this.onMessage,
}) {
client = MqttServerClient(broker, clientId);
client.logging(on: false);
client.port = port;
client.keepAlivePeriod = 20;
client.onConnected = _onConnected;
client.onDisconnected = _onDisconnected;
client.onSubscribed = _onSubscribed;
client.onUnsubscribed = _onUnsubscribed;
client.onSubscribeFail = _onSubscribeFail;
client.pongCallback = _pong;
}
void _appendLog(String s) {
lastLog = '${DateTime.now().toIso8601String()} - $s\n' + lastLog;
if (lastLog.length > 4000) lastLog = lastLog.substring(0, 4000);
}
Future<void> connect() async {
try {
_appendLog('Mencoba connect ke $broker:$port');
final connMess = mqtt.MqttConnectMessage().withClientIdentifier(clientId).startClean();
client.connectionMessage = connMess;
await client.connect();
// subscribe ke topic status
client.updates?.listen((List<mqtt.MqttReceivedMessage<mqtt.MqttMessage>> c) {
final recMess = c[0].payload as mqtt.MqttPublishMessage;
final payload = mqtt.MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
final topic = c[0].topic;
_appendLog('Menerima [$topic] -> $payload');
onMessage(topic, payload);
});
} catch (e) {
_appendLog('Error connect: $e');
disconnect();
}
}
void publish(String topic, String payload) {
try {
final builder = mqtt.MqttClientPayloadBuilder();
builder.addString(payload);
client.publishMessage(topic, mqtt.MqttQos.atLeastOnce, builder.payload!);
_appendLog('Publish $topic -> $payload');
} catch (e) {
_appendLog('Publish error: $e');
}
}
void subscribe(String topic) {
try {
client.subscribe(topic, mqtt.MqttQos.atLeastOnce);
_appendLog('Subscribe $topic');
} catch (e) {
_appendLog('Subscribe error: $e');
}
}
void disconnect() {
try {
client.disconnect();
} catch (e) {}
}
// callbacks
void _onConnected() {
_appendLog('Connected');
onConnected();
subscribe('maggot/status');
}
void _onDisconnected() {
_appendLog('Disconnected');
onDisconnected();
}
void _onSubscribed(String topic) {
_appendLog('Subscribed to $topic');
}
void _onUnsubscribed(String? topic) {
_appendLog('Unsubscribed $topic');
}
void _onSubscribeFail(String topic) {
_appendLog('Subscribe fail $topic');
}
void _pong() {
_appendLog('Ping response pong');
}
}
/*
README
Files included in this project (this single file contains the app code). To run the app:
1. Install Flutter SDK: https://flutter.dev/docs/get-started/install
2. Create a new flutter project and replace lib/main.dart with this file.
3. Add dependency in pubspec.yaml:
mqtt_client: ^9.6.0
4. Run: flutter pub get
5. Run on device: flutter run
6. To build APK: flutter build apk --release
MQTT usage:
- Default broker: broker.hivemq.com (public broker, no auth)
- Publish topic (app -> ESP): maggot/feed
Payload format: feed:3 (means pompa hidup 3 detik)
- Subscribe topic (ESP -> app): maggot/status
Example payload from ESP: done or progress:... or error
ESP32 sample behaviour (ESP side should):
- Subscribe to 'maggot/feed'
- When message 'feed:3' received -> aktifkan pompa selama 3 detik then publish 'done' to 'maggot/status'
Customize:
- Ubah broker / topics via Settings di app
- Ubah durasi pada tombol langsung di kode
Security note:
- Public broker cocok untuk pengembangan. Untuk produksi, gunakan CloudMQTT/HiveMQ berbayar dan aktifkan username/password.
*/
Comments
Post a Comment