#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// Define TFT Pins
#define TFT_CS 53 // Chip Select
#define TFT_RST 8 // Reset Pin
#define TFT_DC 9 // Data/Command Pin
#define TFT_SCK 52 // Clock Pin (SPI)
#define TFT_MISO 50 // MISO Pin (SPI)
#define TFT_MOSI 11 // MOSI Pin (SPI)
Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST, TFT_SCK, TFT_MISO, TFT_MOSI);
// Define analog pin for the potentiometer (simulating load cell)
#define LOAD_CELL_PIN A0
// Define inlet valves, alarm, and buffer actuator
#define INLET_VALVE_A 12
#define INLET_VALVE_B 13
#define INLET_VALVE_C 15
#define ALARM_PIN 2
#define BUFFER_ACTUATOR 16 // Buffer Feeding Actuator
// Define low and high-level sensors for tanks
#define LOW_SENSOR_A 33
#define HIGH_SENSOR_A 34
#define LOW_SENSOR_B 35
#define HIGH_SENSOR_B 36
#define LOW_SENSOR_C 37
#define HIGH_SENSOR_C 38
// Variables for target weights for each tank
const int TARGET_WEIGHT_A = 100; // 100kg for Tank A
const int TARGET_WEIGHT_B = 200; // 200kg cumulative for Tank B
const int TARGET_WEIGHT_C = 1000; // 1000kg (1MT) cumulative for Tank C
// Alarm flags
bool alarmTankALow = false;
bool alarmTankAHigh = false;
bool alarmTankBLow = false;
bool alarmTankBHigh = false;
bool alarmTankCLow = false;
bool alarmTankCHigh = false;
void setup() {
// Initialize Serial and TFT for debugging
Serial.begin(115200);
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
// Setup pin modes
pinMode(LOAD_CELL_PIN, INPUT);
pinMode(INLET_VALVE_A, OUTPUT);
pinMode(INLET_VALVE_B, OUTPUT);
pinMode(INLET_VALVE_C, OUTPUT);
pinMode(ALARM_PIN, OUTPUT);
pinMode(BUFFER_ACTUATOR, OUTPUT);
pinMode(LOW_SENSOR_A, INPUT);
pinMode(HIGH_SENSOR_A, INPUT);
pinMode(LOW_SENSOR_B, INPUT);
pinMode(HIGH_SENSOR_B, INPUT);
pinMode(LOW_SENSOR_C, INPUT);
pinMode(HIGH_SENSOR_C, INPUT);
// Initialize valves, actuator, and alarm to off
digitalWrite(INLET_VALVE_A, LOW);
digitalWrite(INLET_VALVE_B, LOW);
digitalWrite(INLET_VALVE_C, LOW);
digitalWrite(ALARM_PIN, LOW);
digitalWrite(BUFFER_ACTUATOR, LOW);
tft.setCursor(0, 0);
tft.print("System Initialized");
delay(2000);
tft.fillScreen(ILI9341_BLACK);
}
void loop() {
int loadValue = analogRead(LOAD_CELL_PIN); // Read load cell (potentiometer) value
int loadWeight = map(loadValue, 0, 1023, 0, 1000); // Map to a 0-1000 kg range
displayWeightAndAlarms(loadWeight);
updateAlarms(); // Check and update alarm flags
if (!checkLowLevelSensors()) {
activateAlarm("Low level! Check tanks.");
pauseBatching();
return;
}
controlInletValves(loadWeight);
controlBufferActuator(loadWeight);
delay(500);
}
// Function to display weight and alarms on the TFT
void displayWeightAndAlarms(int weight) {
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.print("Day Tank Weight:");
tft.setCursor(0, 30);
tft.print(weight);
tft.print(" kg");
int barLength = map(weight, 0, 1000, 0, 200); // Display weight in bar form
tft.fillRect(10, 60, barLength, 20, ILI9341_GREEN);
int yPosition = 100; // Start position for alarm messages
// Display alarm messages
if (alarmTankALow) {
tft.setCursor(10, yPosition);
tft.print("Tank A: Low Level");
yPosition += 20;
}
if (alarmTankAHigh) {
tft.setCursor(10, yPosition);
tft.print("Tank A: Turn Off Refill");
yPosition += 20;
}
if (alarmTankBLow) {
tft.setCursor(10, yPosition);
tft.print("Tank B: Low Level");
yPosition += 20;
}
if (alarmTankBHigh) {
tft.setCursor(10, yPosition);
tft.print("Tank B: Turn Off Refill");
yPosition += 20;
}
if (alarmTankCLow) {
tft.setCursor(10, yPosition);
tft.print("Tank C: Low Level");
yPosition += 20;
}
if (alarmTankCHigh) {
tft.setCursor(10, yPosition);
tft.print("Tank C: Turn Off Refill");
yPosition += 20;
}
if (!(alarmTankALow || alarmTankAHigh || alarmTankBLow || alarmTankBHigh || alarmTankCLow || alarmTankCHigh)) {
tft.setCursor(10, yPosition);
tft.print("No Alarms");
}
}
// Function to check and update alarm flags
void updateAlarms() {
alarmTankALow = digitalRead(LOW_SENSOR_A) == LOW;
alarmTankAHigh = digitalRead(HIGH_SENSOR_A) == HIGH;
alarmTankBLow = digitalRead(LOW_SENSOR_B) == LOW;
alarmTankBHigh = digitalRead(HIGH_SENSOR_B) == HIGH;
alarmTankCLow = digitalRead(LOW_SENSOR_C) == LOW;
alarmTankCHigh = digitalRead(HIGH_SENSOR_C) == HIGH;
}
// Function to check if low-level sensors detect fluid
bool checkLowLevelSensors() {
if (digitalRead(LOW_SENSOR_A) == LOW) return false;
if (digitalRead(LOW_SENSOR_B) == LOW) return false;
if (digitalRead(LOW_SENSOR_C) == LOW) return false;
return true;
}
// Function to control inlet valves based on target weights and sensor status
void controlInletValves(int weight) {
static bool fillingA = true;
static bool fillingB = false;
static bool fillingC = false;
if (fillingA && weight < TARGET_WEIGHT_A) {
if (digitalRead(LOW_SENSOR_A) == HIGH) {
digitalWrite(INLET_VALVE_A, HIGH);
}
} else if (fillingA) {
digitalWrite(INLET_VALVE_A, LOW);
fillingA = false;
fillingB = true;
}
if (fillingB && weight >= TARGET_WEIGHT_A && weight < TARGET_WEIGHT_B) {
if (digitalRead(LOW_SENSOR_B) == HIGH) {
digitalWrite(INLET_VALVE_B, HIGH);
}
} else if (fillingB) {
digitalWrite(INLET_VALVE_B, LOW);
fillingB = false;
fillingC = true;
}
if (fillingC && weight >= TARGET_WEIGHT_B && weight < TARGET_WEIGHT_C) {
if (digitalRead(LOW_SENSOR_C) == HIGH) {
digitalWrite(INLET_VALVE_C, HIGH);
}
} else if (fillingC && weight >= TARGET_WEIGHT_C) {
digitalWrite(INLET_VALVE_C, LOW);
fillingC = false; // Batch complete
tft.setCursor(0, 150);
tft.print("Batch Ready!");
}
}
// Function to control the buffer feeding actuator
void controlBufferActuator(int weight) {
if (weight >= TARGET_WEIGHT_C) {
digitalWrite(BUFFER_ACTUATOR, HIGH); // Open Buffer Feeding Actuator
} else {
digitalWrite(BUFFER_ACTUATOR, LOW); // Close Buffer Feeding Actuator
}
}
// Function to activate alarm
void activateAlarm(String message) {
digitalWrite(ALARM_PIN, HIGH);
tft.fillScreen(ILI9341_RED);
tft.setCursor(0, 0);
tft.print("ALARM: ");
tft.setCursor(0, 30);
tft.print(message);
delay(3000);
digitalWrite(ALARM_PIN, LOW);
}
// Function to pause batching process
void pauseBatching() {
digitalWrite(INLET_VALVE_A, LOW);
digitalWrite(INLET_VALVE_B, LOW);
digitalWrite(INLET_VALVE_C, LOW);
}