/********************************
Room Temperature Control System
Based On Fuzzy Logic
www.muhilham.com
2018
*********************************/
#include "liquidcrystal_i2c.h"
LiquidCrystal_I2C lcd(0x3F, 16, 2);
#include "DHT.h"
DHT dht(4, DHT11);
int sen_in, sen_out, offset_sen_in, offset_sen_out; // variabel sensor infrared
boolean detect_in = false, detect_out = false;
int count;
float suhu,
uMember,
uDingin, uSejuk, uNormal, uPanas, uSangatPanas,
uSangatSedikit, uSedikit, uSedang, uBanyak, uSangatBanyak,
N_suhu[5], N_orang[5], kondisiSuhu, kondisiOrang, Min[25],
Keluaran, Kecepatan;
String OutputFuzzy;
const int PWM_KIPAS = 5,
P1_KIPAS = 6,
P2_KIPAS = 7,
PWM_EXHAUST = 9,
P1_EXHAUST = 8,
P2_EXHAUST = 10;
long lastTime_readSen = 0, lastTime_LCD = 0;
int state_LCD = 1;
void setup() {
Serial.begin(9600);
lcd.begin();
dht.begin();
for (int i = 0; i <= 1; i++) {
pinMode(i, INPUT);
}
for (int i = 5; i <= 10; i++) {
pinMode(i, OUTPUT);
}
sen_in = analogRead(A0);
sen_out = analogRead(A1);
offset_sen_in = sen_in - 70; // sample sensor masuk
offset_sen_out = sen_out - 70; // sample sensor keluar
count = 0;
temp()
}
void loop() {
sensor_count();
fuzzifikasi();
defuzzifikasi();
Output();
Kecepatan = map(Keluaran, 0, 100, 0, 255);
driveKipas_N_Exhaust(Kecepatan);
}
// -----------------------------------------------------------
// Read DHT Function
float temp() {
float temp = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(temp)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
return temp;
}
// #END Read DHT Function -------------------------------------
void sensor_count() {
sen_in = analogRead(A0);
sen_out = analogRead(A1);
if (sen_in > offset_sen_in) {
detect_in = false;
}
else if (sen_in < offset_sen_in && detect_in == false) {
count++;
detect_in = true;
if (count >= 40)count = 40;
}
if (sen_out > offset_sen_out) {
detect_out = false;
}
else if (sen_out < offset_sen_out && detect_out == false) {
count--;
detect_out = true;
if (count < 0)count = 0;
}
}
void driveKipas_N_Exhaust(float Kecepatan) {
digitalWrite(P1_KIPAS, LOW);
digitalWrite(P2_KIPAS, HIGH);
analogWrite(PWM_KIPAS, Kecepatan);
digitalWrite(P1_EXHAUST, LOW);
digitalWrite(P2_EXHAUST, HIGH);
analogWrite(PWM_EXHAUST, Kecepatan);
}
void hitung_member(int pilih, float Nilai, float A, float B, float C) {
switch (pilih) {
case 1:
if ((Nilai >= A) && (Nilai <= B)) uMember = 1;
if ((Nilai > B) && (Nilai < C)) uMember = (C - Nilai) / (C - B);
if (Nilai >= C) uMember = 0;
break;
case 2:
if ((Nilai <= A) || (Nilai >= C)) uMember = 0;
if ((Nilai > A) && (Nilai < B)) uMember = (Nilai - A) / (B - A);
if ((Nilai > B) && (Nilai < C)) uMember = (C - Nilai) / (C - B);
if (Nilai == B) uMember = 1;
break;
case 3:
if (Nilai <= A) uMember = 0;
if ((Nilai > A) && (Nilai < B)) uMember = (Nilai - A) / (B - A);
if (Nilai >= B) uMember = 1;
break;
}
}
void fuzzifikasi() {
// Suhu
uMember = 0;
hitung_member(1, temp(), 0, 24, 26);
uDingin = uMember;
hitung_member(2, temp(), 24, 26, 29);
uSejuk = uMember;
hitung_member(2, temp(), 26, 29, 32);
uNormal = uMember;
hitung_member(2, temp(), 29, 32, 35);
uPanas = uMember;
hitung_member(3, temp(), 32, 35, 35);
uSangatPanas = uMember;
// Banyak Orang
uMember = 0;
hitung_member(1, count, 0, 5, 10);
uSangatSedikit = uMember;
hitung_member(2, count, 5, 10, 20);
uSedikit = uMember;
hitung_member(2, count, 10, 20, 30);
uSedang = uMember;
hitung_member(2, count, 20, 30, 40);
uBanyak = uMember;
hitung_member(3, count, 30, 40, 40);
uSangatBanyak = uMember;
}
//int fuzzy_set[5][5] = {
// //Cold|Cool|Nor|Hot|Vhot
// {20, 20, 20, 60, 80}, //| Vlow
// {20, 40, 20, 60, 80}, //| Low
// {40, 40, 60, 80, 100}, //| Medium
// {40, 60, 80, 100, 100}, //| High
// {60, 80, 100, 100, 100} //| Very high
//};
//20 = Vslow, 40 = Slow, 60 = Med, 80 = Fast, 100 = Vfast
int fuzzy_set[5][5] = {
//|vLow|Low|Med|High|vHigh
{20, 20, 40, 40, 60}, //| Cold
{20, 40, 40, 60, 80}, //| Cool
{40, 40, 60, 80, 100}, //| Normal
{60, 60, 80, 100, 100}, //| Hot
{80, 80, 100, 100, 100} //| Very hot
};
void defuzzifikasi() {
float pembil = 0, penyeb = 0, centre_of_area = 0;
N_suhu[5] = {};
N_orang[5] = {};
for (int set = 0; set < 25;) {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
float data_uSuhu[5] = {uDingin, uSejuk, uNormal, uPanas, uSangatPanas};
N_suhu[i] = data_uSuhu[i];
float data_uOrang[5] = {uSangatSedikit, uSedikit, uSedang, uBanyak, uSangatBanyak};
N_orang[j] = data_uOrang[j];
kondisiSuhu = max(N_suhu[i], kondisiSuhu);
kondisiOrang = max(N_orang[j], kondisiOrang);
/* Metode COA (Centre Of Area)*/
min[set] = min(N_suhu[i], N_orang[j]);
pembil += Min[set] * fuzzy_set[i][j];
penyeb += Min[set];
delay(5);
set ++;
}
}
}
centre_of_area = pembil / penyeb;
Keluaran = centre_of_area;
}
void basis_Aturan_output() {
if (kondisiSuhu == uDingin && kondisiOrang == uSangatSedikit)OutputFuzzy = "Vslow";
else if (kondisiSuhu == uDingin && kondisiOrang == uSedikit)OutputFuzzy = "Vslow";
else if (kondisiSuhu == uDingin && kondisiOrang == uSedang)OutputFuzzy = "Slow";
else if (kondisiSuhu == uDingin && kondisiOrang == uBanyak)OutputFuzzy = "Slow";
else if (kondisiSuhu == uDingin && kondisiOrang == uSangatBanyak)OutputFuzzy = "Med";
else if (kondisiSuhu == uSejuk && kondisiOrang == uSangatSedikit)OutputFuzzy = "Vslow";
else if (kondisiSuhu == uSejuk && kondisiOrang == uSedikit)OutputFuzzy = "Slow";
else if (kondisiSuhu == uSejuk && kondisiOrang == uSedang)OutputFuzzy = "Slow";
else if (kondisiSuhu == uSejuk && kondisiOrang == uBanyak)OutputFuzzy = "Med";
else if (kondisiSuhu == uSejuk && kondisiOrang == uSangatBanyak)OutputFuzzy = "Fast";
else if (kondisiSuhu == uNormal && kondisiOrang == uSangatSedikit)OutputFuzzy = "Slow";
else if (kondisiSuhu == uNormal && kondisiOrang == uSedikit)OutputFuzzy = "Slow";
else if (kondisiSuhu == uNormal && kondisiOrang == uSedang)OutputFuzzy = "Med";
else if (kondisiSuhu == uNormal && kondisiOrang == uBanyak)OutputFuzzy = "Fast";
else if (kondisiSuhu == uNormal && kondisiOrang == uSangatBanyak)OutputFuzzy = "Vfast";
else if (kondisiSuhu == uPanas && kondisiOrang == uSangatSedikit)OutputFuzzy = "Med";
else if (kondisiSuhu == uPanas && kondisiOrang == uSedikit)OutputFuzzy = "Med";
else if (kondisiSuhu == uPanas && kondisiOrang == uSedang)OutputFuzzy = "Fast";
else if (kondisiSuhu == uPanas && kondisiOrang == uBanyak)OutputFuzzy = "Vfast";
else if (kondisiSuhu == uPanas && kondisiOrang == uSangatBanyak)OutputFuzzy = "Vfast";
else if (kondisiSuhu == uSangatPanas && kondisiOrang == uSangatSedikit)OutputFuzzy = "Fast";
else if (kondisiSuhu == uSangatPanas && kondisiOrang == uSedikit)OutputFuzzy = "Fast";
else if (kondisiSuhu == uSangatPanas && kondisiOrang == uSedang)OutputFuzzy = "Vfast";
else if (kondisiSuhu == uSangatPanas && kondisiOrang == uBanyak)OutputFuzzy = "Vfast";
else if (kondisiSuhu == uSangatPanas && kondisiOrang == uSangatBanyak)OutputFuzzy = "Vfast";
}
void Output() {
//uMember_suhu_count();
basis_Aturan_output();
Tampil_Serial();
Tampil_LCD();
}
void Tampil_Serial() {
//Tampil Serial
Serial.print(" Temp : ");
Serial.print(temp());
Serial.print(" *C ");
Serial.print(" ");
tampil_member_suhu();
if (kondisiSuhu == N_suhu[0])Serial.print("Cold");
else if (kondisiSuhu == N_suhu[1])Serial.print("Cool");
else if (kondisiSuhu == N_suhu[2])Serial.print("Normal");
else if (kondisiSuhu == N_suhu[3])Serial.print("Hot");
else if (kondisiSuhu == N_suhu[4])Serial.print("Very Hot");
Serial.print(" | Count : ");
Serial.print(count);
Serial.print(" ");
tampil_member_count();
if (kondisiOrang == N_orang[0])Serial.print("Very Low");
else if (kondisiOrang == N_orang[1])Serial.print("Low");
else if (kondisiOrang == N_orang[2])Serial.print("Medium");
else if (kondisiOrang == N_orang[3])Serial.print("High");
else if (kondisiOrang == N_orang[4])Serial.print("Very High");
Serial.print(" | ");
if (OutputFuzzy == "Vslow") Serial.print("Fan : Very Slow");
else if (OutputFuzzy == "Slow") Serial.print("Fan : Slow");
else if (OutputFuzzy == "Med") Serial.print("Fan : Medium");
else if (OutputFuzzy == "Fast") Serial.print("Fan : Fast");
else if (OutputFuzzy == "Vfast")Serial.print("Fan : Very Fast");
Serial.print(" LV : ");
Serial.print(Keluaran);
Serial.print("%");
Serial.print(" PWM : ");
Serial.print(Kecepatan);
Serial.println();
}
void Tampil_LCD() {
lcd.backlight();
if (millis() - lastTime_LCD > 5000) {
state_LCD = 1;
lastTime_LCD = millis();
}
if (millis() > lastTime_LCD + 2500) {
state_LCD = 2;
}
if (state_LCD == 1) {
lcd.setCursor (0, 0);
lcd.print("Temp:");
lcd.print((int)temp());
lcd.print("C ");
if (kondisiSuhu == N_suhu[0])lcd.print(" Cold");
if (kondisiSuhu == N_suhu[1])lcd.print(" Cool");
if (kondisiSuhu == N_suhu[2])lcd.print(" Normal");
if (kondisiSuhu == N_suhu[3])lcd.print(" Hot");
if (kondisiSuhu == N_suhu[4])lcd.print("VeryHot");
lcd.setCursor (0, 1);
lcd.print("Cont:");
lcd.print((int)count);
lcd.print(" ");
lcd.setCursor (7, 1);
if (kondisiOrang == N_orang[0])lcd.print(" VeryLow");
if (kondisiOrang == N_orang[1])lcd.print(" Low");
if (kondisiOrang == N_orang[2])lcd.print(" Medium");
if (kondisiOrang == N_orang[3])lcd.print(" High");
if (kondisiOrang == N_orang[4])lcd.print(" VeryHigh");
}
else if (state_LCD == 2) {
lcd.setCursor (0, 0);
lcd.print(" PWM: ");
lcd.print((float)Keluaran);
lcd.print("% ");
lcd.setCursor (0, 1);
if (OutputFuzzy == "Vslow") lcd.print(" Very Slow ");
else if (OutputFuzzy == "Slow") lcd.print(" Slow ");
else if (OutputFuzzy == "Med") lcd.print(" Medium ");
else if (OutputFuzzy == "Fast") lcd.print(" Fast ");
else if (OutputFuzzy == "Vfast")lcd.print(" Very Fast ");
}
}
void uMember_suhu_count() {
Serial.print(" Temp : ");
Serial.print(temp());
Serial.print(" *C ");
Serial.print(" ");
Serial.print("Cold:");
Serial.print(uDingin);
Serial.print(" Cool:");
Serial.print(uSejuk);
Serial.print(" Nor:");
Serial.print(uNormal);
Serial.print(" Hot:");
Serial.print(uPanas);
Serial.print(" VHot:");
Serial.print(uSangatPanas);
Serial.print(" ");
Serial.print(" | Count : ");
Serial.print(count);
Serial.print(" ");
Serial.print("VLow:");
Serial.print(uSangatSedikit);
Serial.print(" Low:");
Serial.print(uSedikit);
Serial.print(" Med:");
Serial.print(uSedang);
Serial.print(" High:");
Serial.print(uBanyak);
Serial.print(" VHigh:");
Serial.println(uSangatBanyak);
}
void tampil_member_suhu() {
//if (uDingin != 0.00) {
Serial.print("Cold:");
Serial.print(uDingin);
//}
//if (uSejuk != 0.00) {
Serial.print(" Cool:");
Serial.print(uSejuk);
//}
//if (uNormal != 0.00) {
Serial.print(" Nor:");
Serial.print(uNormal);
//}
//if (uPanas != 0.00) {
Serial.print(" Hot:");
Serial.print(uPanas);
//}
//if (uSangatPanas != 0.00) {
Serial.print(" VHot:");
Serial.print(uSangatPanas);
//}
Serial.print(" ");
}
void tampil_member_count() {
//if (uSangatSedikit != 0.00) {
Serial.print("VLow:");
Serial.print(uSangatSedikit);
//}
//if (uSedikit != 0.00) {
Serial.print(" Low:");
Serial.print(uSedikit);
//}
//if (uSedang != 0.00) {
Serial.print(" Med:");
Serial.print(uSedang);
//}
//if (uBanyak != 0.00) {
Serial.print(" High:");
Serial.print(uBanyak);
//}
//if (uSangatBanyak != 0.00) {
Serial.print(" VHigh:");
Serial.print(uSangatBanyak);
//}
Serial.print(" ");
}