Semua Tentang Belajar Teknologi Digital Dalam Kehidupan Sehari - Hari

Rabu, 30 Oktober 2024

[Telkomiot.id] Pembacaan Meter Pdam Berbasis Mqtt dan AI-Yolo-Roboflow

 


Mikrokontroler merupakan ujung tombak dari implementasi IOT diberbagai bidang, dimana dengan kemampuan pengolahan sensor yang semakin baik dapat dimanfaatkan untuk membantu kehidupan manusia sehari-hari . Seperti halnya ilustrasi gambar paling atas merupakan pemanfaatan ESP32 untuk membantu pembacaan meter PDAM secara digital dan kemudian saya bersama mahasiswa Teknik Listrik - Vokasi Unesa Surabaya, yang kebetulan lagi Ujian Tengah Semester (UTS), ingin meng-upgrade ilmu jaman sekarang, sehingga dapat memiliki pemahaman "digitalisasi" yang benar dan tepat guna. Ayo ikuti keseruan UTS kali ini dan pembaca bisa juga mencobanya dirumah !


Ada 5 proses penting dalam kerangka berpikir untuk perancangan sistem pembacaan meteran pdam seperti gambar diatas, walau ada keterbatasan di sisi  pengambilan foto (hanya simulasi file gambar meter dalam spiffs) yang akan kita lakukan, perancangan sistem digitalisasi  meter pdam  idealnya seperti ini :


  1. ESP32 / ESP32 CAM mengambil gambar dari meter pdam dan merubahnya menjadi teks ter-encoded base64 
  2. ESP32 mengirimkan gambar dalam bentuk base64 tadi secara MQTT ke sebuah topik
  3. Cloud computing dalam hal ini google colab, melakukan subscribe ke topic dan kemudian menerima data gambar base64, melakukan decoding menjadi gambar jpg kemudian dengan bantuan model yolo/roboflow melakukan deteksi angka meter melalui proses Artificial Inteligence, dan kemudian pembacaan angka meter di publish ke topic reply. 
  4. ESP32 yang sebelumnya sudah subscribe ke topic reply akan menerima angka pembacaan meter dan diolah ke serial monitor atau display LCD/OLED sesuai kreatifitas. 
  5. Database pelanggan di pusat billing center dapat di update secara otomatis dan tagihan dicetak sesuai penggunaan air di pelanggan. 



Perangkat minimum yang kalian gunakan adalah ESP32, resistor 10Kohm dan Push button / tactile switch. Cukup hanya itu saja bisa kalian rangkai dengan atau tanpa projectboard/breadboard. 


FLOWCHART :



Catatan : "GUNAKAN ARDUINO IDE 1.8.XX (VERSI LAMA) JIKA KALIAN INGIN MENGIKUTI LANGKAH DIBAWAH INI YANG BERBASIS SPIFFS , JIKA KALIAN SUDAH PAHAM MENGENAI LITTLE FS SILAHKAN GUNAKAN SAJA ARDUINO IDE 2.X.X (BARU) "


SPIFFS merupakan file system layaknya di komputer untuk menyimpan data-data gambar, teks, audio dll didalam memori flash nya ESP32. Untuk melakukan seting arduino ide 1.8.xx kalian, ikuti langkah berikut :

1. Unduh file zip yang berisikan file java / jar  di : https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/download/1.1/ESP32FS-1.1.zip


Catatan : gambar diatas hanya untuk menunjukkan dimana file dan folder arduino kalian, tidak perlu dibuka atau browse. Cuman di copy nama foldernya lalu dibuka melalui explorer dan pindahkan file jar ke directorynya.


3. Restart arduino ide kalian dan jika berhasil pada menu tools muncul menu baru "ESP32 sketch data upload". Buat file sketch/ino baru dan save terlebih dahulu.

4. Untuk seting jenis board yg dipakai pilih "ESP32 Dev Module" dan seting lainnya berupa pilihan "Huge App" seperti pada gambar berikut:


5. Fotokan meter pdam yg ada di sekitar kalian (gunakan hp) kemudian kecilkan dan compress sampai file JPG nya berukuran dibawah 30Kb namun masih dapat terbaca dengan jelas. Gunakan tools kompresi online yang saya rekomendasikan adalah : https://www.imgonline.com.ua/eng/compress-image-size.php

