Semua Tentang Belajar Teknologi Digital Dalam Kehidupan Sehari - Hari

  • IC Timer 555 yang Multifungsi

    IC timer 555 adalah sirkuit terpadu (chip) yang digunakan dalam berbagai pembangkit timer, pulsa dan aplikasi osilator. Komponen ini digunakan secara luas, berkat kemudahan dalam penggunaan, harga rendah dan stabilitas yang baik

  • Ayo Migrasi TV Digital

    Kami bantu anda untuk memahami lebih jelas mengenai migrasi tv digital, apa sebabnya dan bagaimana efek terhadap kehidupan. Jasa teknisi juga tersedia dan siap membantu instalasi - setting perangkat - pengaturan antena dan distribusi televisi digital ke kamar kos / hotel

  • Bermain DOT Matrix - LOVEHURT

    Project Sederhana dengan Dot Matrix dan Attiny2313. Bisa menjadi hadiah buat teman atau pacarmu yang ulang tahun dengan tulisan dan animasi yang dapat dibuat sendiri.

  • JAM DIGITAL 6 DIGIT TANPA MICRO FULL CMOS

    Jika anda pencinta IC TTL datau CMOS maka project jam digital ini akan menunjukkan bahwa tidak ada salahnya balik kembali ke dasar elektronika digital , sebab semuanya BISA dibuat dengan teknologi jadul

  • Node Red - Kontrol Industri 4.0

    Teknologi kontrol sudah melampaui ekspektasi semua orang dan dengan kemajuan dunia elektronika, kini semakin leluasa berkreasi melalui Node Red

Minggu, 14 Juli 2024

[raspi - yolo] Memanfaatkan Komputer Lain Untuk Membantu Raspi Zero W Mengolah Gambar

 


Judulnya sedikit membuat ambigu, ngapain sih pake raspberry segala kalau juga digunakan PC lain untuk mengolah yolo ? Eiittsss ..saya pingin mensimulasikan raspberry pi zero w saya sebagai pengambil gambar melalui camera raspi ov5647, lalu alat saya ini akan dipasang pada banyak titik untuk medeteksi jumlah orang di bawah lampu jalan. Jadi harga raspi zero w yg cukup murah ditambah camera yg terjangkau menjadi pilihan yang cukup bagus dibanding meng-upgrade ke versi raspi 4 yang jauh harganya walau dapat mengolah gambar dengan lebih bagus (akan di bahas belakangan). Cukup 1 komputer yang processor kelas i5 sudah bisa menjadi server pengolah gambar.




Kali ini saya akan membahas membuat "server" pengolah gambar pada pc saya yang terhubung dengan wifi yang sama dengan raspi zero w yang saya gunakan sebagai simulator pengambil gambar. Untuk itu sebaiknya baca penjelasan sebelumnya untuk memahami yolo-python untuk mendeteksi objek disini:

  • Yolo dan python untuk deteksi objek :  Videonya dilihat disini
  • Deteksi object pada cctv menggunakan python pada node-red : Klik disini

Yang kita gunakan sebagai server lokal adalah flask yang merupakan pilihan favorit untuk mengetest sistem server berbasis python.  Flask adalah sebuah mikroframework web untuk Python yang dikembangkan oleh Armin Ronacher sebagai bagian dari proyek Pocoo. Flask sangat populer karena kesederhanaannya dan fleksibilitasnya, sehingga memungkinkan pengembang untuk membuat aplikasi web dengan cepat dan efisien.

Fitur Utama Flask

  • Ringan dan Fleksibel: Flask tidak memiliki lapisan abstraksi database atau validasi form bawaan, tetapi memungkinkan integrasi dengan banyak pustaka pihak ketiga.
  • WSGI: Flask berbasis pada Werkzeug WSGI toolkit dan Jinja2 templating engine.
  • Routing: Flask menyediakan sistem routing yang mudah digunakan untuk mengarahkan URL ke fungsi Python.
  • Templating: Dengan menggunakan Jinja2, Flask memungkinkan penggunaan template untuk memisahkan logika aplikasi dari tampilan.
  • Blueprints: Flask mendukung modularisasi aplikasi melalui blueprints, yang memungkinkan pengembangan aplikasi besar menjadi lebih terstruktur.
  • Ekstensi: Banyak ekstensi yang tersedia untuk Flask, seperti Flask-SQLAlchemy untuk ORM, Flask-WTF untuk validasi form, dan Flask-Login untuk otentikasi pengguna.

Contoh Aplikasi Sederhana dengan Flask

Berikut adalah contoh dasar aplikasi Flask:
from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello, Flask!'

@app.route('/hello/<name>')
def hello(name):
    return f'Hello, {name}!'

@app.route('/form', methods=['GET', 'POST'])
def form():
    if request.method == 'POST':
        name = request.form['name']
        return redirect(url_for('hello', name=name))
    return render_template('form.html')

