ESP32 CAM DETEKSI WARNA BOLA
Pada kesempatan kali ini saya akan menjelaskan mengenai bagaimana cara membuat sebuah alat yang menggunkan ESP32 Cam sebagai sensor untuk deteksi warna bola. jadi ada 4 bola dengan wana berbeda lalu ditaruh didepan kamera, kemudian kamera mendeteksi nilai RGBnya dan akan menampilkan warna bolanya. berikut kodingnya.
1. Interface
#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>
// ================= WIFI =================
const char* ssid = "ESP32-COLOR";
const char* password = "12345678";
WebServer server(80);
// ================= FLASH =================
#define FLASH_LED 4
// ================= AI THINKER =================
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
// ================= RGB =================
int R=0;
int G=0;
int B=0;
String color="UNKNOWN";
String ballColor="TIDAK ADA";
unsigned long timerRGB=0;
// ================= DATA KALIBRASI =================
struct ColorData
{
int r;
int g;
int b;
String nama;
};
ColorData dataWarna[5];
int jumlahWarna=0;
// ================= SIMPAN KALIBRASI =================
void simpanKalibrasi(String nama)
{
if(jumlahWarna>=5)
return;
dataWarna[jumlahWarna].r=R;
dataWarna[jumlahWarna].g=G;
dataWarna[jumlahWarna].b=B;
dataWarna[jumlahWarna].nama=nama;
jumlahWarna++;
Serial.println("KALIBRASI");
Serial.println(nama);
Serial.print(R);
Serial.print(",");
Serial.print(G);
Serial.print(",");
Serial.println(B);
}
// ================= RESET =================
void resetKalibrasi()
{
jumlahWarna=0;
server.send(
200,
"text/plain",
"RESET OK"
);
}
// ================= BACA RGB =================
void readRGB()
{
camera_fb_t *fb =
esp_camera_fb_get();
if(!fb)
return;
long totalR=0;
long totalG=0;
long totalB=0;
int count=0;
int roi=80;
int startX=(fb->width-roi)/2;
int startY=(fb->height-roi)/2;
for(int y=startY;y<startY+roi;y+=2)
{
for(int x=startX;x<startX+roi;x+=2)
{
int index=(y*fb->width+x)*2;
uint16_t pixel=
(fb->buf[index]<<8)
|
fb->buf[index+1];
int r=
((pixel>>11)&31)*255/31;
int g=
((pixel>>5)&63)*255/63;
int b=
(pixel&31)*255/31;
totalR+=r;
totalG+=g;
totalB+=b;
count++;
}
}
if(count)
{
R=totalR/count;
G=totalG/count;
B=totalB/count;
}
esp_camera_fb_return(fb);
color=detectColor();
}
// ================= DETEKSI WARNA =================
String detectColor()
{
if(jumlahWarna==0)
return "BELUM KALIBRASI";
long jarakMin=999999;
String hasil="UNKNOWN";
for(int i=0;i<jumlahWarna;i++)
{
long dr=R-dataWarna[i].r;
long dg=G-dataWarna[i].g;
long db=B-dataWarna[i].b;
long jarak=
dr*dr+
dg*dg+
db*db;
if(jarak<jarakMin)
{
jarakMin=jarak;
hasil=dataWarna[i].nama;
}
}
if(jarakMin>8000)
return "UNKNOWN";
return hasil;
}
// ================= DETEKSI BOLA =================
void detectBall()
{
if(color=="MERAH")
ballColor="🔴 BOLA MERAH";
else if(color=="HIJAU")
ballColor="🟢 BOLA HIJAU";
else if(color=="BIRU")
ballColor="🔵 BOLA BIRU";
else if(color=="KUNING")
ballColor="🟡 BOLA KUNING";
else if(color=="PUTIH")
ballColor="⚪ BOLA PUTIH";
else
ballColor="⚫ TIDAK ADA BOLA";
}
// ================= WEB DATA =================
void dataRGB()
{
String json="{";
json+="\"R\":"+String(R)+",";
json+="\"G\":"+String(G)+",";
json+="\"B\":"+String(B)+",";
json+="\"COLOR\":\""+color+"\",";
json+="\"BALL\":\""+ballColor+"\"";
json+="}";
server.send(
200,
"application/json",
json
);
}
// ================= WEB KALIBRASI =================
void webKalibrasi()
{
if(server.hasArg("warna"))
{
simpanKalibrasi(
server.arg("warna")
);
}
server.send(
200,
"text/plain",
"OK"
);
}
// ================= HALAMAN WEB =================
void home()
{
String html=R"rawliteral(
<html>
<head>
<meta name='viewport' content='width=device-width'>
<style>
body{
text-align:center;
font-family:Arial;
}
button{
font-size:18px;
padding:10px;
margin:5px;
}
</style>
</head>
<body>
<h2>
ESP32 COLOR BALL DETECTOR
</h2>
<h3>RGB</h3>
R :
<span id="r">
0
</span>
<br>
G :
<span id="g">
0
</span>
<br>
B :
<span id="b">
0
</span>
<h2 id="warna">
UNKNOWN
</h2>
<hr>
<h2>
DETEKSI BOLA
</h2>
<h1 id="bola">
⚫ TIDAK ADA
</h1>
<hr>
<h3>
KALIBRASI WARNA
</h3>
<button onclick="kal('MERAH')">
MERAH
</button>
<button onclick="kal('HIJAU')">
HIJAU
</button>
<button onclick="kal('BIRU')">
BIRU
</button>
<button onclick="kal('KUNING')">
KUNING
</button>
<button onclick="kal('PUTIH')">
PUTIH
</button>
<br>
<button onclick="reset()">
RESET
</button>
<script>
function kal(w)
{
fetch('/kal?warna='+w);
}
function reset()
{
fetch('/reset');
}
setInterval(()=>{
fetch('/data')
.then(x=>x.json())
.then(d=>{
r.innerHTML=d.R;
g.innerHTML=d.G;
b.innerHTML=d.B;
warna.innerHTML=d.COLOR;
bola.innerHTML=d.BALL;
});
},500);
</script>
</body>
</html>
)rawliteral";
server.send(
200,
"text/html",
html
);
}
// ================= SETUP =================
void setup()
{
Serial.begin(115200);
pinMode(
FLASH_LED,
OUTPUT
);
digitalWrite(
FLASH_LED,
LOW
);
camera_config_t config;
config.ledc_channel=LEDC_CHANNEL_0;
config.ledc_timer=LEDC_TIMER_0;
config.pin_d0=Y2_GPIO_NUM;
config.pin_d1=Y3_GPIO_NUM;
config.pin_d2=Y4_GPIO_NUM;
config.pin_d3=Y5_GPIO_NUM;
config.pin_d4=Y6_GPIO_NUM;
config.pin_d5=Y7_GPIO_NUM;
config.pin_d6=Y8_GPIO_NUM;
config.pin_d7=Y9_GPIO_NUM;
config.pin_xclk=XCLK_GPIO_NUM;
config.pin_pclk=PCLK_GPIO_NUM;
config.pin_vsync=VSYNC_GPIO_NUM;
config.pin_href=HREF_GPIO_NUM;
config.pin_sscb_sda=SIOD_GPIO_NUM;
config.pin_sscb_scl=SIOC_GPIO_NUM;
config.pin_pwdn=PWDN_GPIO_NUM;
config.pin_reset=RESET_GPIO_NUM;
config.xclk_freq_hz=20000000;
config.pixel_format=PIXFORMAT_RGB565;
config.frame_size=FRAMESIZE_QQVGA;
config.fb_count=1;
esp_camera_init(&config);
WiFi.mode(WIFI_AP);
WiFi.softAP(
ssid,
password
);
Serial.println(
WiFi.softAPIP()
);
server.on("/",home);
server.on("/data",dataRGB);
server.on("/kal",webKalibrasi);
server.on("/reset",resetKalibrasi);
server.begin();
}
// ================= LOOP =================
void loop()
{
server.handleClient();
if(millis()-timerRGB>500)
{
readRGB();
detectBall();
timerRGB=millis();
}
}
#include <WiFi.h>
#include <WebServer.h>
// ================= WIFI =================
const char* ssid = "ESP32-COLOR";
const char* password = "12345678";
WebServer server(80);
// ================= FLASH =================
#define FLASH_LED 4
// ================= AI THINKER =================
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
// ================= RGB =================
int R=0;
int G=0;
int B=0;
String color="UNKNOWN";
String ballColor="TIDAK ADA";
unsigned long timerRGB=0;
// ================= DATA KALIBRASI =================
struct ColorData
{
int r;
int g;
int b;
String nama;
};
ColorData dataWarna[5];
int jumlahWarna=0;
// ================= SIMPAN KALIBRASI =================
void simpanKalibrasi(String nama)
{
if(jumlahWarna>=5)
return;
dataWarna[jumlahWarna].r=R;
dataWarna[jumlahWarna].g=G;
dataWarna[jumlahWarna].b=B;
dataWarna[jumlahWarna].nama=nama;
jumlahWarna++;
Serial.println("KALIBRASI");
Serial.println(nama);
Serial.print(R);
Serial.print(",");
Serial.print(G);
Serial.print(",");
Serial.println(B);
}
// ================= RESET =================
void resetKalibrasi()
{
jumlahWarna=0;
server.send(
200,
"text/plain",
"RESET OK"
);
}
// ================= BACA RGB =================
void readRGB()
{
camera_fb_t *fb =
esp_camera_fb_get();
if(!fb)
return;
long totalR=0;
long totalG=0;
long totalB=0;
int count=0;
int roi=80;
int startX=(fb->width-roi)/2;
int startY=(fb->height-roi)/2;
for(int y=startY;y<startY+roi;y+=2)
{
for(int x=startX;x<startX+roi;x+=2)
{
int index=(y*fb->width+x)*2;
uint16_t pixel=
(fb->buf[index]<<8)
|
fb->buf[index+1];
int r=
((pixel>>11)&31)*255/31;
int g=
((pixel>>5)&63)*255/63;
int b=
(pixel&31)*255/31;
totalR+=r;
totalG+=g;
totalB+=b;
count++;
}
}
if(count)
{
R=totalR/count;
G=totalG/count;
B=totalB/count;
}
esp_camera_fb_return(fb);
color=detectColor();
}
// ================= DETEKSI WARNA =================
String detectColor()
{
if(jumlahWarna==0)
return "BELUM KALIBRASI";
long jarakMin=999999;
String hasil="UNKNOWN";
for(int i=0;i<jumlahWarna;i++)
{
long dr=R-dataWarna[i].r;
long dg=G-dataWarna[i].g;
long db=B-dataWarna[i].b;
long jarak=
dr*dr+
dg*dg+
db*db;
if(jarak<jarakMin)
{
jarakMin=jarak;
hasil=dataWarna[i].nama;
}
}
if(jarakMin>8000)
return "UNKNOWN";
return hasil;
}
// ================= DETEKSI BOLA =================
void detectBall()
{
if(color=="MERAH")
ballColor="🔴 BOLA MERAH";
else if(color=="HIJAU")
ballColor="🟢 BOLA HIJAU";
else if(color=="BIRU")
ballColor="🔵 BOLA BIRU";
else if(color=="KUNING")
ballColor="🟡 BOLA KUNING";
else if(color=="PUTIH")
ballColor="⚪ BOLA PUTIH";
else
ballColor="⚫ TIDAK ADA BOLA";
}
// ================= WEB DATA =================
void dataRGB()
{
String json="{";
json+="\"R\":"+String(R)+",";
json+="\"G\":"+String(G)+",";
json+="\"B\":"+String(B)+",";
json+="\"COLOR\":\""+color+"\",";
json+="\"BALL\":\""+ballColor+"\"";
json+="}";
server.send(
200,
"application/json",
json
);
}
// ================= WEB KALIBRASI =================
void webKalibrasi()
{
if(server.hasArg("warna"))
{
simpanKalibrasi(
server.arg("warna")
);
}
server.send(
200,
"text/plain",
"OK"
);
}
// ================= HALAMAN WEB =================
void home()
{
String html=R"rawliteral(
<html>
<head>
<meta name='viewport' content='width=device-width'>
<style>
body{
text-align:center;
font-family:Arial;
}
button{
font-size:18px;
padding:10px;
margin:5px;
}
</style>
</head>
<body>
<h2>
ESP32 COLOR BALL DETECTOR
</h2>
<h3>RGB</h3>
R :
<span id="r">
0
</span>
<br>
G :
<span id="g">
0
</span>
<br>
B :
<span id="b">
0
</span>
<h2 id="warna">
UNKNOWN
</h2>
<hr>
<h2>
DETEKSI BOLA
</h2>
<h1 id="bola">
⚫ TIDAK ADA
</h1>
<hr>
<h3>
KALIBRASI WARNA
</h3>
<button onclick="kal('MERAH')">
MERAH
</button>
<button onclick="kal('HIJAU')">
HIJAU
</button>
<button onclick="kal('BIRU')">
BIRU
</button>
<button onclick="kal('KUNING')">
KUNING
</button>
<button onclick="kal('PUTIH')">
PUTIH
</button>
<br>
<button onclick="reset()">
RESET
</button>
<script>
function kal(w)
{
fetch('/kal?warna='+w);
}
function reset()
{
fetch('/reset');
}
setInterval(()=>{
fetch('/data')
.then(x=>x.json())
.then(d=>{
r.innerHTML=d.R;
g.innerHTML=d.G;
b.innerHTML=d.B;
warna.innerHTML=d.COLOR;
bola.innerHTML=d.BALL;
});
},500);
</script>
</body>
</html>
)rawliteral";
server.send(
200,
"text/html",
html
);
}
// ================= SETUP =================
void setup()
{
Serial.begin(115200);
pinMode(
FLASH_LED,
OUTPUT
);
digitalWrite(
FLASH_LED,
LOW
);
camera_config_t config;
config.ledc_channel=LEDC_CHANNEL_0;
config.ledc_timer=LEDC_TIMER_0;
config.pin_d0=Y2_GPIO_NUM;
config.pin_d1=Y3_GPIO_NUM;
config.pin_d2=Y4_GPIO_NUM;
config.pin_d3=Y5_GPIO_NUM;
config.pin_d4=Y6_GPIO_NUM;
config.pin_d5=Y7_GPIO_NUM;
config.pin_d6=Y8_GPIO_NUM;
config.pin_d7=Y9_GPIO_NUM;
config.pin_xclk=XCLK_GPIO_NUM;
config.pin_pclk=PCLK_GPIO_NUM;
config.pin_vsync=VSYNC_GPIO_NUM;
config.pin_href=HREF_GPIO_NUM;
config.pin_sscb_sda=SIOD_GPIO_NUM;
config.pin_sscb_scl=SIOC_GPIO_NUM;
config.pin_pwdn=PWDN_GPIO_NUM;
config.pin_reset=RESET_GPIO_NUM;
config.xclk_freq_hz=20000000;
config.pixel_format=PIXFORMAT_RGB565;
config.frame_size=FRAMESIZE_QQVGA;
config.fb_count=1;
esp_camera_init(&config);
WiFi.mode(WIFI_AP);
WiFi.softAP(
ssid,
password
);
Serial.println(
WiFi.softAPIP()
);
server.on("/",home);
server.on("/data",dataRGB);
server.on("/kal",webKalibrasi);
server.on("/reset",resetKalibrasi);
server.begin();
}
// ================= LOOP =================
void loop()
{
server.handleClient();
if(millis()-timerRGB>500)
{
readRGB();
detectBall();
timerRGB=millis();
}
}
3. VIDEO HASILNYA


No comments:
Post a Comment