6. Pindahkan file gambar tadi (rename dulu dengan pdam.jpg) ke folder baru bernama "data" yg lokasinya satu tingkat dibawah folder dimana kalian menyimpan sketch atau file .ino, seperti pada ilustrasi berikut:


7. Untuk memindahkan file ke ESP32, maka setelah file gambar pdam.jpg tersimpan di folder /data, cukup lanjutkan dengan pilih tools => ESP32 sketch upload, sampai sukses seperti gambar berikut:



Selanjutnya kita akan melakukan coding ke ESP32 kita yang akan bertujuan untuk mengirimkan data secara mqtt, sehingga dibutuhkan library "pubsubclient" yang  bisa kalian install seperti biasanya. Namun karena ada keterbatasan maksimum teks yg bisa dikirim, maka kita butuh melakukan "tweak" terhadap librarynya dan ikuti saja langkah berikut:


1. Masuk ke folder arduino kamu lalu menuju libraries/pubsubclient/src dan cari file bernama pubsubclient.h lalu edit menggunakan teks editor. Temukan item bernama #define MQTT_MAX_PACKET_SIZE 256 , lalu ganti menjadi 50000 seperti gambar dibawah:




2. Setelah library disimpan, maka dapat melakukan editing coding sebagai acuan dibawah ini, sesuaikan dengan yg kamu pakai.  Saya menggunakan broker : mqtt.telkomiot.id karena masih gratis dan kecepatan serta quotanya dapat digunakan untuk data mqtt yg lumayan panjang. Jadi jika belum punya akunnya silahkan daftar dulu di www.telkomiot.id


//UTS MIKROKONTROLER 2024
//d4 teknik listrik vokasi unesa surabaya
//by: nyoman yudi kurniawan ST

#include <WiFi.h>
#include <SPIFFS.h>
#include <PubSubClient.h>
#include <Base64.h>  

#define tombol 19 //sesuaikan pin tombol yg digunakan

//sesaikan wifi yang kamu pake
const char* ssid = "Nama Wifi";
const char* password = "password";

//Kita gunakan telkomiot sebagai broker, perhatikan baik-baik
const char* mqtt_server = "mqtt.telkomiot.id"; // jangan pernah ubah ini
const char* mqtt_key = "18f8e70xxxxxxxx"; // access key akun
const char* mqtt_token = "18f8e70xxxxxxx"; // token key akun

// topic dan reply silahkan ditambah no kelompok kamu di akhir,
// semisal "/tlunesa/pdam-12" , jangan sampai sama kelompok lain 
const char* topic = "/tlunesa/pdam"; 
const char* reply = "/tlunesa/pdam/reply"; 

WiFiClient espClient;
PubSubClient client(espClient);

// Function untuk terhubung ke wifi
void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print(F("UTS Mikrokontroler 2024 - Menghubungkan ke "));
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

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

// Function untuk koneksi MQTT
void reconnect() {
  while (!client.connected()) {
    Serial.print(F("Mencoba koneksi MQTT ..."));
    String clientId = "Unesa-d4-";
    clientId += String(random(0xffff), HEX);
    // menghubungkan..
    if (client.connect(clientId.c_str(),mqtt_key,mqtt_token)) {
      Serial.println(F("Terhubung ! dan Subscribe"));
      client.subscribe(reply);
    } else {
      Serial.print(F("failed, rc="));
      Serial.print(client.state());
      delay(5000);
    }
  }
}

void setup() {

  pinMode(tombol, INPUT);
  Serial.begin(9600);

  // Inisialisasi SPIFFS
  if (!SPIFFS.begin()) {
    Serial.println(F("SPIFFS Mount gagal"));
    return;
  }

  // Inisialisasi WiFi and MQTT
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

 //jika tombol ditekan (aktif low)
 if (!digitalRead(tombol))
 {
  Serial.println("");
  Serial.println(F("Tombol Ditekan.."));
  
  // buka gambar di binary mode, catatan : maksimal 30kb
  File file = SPIFFS.open("/pdam.jpg", "rb");
  if (!file) {
    Serial.println(F("Gagal membuka file di spiffs"));
    return;
  }

  // Read the file size
  size_t fileSize = file.size();
  Serial.print("File size: ");
  Serial.println(fileSize);

  // memesan alamat memory
  uint8_t* buffer = (uint8_t*)malloc(fileSize);
  if (buffer == nullptr) {
    Serial.println(F("Kesalahan mengalokasi buffer memori"));
    file.close();
    return;
  }

  // Baca data binarry ke buffer
  file.read(buffer, fileSize);
  file.close();

  // Encode gambar dalam Base64
  String encodedImage = base64::encode(buffer, fileSize);

  // bersihkan buffer
  free(buffer);

  // Publish ke topik MQTT
  
 if (client.publish(topic, encodedImage.c_str())) {
    Serial.println(F("Gambar berhasil di publish"));
  } else {
    Serial.println(F("Gagal mengirim gambar"));
  }
  // Biar brokernya gak tewas
  delay(1000);
 }   
}