if __name__ == '__main__':
    app.run(debug=True)

Kalau kita test pada python, hasilnya seperti ini pada browser :



Penjelasan Contoh:

  • Importing Flask: Mengimpor Flask dan modul terkait lainnya.
  • Inisialisasi Aplikasi: app = Flask(__name__) menginisialisasi aplikasi Flask.
  • Route and View Functions: @app.route('/') mendefinisikan route untuk halaman utama. Fungsi home akan mengembalikan string "Hello, Flask!".
  • Dynamic Route: @app.route('/hello/<name>') mendefinisikan route dinamis yang menerima parameter name.
  • Form Handling: Route /form menerima metode GET dan POST. Jika metode POST, data dari form akan diambil dan pengguna akan diarahkan ke halaman hello.

Kelebihan Flask

  • Kesederhanaan: Mudah dipelajari dan digunakan, cocok untuk pemula maupun pengembang berpengalaman.
  • Fleksibilitas: Dapat dengan mudah disesuaikan sesuai kebutuhan aplikasi.
  • Komunitas: Komunitas yang besar dan aktif, menyediakan banyak tutorial dan dukungan.

Kelemahan Flask

  • Kurangnya Fitur Bawaan: Tidak memiliki banyak fitur bawaan seperti framework web lain yang lebih besar (misalnya, Django).
  • Pengaturan Manual: Banyak fitur yang harus diatur dan diintegrasikan secara manual.

Flask sangat cocok untuk aplikasi web kecil hingga menengah, API, dan proyek yang membutuhkan fleksibilitas tinggi.


Selanjutnya pada raspi zero w akan saya buat script python untuk mengirimkan gambar ke server saya :

import sys
import requests
import cv2
import time

def send_image(image_path, server_url):
    # Read image from file
    image = cv2.imread(image_path)
    if image is None:
        print(f"Failed to load image {image_path}")
        return

    # Encode image as JPEG
    _, img_encoded = cv2.imencode('.jpg', image)

    # Measure the start time for the network request
    start_time = time.time()

    # Send the image to the Flask server
    response = requests.post(f"{server_url}/detect", files={"image": img_encoded.tobytes()})

    # Measure the end time for the network request
    end_time = time.time()

    # Calculate network time
    network_time = end_time - start_time

    # Check and parse the response
    response_data = response.json()
    server_processing_time_str = response_data.get('processing_time', None)

    if server_processing_time_str is not None:
        try:
            server_processing_time = float(server_processing_time_str)
            print(f"Server processing time: {server_processing_time:.2f} seconds")
        except ValueError:
            print("Error: Server processing time is not a valid float.")
            server_processing_time = None
    else:
        print("Server processing time not found in response.")
        server_processing_time = None

    print(response_data)
    print(f"Network time: {network_time:.2f} seconds")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python myscript.py <image_path> <server_url>")
    else:
        image_path = sys.argv[1]
        server_url = sys.argv[2]
        send_image(image_path, server_url)

Script diatas akan menggunakan cara panggil : 

python flask.py <nama_gambar.jpg> <ip_server_flask:port>


Sedangkan pada sisi server, seperti yang sudah saya bahas pada cara pengolahan yolo sebelumnya  disini, maka script yang saya buat sebagai berikut :


from flask import Flask, request, jsonify
import cv2
import numpy as np
import time


app = Flask(__name__)


yolo = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
classes = []

with open("coco.names", "r") as file:
    classes = [line.strip() for line in file.readlines()]


layer_names = yolo.getLayerNames()
output_layers = [layer_names[i - 1] for i in yolo.getUnconnectedOutLayers()]

colorRed = (0,0,255)
colorGreen = (0,255,0)

