Translate

Jasa Pembuatan Drone atau QUADCOPTER atau Drone FPV

Jasa Pembuatan Drone atau QUADCOPTER atau Drone FPV


JASA PEMBUATAN DRONE & QUADCOPTER KUSTOM 🚁💥

Punya kebutuhan kustomisasi drone, rakitan FPV, atau proyek riset mikrokontroler? Kami siap bantu dari nol sampai terbang!

🛠️ Layanan yang Kami Melayani:

  • Quadcopter Standar & Custom Frame (Frame F450, DIY, dll.)

  • Drone FPV (Racing, Freestyle, & Cinematic)

  • Integrasi Mikrokontroler (Arduino, ESP32, STM32, dll.)

  • Perakitan, Setting Flight Controller, & Tuning

  • Konsultasi & Service / Troubleshooting

Cocok untuk kebutuhan hobi, tugas akhir/riset kampus, hingga kebutuhan pemetaan/cinematic kustom.

📲 Minat / Konsultasi Gratis:

  • WhatsApp: 085726496643

  • TikTok: @yanuarm3

  • YouTube: Project diy microcontroller


VIDEO HASILNYA




JASA PEMBUATAN ALAT UNTUK TUGAS AKHIR / UMUM dan JASA PEMBUATAN PROGRAM / CODING

JASA PEMBUATAN ALAT UNTUK TUGAS AKHIR / UMUM  dan JASA PEMBUATAN PROGRAM / CODING


Sedang mengerjakan Tugas Akhir, Skripsi, Proyek, atau penelitian berbasis mikrokontroler dan IoT? Kami membantu dalam pembuatan program, perancangan alat, integrasi hardware-software, hingga bimbingan online sesuai kebutuhan proyek Anda.

🔧 SPESIALISASI:
• Arduino
• ESP32 & ESP32-S3
• Internet of Things (IoT)
• Website & Web Monitoring
• AI / Artificial Intelligence
• Bluetooth, WiFi & Internet
• Android MIT App Inventor
• Blynk, ThingSpeak & Firebase
• Website Hosting
• Data Logger & Monitoring
• Sistem Otomatisasi & Kontrol
• Software Interface VB6 / VB.NET / Delphi 7 & versi terbaru

💻 JASA CODING
Mulai dari Rp300.000, menyesuaikan tingkat kesulitan dan kebutuhan program.

🛠️ PEMBUATAN ALAT
Mulai dari Rp500.000 hingga > Rp2.000.000, menyesuaikan spesifikasi, komponen, fitur, dan tingkat kompleksitas alat.

📚 BIMBINGAN ONLINE
Membantu memahami coding, rangkaian, cara kerja sistem, troubleshooting, pengujian, dan pengembangan proyek sehingga proyek dapat dipahami dan dikembangkan sesuai kebutuhan.

💡 Konsultasikan terlebih dahulu!
Setiap proyek memiliki tingkat kesulitan dan kebutuhan komponen yang berbeda. Harga menyesuaikan kompleksitas dan spesifikasi proyek.

📱 PEMESANAN & KONSULTASI
WhatsApp: 0857-2649-6643

▶️ YouTube: Project DIY Microcontroller
🎵 TikTok: @yanuarm3

Melayani proyek mikrokontroler, IoT, monitoring, otomasi, interface komputer, aplikasi Android, hingga sistem berbasis Internet.










Kursus Private Robotika Area kota Batang - Pekalongan Jawa Tengah

Kursus Private Robotika Area kota Batang - Pekalongan Jawa Tengah

kursus private robotika
kelas SD SMP SMA dengan ketentuan yaitu
1. materi robotika dasar
2. materi elektronika dasar
3. materi bahasa pemrograman dasar Arduino
4. area murid di kota batang dan pekalongan
5. guru / tentor siap datang ke rumah murid 
6. waktu belajar 2 jam
7. biaya 500rb / 4 kali pertemuan

 minat hubungi WA 085726496643 (Yanuar) 

channel YOUTUBE = https://www.youtube.com/@DIYmicrocontroller

Channel TIKTOK = @yanuarm3 

  

 

Monitor Suhu & Kelembaban via Bluetooth ESP32 MIT INVENTOR dan Kendali LED

Monitor Suhu & Kelembaban via Bluetooth ESP32 MIT INVENTOR dan Kendali LED
 

       Pada kesempatan kali ini saya akan menjelaskan mengenai bagaimana cara membuat sebuah alat untuk monitor suhu kelembaban secara realtime dengan mnggunakan ESP32 via Bluetooth, aplikasi yang digunakan yaitu MIT Inventor dan koding juga sudah saya berikan pada page ini. untuk lebih jelasnya berikut detailnya.
 
 
1. Skema
 
 
 
2. Interface MIT INVENTOR
 


 
 