//callback untuk membaca hasil subscribe/reply

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print(F("Pesan masuk ["));
  Serial.print(topic);
  Serial.print(F("]  Pembacaan Meter :"));
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
 

}

3. Setelah sukses melakukan upload coding, kalian bisa menggunakan aplikasi MQTT seperti mqtt.fx untuk mengetest apakah data berhasil terkirim atau tidak (tentunya setelah tombol dipencet) dengan bantuan aplikasi online base64 decoding : https://base64.guru/converter/decode/image




Google colab merupakan fasilitas gratis dari google untuk meng-explore dunia cloud computing. Kali ini kita akan manfaatkan google cloud untuk mengolah data gambar kemudian melakukan komputasi AI melalui API yolo-roboflow untuk menterjemahkan data gambar meter pdam menjadi data pembacaan meter pdam.  Lakukan langkah berikut untuk membuat cloud server pembaca meter pdam di google colab :


1. Buka google colab ( https://colab.research.google.com/ ) dan login menggunakan akun google kalian. Buatlah notebook baru lalu beri nama sepantasnya. Koneksikan dengan runtime dan lakukan langkah pertama memasukkan perintah intalasi library seperti berikut :


#instal dependecies dulu biar gak salah paham
!pip install paho-mqtt==1.6.0
!pip install inference


Proses mungkin agak lama dan ada warning untuk Mulai Ulang sesi, lakukan saja seperti gambar:



2. Lanjutkan dengan menambahkan coding python sesuai contoh berikut, lalu jalankan dengan panah di kiri atas:

#UTS MIKROKONTROLER 2024
#d4 teknik listrik vokasi unesa surabaya
#by: nyoman yudi kurniawan ST

import cv2
from inference_sdk import InferenceHTTPClient
from google.colab.patches import cv2_imshow
from random import randrange
import base64
import numpy as np
import time
from paho.mqtt import client as mqtt_client


# Inisialisasi broker , samakan dengan script di esp32

broker_address="mqtt.telkomiot.id"
broker_port=1883
mqtt_key = "18f8e70xxxxxxxxxx"
mqtt_token = "18f8e70xxxxxxxxx"
topic = "/tlunesa/pdam"
reply = "/tlunesa/pdam/reply"



#koneksi ke broker
def connect_mqtt() -> mqtt_client:
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Berhasil Terhubung MQTT Broker!")
        else:
            print("Gagal koneksi mqtt, return code %d\n", rc)
    def on_publish(client,userdata,result):
        print("data reply terkirim ke broker")

    client= mqtt_client.Client(f'unesa-client-{randrange(0,1000)}')
    client.on_connect = on_connect
    client.on_publish = on_publish
    client.username_pw_set(mqtt_key,mqtt_token)
    client.connect(broker_address,broker_port, 60 )

    return client


#subscribe ke mqtt broker
def subscribe(client: mqtt_client):

    client.subscribe(topic)
    client.on_message = on_message


def on_message(client, userdata, message):

    print("Data foto masuk...")
    # Get the payload (Base64-encoded image)
    base64_image = message.payload.decode('utf-8')

    # Decode the Base64 string to binary image data
    image_data = base64.b64decode(base64_image)

    # Convert the binary data to a NumPy array
    np_arr = np.frombuffer(image_data, np.uint8)

    # Decode the image from the NumPy array
    image = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)

    #terhubung dengan server Yolo / roboflow
    #jika API key nya penuh, kalian bisa daftar gratis sendiri
    CLIENT = InferenceHTTPClient(
        api_url="https://detect.roboflow.com",
        api_key="fuOy83MqlC1LtKZ25J0p" 
        )
    #lakukan pendeteksi object dengan model yolo
    results = CLIENT.infer(image, model_id="water-meter-dataset/1")


    # mendapatkan prediksi object dari result
    predictions = results['predictions']
    # Mengecek prediksis dan mengambar boxes
    for prediction in predictions:
        # Get the bounding box coordinates
        x = int(prediction['x'])
        y = int(prediction['y'])
        width = int(prediction['width'])
        height = int(prediction['height'])

        # Menggambar bounding box pada gambar meter
        cv2.rectangle(image, (x-int(width/2), y-int(height/2)), (x + int(width/2), y + int(height/2)), (0, 0, 255), 2)
        # Ambil class ID dari angka meter
        class_id = prediction['class']
        # Tambahkan nomer meter pada box 
        cv2.putText(image, class_id, (x-int(width/2), y+height+5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2)

    #tampilin gambar hasil pengolahan yolo
    cv2_imshow(image)
    # Sorting the predictions list by 'x'
    sorted_predictions = sorted(results["predictions"], key=lambda d: d["x"])

    # penggabungan class dari nomer menjadi teks
    class_order_numbers = [int(item["class"]) for item in sorted_predictions]
    combined_number = str("".join(map(str, class_order_numbers)))

    # Jadi deh angka pembacaan meter, lalu publish kembali ke topic reply
    print( f'pembacaan meter pdam:{combined_number}')
    client.publish(reply, combined_number)



try:
    client = connect_mqtt()
    subscribe(client)

    # Start the MQTT loop 
    client.loop_start()

    time.sleep(600)  #biargak kelamaan

except KeyboardInterrupt:
    print("KeyboardInterrupt terdeteksi, stop mqtt loop...")

finally:
    client.loop_stop()
    client.disconnect()
    print("MQTT loop selesai dan client terputus")


3. Hasilnya sebagai berikut , dan pada serial monitor / debug arduino ide juga terkirim angka pembacaan meter




4. Kreatifitas kalian bisa tambahkan LCD / OLED untuk menampilkan data pembacaan meter di display yang kalian pilih. Bisa juga LED berkedip jika ada reply yg masuk, sesuaikan dengan kemampuan kalian saja. 


Hasil paling baik dari UTS mahasiswa saya dapat dilihat pada video berikut :










Share:

0 komentar:

Posting Komentar

Kontak Penulis



12179018.png (60×60)
+628155737755

Mail : ahocool@gmail.com

Site View

Categories

555 (8) 7 segmen (3) adc (4) amplifier (2) analog (19) android (14) antares (11) arduino (28) artikel (11) attiny (3) attiny2313 (19) audio (5) baterai (5) blog (1) bluetooth (1) chatgpt (2) cmos (2) crypto (2) dasar (46) digital (11) dimmer (5) display (3) esp8266 (26) euro2020 (13) gcc (1) gsm (1) iklan (1) infrared (2) Input Output (3) iot (76) jam (7) jualan (12) kereta api (1) keyboard (1) keypad (3) kios pulsa (2) kit (6) komponen (17) komputer (3) komunikasi (1) kontrol (8) lain-lain (8) lcd (2) led (14) led matrix (6) line tracer (1) lm35 (1) lora (11) lorawan (2) MATV (1) memory (1) metal detector (4) microcontroller (70) micropython (6) mikrokontroler (2) mikrokontroller (14) mikrotik (5) modbus (9) mqtt (3) ninmedia (5) ntp (1) paket belajar (19) palang pintu otomatis (1) parabola (88) pcb (2) power (1) praktek (2) project (33) proyek (1) python (8) radio (28) raspberry pi (9) remote (1) revisi (1) rfid (1) robot (1) rpm (2) rs232 (1) script break down (3) sdcard (3) sensor (2) sharing (3) signage (1) sinyal (1) sms (6) software (18) solar (1) solusi (1) tachometer (2) technology (1) teknologi (2) telegram (2) telepon (9) televisi (167) television (28) telkomiot (5) transistor (2) troubleshoot (3) tulisan (94) tutorial (108) tv digital (6) tvri (2) vu meter (2) vumeter (2) wav player (3) wayang (1) wifi (3) yolo (7)

Arsip Blog

Diskusi


kaskus
Forum Hobby Elektronika