# #Loading Images
def detect_objects(img):
    starting_time = time.time()
    height, width, channels = img.shape

    # # Detecting objects
    blob = cv2.dnn.blobFromImage(img, 0.00392, (255, 255), (0, 0, 0), True, crop=False)

    yolo.setInput(blob)
    outputs = yolo.forward(output_layers)

    class_ids = []
    confidences = []
    boxes = []
    for output in outputs:
        for detection in output:
            scores = detection[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            if confidence > 0.4 and ( class_id == 0 or class_id == 2 or class_id == 3 ): # 0 = orang, 2 = motor , 3 = mobil 
                center_x = int(detection[0] * width)
                center_y = int(detection[1] * height)
                w = int(detection[2] * width)
                h = int(detection[3] * height)

                x = int(center_x - w / 2)
                y = int(center_y - h / 2)

                boxes.append([x, y, w, h])
                confidences.append(float(confidence))
                class_ids.append(class_id)


    indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
    org = 0
    mob = 0
    mot = 0

    for i in range(len(boxes)):
        if i in indexes:
            if class_ids[i] == 0:
                org = org + 1
                label = 'orang : ' + repr(org)
            elif class_ids[i] == 2:
                mob = mob + 1
                label = 'mobil : ' + repr(mob)
            elif class_ids[i] == 3:
                mot = mot + 1
                label = 'motor : ' + repr(mot)
            x, y, w, h = boxes[i]
            #label = str(classes[class_ids[i]]) + ', x=' +repr(x) + ',y=' +repr(y)
            #label = str(classes[class_ids[i]]) + '- no: ' + repr(i+1)
            cv2.rectangle(img, (x, y), (x + w, y + h), colorGreen, 3)
            cv2.putText(img, label, (x, y -5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255) )




    print("{")
    print(f"\"Jumlah Orang\": {org},")
    print(f"\"Jumlah Mobil\": {mob},")
    print(f"\"Jumlah Motor\": {mot},")

    elapsed_time = time.time() - starting_time
    print("\"processing time\":" + repr(elapsed_time)  )
    print("}")
    cv2.imwrite("output.jpg",img) 
    return {"Orang": org, "Mobil": mob, "Motor": mot, "time": elapsed_time }
    

@app.route("/detect", methods=["POST"])
def detect():
    file = request.files["image"]
    npimg = np.fromfile(file, np.uint8)
    image = cv2.imdecode(npimg, cv2.IMREAD_COLOR)
    result = detect_objects(image)
    return jsonify(result)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

Dan hasilnya sebagai berikut :



Nah...bisa dan cepat bukan ? Jadi file gambar yang saya tampilkan output.jpg diatas merupakan hasil pengolahan gambar pada pc saya sebagai sever dan kemudian dikembalikan ke raspberry pi zero w sebagai json hasil perhitungan jumlah orang. Jadi cukup 1 server bisa melayani banyak alat pengambil gambar yang sama menggunakan raspberry pi zero w yang harganya lumayan murah.

Bagaimana jika PC nya tidak tersedia dan hanya ada jaringan wifi dilokasi ? Kita kan bahas selanjutnya memanfaatkan komputasi cloud dari google lanjut disini.
Share:

[raspi - yolo] Apakah raspberry pi w zero dapat menjalankan yolo ?

 



Wah gak kerasa sudah lama sekali saya tidak menyentuh raspberry pi zero saya hampir 4 tahun setelahnya baru sempat menyentuhnya lagi. Jadi pembaca yang ingin mengetahui bagaimana mengenal seri raspberry pi paling minim dapat kembali ke : https://www.aisi555.com/2020/07/solder-pi-bermain-dengan-gpio-dan.html dan bisa mengenal dasar-dasar raspberry pi dalam konteks GPIO dan padanannya ketika dimanfaatkan layaknya mikrokontroller. 



Kali ini saya yang sedang berkutat dengan dunia image processing berbasis yolo ingin menge-test apakah dengan processor dual core 1Ghz dan ram 512 Kb dapat menjalankan yolo ? Dari beberapa literatur di internet (dan chatgpt tentunya) kita akan menggunakan opencv dan yolo v3 tiny. Tidak lupa saya memformat ulang raspberry pi zero w saya dengan OS terbaru mengunakan software windows - Raspberry Pi Imager dan saya pilihkan Os  lite-32 tanpa desktop agar menghemat space. Jadi saya mengandalkan putty untuk meng-edit semua raspberry saya.



Raspberry Pi Zero W, dengan kekuatan pemrosesan dan memorinya yang terbatas, paling cocok untuk versi ringan YOLO (You Only Look Once) yang dioptimalkan untuk lingkungan dengan sumber daya rendah. Model YOLO umumnya intensif secara komputasi, jadi untuk Raspberry Pi Zero W, Anda harus fokus pada versi yang lebih ringkas yang dirancang untuk efisiensi. Berikut adalah versi yang lebih mungkin kompatibel:

  • YOLOv3 Tiny: Ini adalah versi sederhana dari YOLOv3 yang dirancang agar lebih cepat dan memerlukan lebih sedikit daya komputasi. Ini adalah pilihan bagus untuk perangkat dengan sumber daya terbatas.
  • YOLOv4 Tiny: Mirip dengan YOLOv3 Tiny, ini adalah versi YOLOv4 yang dioptimalkan dan dirancang untuk berjalan pada perangkat dengan kemampuan komputasi lebih rendah.
  • YOLO-Nano: Ini adalah model ringan lainnya yang bertujuan untuk memberikan keseimbangan yang baik antara kinerja dan penggunaan sumber daya.
  • Tiny YOLOv2: Versi ini juga terkenal dengan efisiensinya dan dapat menjadi pilihan yang cocok untuk Raspberry Pi Zero W.

Instalasi dan Pengaturan:

Berikut panduan umum tentang cara menjalankan salah satu model ini di Raspberry Pi Zero W Anda:

1. Instal dependencies:

Pastikan Anda telah menginstal Python (disarankan Python 3).
Instal perpustakaan yang diperlukan seperti NumPy, OpenCV, dan TensorFlow Lite atau PyTorch bergantung pada model dan kerangka kerja yang Anda pilih.

sudo apt-get update
sudo apt-get install python3-pip
sudo pip3 install numpy opencv-python



2. Unduh weight dan Konfigurasi pre-trained:

Unduh file konfigurasi Tiny YOLO dan file bobot. Misalnya, Anda bisa mendapatkan bobot dan konfigurasi YOLOv3 Tiny dari situs web resmi YOLO atau repositori GitHub.
Konversikan ke TensorFlow Lite (Opsional):


wget https://pjreddie.com/media/files/yolov3-tiny.weights
wget https://github.com/pjreddie/darknet/blob/master/cfg/yolov3-tiny.cfg -O yolov3-tiny.cfg
wget https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names


3.Jika menggunakan TensorFlow Lite, konversikan model ke format TensorFlow Lite, yang lebih dioptimalkan untuk perangkat tersemat.

pip3 install tensorflow
Lanjutkan instalasi converter tensorflow lite, jika ini terasa susah skip saja karena saya tidak menggunakannya

4.Jalankan Modelnya:

Tulis skrip untuk memuat model dan menjalankan inferensi. Berikut ini contoh sederhana menggunakan OpenCV dan model YOLOv3 Tiny:

import cv2
import numpy as np

net = cv2.dnn.readNet("yolov3-tiny.weights", "yolov3-tiny.cfg")
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)