3. Program Arduino IDE
 
#include "DHT.h"
#include "BluetoothSerial.h"

#define DHTPIN 13
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

int LED_PIN = 12;
BluetoothSerial SerialBT;

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN,OUTPUT);
  dht.begin();

  SerialBT.begin("ESP32_SENSOR");
  
  Serial.println("Bluetooth aktif");
}

void loop() {

  int suhu = dht.readTemperature();
  int kelembaban = dht.readHumidity();

  if (isnan(suhu) || isnan(kelembaban)) {
    return;
  }

  String data = String(suhu) + "|" + String(kelembaban);

  SerialBT.println(data);
  Serial.println(data);

  if (SerialBT.available()) {

    char data = SerialBT.read();

    //Serial.print("Data diterima: ");
    //Serial.println(data);

    if (data == '1') {
      digitalWrite(LED_PIN, HIGH);
      //SerialBT.println("LED ON");
      Serial.println("LED ON");
    }

    else if (data == '0') {
      digitalWrite(LED_PIN, LOW);
      //SerialBT.println("LED OFF");
      Serial.println("LED OFF");
    }
  }


  delay(100);
}
 
 
4. VIDEO HASILNYA
 
 

Monitoring 2 Suhu via Website Hosting + Realtime Grafik DataLogger

Monitoring 2 Suhu via Website Hosting + Realtime Grafik DataLogger 
 

        Pada kesempatan kali ini saya akan menjelaskan mengenai bagaimana cara membuat sebuah alat yang daapaat memonitor 2 buah suhu secaraa terpisah tapi bisa dimasukkan ke dalam 1 website dan 1 database. untuk database saya menggunakan https://supabase.com dan untuk datamanager dan website saya menggunakan hosting dari infinityfree.com. untuk detailnya yaitu seperti berikut.
 
 
1. Skema
 

 
2. Interface
 




 
 
3. VIDEO HASILNYA
 

 
4. Program ESP32 - Batang / Semarang
 
 #include <WiFi.h>
#include <HTTPClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <time.h>

// ================= WIFI =================

const char* ssid = "wifihpku";
const char* password = "12345678";

// ================= SUPABASE =================

String supabaseURL =
"https://yizpzxixllbgixxxxxxx.supabase.co/rest/v1/suhu_data";

String supabaseKey =
"sb_publishable_mJNp2PCt9civsxe26URVYg_dxxxxxxx";

// ================= DEVICE =================

// ESP32 pertama

String device = "ESP32_BATANG";
String kota = "Batang";

// ESP32 kedua ubah menjadi:
// String device = "ESP32_SEMARANG";
// String kota = "Semarang";

// ================= DS18B20 =================

#define ONE_WIRE_BUS 13

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

void setup(){

Serial.begin(115200);

sensors.begin();

// WIFI

WiFi.begin(ssid,password);

Serial.print("Connecting");

while(WiFi.status()!=WL_CONNECTED){

delay(500);

Serial.print(".");

}

Serial.println();

Serial.println("WiFi Connected");

// waktu WIB

configTime(
7*3600,
0,
"pool.ntp.org",
"time.nist.gov"
);

}

String getTime(){

struct tm timeinfo;

if(!getLocalTime(&timeinfo)){

return "NULL";

}

char waktu[30];

strftime(

waktu,

sizeof(waktu),

"%Y-%m-%d %H:%M:%S",

&timeinfo

);

return String(waktu);

}

void kirimSupabase(float suhu){

if(WiFi.status()==WL_CONNECTED){

HTTPClient http;

http.begin(supabaseURL);

http.addHeader(
"Content-Type",
"application/json"
);

http.addHeader(
"apikey",
supabaseKey
);

http.addHeader(
"Authorization",
"Bearer "+supabaseKey
);

String data = "{";

data += "\"device\":\""+device+"\",";

data += "\"kota\":\""+kota+"\",";

data += "\"suhu\":"+String(suhu)+",";

data += "\"waktu\":\""+getTime()+"\"";

data += "}";

Serial.println(data);

int code=http.POST(data);

Serial.print("Response Supabase : ");

Serial.println(code);

http.end();

}

}

void loop(){

sensors.requestTemperatures();

float suhu = sensors.getTempCByIndex(0);

if(suhu == -127){

Serial.println("Sensor DS18B20 tidak terbaca");

return;

}

Serial.print("Suhu ");

Serial.print(kota);

Serial.print(" : ");

Serial.println(suhu);

kirimSupabase(suhu);

delay(5000);

}
 
 
 
5. Api.php
 
<?php

$supabase_url = "https://yizpzxixllbgixxxxxxx.supabase.co/rest/v1/suhu_data";

$supabase_key = "sb_publishable_mJNp2PCt9civsxe26URVYg_dxxxxxxx";

