Manual Guide
Manual Guide
mengukur kadar nutrisi pada tanah seperti nitrogen, fosfor, kalium, dan pH.
Selain itu, LeafyNourish juga dapat memantau suhu dan kelembapan sekitar
KOMPONEN PROTOTYPE
PETUNJUK PENGOPERASIAN
prototipe alat. Selanjunya untuk mengukur kadar nutrisi tanah, Sensor NPK
dan pH Tanah ditancapkan ke Tanah yang ingin diukur kadar nutrisi nya.
untuk aplikasi menampilkan hasil rekomendasi beserta data nutrisi, suhu dan
ARDUINO
#include <WiFi.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <FirebaseESP32.h>
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
#include "DHT.h"
//sensor dht11
#define DHTPIN 2
#define DHTTYPE DHT11
//variabel
int ADC;
float lastReading;
float pH;
const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};
byte values[11];
SoftwareSerial mod(RX_PIN, TX_PIN); //RI_2, DI 3
//Wifi
const char* ssid = "Internet Berbayar ya Guys";
const char* password = "rorororo";
//Firebase
#define DATABASE_URL "https://leafynourish-default-rtdb.asia-
southeast1.firebasedatabase.app/"
#define API_KEY "AIzaSyDrfmQbuKuiWFyRkYcm6Zwkos8Z5V-Revo"
FirebaseAuth auth;
FirebaseConfig config;
void setup() {
Serial.begin(115200);
mod.begin(4800);
pinMode(RE_DE, OUTPUT);
dht.begin();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
analogReadResolution(10);
pinMode(DMSpin, OUTPUT);
digitalWrite(DMSpin, HIGH);
}
void loop() {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
digitalWrite(DMSpin, LOW);
delay(5 * 1000);
ADC = analogRead(adcPin);
pH = (-0.0865 * ADC) + 7.9513;
if (pH != lastReading) {
lastReading = pH;
}
digitalWrite(DMSpin, HIGH);
delay(3 * 1000); // wait for DMS ready
FirebaseJson data;
if (isnan(temp) || isnan(hum)) {
Serial.println("Gagal Mengirim data Suhu & Kelembapan || Cek
DHT11");
} else {
data.add("suhu", temp);
data.add("kelembapan", hum);
}
data.add("nitrogen", val1);
data.add("fosfor", val2);
data.add("kalium", val3);
data.add("ph", lastReading);
int nitrogen() {
digitalWrite(RE_DE, HIGH);
delay(100);
if (mod.write(nitro, sizeof(nitro)) == 8) {
mod.flush();
digitalWrite(RE_DE, LOW);
delay(200);
for (byte i = 0; i < 7; i++) {
//Serial.print(mod.read(),HEX);
values[i] = mod.read();
// Serial.print(values[i],HEX);
}
// Serial.println();
}
return values[3] << 8 | values[4];
}
int phosphorous() {
digitalWrite(RE_DE, HIGH);
delay(100);
if (mod.write(phos, sizeof(phos)) == 8) {
mod.flush();
digitalWrite(RE_DE, LOW);
delay(200);
for (byte i = 0; i < 7; i++) {
//Serial.print(mod.read(),HEX);
values[i] = mod.read();
// Serial.print(values[i],HEX);
}
// Serial.println();
}
return values[3] << 8 | values[4];
}
int potassium() {
digitalWrite(RE_DE, HIGH);
delay(100);
if (mod.write(pota, sizeof(pota)) == 8) {
mod.flush();
digitalWrite(RE_DE, LOW);
delay(200);
for (byte i = 0; i < 7; i++) {
//Serial.print(mod.read(),HEX);
values[i] = mod.read();
// Serial.print(values[i],HEX);
}
// Serial.println();
}
return values[3] << 8 | values[4];
}
ANDROID
MainActivity.Kt
class MainActivity : AppCompatActivity() {
private lateinit var databaseReference:
DatabaseReference
private lateinit var tvSuhuValue: TextView
private lateinit var tvHumValue: TextView
private lateinit var tvNitrogenValue: TextView
private lateinit var tvFosforValue: TextView
private lateinit var tvKaliumValue: TextView
private lateinit var tvPHValue: TextView
private lateinit var tvRecom: TextView
tvSuhuValue = findViewById(R.id.tvSuhuValue)
tvHumValue = findViewById(R.id.tvHumValue)
tvNitrogenValue =
findViewById(R.id.tvNitrogenValue)
tvFosforValue = findViewById(R.id.tvFosforValue)
tvKaliumValue = findViewById(R.id.tvKaliumValue)
tvPHValue = findViewById(R.id.tvPHValue)
tvRecom = findViewById(R.id.tvRecom)
tvRecom.setOnClickListener {
val intent = Intent(this@MainActivity,
RecommendationActivity::class.java)
startActivity(intent)
}
databaseReference =
FirebaseDatabase.getInstance().reference.child("sensor_data
")
tvSuhuValue.text = suhu?.toString() ?:
"0°C"
tvHumValue.text = kelembapan?.toString() ?:
"0%"
tvNitrogenValue.text = nitrogen?.toString()
?: "0"
tvFosforValue.text = fosfor?.toString() ?:
"0"
tvKaliumValue.text = kalium?.toString() ?:
"0"
tvPHValue.text = roundePh.toString() ?:
"0.0f"
setTextAndClickListener(tvSuhuValue,
"suhu")
setTextAndClickListener(tvHumValue,
"kelembapan")
setTextAndClickListener(tvNitrogenValue,
"nitrogen")
setTextAndClickListener(tvFosforValue,
"fosfor")
setTextAndClickListener(tvKaliumValue,
"kalium")
setTextAndClickListener(tvPHValue, "ph")
}
DetailActivity.Kt
package com.ananta.leafynourish
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.Description
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.google.firebase.database.ChildEventListener
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
class DetailActivity : AppCompatActivity() {
private lateinit var lineChart: LineChart
private lateinit var valueEventListener:
ValueEventListener
private lateinit var databaseReference:
DatabaseReference
lineChart = findViewById(R.id.lineChart)
// Konfigurasi Chart
lineChart.description.isEnabled = false
lineChart.legend.isEnabled = false
lineChart.animateX(500)
if (data != null) {
updateChart(data)
}
}
}
})
}
RecommendationFragment.Kt
class RecommendationFragment : Fragment() {
private var startTimeMillis: Long = 0
private var endTimeMillis: Long = 0
tvSuhuData = view.findViewById(R.id.tvSuhuData)
tvHumData = view.findViewById(R.id.tvHumData)
tvNitrogenData =
view.findViewById(R.id.tvNitrogenData)
tvFosforData = view.findViewById(R.id.tvFosforData)
tvKaliumData = view.findViewById(R.id.tvKaliumData)
tvPHData = view.findViewById(R.id.tvPHData)
tvResult = view.findViewById(R.id.tvResult)
databaseReference =
FirebaseDatabase.getInstance().reference.child("sensor_data
") // Ganti "data" dengan nama node di database Anda
return view
}
databaseReference.addListenerForSingleValueEvent(object :
ValueEventListener{
@SuppressLint("SetTextI18n")
override fun onDataChange(dataSnapshot:
DataSnapshot) {
var lastDataSnapshot: DataSnapshot? = null
for (childSnapshot in
dataSnapshot.children) {
lastDataSnapshot = childSnapshot
}
if (lastDataSnapshot != null) {
startTimeMillis =
System.currentTimeMillis()
val startTime =
getCurrentTimeFormatted()
val responseTimeMillis =
endTimeMillis - startTimeMillis
val responseTimeSeconds =
responseTimeMillis / 1000.0
Toast.makeText(activity,
"Response Time: $responseTimeSeconds seconds",
Toast.LENGTH_SHORT).show()
Log.d("TimeIqqnfo", "startTime:
$startTime")
Log.d("TimeInfo", "endTime:
$endTime")
requireActivity().runOnUiThread
{
try {
val jsonObject =
JSONObject(response)
val data =
jsonObject.getString("Plant")
if (data == "1") {
tvResult.text =
"Padi"
} else if (data == "2")
{
tvResult.text =
"Jagung"
} else if (data == "3")
{
tvResult.text =
"Buncis"
} else if (data == "4")
{
tvResult.text =
"Kacang Merah"
} else if (data == "5")
{
tvResult.text =
"Kacang Gude"
} else if (data == "6")
{
tvResult.text =
"Kacang Hijau"
} else if (data == "7")
{
tvResult.text =
"Gram Hitam"
} else if (data == "8")
{
tvResult.text =
"Delima"
} else if (data == "9")
{
tvResult.text =
"Pisang"
} else if (data ==
"10") {
tvResult.text =
"Mangga"
} else if (data ==
"11") {
tvResult.text =
"Anggur"
} else if (data ==
"12") {
tvResult.text =
"Semangka"
} else if (data ==
"13") {
tvResult.text =
"Melon"
} else if (data ==
"14") {
tvResult.text =
"Apel"
} else if (data ==
"15") {
tvResult.text =
"Jeruk"
} else if (data ==
"16") {
tvResult.text =
"Pepaya"
} else if (data ==
"17") {
tvResult.text =
"Kelapa"
} else if (data ==
"18") {
tvResult.text =
"Kapas"
} else if (data ==
"19") {
tvResult.text =
"Rami/Yute"
}else {
tvResult.text =
"Kopi"
}
} catch (e: JSONException)
{
e.printStackTrace()
}
}
},
Response.ErrorListener { error ->
Toast.makeText(activity,
error.message, Toast.LENGTH_SHORT).show()
}) {
}
})
}
MACHINE LEARNING
Building Model
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import json
data =
pd.read_csv('/content/drive/MyDrive/Kampus/Skripsi/Dataset/Crop_reco
mmendation.csv')
data
data.isnull().sum()
duplicate_rows = data[data.duplicated()]
print("\nNilai Duplikat:")
print(duplicate_rows)
data
X = new_data.drop(columns=['label'])
y = new_data['label']
uniq_num = y.nunique()
uniq_val = y.unique()
for i in range(uniq_num):
y.replace(uniq_val[i], i+1, inplace= True)
# membagi data menjadi train dan test untuk setiap atribut dan label
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.4082482904638631, shuffle=True, random_state=8)
rf = RandomForestClassifier(random_state=10)
lgbm = lgb.LGBMClassifier(verbose=-1, n_estimators=10,
random_state=42)
svm_model = svm.SVC(probability=True)
# Ensemble of Models
estimator = []
estimator.append(('RF', rf))
estimator.append(('LGBM', lgbm))
estimator.append(('SVM', svm_model))
import pickle
with open('ml_model.pkl', 'wb') as file:
pickle.dump(hard_voting, file)
Flask API
app.py
from flask import Flask, request, jsonify
from sklearn.preprocessing import MinMaxScaler
import numpy as np
import pickle
app = Flask(__name__)
@app.route('/')
def index():
return "Hello world"
@app.route("/predict", methods=["POST"])
def predict():
nitrogen = request.form.get('nitrogen')
fosfor = request.form.get('fosfor')
kalium = request.form.get('kalium')
suhu = request.form.get('suhu')
kelembapan = request.form.get('kelembapan')
ph = request.form.get('ph')
recommendation = model.predict(input_query)[0]
return jsonify({"Plant":str(recommendation)})
if __name__ == '__main__':
app.run(debug=True)
vercel.json
{
"version": 2,
"builds": [
{
"src": "app.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "app.py"
},
{
"src": "/predict",
"methods": ["POST"],
"dest": "app.py"
}
]
}
requirements.txt
flask
numpy
scikit-learn == 1.2.2
lightgbm
Untuk melihat video penggunaan prototype dapat dilihat pada link video
berikut : https://youtu.be/8pFQK4VkNho