def load_image(img_path):
    image = cv2.imread(img_path)
    blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), swapRB=True, crop=False)
    net.setInput(blob)
    return image

def get_outputs():
    layer_names = net.getLayerNames()
    output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
    return output_layers

def detect_objects(image):
    detections = net.forward(get_outputs())
    for detection in detections:
        for obj in detection:
            scores = obj[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            if confidence > 0.5:
                center_x = int(obj[0] * image.shape[1])
                center_y = int(obj[1] * image.shape[0])
                w = int(obj[2] * image.shape[1])
                h = int(obj[3] * image.shape[0])
                x = int(center_x - w / 2)
                y = int(center_y - h / 2)
                cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
    return image

image = load_image("your_image.jpg")
output_image = detect_objects(image)
#cv2.imshow("Output", output_image)
#cv2.waitKey(0)
#cv2.destroyAllWindows()


Hasilnya ?


Gagal bokk...ternyata hasil nya sangat  tergantung pada kecerahan gambar dan sangat lambat jika menggunakan gamabr yang lebih besar resolusinya.


wah saya padahal punya proyek untuk mengatur nyala lampu dengan perbandingan jumlah orang dibawah lampu... lalu bagaimana ? Pada bagian selanjutnya saya akan memanfaatkan "komputer lain " yang akan dipinjam kekuatan komputasinya. Apakah google cloud bisa? Silahkan lanjut baca disini.. 

Share:

Sabtu, 15 Juni 2024

IOT - GPS dengan bantuan apps smartphone netGPS

 


Kalau kita kembali belajar IOT di awal-awal maka akan dikenalkan dengan yang namanya piramida IOT. Bagian paling ujung dari piramida ini adalah pelaporan ke orang yang akan membutuhkan informasi melalui IOT. Salah satu contoh pelaporan adalah GIS (Geographic Information System) dimana data yang diambil oleh sensor dan dikirimkan secara IOT akan ditampilkan pada peta. Tentunya cuap-cuap saya diawal ini akan terasa omong kosong kalau alat GPS nya seperti yang pernah saya bahas disini, susah di koneksikan...ala mak jang !

Sadar atau tidak sadar, pada kenyataannya, smartphone yang kita pakai mesti ada penerima GPS lho mas broo ! nah..benda yang selalu kita pegang tiap saat ini seharusnya dan pastinya dapat memberikan koordinat bujur dan lintang selama berada pada lokasi terbuka. Masalahnya bagaimana cara membagi pembacaan hardware GPS pada smartphone android ke perangkat IOT? 



Aplikasi android yang saya gunakan adalah netGPS yang akan mengirimkan data GPS secara TCP (berfungsi sebagai TCP server) dan mengirimkan sebagai teks log dari berbagai macam standar data GPS yang digunakan oleh smartphone android. Aplikasi ini cukup jadul jadi jika ingin menginstallnya harap gunakan cara selain google play jika ternyata HP kamu ditolak.




Contoh standar pembacaan teks NMEA (National Marine Electronics Association)  yang saya gunakan sederhana saja cukup sebaris ( karena saya butuhnya hanya koordinat saja) dan saya pilihkan standar $GPRMC. Saya butuh membayar 15ribu rupiah ke aplikasi ini untuk dapat memilih secara custom pesannya seperti pada gambar diatas. Dari sebuah website saya dapatkan standar pesannya adalah sebagai berikut:


$GPRMC

Recommended minimum specific GPS/Transit data

eg1. $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
eg2. $GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68

225446 Time of fix 22:54:46 UTC A Navigation receiver warning A = OK, V = warning 4916.45,N Latitude 49 deg. 16.45 min North 12311.12,W Longitude 123 deg. 11.12 min West 000.5 Speed over ground, Knots 054.7 Course Made Good, True 191194 Date of fix 19 November 1994 020.3,E Magnetic variation 20.3 deg East *68 mandatory checksum

Dan kemudian saya parsing data dari teks $GPRMC, namun karena saya tukang koding abal-abal, butuh bantuan chatGPT dan hasilnya saya diberikan script yang sangat jitu !


#include <ESP8266WiFi.h>

const char* ssid = "YourHotspotSSID";
const char* password = "YourHotspotPassword";

// Example NMEA GPRMC string
String nmeaString = "$GPRMC,043652,A,0713.64753,S,11243.78,E,,,290524,000.7,E,A*33";

void setup() {
  Serial.begin(115200);
  parseNMEA(nmeaString);
}

void loop() {
  // No code needed here for this example
}

double convertNMEACoordinate(String nmeaCoord, bool isLongitude) {
  // Determine the length of degrees part (3 for longitude, 2 for latitude)
  int degreesLength = isLongitude ? 3 : 2;
  // Extract the degrees part
  double degrees = nmeaCoord.substring(0, degreesLength).toInt();
  // Extract the minutes part and convert to decimal
  double minutes = nmeaCoord.substring(degreesLength).toFloat();
  degrees += minutes / 60.0;
  return degrees;
}

void parseNMEA(String nmea) {
  // Check if the string starts with "$GPRMC"
  if (nmea.startsWith("$GPRMC")) {
    // Buffer for each field in the NMEA string
    char buf[75];
    nmea.toCharArray(buf, 75);

    // Tokenize the NMEA string by comma
    char* token = strtok(buf, ",");
    
    // Index to track the position in the NMEA string
    int index = 0;
    
    // Variables to hold parsed data
    String time, status, latitude, latitudeDirection;
    String longitude, longitudeDirection, date;

    while (token != NULL) {
      switch (index) {
        case 1: time = String(token); break;
        case 2: status = String(token); break;
        case 3: latitude = String(token); break;
        case 4: latitudeDirection = String(token); break;
        case 5: longitude = String(token); break;
        case 6: longitudeDirection = String(token); break;
        case 9: date = String(token); break;
      }
      token = strtok(NULL, ",");
      index++;
    }

    // Convert latitude and longitude
    double latitudeDegrees = convertNMEACoordinate(latitude, false);
    if (latitudeDirection == "S") {
      latitudeDegrees = -latitudeDegrees;
    }

    double longitudeDegrees = convertNMEACoordinate(longitude, true);
    if (longitudeDirection == "W") {
      longitudeDegrees = -longitudeDegrees;
    }

    // Prepare buffer for formatted longitude
    char longitudeStr[20];
    dtostrf(longitudeDegrees, 1, 7, longitudeStr);

    // Prepare buffer for the final concatenated string
    char resultStr[40];  // Adjust size based on expected combined length
    strcpy(resultStr, "latitude ");
    strcat(resultStr, longitudeStr);

    // Print the parsed data
    Serial.println("Time: " + time);
    Serial.println("Status: " + status);
    Serial.print("Latitude: ");
    Serial.println(latitudeDegrees, 7);
    Serial.print("Longitude: ");
    Serial.println(longitudeDegrees, 7);
    Serial.print("Concatenated String: ");
    Serial.println(resultStr);  // Print concatenated string
    Serial.println("Date: " + date);

    // Convert and print additional data if necessary
    // Convert time to HH:MM:SS format
    String hours = time.substring(0, 2);
    String minutes = time.substring(2, 4);
    String seconds = time.substring(4, 6);
    Serial.println("Formatted Time: " + hours + ":" + minutes + ":" + seconds);

    // Convert date to DD/MM/YY format
    String day = date.substring(0, 2);
    String month = date.substring(2, 4);
    String year = date.substring(4, 6);
    Serial.println("Formatted Date: " + day + "/" + month + "/" + year);
  } else {
    Serial.println("Invalid NMEA string");
  }
}

Penjelasan:

1. Function konversi NMEA  (convertNMEACoordinate): 

  • Mengonversi koordinat NMEA ke format derajat desimal.


2. Function Penguraian (parseNMEA):

  • Memberi token pada string NMEA dan mengekstrak bidang yang relevan.
  • Mengonversi lintang dan bujur menjadi derajat desimal.
  • Menyesuaikan tanda berdasarkan arah (N/S untuk garis lintang, E/W untuk garis bujur).

3. Memformat Bujur/Lintang:

  • Fungsi dtostrf memformat garis bujur/lintang menjadi string dengan 7 tempat desimal.

4. Concatenate string:

  • Buffer resultStr disiapkan untuk menampung hasil gabungan.
  • Fungsi strcpy menginisialisasi resultStr dengan label "latitude".
  • Fungsi strcat menambahkan string garis bujur yang diformat ke resultStr.

5. Print / output :

  • String gabungan dicetak ke Serial Monitor.

Kode ini mem-parsing string NMEA GPRMC, mengubah garis lintang dan garis bujur menjadi derajat desimal, memformat garis bujur menjadi string dengan 7 tempat desimal, dan menggabungkannya dengan label longitude dan latitude. String gabungan kemudian dicetak pada serial monitor.




Untuk menerima pesan $GPRMC dari smartphone, saya akan membuat ESP8266-wemos saya sebagai client dan terhubung dengan hotpsot dari Smartphone yang saya gunakan. Hal ini akan memudahkan saya karena Smartphone saya fungsikan sebagai TCP server di IP Gatewaynya ( 192.168.43.1) pada port yg saya pilih 8088. IP ini adalah IP umum yang digunakan oleh hotspot smartphone android, namun sudah saya akali pada script agar TCP server yang di-bind-kan adalah IP gatewaynya, selanjutnya menunggu data GPS berupa teks $GPRMC.


/* GPS SMARTPHONE (netGPS Android) to ESP8266
Hardware : DHT 11 & OLED SSD1306 128x64
This script is incomplete, you should add data sending 
via IOT protocol, MQTT, HTTP  or Lora
www.aisi555.com 
*/


#include <ESP8266WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "DHT.h"


#define SCREEN_WIDTH 128 // display display width, in pixels
#define SCREEN_HEIGHT 64 // display display height, in pixels

#define DHT_PIN D4   // pin sensor DS18B20


#define display_RESET     -1 // Reset pin 
#define SCREEN_ADDRESS 0x3C ///address i2c oled 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, display_RESET);



#define DHTTYPE DHT11  //Sensor DHT11
DHT dht(DHT_PIN, DHTTYPE); 


const char* ssid = "myHotspot";
const char* password = "99999999";

// Server details
IPAddress serverIP;  // Define server IP address (gateway IP)
const uint16_t serverPort = 8088;

WiFiClient client;

bool gpsOK = false;
char longitudeStr[20];
char latitudeStr[20];

void setup() {
  Serial.begin(9600);
   Serial.println("");
  Serial.println(F(" ...www.aisi555.com GPS From Smartphone ...."));

    // initialize display display with address 0x3C for 128x64
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    while (true);
  }

  delay(2000);         // wait for initializing
  display.clearDisplay(); // clear display

  
  display.setTextSize(1);          // text size
  display.setTextColor(WHITE);     // text color
  
  displayDisplayCenter("www.aisi555.com", 4);
  displayDisplayCenter("Connecting to wifi.. ",56);

  
    // Connect to Wi-Fi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);



  display.clearDisplay(); // clear display
  displayDisplayCenter("www.aisi555.com", 4);
  displayDisplayCenter("Connecting to Aps..",56);
  
  IPAddress gatewayIP = WiFi.gatewayIP();
  serverIP = gatewayIP;  // Use the gateway IP as server IP

  // Attempt to connect to the server
  if (!client.connect(serverIP, serverPort)) {
    Serial.println("Connection to server failed");
  } else {
    Serial.println("Connected to server");
  }


  dht.begin();

  
}


