Papan Disokong
ESP8266 (NodeMCU) atau ESP32
Sensor
HC-SR04 Ultrasonic × 12 unit
Protokol
HTTP POST ke API endpoint
Library Arduino Diperlukan
Pasang library berikut melalui Arduino IDE → Sketch → Include Library → Manage Libraries:
ArduinoJson (bblanchon)ESP8266WiFi (built-in)ESP8266HTTPClient (built-in)
Jadual Wiring Sensor (Contoh)
| Slot | Pin TRIG | Pin ECHO |
|---|---|---|
| A1 | D1 (GPIO5) | D2 (GPIO4) |
| A2 | D3 (GPIO0) | D4 (GPIO2) |
| A3 | D5 (GPIO14) | D6 (GPIO12) |
| B1 | D7 (GPIO13) | D8 (GPIO15) |
| B2 | D0 (GPIO16) | D9 (GPIO3) |
| B3 | GPIO17 | GPIO18 |
| C1–C3 / D1–D3 | Pin tambahan | ESP32 atau I2C expander |
Untuk 12 slot, gunakan ESP32 (lebih banyak pin GPIO tersedia) atau tambah I2C GPIO expander seperti PCF8574.
Format Data yang Dihantar
Arduino menghantar HTTP POST ke /api/parking/update dengan body JSON:
{
"readings": [
{ "slotId": 1, "distance": 8 },
{ "slotId": 2, "distance": 120 },
{ "slotId": 3, "distance": 5 },
...
]
}Jarak ≤ 15 cm = slot TERISI (lampu merah). Jarak > 15 cm = slot KOSONG (lampu hijau).
smartpark_parking.ino
/*
* SmartPark — Sistem Pengesanan Parking Arduino
* Papan: ESP8266 (NodeMCU) atau ESP32
* Sensor: HC-SR04 Ultrasonic x12
*
* Sambungan wiring (contoh untuk 2 sensor pertama):
* Sensor 1 TRIG -> D1 (GPIO5)
* Sensor 1 ECHO -> D2 (GPIO4)
* Sensor 2 TRIG -> D3 (GPIO0)
* Sensor 2 ECHO -> D4 (GPIO2)
* VCC -> 5V, GND -> GND
*
* Ulang pattern TRIG/ECHO untuk slot 3-12 mengikut pin yang tersedia.
*/
#include <ESP8266WiFi.h> // Guna <WiFi.h> untuk ESP32
#include <ESP8266HTTPClient.h> // Guna <HTTPClient.h> untuk ESP32
#include <ArduinoJson.h>
// =====================
// KONFIGURASI WIFI
// =====================
const char* WIFI_SSID = "NAMA_WIFI_ANDA";
const char* WIFI_PASSWORD = "KATA_LALUAN_WIFI";
// =====================
// KONFIGURASI SERVER
// =====================
// Guna IP awam jika di Vercel, atau IP LAN jika server tempatan
const String SERVER_URL = "https://YOUR_APP.vercel.app/api/parking/update";
// =====================
// KONFIGURASI SENSOR
// =====================
#define NUM_SLOTS 12
#define OCCUPIED_THRESHOLD_CM 15 // Jarak <= 15cm = slot terisi
#define SEND_INTERVAL_MS 2000 // Hantar data setiap 2 saat
// Pin TRIG dan ECHO untuk setiap slot
// Laraskan mengikut wiring sebenar anda
const int TRIG_PINS[NUM_SLOTS] = {5, 0, 14, 12, 13, 15, 3, 1, 9, 10, 4, 2};
const int ECHO_PINS[NUM_SLOTS] = {4, 2, 12, 13, 15, 3, 1, 16, 10, 9, 2, 14};
// =====================
// FUNGSI UKUR JARAK
// =====================
float measureDistance(int trigPin, int echoPin) {
// Hantar pulse ultrasonic
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Baca masa echo kembali (timeout 30ms)
long duration = pulseIn(echoPin, HIGH, 30000);
if (duration == 0) {
return 999.0; // Tiada objek dikesan
}
// Tukar ke cm (kelajuan bunyi = 343 m/s)
float distanceCm = (duration * 0.0343) / 2.0;
return distanceCm;
}
// =====================
// SETUP
// =====================
void setup() {
Serial.begin(115200);
delay(100);
// Set pin sensor
for (int i = 0; i < NUM_SLOTS; i++) {
pinMode(TRIG_PINS[i], OUTPUT);
pinMode(ECHO_PINS[i], INPUT);
}
// Sambung WiFi
Serial.print("Menyambung ke WiFi: ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi bersambung!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
// =====================
// LOOP UTAMA
// =====================
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi terputus. Cuba sambung semula...");
WiFi.reconnect();
delay(5000);
return;
}
// Baca semua sensor dan bina JSON
StaticJsonDocument<512> doc;
JsonArray readings = doc.createNestedArray("readings");
for (int i = 0; i < NUM_SLOTS; i++) {
float dist = measureDistance(TRIG_PINS[i], ECHO_PINS[i]);
JsonObject reading = readings.createNestedObject();
reading["slotId"] = i + 1;
reading["distance"] = (int)dist;
Serial.print("Slot ");
// Section: A=1-3, B=4-6, C=7-9, D=10-12
char sections[] = "AABBCCDD";
char sec = (i < 3) ? 'A' : (i < 6) ? 'B' : (i < 9) ? 'C' : 'D';
int secSlot = (i % 3) + 1;
Serial.print(sec);
Serial.print(secSlot);
Serial.print(": ");
Serial.print(dist);
Serial.print(" cm — ");
Serial.println(dist <= OCCUPIED_THRESHOLD_CM ? "TERISI" : "KOSONG");
// Delay kecil antara sensor untuk elak interferens
delay(30);
}
// Serialkan JSON
String jsonBody;
serializeJson(doc, jsonBody);
// Hantar ke API
WiFiClient client;
HTTPClient http;
http.begin(client, SERVER_URL);
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(jsonBody);
if (httpCode == HTTP_CODE_OK) {
Serial.println("Data berjaya dihantar!");
} else {
Serial.print("Ralat HTTP: ");
Serial.println(httpCode);
}
http.end();
delay(SEND_INTERVAL_MS);
}