#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "DHT.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// #include <Adafruit_SH110X.h>
#include <Keypad.h>
#include <PID_v1.h>
// intervals------------------------------------------------------
unsigned long previousMillis_for_updating_display = 0;
const long interval_for_updating_display = 5000; // interval for updating display
unsigned long previousMillis_for_reading_sensors = 0;
const long interval_for_reading_sensors = 2000; // interval for reading sensors
// Temperature Sensor (DS18B20) -----------------------------------
// Define the number of sensors
const int NUM_DS18B20_SENSORS = 4;
// Define an array to hold the addresses of all sensors
// { 0x28, 0x8C, 0xBC, 0x80, 0xE3, 0xE1, 0x3C, 0xB1 },
// { 0x28, 0x48, 0x9B, 0x80, 0xE3, 0xE1, 0x3C, 0x5B },
// { 0x28, 0xEF, 0x2A, 0x58, 0xD4, 0xE1, 0x3C, 0xB9 },
// { 0x28, 0x8, 0x5E, 0x80, 0xE3, 0xE1, 0x3C, 0xDE }
DeviceAddress sensorAddresses[NUM_DS18B20_SENSORS] = {
{ 0x10, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52 },
{ 0x10, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23 },
{ 0x10, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x97 },
{ 0x10, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4F }
};
// Define a structure to hold temperature data for one sensor
struct Ds18b20_SensorData {
float tempC;
float tempF;
};
// Create an array of SensorData structures to hold data for all sensors
Ds18b20_SensorData ds18b20_SensorDataArray[NUM_DS18B20_SENSORS];
float average_temperature = 0.0;
// const byte ONE_WIRE_BUS = 0;
#define ONE_WIRE_BUS 4
// Setup a oneWire instance to communicate with a OneWire device
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
void reading_ds18b20_sensors() {
Serial.print("Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.println("DONE");
for (int i = 0; i < NUM_DS18B20_SENSORS; i++) {
// Get temperature data for each sensor
ds18b20_SensorDataArray[i].tempC = sensors.getTempC(sensorAddresses[i]);
ds18b20_SensorDataArray[i].tempF = sensors.getTempF(sensorAddresses[i]);
// Print temperature data for each sensor
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.print(" (*C): ");
Serial.print(ds18b20_SensorDataArray[i].tempC);
Serial.print(" Sensor ");
Serial.print(i + 1);
Serial.print(" (*F): ");
Serial.println(ds18b20_SensorDataArray[i].tempF);
}
}
// Humidity & Temperature Sensor (DHT11) ------------------------
// for simulator-------------------------------------------------
#define DHT_PIN1 1 // Digital pin connected to the DHT sensor
#define DHT_PIN2 2
#define DHT_PIN3 3
#define DHT_PIN4 4
// #define DHT_PIN1 0 // Digital pin connected to the DHT sensor
// #define DHT_PIN2 1
// #define DHT_PIN3 15
// #define DHT_PIN4 2
#define NUM_DHT11_SENSORS 4
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
struct DHT_SensorData {
float humidity;
float temperatureC;
float temperatureF;
};
DHT dht[NUM_DHT11_SENSORS] = {
DHT(DHT_PIN1, DHTTYPE), // Initialize DHT sensor 1
DHT(DHT_PIN2, DHTTYPE), // Initialize DHT sensor 2
DHT(DHT_PIN3, DHTTYPE), // Initialize DHT sensor 3
DHT(DHT_PIN4, DHTTYPE) // Initialize DHT sensor 4
};
DHT_SensorData dht11_SensorDataArray[NUM_DHT11_SENSORS];
float average_humidity = 0.0;
void reading_dht11_sensors() {
for (int i = 0; i < NUM_DHT11_SENSORS; i++) {
dht11_SensorDataArray[i].humidity = dht[i].readHumidity();
dht11_SensorDataArray[i].temperatureC = dht[i].readTemperature();
dht11_SensorDataArray[i].temperatureF = dht[i].readTemperature(true);
if (isnan(dht11_SensorDataArray[i].humidity) || isnan(dht11_SensorDataArray[i].temperatureC) || isnan(dht11_SensorDataArray[i].temperatureF)) {
Serial.print("Failed to read from DHT sensor ");
Serial.println(i + 1);
continue;
}
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.print(": Humidity: ");
Serial.print(dht11_SensorDataArray[i].humidity);
Serial.print("% Temperature: ");
Serial.print(dht11_SensorDataArray[i].temperatureC);
Serial.print("°C ");
Serial.print(dht11_SensorDataArray[i].temperatureF);
Serial.println("°F");
}
}
// PI Controller--------------------------------------------------
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
double Kp = 2, Ki = 2, Kd = 0;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, REVERSE);
// state------------------------------------------------
// input_setpoint / output / input
String state = "output";
// Setpoint---------------------------------------------
float new_setpoint = 0;
float temperature_setpoint = 32.0;
float humidity_setpoint = 30.0;
int z2 = 0;
char attempt_setpoint[4] = {'_', '_', '_', '_'}; // create an array for the four attempts
// PINS ------------------------------------------------
// #define KEYPAD_PIN1 13
// #define KEYPAD_PIN2 12
// #define KEYPAD_PIN3 14
// #define KEYPAD_PIN4 27
// #define KEYPAD_PIN5 26
// #define KEYPAD_PIN6 25
// #define KEYPAD_PIN7 33
// #define KEYPAD_PIN8 32
// for simulator-------------------------------------------------
// byte rowPins[ROWS] = {17, 16, 15, 14}; //connect to the row pinouts of the keypad
// byte colPins[COLS] = {13, 12, 11, 10}; //connect to the column pinouts of the keypad
#define KEYPAD_PIN1 10
#define KEYPAD_PIN2 11
#define KEYPAD_PIN3 12
#define KEYPAD_PIN4 13
#define KEYPAD_PIN5 14
#define KEYPAD_PIN6 15
#define KEYPAD_PIN7 16
#define KEYPAD_PIN8 17
// #define SSR_PIN1 16
// #define SSR_PIN2 17
// #define SSR_PIN3 5
// #define SSR_PIN4 18
// for simulator-------------------------------------------------
#define SSR_PIN1 18
#define SSR_PIN2 19
#define SSR_PIN3 20
#define SSR_PIN4 21
// OLED SH------------------------------------------------
// /* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
// #define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
// //#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
// #define SCREEN_WIDTH 128 // OLED display width, in pixels
// #define SCREEN_HEIGHT 64 // OLED display height, in pixels
// #define OLED_RESET -1 // QT-PY / XIAO/media/numan/New Volume/0 Backup 0/3 Laptop (dell latitude e7440)/backup 1 (6 Oct 2023)/snap/arduino/85/Arduino/libraries/PID
// Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// #define OLED_WHITE_COLOR SH110X_WHITE
// #define OLED_BLACK_COLOR SH110X_BLACK
// OLED SDD------------------------------------------------
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define OLED_WHITE_COLOR WHITE
#define OLED_BLACK_COLOR BLACK
// Keypad -------------------------------------------------
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {KEYPAD_PIN8, KEYPAD_PIN7, KEYPAD_PIN6, KEYPAD_PIN5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {KEYPAD_PIN4, KEYPAD_PIN3, KEYPAD_PIN2, KEYPAD_PIN1}; //connect to the column pinouts of the keypad
//Create an object of keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
#define PASSWORD_LENGTH 4
char PASSWORD[PASSWORD_LENGTH] = {'1', '2', '3', '4'}; // Put the wanted password keys here
char attempt[PASSWORD_LENGTH] = {0, 0, 0, 0}; // create an array for the four attempts
int z = 0;
// 'locks', 24x24px
const unsigned char lock_bitmap_24px [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0x00, 0xff, 0xfe, 0x00, 0x7f, 0xfc,
0x3c, 0x3f, 0xfc, 0x7e, 0x3f, 0xfc, 0x7e, 0x3f, 0xfc, 0x7e, 0x3f, 0xfc, 0x7e, 0x3f, 0xfc, 0x7e,
0x3f, 0xf0, 0x00, 0x0f, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07,
0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xf0, 0x00, 0x0f, 0xf8,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// 'lock (1)', 24x24px
const unsigned char unlock_bitmap_24px [] PROGMEM = {
0xff, 0xfe, 0x07, 0xff, 0xfc, 0x03, 0xff, 0xf8, 0x01, 0xff, 0xf0, 0x60, 0xff, 0xf0, 0xf0, 0xff,
0xf1, 0xf8, 0xff, 0xf1, 0xf8, 0xff, 0xf1, 0xf8, 0xff, 0xf1, 0xf8, 0xff, 0xf1, 0xf8, 0xc0, 0x00,
0xf8, 0x80, 0x00, 0x7f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f,
0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00,
0x00, 0x3f, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x7f
};
// 'hen', 64x64px
const unsigned char hen_bitmap_64px [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x63, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x36, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1c, 0xe1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x66, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x18, 0x00, 0x00, 0x38, 0x00,
0x00, 0x13, 0x00, 0x0c, 0x00, 0x00, 0x78, 0x00, 0x00, 0x13, 0x00, 0x06, 0x00, 0x00, 0xc8, 0x00,
0x00, 0x1f, 0x00, 0x03, 0x00, 0x03, 0x98, 0x00, 0x00, 0x0e, 0x00, 0x01, 0xe0, 0x0f, 0x1c, 0x00,
0x00, 0x06, 0x00, 0x60, 0xff, 0xfe, 0x06, 0x00, 0x00, 0x0c, 0x01, 0xe0, 0x0f, 0xf0, 0x04, 0x00,
0x00, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x00,
0x00, 0x08, 0x0c, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x08, 0x0c, 0x00, 0x03, 0xf0, 0x06, 0x00,
0x00, 0x08, 0x08, 0x00, 0x00, 0xfe, 0x06, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x06, 0x0c, 0x00,
0x00, 0x0c, 0x0c, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x06, 0x18, 0x00,
0x00, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x06, 0x06, 0x00, 0x08, 0x38, 0x30, 0x00,
0x00, 0x06, 0x07, 0x00, 0x0f, 0xf0, 0x60, 0x00, 0x00, 0x03, 0x03, 0x80, 0x07, 0x80, 0x60, 0x00,
0x00, 0x03, 0x80, 0xe0, 0x01, 0x80, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x78, 0x03, 0x00, 0xc0, 0x00,
0x00, 0x00, 0xe0, 0x1f, 0x0e, 0x01, 0x80, 0x00, 0x00, 0x00, 0x70, 0x07, 0xfc, 0x03, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x00, 0x70, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x03, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x80, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x61, 0xc1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xf3, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf0, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'smart', 64x64px
const unsigned char smart_poultry_farm_bitmap_64px [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x07, 0x80, 0x00, 0x00,
0x00, 0x00, 0x03, 0x87, 0xe1, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0xf8, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x3f, 0x80, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfe, 0x00, 0x00,
0x00, 0x01, 0xf8, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00,
0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
0x00, 0x18, 0x0f, 0xff, 0xff, 0xf0, 0x18, 0x00, 0x00, 0x38, 0x0f, 0xff, 0xff, 0xf0, 0x1c, 0x00,
0x00, 0x70, 0x0c, 0x01, 0x80, 0x30, 0x0e, 0x00, 0x00, 0xe0, 0x0c, 0x01, 0x80, 0x30, 0x07, 0x00,
0x01, 0xc0, 0x0c, 0x01, 0x80, 0x30, 0x03, 0x80, 0x03, 0x80, 0x0c, 0x01, 0x80, 0x30, 0x01, 0xc0,
0x07, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0xe0, 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0xf0,
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
0x03, 0x0f, 0x8f, 0xff, 0xff, 0xff, 0xf0, 0xc0, 0x03, 0x0f, 0x8f, 0xff, 0xff, 0xff, 0xf0, 0xc0,
0x03, 0x1f, 0x80, 0x07, 0xe0, 0x00, 0x30, 0xc0, 0x03, 0x3c, 0xc0, 0x0f, 0xf0, 0x00, 0x30, 0xc0,
0x03, 0x3c, 0xc0, 0x1d, 0xb8, 0x00, 0x30, 0xc0, 0x03, 0x0e, 0xc0, 0x01, 0x9c, 0x00, 0x30, 0xc0,
0x03, 0x06, 0x60, 0x01, 0x8e, 0x00, 0x30, 0xc0, 0x03, 0x06, 0x63, 0xc1, 0x87, 0x00, 0x30, 0xc0,
0x03, 0x0e, 0x7f, 0xc1, 0x83, 0x80, 0x30, 0xc0, 0x03, 0x1c, 0x7e, 0xe1, 0x81, 0xc0, 0x30, 0xc0,
0x03, 0x18, 0x18, 0x61, 0x80, 0xe0, 0x30, 0xc0, 0x03, 0x18, 0x00, 0x61, 0x80, 0x70, 0x30, 0xc0,
0x03, 0x19, 0xc0, 0x61, 0x80, 0x38, 0x30, 0xc0, 0x03, 0x18, 0xfc, 0xe1, 0x80, 0x1c, 0x30, 0xc0,
0x03, 0x1c, 0x79, 0xc1, 0x80, 0x0e, 0x30, 0xc0, 0x03, 0x0e, 0x01, 0x81, 0x80, 0x07, 0x30, 0xc0,
0x03, 0x07, 0x03, 0x81, 0x80, 0x03, 0xb0, 0xc0, 0x03, 0x03, 0x87, 0x01, 0x80, 0x01, 0xf0, 0xc0,
0x03, 0x01, 0xfe, 0x01, 0x80, 0x00, 0xf0, 0xc0, 0x03, 0x00, 0xfc, 0x01, 0x80, 0x00, 0x70, 0xc0,
0x03, 0xf8, 0x30, 0x7f, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xf8, 0x30, 0x7f, 0xff, 0xff, 0xff, 0xc0,
0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'fan_bitmap', 16x16px
const unsigned char fan_bitmap_16px [] PROGMEM = {
0x00, 0x00, 0x06, 0x18, 0x05, 0x00, 0x04, 0x80, 0x04, 0x9f, 0x07, 0x80, 0x3e, 0xfc, 0x4c, 0x44,
0x8c, 0x48, 0xfe, 0xf0, 0x07, 0x80, 0x04, 0x9f, 0x04, 0x80, 0x02, 0x80, 0x01, 0x98, 0x00, 0x00
};
// 'thermometer_bitmap', 16x16px
const unsigned char thermometer_bitmap_16px [] PROGMEM = {
0x01, 0x80, 0x02, 0x40, 0x02, 0x5c, 0x02, 0x40, 0x02, 0x48, 0x02, 0x40, 0x02, 0x40, 0x02, 0x5c,
0x06, 0x60, 0x0d, 0xb0, 0x0b, 0xd0, 0x0b, 0xd0, 0x0b, 0xd0, 0x09, 0x90, 0x06, 0x60, 0x03, 0xc0
};
// 'humidity_bitmap', 16x16px
const unsigned char humidity_bitmap_16px [] PROGMEM = {
0x02, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x09, 0x80, 0x10, 0x80, 0x30, 0x00, 0x60, 0x00, 0x40, 0xee,
0xc1, 0xbb, 0x80, 0x00, 0x8e, 0xee, 0xdb, 0xbb, 0x40, 0x00, 0x60, 0x40, 0x39, 0xc0, 0x0f, 0x80
};
// 'Disconnect', 16x16px
const unsigned char disconnect_bitmap_16px [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0x03, 0xfb, 0x33, 0xf1, 0xf3, 0xf8, 0xe3, 0xfc, 0x67,
0xe6, 0x3f, 0xc7, 0x1f, 0xcf, 0x8f, 0xcc, 0xdf, 0xc0, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff
};
// OLED Display Functions ------------------------------------------------
void display_pass() {
display.setTextSize(2);
display.setCursor(z * 15, 25);
display.println("*");
display.display();
}
void display_border() {
display.drawRect(0, 0, 128, 64, OLED_WHITE_COLOR);
// display.drawRoundRect(0, 0, 128, 64, 4, OLED_WHITE_COLOR);
}
void display_setpoint() {
display.clearDisplay();
display.setTextSize(2);
display.setCursor(20, 10);
display.println("SP temp");
display.setCursor(10, 40);
display.print("[ ");
for (int i = 0; i < 4; i++) {
display.print(attempt_setpoint[i]);
}
display.println(" ]");
display.display();
}
void display_key_msg(String msg) {
display.setTextSize(1);
display.setCursor(15, 45);
display.println(msg);
display.display();
delay(2000);
}
void display_fan(int x, int y, int fan_number, int fan_state) {
display.setTextColor(OLED_WHITE_COLOR); // set text color
display.setTextSize(1);
display.drawBitmap(x, y, fan_bitmap_16px, 16, 16, 1);
display.setCursor(x, y + 20); // set position to display (x,y)
display.print("Fan");
display.println(fan_number);
display.fillRoundRect(x + 28, y + 8, 22, 10, 2, OLED_WHITE_COLOR);
display.setTextColor(OLED_BLACK_COLOR, OLED_WHITE_COLOR); // 'inverted' text
display.setCursor(x + 30, y + 10); // set position to display (x,y)
if (fan_state == 0) {
display.println("OFF"); // set text
} else {
display.println("ON"); // set text
}
}
void display_temperature_sensor(int x, int y, int sensor_number, float temperature) {
display.setTextColor(OLED_WHITE_COLOR); // set text color
display.setTextSize(1);
display.drawBitmap(x, y, thermometer_bitmap_16px, 16, 16, 1);
display.setCursor(x, y + 20); // set position to display (x,y)
display.print("Temp");
display.println(sensor_number); // set text
// disconnect_bitmap_16px
if (temperature == -127.0) {
display.drawBitmap(x + 35, y + 5, disconnect_bitmap_16px, 16, 16, 1);
} else {
display.fillRoundRect(x + 28, y + 8, 27, 10, 2, OLED_WHITE_COLOR);
display.setTextColor(OLED_BLACK_COLOR, OLED_WHITE_COLOR); // 'inverted' text
display.setCursor(x + 30, y + 10); // set position to display (x,y)
display.println(temperature, 1); // set text
}
}
void display_humidity_sensor(int x, int y, int sensor_number, float humidity) {
display.setTextColor(OLED_WHITE_COLOR); // set text color
display.setTextSize(1);
display.drawBitmap(x, y, humidity_bitmap_16px, 16, 16, 1); //good1
display.setCursor(x, y + 20); // set position to display (x,y)
display.print("Hum");
display.println(sensor_number); // set text
if (humidity >= 0 && humidity <= 100) {
display.fillRoundRect(x + 28, y + 8, 22, 10, 2, OLED_WHITE_COLOR);
display.setTextColor(OLED_BLACK_COLOR, OLED_WHITE_COLOR); // 'inverted' text
display.setCursor(x + 30, y + 10); // set position to display (x,y)
display.print(humidity, 1); // set text
display.println("%"); // set text
} else {
display.drawBitmap(x + 35, y + 5, disconnect_bitmap_16px, 16, 16, 1);
}
}
void display_sensor_setpoint(String sensor, float sensor_value, float sensor_setpoint, char unit) {
display.setTextColor(OLED_WHITE_COLOR); // set text color
display.setTextSize(2);
//sp and pv
display.setCursor(40, 10);
display.println(sensor);
display.setTextSize(1);
display.setCursor(35, 35);
display.print("PV : ");
display.print(sensor_value, 1);
display.println(unit);
display.setCursor(35, 45);
display.print("SP : ");
display.print(sensor_setpoint, 1);
display.println(unit);
}
void updateDisplay() {
static int state = 0; // Keeps track of which display state we are in
display.clearDisplay(); // clear display
display_border();
switch (state) {
case 0:
display.drawLine(0, 32, display.width() - 1, 32, OLED_WHITE_COLOR);
display.drawLine(64, 0, 64, display.height() - 1, OLED_WHITE_COLOR);
display_fan(5, 2, 1, digitalRead(SSR_PIN1));
display_fan(5, 35, 2, digitalRead(SSR_PIN2));
display_fan(70, 2, 3, digitalRead(SSR_PIN3));
display_fan(70, 35, 4, digitalRead(SSR_PIN4));
break;
case 1:
display.drawLine(0, 32, display.width() - 1, 32, OLED_WHITE_COLOR);
display.drawLine(64, 0, 64, display.height() - 1, OLED_WHITE_COLOR);
display_temperature_sensor(5, 2, 1, ds18b20_SensorDataArray[0].tempC);
display_temperature_sensor(5, 35, 2, ds18b20_SensorDataArray[1].tempC);
display_temperature_sensor(70, 2, 3, ds18b20_SensorDataArray[2].tempC);
display_temperature_sensor(70, 35, 4, ds18b20_SensorDataArray[3].tempC);
break;
case 2:
display.drawLine(0, 32, display.width() - 1, 32, OLED_WHITE_COLOR);
display.drawLine(64, 0, 64, display.height() - 1, OLED_WHITE_COLOR);
display_humidity_sensor(5, 2, 1, dht11_SensorDataArray[0].humidity);
display_humidity_sensor(5, 35, 2, dht11_SensorDataArray[1].humidity);
display_humidity_sensor(70, 2, 3, dht11_SensorDataArray[2].humidity);
display_humidity_sensor(70, 35, 4, dht11_SensorDataArray[3].humidity);
break;
case 3:
display_sensor_setpoint("Temp", average_temperature, temperature_setpoint, 'C');
break;
case 4:
display_sensor_setpoint("Hum", average_humidity, humidity_setpoint, '%');
break;
}
display.display();
// Increment state and loop back to 0 if greater than 4
state = (state + 1) % 5;
}
// Keypad Functions ------------------------------------------------
void correctKEY() { // do this if the correct KEY is entered
display.drawBitmap(55, 10, lock_bitmap_24px, 24, 24, 1);
// display_key_msg("KEY ACCEPTED");
display_key_msg("Correct Password");
state = "input_setpoint";
}
void incorrectKEY() { // do this if an incorrect KEY is entered
display.drawBitmap(55, 10, unlock_bitmap_24px, 24, 24, 2);
// display_key_msg("KEY REJECTED!");
display_key_msg("Incorrect Password");
state = "output";
}
void checkKEY() {
int correct = 0;
//loop to let users enter four keys
for (int i = 0; i < PASSWORD_LENGTH ; i++ ) {
//compare the entered key with the password
if (attempt[i] == PASSWORD[i]) {
correct++; // incease it, whenever there is a correct key
}
}
// if the correct keys become four keys do ...
if (correct == PASSWORD_LENGTH) {
correctKEY();
} else {
incorrectKEY();
}
// clear previous key input
for (int zz = 0; zz < PASSWORD_LENGTH; zz++) {
attempt[zz] = 0;
}
}
void readKeypad(String for_why) {
if (for_why == "for_password")
{
char key = keypad.getKey();
if (key != NO_KEY)
{
switch (key)
{
case '*': // the password should be entered after this symbol
display.setTextSize(1); // set text size
display.setTextColor(OLED_WHITE_COLOR); // set text color
z = 0;
state = "input";
break;
case '#': // the password should be finished by this symbol
if (state == "input")
{
// delay(100); // added debounce
display.clearDisplay();
// display.display();
if (z == PASSWORD_LENGTH)
{
checkKEY(); // call this function
}
else
{
incorrectKEY();
}
z = 0;
break;
}
default:
if (state == "input")
{
attempt[z] = key;
z++;
if (z == 1)
{
display.clearDisplay();
}
display_pass();
// Serial.println("*");
}
}
}
}
else if (for_why == "for_control")
{
char key = keypad.getKey();
if (key != NO_KEY)
{
switch (key)
{
case '#'://-----------------------------------
display.clearDisplay();
state = "output";
delay(100); // added debounce
for (int i = 0; i < 4; i++)
{
attempt_setpoint[i] = '_';
}
new_setpoint = 0;
break;
default://-----------------------------------
if (z2 == 2)
{
attempt_setpoint[z2] = '.';
attempt_setpoint[z2 + 1] = key;
String neww = "0.#";
neww[2] = key;
float temp = neww.toFloat();
new_setpoint += temp;
temperature_setpoint = new_setpoint;
Setpoint = temperature_setpoint;
for (int i = 0; i < 4; i++)
{
attempt_setpoint[i] = '_';
}
z2 = 0;
new_setpoint = 0;/////////
state = "output";
break;
}
else
{
attempt_setpoint[z2] = key;
String temp_str = "0";
temp_str[0] = key;
int newint = temp_str.toInt();
if (new_setpoint == 0)
{
new_setpoint += newint;
}
else
{
new_setpoint *= 10;
new_setpoint += newint;
}
z2++;
}
display.clearDisplay();
display_setpoint();
// Serial.println("*");
}
}
display_setpoint();
}
}
// ========================= Void Setup ============================
void setup() {
Serial.begin(115200);
// Relays Pin Configuration-----------------------
pinMode(SSR_PIN1, OUTPUT);
pinMode(SSR_PIN2, OUTPUT);
pinMode(SSR_PIN3, OUTPUT);
pinMode(SSR_PIN4, OUTPUT);
digitalWrite(SSR_PIN1, LOW);
digitalWrite(SSR_PIN2, LOW);
digitalWrite(SSR_PIN3, LOW);
digitalWrite(SSR_PIN4, LOW);
// PI Controller Configuration--------------------
Setpoint = temperature_setpoint;
//turn the PID on
myPID.SetMode(AUTOMATIC);
// OLED Display Configuration---------------------
// display.begin(i2c_Address, true); // Address 0x3C default
// // initialize OLED display with I2C address 0x3C
// if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
// Serial.println(F("failed to start SSD1306 OLED"));
// while (1);
// }
// OLED SDD1306--------------------------------------------------
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
// Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.fillRoundRect(10, 15, 50, 40, 4, OLED_WHITE_COLOR);
display.setTextSize(1); // set text size
display.setTextColor(OLED_BLACK_COLOR); // set text color
display.setCursor(20, 25);
display.println("SMART");
display.setCursor(15, 35);
display.println("POULTRY");
// display.drawBitmap(35, 2, hen_bitmap_64px, 64, 64, 1);
display.drawBitmap(64, 2, smart_poultry_farm_bitmap_64px, 64, 64, 1);
display.setTextColor(OLED_WHITE_COLOR);
display.display();
// DS18B20 Configuration--------------------------
sensors.begin();
// DHT11 Configuration----------------------------
for (int i = 0; i < NUM_DHT11_SENSORS; i++) {
dht[i].begin();
}
}
// ========================= Void Loop ============================
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis_for_reading_sensors >= interval_for_reading_sensors) {
previousMillis_for_reading_sensors = currentMillis;
reading_ds18b20_sensors();
reading_dht11_sensors();
float sum = 0.0;
for (int i = 0; i < NUM_DS18B20_SENSORS; i++) {
sum += ds18b20_SensorDataArray[i].tempC;
}
average_temperature = sum / NUM_DS18B20_SENSORS;
sum = 0.0;
for (int i = 0; i < NUM_DHT11_SENSORS; i++) {
sum += dht11_SensorDataArray[i].humidity;
}
average_humidity = sum / NUM_DHT11_SENSORS;
Input = average_temperature;
myPID.Compute();
// Relay Control with Pi controller---------------
if (Output > 0) {
if (Output > 30) {
digitalWrite(SSR_PIN4, HIGH);
} else if (Output > 20) {
digitalWrite(SSR_PIN3, HIGH);
digitalWrite(SSR_PIN4, LOW);
} else if (Output > 10) {
digitalWrite(SSR_PIN2, HIGH);
digitalWrite(SSR_PIN3, LOW);
digitalWrite(SSR_PIN4, LOW);
} else {
digitalWrite(SSR_PIN1, HIGH);
digitalWrite(SSR_PIN2, LOW);
digitalWrite(SSR_PIN3, LOW);
digitalWrite(SSR_PIN4, LOW);
}
} else {
digitalWrite(SSR_PIN1, LOW);
digitalWrite(SSR_PIN2, LOW);
digitalWrite(SSR_PIN3, LOW);
digitalWrite(SSR_PIN4, LOW);
}
}
// State Management-------------------------------
if (state == "input_setpoint")
{
readKeypad("for_control");
}
else {
readKeypad("for_password");
if (state == "output") {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis_for_updating_display >= interval_for_updating_display) {
previousMillis_for_updating_display = currentMillis;
updateDisplay();
}
}
}
}
esp:0
esp:1
esp:2
esp:3
esp:4
esp:5
esp:6
esp:7
esp:8
esp:9
esp:10
esp:11
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:20
esp:21
esp:26
esp:33
esp:34
esp:35
esp:36
esp:37
esp:38
esp:39
esp:40
esp:41
esp:42
esp:45
esp:46
esp:3V3
esp:5V
esp:GND.1
esp:TX
esp:RX
esp:RST
esp:GND.2
Loading
ds18b20
ds18b20
Loading
ds18b20
ds18b20
Loading
ds18b20
ds18b20
Loading
ds18b20
ds18b20
r1:1
r1:2
dht1:VCC
dht1:SDA
dht1:NC
dht1:GND
dht2:VCC
dht2:SDA
dht2:NC
dht2:GND
dht3:VCC
dht3:SDA
dht3:NC
dht3:GND
dht4:VCC
dht4:SDA
dht4:NC
dht4:GND
r2:1
r2:2
r3:1
r3:2
r4:1
r4:2
r5:1
r5:2
Loading
ssd1306
ssd1306
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4
relay3:VCC
relay3:GND
relay3:IN
relay3:NC
relay3:COM
relay3:NO
relay4:VCC
relay4:GND
relay4:IN
relay4:NC
relay4:COM
relay4:NO
relay5:VCC
relay5:GND
relay5:IN
relay5:NC
relay5:COM
relay5:NO
relay6:VCC
relay6:GND
relay6:IN
relay6:NC
relay6:COM
relay6:NO