void writeTempHumid(){ //kirim data pengukuran DHT
   
 
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    if (isnan(h) || isnan(t)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    
    Serial.print("Humidity: "); 
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: "); 
    Serial.print(t);
    Serial.println(" °C ");
  
    String tempString;
  
    tempString  = String(t, 1); // 
    tempString += (char)247;
    tempString += "C | ";
    tempString += String(h, 0);;
    tempString += " %";
  
    //biar ketumpuk hitam dulu biar bersih

    display.fillRect(0,17,128,48,BLACK);
    
  //lanjut tulis warna putih
   display.setTextColor(WHITE);
   
   String latString;
   latString  = "Lat: ";
   latString += String(latitudeStr);
   displayDisplayCenter(latString,20);

   String lonString;
   lonString  = "Lon: ";
   lonString += String(longitudeStr);
   displayDisplayCenter(lonString,30);
   displayDisplayCenter(tempString,42);

   if(gpsOK)displayDisplayCenter("GPS is Connected",56);
   else displayDisplayCenter("GPS disconnected !",56);


   /* ADD YOUR IOT DATA SENDING SCRIPT BELOW  */
   
  }


void loop() {

  if (runEvery(5000)) {
    writeTempHumid();
  }
  
  if (client.connected()) {
    // Check if data is available to read
    
    gpsOK=true;
    
    while (client.available()) {
      String receivedData = client.readStringUntil('\n');  // Read data until newline
      Serial.print("Received data: ");
      Serial.println(receivedData);

      // Process the received data
      // Add your data processing logic here

      parseNMEA(receivedData);
    }
  } else {
    // Reconnect if connection is lost
    if (!client.connect(serverIP, serverPort)) {
      Serial.println("Reconnection to server failed");
      gpsOK=false;
      delay(1000);  // Wait before retrying
    } else {
      Serial.println("Reconnected to server");
    }
  }
}

//function agar tulisan rata tengah (center)

void displayDisplayCenter(String text, int posisi) {
  int16_t x1;
  int16_t y1;
  uint16_t width;
  uint16_t height;

  display.getTextBounds(text, 0, 0, &x1, &y1, &width, &height);

  display.setCursor((SCREEN_WIDTH - width) / 2, posisi);
  display.println(text); // text to display
  display.display();
}



double convertNMEACoordinate(String nmeaCoord, bool isLongitude) {
  // Determine the length of degrees part (3 for longitude, 2 for latitude)
  int degreesLength = isLongitude ? 3 : 2;
  // Extract the degrees part
  double degrees = nmeaCoord.substring(0, degreesLength).toInt();
  // Extract the minutes part and convert to decimal
  double minutes = nmeaCoord.substring(degreesLength).toFloat();
  degrees += minutes / 60.0;
  return degrees;
}

void parseNMEA(String nmea) {
  // Check if the string starts with "$GPRMC"
  if (nmea.startsWith("$GPRMC")) {
    // Buffer for each field in the NMEA string
    char buf[75];
    nmea.toCharArray(buf, 75);

    // Tokenize the NMEA string by comma
    char* token = strtok(buf, ",");
    
    // Index to track the position in the NMEA string
    int index = 0;
    
    // Variables to hold parsed data
    String time, status, latitude, latitudeDirection;
    String longitude, longitudeDirection,date;

    while (token != NULL) {
      switch (index) {
        case 1: time = String(token); break;
        case 2: status = String(token); break;
        case 3: latitude = String(token); break;
        case 4: latitudeDirection = String(token); break;
        case 5: longitude = String(token); break;
        case 6: longitudeDirection = String(token); break;
        case 9: date = String(token); break;
      }
      token = strtok(NULL, ",");
      index++;
    }

    // Convert latitude and longitude
    double latitudeDegrees = convertNMEACoordinate(latitude, false);
    if (latitudeDirection == "S") {
      latitudeDegrees = -latitudeDegrees;
    }

    double longitudeDegrees = convertNMEACoordinate(longitude, true);
    if (longitudeDirection == "W") {
      longitudeDegrees = -longitudeDegrees;
    }

    //kirim ke display 
    dtostrf(longitudeDegrees, 1, 7, longitudeStr);
    dtostrf(latitudeDegrees, 1, 7, latitudeStr);
    

    // Print the parsed data
    Serial.println("Time: " + time);
    Serial.println("Status: " + status);
    Serial.print("Latitude: ");
    Serial.println(latitudeDegrees, 7);
    Serial.print("Longitude: ");
    Serial.println(longitudeDegrees, 7);
    Serial.println("Date: " + date);

    // Convert and print additional data if necessary
    // Convert time to HH:MM:SS format
    String hours = time.substring(0, 2);
    String minutes = time.substring(2, 4);
    String seconds = time.substring(4, 6);
    Serial.println("Formatted Time: " + hours + ":" + minutes + ":" + seconds);

    // Convert date to DD/MM/YY format
    String day = date.substring(0, 2);
    String month = date.substring(2, 4);
    String year = date.substring(4, 6);
    Serial.println("Formatted Date: " + day + "/" + month + "/" + year);
  } else {
    Serial.println("Invalid NMEA string");
  }
}

//timer
boolean runEvery(unsigned long interval)
{
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;
    return true;
  }
  return false;
}