$curl = curl_init();

curl_setopt_array($curl,[

CURLOPT_URL => $supabase_url."?select=*&order=id.desc&limit=100",

CURLOPT_RETURNTRANSFER => true,

CURLOPT_HTTPHEADER => [

"apikey: ".$supabase_key,

"Authorization: Bearer ".$supabase_key,

"Content-Type: application/json"

]

]);

$response = curl_exec($curl);

curl_close($curl);

header("Content-Type: application/json");

echo $response;

?> 
 
 
6. index.php
 
<!DOCTYPE html>
<html>

<head>

<title>Monitoring Suhu ESP32</title>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<style>

*{
box-sizing:border-box;
}

body{

margin:0;
font-family:'Segoe UI',Arial,sans-serif;
background:#120021;
color:#ffd700;

}

.header{

background:linear-gradient(135deg,#5a189a,#240046);
padding:25px;
text-align:center;
box-shadow:0 5px 20px #000;

}

.header h1{

margin:0;
font-size:34px;

}

.header p{

color:#fff3a0;

}

.container{

width:92%;
margin:auto;

}

.map-box{

margin-top:25px;
background:#240046;
padding:25px;
border-radius:25px;
box-shadow:0 0 20px #000;
text-align:center;

}

.map-box h2{

color:#ffd700;

}

.peta{

width:90%;
max-width:1000px;
height:260px;
object-fit:cover;

border-radius:20px;

border:3px solid #7b2cbf;

}

.cards{

display:grid;
grid-template-columns:repeat(2,1fr);
gap:25px;

margin-top:25px;

}

.card{

background:#240046;
padding:25px;
border-radius:25px;
text-align:center;

box-shadow:0 0 20px #000;

}

.card h2{

color:#ffd700;

}

.nilai{

font-size:70px;
font-weight:bold;

color:#ffd700;

}

.status{

color:#00ff99;
font-weight:bold;

}

.panel{

background:#240046;
margin-top:25px;

padding:25px;

border-radius:25px;

box-shadow:0 0 20px #000;

}

.chart{

height:400px;

}

canvas{

width:100%!important;
height:100%!important;

}

table{

width:100%;
border-collapse:collapse;

}

th{

background:#5a189a;
color:#ffd700;

}

td,th{

padding:12px;
text-align:center;

border-bottom:1px solid #7b2cbf;

}

tr:hover{

background:#3c096c;

}

@media(max-width:700px){

.cards{

grid-template-columns:1fr;

}

}

</style>

</head>

<body>

<div class="header">

<h1>🌡 MONITORING SUHU ESP32</h1>

<p>DS18B20 Temperature Sensor</p>

</div>

<div class="container">

<!-- PETA -->

<div class="map-box">

<h2>🗺 PETA JAWA</h2>

<img src="jawa-map.png" class="peta">

</div>

<!-- NILAI SUHU -->

<div class="cards">

<div class="card">

<h2>📍 ESP32 BATANG</h2>

<div id="batang" class="nilai">

-- °C

</div>

<div class="status">

● ONLINE

</div>

</div>

<div class="card">

<h2>📍 ESP32 SEMARANG</h2>

<div id="semarang" class="nilai">

-- °C

</div>

<div class="status">

● ONLINE

</div>

</div>

</div>

<!-- GRAFIK -->

<div class="panel">

<h2>📈 Grafik Suhu Batang</h2>

<div class="chart">

<canvas id="grafikBatang"></canvas>

</div>

</div>

<div class="panel">

<h2>📈 Grafik Suhu Semarang</h2>

<div class="chart">

<canvas id="grafikSemarang"></canvas>

</div>

</div>

<!-- LOGGER -->

<div class="panel">

<h2>📋 Logger Data 100 Terakhir</h2>

<table>

<tr>

<th>No</th>
<th>Device</th>
<th>Kota</th>
<th>Suhu</th>
<th>Waktu</th>

</tr>

<tbody id="logger"></tbody>

</table>

</div>

</div>

<script>

let chartBatang;

let chartSemarang;

function loadData(){

fetch("api.php")

.then(res=>res.json())

.then(data=>{

let batang=[];

let semarang=[];

let waktuBatang=[];

let waktuSemarang=[];

let suhuBatang=0;

let suhuSemarang=0;

let idBatang=0;

let idSemarang=0;

data.slice().reverse().forEach(item=>{

if(item.device=="ESP32_BATANG"){

batang.push(Number(item.suhu));

waktuBatang.push(item.waktu);

if(Number(item.id)>idBatang){

idBatang=item.id;

suhuBatang=item.suhu;

}

}

if(item.device=="ESP32_SEMARANG"){

semarang.push(Number(item.suhu));

waktuSemarang.push(item.waktu);

if(Number(item.id)>idSemarang){

idSemarang=item.id;

suhuSemarang=item.suhu;

}

}

});

document.getElementById("batang").innerHTML =

Number(suhuBatang).toFixed(2)+" °C";

document.getElementById("semarang").innerHTML =

Number(suhuSemarang).toFixed(2)+" °C";

if(chartBatang){

chartBatang.destroy();

}

chartBatang=new Chart(

document.getElementById("grafikBatang"),

{

type:"line",

data:{

labels:waktuBatang,

datasets:[{

label:"ESP32 BATANG",

data:batang,

borderColor:"#ffd700",

backgroundColor:"rgba(255,215,0,0.2)",

fill:true,

tension:0.4,

borderWidth:3

}]

},

options:{

responsive:true,

maintainAspectRatio:false

}

}

);

if(chartSemarang){

chartSemarang.destroy();

}

chartSemarang=new Chart(

document.getElementById("grafikSemarang"),

{

type:"line",

data:{

labels:waktuSemarang,

datasets:[{

label:"ESP32 SEMARANG",

data:semarang,

borderColor:"#00ffff",

backgroundColor:"rgba(0,255,255,0.2)",

fill:true,

tension:0.4,

borderWidth:3

}]

},

options:{

responsive:true,

maintainAspectRatio:false

}

}

);

let html="";

data.forEach((item,index)=>{

html+=`

<tr>

<td>${index+1}</td>

<td>${item.device}</td>

<td>${item.kota}</td>

<td>${item.suhu} °C</td>

<td>${item.waktu}</td>

</tr>

`;

});

document.getElementById("logger").innerHTML=html;

});

}

loadData();

setInterval(loadData,5000);

</script>

</body>

</html> 
 
 

Monitoring Suhu Kelembaban via Website Fitur Grafik dan Datalogger Realtime

Monitoring Suhu Kelembaban via Website Fitur Grafik dan Datalogger Realtime 
 

         Pada kesempatan kali ini saya akan menjelaskan mengenai bagaimana cara membuat sebuah alat untuk memonitoring suhu dan kelembaban dengan sensor DHT11 kemudian data tersebuut masuk ke database https://supabase.com setelah masuk ke dalam web itu untuk tampilannya saya gunakan https://www.infinityfree.com/ jadi saya gunakan 2 web itu karena jika saya gunakan infinityfree saja ada masalah saat pengiriman datanya. untuk lebih jelasnya berikut koding dan interfacenya.
 
 
1. Skema
 
 
 
2. Interface
 


 


 
 
3. Koding Arduino IDE
 
#include <WiFi.h>
#include <HTTPClient.h>
#include <DHT.h>

#define DHTPIN 13
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

// WIFI
const char* ssid = "wifihpku";
const char* password = "123456789";

// SUPABASE
String supabaseURL = "https://yizpzxixllbgixxxxxxx.supabase.co/rest/v1/dht11_data";

String supabaseKey = "sb_publishable_mJNp2PCt9civsxe26URVYg_xxxxxxxx";

void setup() {

  Serial.begin(115200);

  dht.begin();

  WiFi.begin(ssid,password);

  Serial.print("Menghubungkan WiFi");

  while(WiFi.status()!=WL_CONNECTED){

    delay(500);
    Serial.print(".");

  }

  Serial.println();
  Serial.println("WiFi Terhubung");

}

void loop() {

  int suhu = dht.readTemperature();
  int kelembaban = dht.readHumidity();

  if(isnan(suhu) || isnan(kelembaban)){

    Serial.println("Sensor gagal membaca");
    delay(1000);
    return;

  }

  Serial.print("Suhu : ");
  Serial.println(suhu);

  Serial.print("Kelembaban : ");
  Serial.println(kelembaban);

  if(WiFi.status()==WL_CONNECTED){

    HTTPClient http;

    http.begin(supabaseURL);

    http.addHeader(
      "Content-Type",
      "application/json"
    );

    http.addHeader(
      "apikey",
      supabaseKey
    );

    http.addHeader(
      "Authorization",
      "Bearer " + supabaseKey
    );

    String json = 
    "{"
    "\"suhu\":" + String(suhu) +
    ",\"kelembaban\":" + String(kelembaban) +
    "}";

    Serial.println("Kirim:");
    Serial.println(json);
    int response = http.POST(json);

    Serial.print("Response: ");
    Serial.println(response);

    Serial.println(http.getString());

    http.end();

  }

  delay(1000);

}
 
 
4. Program index.html
 
<!DOCTYPE html>
<html>
<head>

<title>ESP32 DHT11 Monitoring</title>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<style>

*{
box-sizing:border-box;
}

body{
margin:0;
font-family:Arial,sans-serif;
background:#052e22;
color:white;
}

.header{
text-align:center;
padding:25px;
font-size:30px;
font-weight:bold;
}

.container{
width:92%;
margin:auto;
}


/* CARD */

.cards{

display:flex;
justify-content:center;
gap:25px;
flex-wrap:wrap;

}

.card{

background:#0b5139;
width:280px;
padding:25px;
border-radius:20px;
text-align:center;
box-shadow:0 5px 20px #0005;

}

.value{

font-size:45px;
font-weight:bold;
color:#00ff99;

}


/* BUTTON */

.btn-download{

background:#00a86b;
color:white;

border:none;

padding:12px 25px;

border-radius:25px;

font-size:16px;

cursor:pointer;

font-weight:bold;

margin-bottom:20px;

}

.btn-download:hover{

background:#00ff99;
color:#003b25;

}

/* CHART */

.chart-box{

background:#083b2b;

margin-top:25px;

padding:20px;

border-radius:20px;

cursor:pointer;

}

.chart-container{

height:230px;

}

.chart-container.fullscreen{

position:fixed;

top:20px;

left:20px;

right:20px;

bottom:20px;

height:auto;

background:#052e22;

z-index:999;

padding:30px;

border-radius:20px;

}

.chart-container canvas{

width:100%!important;

height:100%!important;

}

/* TABLE */

.table-box{

background:#083b2b;

margin-top:25px;

padding:20px;

border-radius:20px;

}

table{

width:100%;

border-collapse:collapse;

}

th{

background:#00a86b;

padding:14px;

}

td{

padding:12px;

text-align:center;

}

tr:nth-child(even){

background:#0b5139;

}

tr:nth-child(odd){

background:#06452f;

}

tr:hover{

background:#007f5f;

}

.badge-suhu{

background:#ff7b54;

padding:7px 15px;

border-radius:20px;

font-weight:bold;

}

.badge-hum{

background:#3498db;

padding:7px 15px;

border-radius:20px;

font-weight:bold;

}

</style>
</head>
<body>
<div class="header">

🌿 ESP32 DHT11 MONITORING

</div>

<div class="container">

<div class="cards">

<div class="card">

<h2>🌡 Suhu</h2>

<div class="value">

<span id="suhu">0</span> °C

</div>

</div>

<div class="card">

<h2>💧 Kelembaban</h2>

<div class="value">

<span id="kelembaban">0</span> %

</div>

</div>


</div>

<div class="chart-box">

<h2>📈 Grafik Suhu</h2>

<div class="chart-container"
onclick="besarGrafik(this)">

<canvas id="grafikSuhu"></canvas>

</div>

</div>

<div class="chart-box">

<h2>📈 Grafik Kelembaban</h2>

<div class="chart-container"
onclick="besarGrafik(this)">

<canvas id="grafikHum"></canvas>

</div>

</div>

<div class="table-box">

<h2>📋 Logger 100 Data Terakhir</h2>

<button class="btn-download"
onclick="downloadExcel()">

📥 Download Excel

</button>

<table>

<thead>

<tr>

<th>No</th>

<th>Waktu</th>

<th>Suhu</th>

<th>Kelembaban</th>

</tr>

</thead>

<tbody id="tabel">

</tbody>

</table>

</div>

</div>

<script type="module">

import { createClient }

from "https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm";

// SUPABASE

const SUPABASE_URL =
"https://yizpzxixllbgixxxxxxx.supabase.co";

const SUPABASE_KEY =
"sb_publishable_mJNp2PCt9civsxe26URVYg_xxxxxxxx";

const supabase =
createClient(
SUPABASE_URL,
SUPABASE_KEY
);

let chartSuhu;

let chartHum;

let dataExcel=[];

async function loadData(){

let {data,error}=await supabase

.from("dht11_data")

.select("*")

.order("id",{ascending:false})

.limit(100);

if(error){

console.log(error);

return;

}

dataExcel=data;

data=data.reverse();

let waktu=[];

let suhu=[];

let hum=[];

data.forEach(item=>{

waktu.push(

new Date(item.waktu)
.toLocaleTimeString()

);

suhu.push(item.suhu);

hum.push(item.kelembaban);

});

document.getElementById("suhu").innerHTML=

suhu[suhu.length-1] ?? 0;

document.getElementById("kelembaban").innerHTML=

hum[hum.length-1] ?? 0;

let isi="";

let no=1;

data.slice().reverse().forEach(item=>{

isi+=`

<tr>

<td>${no}</td>


<td>

${new Date(item.waktu).toLocaleString()}

</td>

<td>

<span class="badge-suhu">

${item.suhu} °C

</span>

</td>

<td>

<span class="badge-hum">

${item.kelembaban} %

</span>

</td>

</tr>

`;

no++;

});

document.getElementById("tabel").innerHTML=isi;

if(chartSuhu)

chartSuhu.destroy();

chartSuhu=new Chart(

document.getElementById("grafikSuhu"),

{

type:"line",

data:{

labels:waktu,

datasets:[{

label:"Suhu °C",

data:suhu,

borderColor:"#00ff99",

backgroundColor:
"rgba(0,255,153,.2)",

fill:true,

tension:.4

}]

},

options:{

responsive:true,

maintainAspectRatio:false

}

}

);

if(chartHum)

chartHum.destroy();

chartHum=new Chart(

document.getElementById("grafikHum"),

{

type:"line",

data:{

labels:waktu,

datasets:[{

label:"Kelembaban %",

data:hum,

borderColor:"#3498db",

backgroundColor:
"rgba(52,152,219,.2)",

fill:true,

tension:.4

}]

},

options:{

responsive:true,

maintainAspectRatio:false

}

}

);

}

window.besarGrafik=function(el){

el.classList.toggle("fullscreen");

}

window.downloadExcel=function(){

let csv="No,Waktu,Suhu,Kelembaban\n";

dataExcel.forEach((item,index)=>{

csv+=

`${index+1},${item.waktu},${item.suhu},${item.kelembaban}\n`;

});

let blob=new Blob(

[csv],

{
type:"text/csv"
}

);

let url=URL.createObjectURL(blob);

let a=document.createElement("a");

a.href=url;

a.download="logger_DHT11.csv";

a.click();

URL.revokeObjectURL(url);

}

setInterval(loadData,2000);

loadData();

</script>

</body>
</html> 
 
 
 
4. VIDEO HASILNYA
 

 
 
 
 
 
 

ESP32 Cam Kirim Foto ke Telegram

ESP32 Cam Kirim Foto ke Telegram
 

        Pada kesempatan kali ini saya akan menjelaskan bagaimana cara membuat sebuah alat dengan ESP32 cam untuk mengirim gambar ke telegram, fungsi dari alat ini yaitu untuk fitur pemantauan, jadi misal lagi di tempat kerja lalu ingin melihat kondisi real yang ada disana bisa dipantau via telegram dan gambarnya bisa di share ke group atau status media sosial. untuk lebih jelasnya berkut adalah koding dan haslnya.
 
 
1. Hasilnya
 

 
2. Program ESP32 Cam
 
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "esp_camera.h"

// =====================================================
// WIFI
// =====================================================


const char* WIFI_SSID = "hotspotkuwifi";
const char* WIFI_PASSWORD = "123456789";

// ================================
// TELEGRAM
// ================================

// Gunakan token baru
String BOT_TOKEN = "8599566365:AAHWGXsuTQp5IROs0d9HIV9gFd9DyG8xx1x";


// Chat ID tujuan
const char* CHAT_ID = "7796726911";

// =====================================================
// PIN ESP32-CAM 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

// =====================================================
// TELEGRAM UPDATE
// =====================================================

long lastUpdateID = 0;

unsigned long lastCheck = 0;

const unsigned long CHECK_INTERVAL = 1000;


// =====================================================
// INISIALISASI CAMERA
// =====================================================

bool setupCamera() {

  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;

  // Kompatibilitas beberapa versi ESP32 Core

#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 2

  config.pin_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;

#else

  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;

#endif

  config.pin_pwdn  = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;

  config.xclk_freq_hz = 20000000;

  // Langsung menghasilkan JPG
  config.pixel_format = PIXFORMAT_JPEG;

  // Mulai VGA supaya stabil
  config.frame_size = FRAMESIZE_VGA;

  config.jpeg_quality = 12;

  config.fb_count = 1;


  Serial.println("Memulai kamera...");


  esp_err_t err =
    esp_camera_init(&config);


  if (err != ESP_OK) {

    Serial.printf(
      "Camera gagal. Error: 0x%x\n",
      err
    );

    return false;
  }


  sensor_t* sensor =
    esp_camera_sensor_get();


  sensor->set_framesize(
    sensor,
    FRAMESIZE_VGA
  );


  sensor->set_quality(
    sensor,
    12
  );


  Serial.println(
    "Camera berhasil."
  );


  return true;
}


// =====================================================
// CONNECT WIFI
// =====================================================

void connectWiFi() {

  WiFi.mode(WIFI_STA);

  WiFi.begin(
    WIFI_SSID,
    WIFI_PASSWORD
  );


  Serial.print(
    "Menghubungkan WiFi"
  );


  while (
    WiFi.status() != WL_CONNECTED
  ) {

    delay(500);

    Serial.print(".");
  }


  Serial.println();

  Serial.println(
    "WiFi terhubung"
  );


  Serial.print(
    "IP: "
  );

  Serial.println(
    WiFi.localIP()
  );


  Serial.print(
    "Signal: "
  );

  Serial.print(
    WiFi.RSSI()
  );

  Serial.println(
    " dBm"
  );
}


// =====================================================
// HAPUS WEBHOOK
// Supaya getUpdates bisa digunakan
// =====================================================

void deleteWebhook() {

  WiFiClientSecure client;

  client.setInsecure();


  HTTPClient https;


  String url =
    "https://api.telegram.org/bot"
    + BOT_TOKEN
    + "/deleteWebhook?drop_pending_updates=true";


  Serial.println(
    "Menyiapkan Telegram..."
  );


  if (
    https.begin(
      client,
      url
    )
  ) {

    int httpCode =
      https.GET();


    Serial.print(
      "deleteWebhook HTTP: "
    );

    Serial.println(
      httpCode
    );


    https.end();
  }
}


// =====================================================
// KIRIM FOTO JPG KE TELEGRAM
// =====================================================

bool sendPhotoTelegram(
  String chatID
) {

  Serial.println();
  Serial.println(
    "=============================="
  );

  Serial.println(
    "MENGAMBIL FOTO"
  );

  Serial.println(
    "=============================="
  );


  // ===================================================
  // BUANG FRAME PERTAMA
  // ===================================================

  camera_fb_t* fb =
    esp_camera_fb_get();


  if (fb) {

    esp_camera_fb_return(fb);

    fb = NULL;
  }


  delay(200);


  // ===================================================
  // AMBIL FOTO BARU
  // ===================================================

  fb =
    esp_camera_fb_get();


  if (!fb) {

    Serial.println(
      "Gagal mengambil gambar!"
    );

    return false;
  }


  Serial.print(
    "Resolusi: "
  );

  Serial.print(
    fb->width
  );

  Serial.print(
    " x "
  );

  Serial.println(
    fb->height
  );


  Serial.print(
    "Ukuran JPG: "
  );

  Serial.print(
    fb->len
  );

  Serial.println(
    " bytes"
  );


  // ===================================================
  // CONNECT TELEGRAM
  // ===================================================

  WiFiClientSecure client;

  client.setInsecure();

  client.setTimeout(15000);


  Serial.println(
    "Menghubungkan Telegram..."
  );


  if (
    !client.connect(
      "api.telegram.org",
      443
    )
  ) {

    Serial.println(
      "Koneksi Telegram gagal!"
    );


    esp_camera_fb_return(fb);

    return false;
  }


  Serial.println(
    "Telegram connected"
  );


  // ===================================================
  // MULTIPART FORM DATA
  // ===================================================

  String boundary =
    "ESP32CAMBoundary";


  String head =

    "--" + boundary + "\r\n"

    "Content-Disposition: form-data; "
    "name=\"chat_id\"\r\n\r\n"

    + chatID +

    "\r\n"

    "--" + boundary + "\r\n"

    "Content-Disposition: form-data; "
    "name=\"photo\"; "
    "filename=\"esp32cam.jpg\"\r\n"

    "Content-Type: image/jpeg\r\n\r\n";


  String tail =

    "\r\n--"
    + boundary
    + "--\r\n";


  size_t contentLength =
    head.length()
    +
    fb->len
    +
    tail.length();


  // ===================================================
  // HTTP POST
  // ===================================================

  client.print(
    "POST /bot"
  );

  client.print(
    BOT_TOKEN
  );

  client.println(
    "/sendPhoto HTTP/1.1"
  );


  client.println(
    "Host: api.telegram.org"
  );


  client.println(
    "Connection: close"
  );


  client.print(
    "Content-Type: multipart/form-data; boundary="
  );

  client.println(
    boundary
  );


  client.print(
    "Content-Length: "
  );

  client.println(
    contentLength
  );


  client.println();


  // ===================================================
  // KIRIM HEADER
  // ===================================================

  client.print(
    head
  );


  // ===================================================
  // KIRIM DATA JPG
  // ===================================================

  size_t sent = 0;

  unsigned long sendTimeout =
    millis();


  while (
    sent < fb->len
  ) {

    size_t remaining =
      fb->len - sent;


    size_t chunkSize =
      remaining > 1024
      ? 1024
      : remaining;


    size_t written =
      client.write(
        fb->buf + sent,
        chunkSize
      );


    if (written > 0) {

      sent += written;

      sendTimeout =
        millis();

    } else {

      if (
        millis() - sendTimeout >
        10000
      ) {

        Serial.println(
          "Timeout mengirim JPG"
        );

        break;
      }

      delay(10);
    }


    delay(1);
  }


  client.print(
    tail
  );


  Serial.print(
    "JPG terkirim: "
  );

  Serial.print(
    sent
  );

  Serial.print(
    "/"
  );

  Serial.println(
    fb->len
  );


  // Frame sudah selesai
  esp_camera_fb_return(fb);

  fb = NULL;


  // ===================================================
  // BACA RESPONSE TELEGRAM
  // ===================================================

  bool telegramOK =
    false;


  unsigned long timeout =
    millis();


  Serial.println(
    "Menunggu response Telegram..."
  );


  while (
    millis() - timeout <
    15000
  ) {

    while (
      client.available()
    ) {

      String line =
        client.readStringUntil('\n');


      Serial.println(
        line
      );


      if (
        line.indexOf(
          "\"ok\":true"
        ) >= 0
      ) {

        telegramOK =
          true;
      }


      timeout =
        millis();
    }


    if (
      !client.connected()
    ) {

      break;
    }


    delay(10);
  }


  client.stop();


  if (telegramOK) {

    Serial.println();
    Serial.println(
      "FOTO BERHASIL DIKIRIM!"
    );

  } else {

    Serial.println();
    Serial.println(
      "FOTO GAGAL DIKIRIM!"
    );
  }


  return telegramOK;
}


// =====================================================
// CEK PESAN TELEGRAM
// =====================================================

void checkTelegram() {

  WiFiClientSecure client;

  client.setInsecure();


  HTTPClient https;


  String url =
    "https://api.telegram.org/bot"
    + BOT_TOKEN
    + "/getUpdates?offset="
    + String(lastUpdateID + 1)
    + "&limit=5&timeout=0";


  if (
    !https.begin(
      client,
      url
    )
  ) {

    Serial.println(
      "HTTP Telegram gagal"
    );

    return;
  }


  int httpCode =
    https.GET();


  if (
    httpCode != 200
  ) {

    Serial.print(
      "getUpdates HTTP Error: "
    );

    Serial.println(
      httpCode
    );


    https.end();

    return;
  }


  String payload =
    https.getString();


  https.end();


  // ===================================================
  // PARSE JSON
  // ===================================================

  DynamicJsonDocument doc(
    16384
  );


  DeserializationError error =
    deserializeJson(
      doc,
      payload
    );


  if (error) {

    Serial.print(
      "JSON error: "
    );

    Serial.println(
      error.c_str()
    );

    return;
  }


  JsonArray results =
    doc["result"].as<JsonArray>();


  for (
    JsonObject update : results
  ) {

    long updateID =
      update["update_id"] | 0;


    if (
      updateID >
      lastUpdateID
    ) {

      lastUpdateID =
        updateID;
    }


    // Pastikan update berisi message

    if (
      update["message"].isNull()
    ) {

      continue;
    }


    const char* textRaw =
      update["message"]["text"] | "";


    String text =
      String(textRaw);


    // Telegram chat ID sekarang bisa besar.
    // Ambil sebagai 64-bit.

    int64_t chatIDNumber =
      update["message"]["chat"]["id"]
      .as<int64_t>();


    char chatBuffer[32];


    snprintf(
      chatBuffer,
      sizeof(chatBuffer),
      "%lld",
      (long long)chatIDNumber
    );


    String chatID =
      String(chatBuffer);


    Serial.println();
    Serial.println(
      "------------------------------"
    );

    Serial.print(
      "Chat ID : "
    );

    Serial.println(
      chatID
    );


    Serial.print(
      "Pesan   : "
    );

    Serial.println(
      text
    );


    // =================================================
    // PERINTAH /foto
    // =================================================

    if (
      text == "/foto"
      ||
      text.startsWith(
        "/foto@"
      )
    ) {

      Serial.println(
        "Perintah /foto diterima"
      );


      sendPhotoTelegram(
        chatID
      );
    }
  }
}


// =====================================================
// SETUP
// =====================================================

void setup() {

  Serial.begin(
    115200
  );


  delay(1000);


  Serial.println();
  Serial.println(
    "================================"
  );

  Serial.println(
    "ESP32-CAM TELEGRAM /FOTO"
  );

  Serial.println(
    "================================"
  );


  // CAMERA

  if (
    !setupCamera()
  ) {

    Serial.println(
      "Camera gagal."
    );

    return;
  }


  // WIFI

  connectWiFi();


  // getUpdates tidak bisa digunakan
  // jika bot masih memakai webhook.

  deleteWebhook();


  Serial.println();
  Serial.println(
    "================================"
  );

  Serial.println(
    "SISTEM SIAP"
  );

  Serial.println(
    "Kirim /foto ke Telegram"
  );

  Serial.println(
    "================================"
  );
}


// =====================================================
// LOOP
// =====================================================

void loop() {

  // Reconnect WiFi

  if (
    WiFi.status() !=
    WL_CONNECTED
  ) {

    connectWiFi();
  }


  // Cek Telegram setiap 1 detik

  if (
    millis() - lastCheck >=
    CHECK_INTERVAL
  ) {

    lastCheck =
      millis();


    checkTelegram();
  }
}
 
 
 
3. VIDEO HASILNYA