Dan jika script kamu benar dapat mengirimkan data GPS menggunakan lorawan seperti berikut :
 


Dan kemudian pengolahan data GIS nya kita dapat manfaatkan google maps atau yang secara online yaitu kepler.gl (lihat gambar paling atas). Keberhasilan pengaplikasian trik saya ini sangat bergantung pada sensitifitas GPS receiver pada smartphone, sehingga syarat mutlak adalah HP kamu berada pada lokasi yg open space / langit terbuka.

SELAMAT MENCOBA
Share:

Selasa, 04 Juni 2024

Magang Industri Unesa 2024 - Topik : LoRa & LoRaWan

 


Kegiatan magang industri kali ke-3 bersama mahasiswa prodi teknik listrik fakultas vokasi Universitas Negeri Surabaya baru saja menyelesaikan presentasi dan pemaparan tugas akhir. Magang ini berlangsung dari februari 2024 s/d mei 2024 dan mengambil topik komunikasi LoRa dan LoRaWan. Masih berpola magang secara mandiri, disini perusahaan saya men-simulasikan sebuah proyek ke masing-masing peserta yang berjumlah 4 orang. 

Kali ini saya akan membagi apa saja hasil dari project yang saya berikan yang mungkin berguna bagi pembaca, terutama mahasiswa yang mungkin masih kebingungan mencari ide untuk praktek kerja atau tugas akhir.


- M. Erfin Pratama Setyawan : Antena LoRa 433 Mhz



Tugas yang dikerjakan adalah merancang antena Lora 433 Mhz  dengan 3 type antena yaitu :

  • Stick antenna
  • Dipole Antena
  • Yagi Antena

Pada dasarnya antena yang dirancang harus mengikuti kaedah-kaedah dan hitungan fisika dari propagasi gelombang radio dan ini mungkin agak melenceng dari jurusan kuliah peserta magang. Namun  ini tidak menjadi masalah, sebab satu hal yang sangat vital dalam pengiriman Long Range adalah antena yang MATCH ! Sehingga daya pancar dari modul semtech SX1278 yang hanya 100 miliwatt  dapat memancar dengan efisien dan kemudian diterima sinyalnya dengan baik pula disisi penerima.

Dan benar saja hasil dari tugas akhir mas erfin dapat mengirim LoRa dari 2 ujung jembatan suramadu menggunakan antena yagi modifikasi antena TV. Jaraknya cukup mencengangkan yaitu 5 km lebih. Begitu juga berhasil mengirimkan sinyal antara 2 gedung kampus Unesa ketintang vs Unesa lidah dengan jarak 6.5 km.



Video presentasi selengkapnya dapat dilihat disini :




- Yoko Hermanto : IOT Gateway untuk pertanian

 



Salah satu kegunaan komunikasi lora adalah untuk membantu bidang pertanian, dimana umumnya lahan pertanian berada pada lokasi di pedesaan. Lokasi yang kemungkinan besar akan kesulitan dijangkau sinyal GSM maupun wifi menginspirasi yoko untuk membuat sebuah IOT gateway yang akan menerima data suhu dan kelembaban tanah di sebuah lokasi pertanian.

Simulasi dilakukan dengan membaca kondisi tanah di sebuah pot yang terdapat tanaman sri rejeki (aglonema). Secara konsep IOT pada edge node computing , seharusnya microcontroller esp32 yang digunakan sudah mampu untuk melakukan pengukuran sensor kelembaban tanah secara mandiri dan melakukan otomasi penyiraman air ke dalam pot. 



IOT gateway nya akan menerima data dari komunikasi point yo point LoRa  dan kemudian mengirimkannya melalui protokol MQTT menuju aplikasi di sisi internet lainnya seperti MQTT Explorer. Video selengkapnya bisa dilihat disini:




- Satria Ego Varia : Monitoring & Kontrol Listrik Jarak Jauh Dengan LoRa - Whatsapp 



Kalau ini saya lumayan kagum dengan kemampuan koding peserta magang ini. Jadi saya persingkat saja, alat yang dibuat adalah kontrol relay serta monitoring beban listrik ac (sensor pzem) yang kemudian dikirimkan menggunakan esp32 dan komunikasi P2P antar modul LoRa, dimana mikrokontroler di salah satu sisi bertindak sebagai IOT gateway. Ajaibnya ujung dari sistem IOT adalah pelaporan serta kontrol kelistrikan menggunakan whatsapp. Canggih bukan ? Yuk kita simak saja videonya :




- Ajudan Laksamana : Drive Test Coverage Lorawan di Surabaya -Sidoarjo



Saya lumayan gembira bercampur sedih dengan tugas akhir magang yg dipegang judan ini, karena sebenarnya modul GPS yang saya pinjamkan  ini merupakan modul jadul yg dulu saya persiapkan untuk kawan yang memberi project IOT pertama saya. Masih ingat tulisan saya disini ? Ujung nya proyek ini gagal karena sang pemberi proyek direnggut covid 19.

Tugas yang saya berikan juga kelanjutan dari perkenalan pertama saya menggunakan LoRaWan Telkom Antares (baca disini)  dimana alat yang digunakan masih yang dulu itu, hasil solderan saya sendiri, dan kini hanya ditambahakan modul GPS ke port RX nya. Walau judan kemudian agak terhalang karena sakit, dia berhasil melakukan drive test yang cukup menggambarkan betapa buruknya coverage LoRaWan telkom di Surabaya-Sidoarjo.




Ada yang tertarik magang di saya lagi? Eittt episode selanjutnya bertemakan "Image Processing" dan "Artificial Inteligent" lhooo... Berani ?

Share:

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 (12) antares (11) arduino (27) 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 (73) 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 (1) 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 (4) transistor (2) troubleshoot (3) tulisan (93) 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