#include <LiquidCrystal_I2C.h>
// Define the I2C address and LCD size
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int buttonPin = 2; // Define the button pin
const int sotPin = 13; // Pin for SOT
const int eotPin = 12; // Pin for EOT
const int binPins[4] = {3, 4, 5, 6}; // Pins for BIN 1-4
const int increaseTimeButtonPin = 9; // Pin for the increase time button
const int decreaseTimeButtonPin = 10; // Pin for the decrease time button
const unsigned long sot_LH_time = 400;
//const unsigned long sot_HIGH_time = 200;
const unsigned long bin_LH_time = 400;
//const unsigned long eot_LH_time = 15;
const unsigned long LCD_time = 400; //LCDtime
const unsigned long bin_TIMEOUT = 1000; // Timeout for bin signals
const unsigned long eot_TIMEOUT = 1000; // Timeout for eot signal
int buttonState = 0; // Variable to store the button state
int lastButtonState = 0; // Variable to store the last button state
int increaseTimeButtonState = 0;
int lastIncreaseTimeButtonState = 0;
int decreaseTimeButtonState = 0;
int lastDecreaseTimeButtonState = 0;
unsigned long lcdUpdateTime = 0;
bool updatingLCD = false;
unsigned long testTime = 200; // Initial test time (in milliseconds)
const unsigned long minTestTime = 200; // Minimum test time
const unsigned long maxTestTime = 5000; // Maximum test time
unsigned long startTestTime = 0; // Variable to record the start time of the test
int errorstate = 0;
//setup-----------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(9600); // Initialize serial communication at 9600 baud rate
lcd.init(); // Initialize the LCD
lcd.backlight(); // Turn on LCD backlight
pinMode(buttonPin, INPUT); // Set button pin as input
pinMode(sotPin, OUTPUT); // Set SOT pin as output
pinMode(eotPin, INPUT); // Set EOT pin as input
for (int i = 0; i < 4; i++) {
pinMode(binPins[i], INPUT); // Set BIN pins as input
}
pinMode(increaseTimeButtonPin, INPUT); // Set increase time button pin as input
pinMode(decreaseTimeButtonPin, INPUT); // Set decrease time button pin as input
digitalWrite(sotPin, HIGH);
digitalWrite(eotPin, HIGH);
for (int i = 0; i < 4; i++) {
digitalWrite(binPins[i], HIGH);
}
// Display initial messages on LCD
lcd.setCursor(9, 0);
lcd.print("S:H");
for (int i = 0; i < 4; i++) {
lcd.setCursor(0, 0);
lcd.print("B1:");
lcd.print("H");
lcd.setCursor(5, 0);
lcd.print("B3:");
lcd.print("H");
lcd.setCursor(0, 1);
lcd.print("B2:");
lcd.print("H");
lcd.setCursor(5, 1);
lcd.print("B4:");
lcd.print("H");
}
lcd.setCursor(13, 0);
lcd.print("E:H");
lcd.setCursor(9, 1);
lcd.print("T");
lcd.print(testTime);
lcd.print("ms ");
}
//loop------------------------------------------------------------------------------------------------------
void loop() {
readButton();
if (buttonState == LOW && lastButtonState == HIGH) {
errorstate = 0;
initLCD();
while (errorstate == 0) {
if (checkAllSignalsHigh()) {
sendSOT();
receiveSignals();
errorstate = checkAfterReceive();
resetAllPins();
}
}
}
adjustTestTime();
lastButton();
}
//-------------------
void initLCD() {
// Display initial messages on LCD
lcd.clear();
lcd.setCursor(9, 0);
lcd.print("S:H");
for (int i = 0; i < 4; i++) {
lcd.setCursor(0, 0);
lcd.print("B1:");
lcd.print("H");
lcd.setCursor(5, 0);
lcd.print("B3:");
lcd.print("H");
lcd.setCursor(0, 1);
lcd.print("B2:");
lcd.print("H");
lcd.setCursor(5, 1);
lcd.print("B4:");
lcd.print("H");
}
lcd.setCursor(13, 0);
lcd.print("E:H");
lcd.setCursor(9, 1);
lcd.print("T");
lcd.print(testTime);
lcd.print("ms ");
}
//readAndlastButton----------------------------------------------------------------------------------------
void readButton() {
buttonState = digitalRead(buttonPin); // Read button state
increaseTimeButtonState = digitalRead(increaseTimeButtonPin); // Read increase time button state
decreaseTimeButtonState = digitalRead(decreaseTimeButtonPin); // Read decrease time button state
//Serial.println("1111");
}
void lastButton() {
lastButtonState = buttonState; // Save the current state as the last state
lastIncreaseTimeButtonState = increaseTimeButtonState; // Save the current state as the last state
lastDecreaseTimeButtonState = decreaseTimeButtonState; // Save the current state as the last state
}
//BeforeCondition-------------------------------------------------------------------------------------------
bool checkAllSignalsHigh() {
bool allHigh = true;
String lowSignals = "";
// Check if SOT, EOT, and BIN pins are all HIGH
if (digitalRead(sotPin) != HIGH) {
allHigh = false;
lowSignals += "SOT ";
}
if (digitalRead(eotPin) != HIGH) {
allHigh = false;
lowSignals += "EOT ";
}
for (int i = 0; i < 4; i++) {
if (digitalRead(binPins[i]) != HIGH) {
allHigh = false;
lowSignals += "BIN" + String(i + 1) + " ";
}
}
if (!allHigh) {
displayLowSignalMessage(lowSignals);
Serial.print("FOUND LOW SIGNAL : ");
Serial.println(lowSignals);
resetAllPins();
}
return allHigh;
}
//sendSOT---------------------------------------------------------------------------------------------------
void sendSOT() {
startTestTime = millis(); // Record the start time
digitalWrite(sotPin, LOW); // Set SOT to LOW
updateLCDs();
Serial.println("SOT: LOW");
delay(sot_LH_time); // Wait for SOT signal duration
digitalWrite(sotPin, HIGH); // Set SOT to HIGH
updateLCDs();
Serial.println("SOT: HIGH");
delay(testTime);
}
//receiveEOT,BINS-------------------------------------------------------------------------------------------
void receiveSignals() {
unsigned long startTime = millis();
bool binReceived[4] = {false, false, false, false};
bool multipleBinsLow = false;
String lowBins = ""; // For storing which bins are LOW
bool eotLow = false;
// Wait for EOT to go LOW
while (digitalRead(eotPin) != LOW) {
if (millis() - startTime >= eot_TIMEOUT) {
return;
}
}
// Wait for EOT to go LOW
while (millis() - startTime < eot_TIMEOUT) {
if (digitalRead(eotPin) == LOW) {
eotLow = true;
digitalWrite(eotPin, LOW);
updateLCDe();
Serial.println("EOT: LOW");
break;
}
//delay(1);
}
// Continue with checking BINs if no timeout
while (millis() - startTime < bin_TIMEOUT) {
for (int i = 0; i < 4; i++) {
if (digitalRead(binPins[i]) == LOW && !binReceived[i]) {
binReceived[i] = true;
// Set BIN pin to LOW and display on LCD
digitalWrite(binPins[i], LOW);
updateLCDb(i);
Serial.print("BIN");
Serial.print(i + 1);
Serial.println(": LOW");
// Wait for BIN LOW to HIGH duration
delay(bin_LH_time);
// Set both BIN and EOT to HIGH together
digitalWrite(binPins[i], HIGH);
digitalWrite(eotPin, HIGH);
// Update LCD for BIN and EOT
updateLCDe();
updateLCDb(i);
Serial.println("EOT: HIGH");
Serial.print("BIN");
Serial.print(i + 1);
Serial.println(": HIGH");
}
}
}
calculateTestTime(); // Calculate and display the elapsed test time
}
//AfterCondition--------------------------------------------------------------------------------------------
int checkAfterReceive() {
unsigned long startTime = millis();
bool binReceived[4] = {false, false, false, false};
String lowBins = ""; // For storing which bins are LOW
int lowBinCount = 0;
// Wait for EOT to go LOW and then HIGH again
bool eotWentLow = false;
while (millis() - startTime < eot_TIMEOUT) {
if (digitalRead(eotPin) == LOW) {
eotWentLow = true;
while (millis() - startTime < eot_TIMEOUT) {
if (digitalRead(eotPin) == HIGH) {
// EOT went low and then high
break;
}
delay(1); // Small delay to avoid excessive loop cycles
}
break;
}
//delay(1); // Small delay to avoid excessive loop cycles
}
if (!eotWentLow) {
// If EOT did not go low within the timeout period, exit the function
updateLCDt();
Serial.println("TEST TIMEOUT");
return 1;
}
// Continue with checking BINs if no timeout
startTime = millis();
while (millis() - startTime < bin_TIMEOUT) {
for (int i = 0; i < 4; i++) {
if (digitalRead(binPins[i]) == LOW && !binReceived[i]) {
binReceived[i] = true;
lowBinCount++;
if (lowBinCount >= 2) {
lowBins += "BIN" + String(i + 1) + " "; // Append BIN index to lowBins
displayMultipleBinMessage(lowBins);
Serial.print("MULTIPLE BIN: ");
Serial.println(lowBins);
return 1; // Stop function when displaying Multiple BIN message
} else {
lowBins = "BIN" + String(i + 1) + " "; // Initialize lowBins with first LOW BIN
}
}
}
//delay(1); // Small delay to avoid excessive loop cycles
}
// Check if no BIN signals went low during the EOT low period
if (lowBinCount == 0) {
displayNoBINMessage();
Serial.println("NO BIN");
return 1;
}
// Ensure that the BIN signals are displayed properly
for (int i = 0; i < 4; i++) {
if (binReceived[i]) {
updateLCDb(i);
}
}
return 0;
}
//resetSOT,EOT,BINS-----------------------------------------------------------------------------------------
void resetAllPins() {
digitalWrite(sotPin, HIGH);
digitalWrite(eotPin, HIGH);
for (int i = 0; i < 4; i++) {
digitalWrite(binPins[i], HIGH);
}
if (errorstate == 0) {
lcd.clear();
lcd.setCursor(9, 0);
lcd.print("S:H");
for (int i = 0; i < 4; i++) {
lcd.setCursor(0, 0);
lcd.print("B1:");
lcd.print("H");
lcd.setCursor(5, 0);
lcd.print("B3:");
lcd.print("H");
lcd.setCursor(0, 1);
lcd.print("B2:");
lcd.print("H");
lcd.setCursor(5, 1);
lcd.print("B4:");
lcd.print("H");
}
lcd.setCursor(13, 0);
lcd.print("E:H");
updateTestTimeOnLCD();
}
}
//+,-testtime----------------------------------------------------------------------------------------------
void adjustTestTime() {
if (increaseTimeButtonState == LOW && lastIncreaseTimeButtonState == HIGH) {
increaseTestTime();
updateTestTimeOnLCD();
}
if (decreaseTimeButtonState == LOW && lastDecreaseTimeButtonState == HIGH) {
decreaseTestTime();
updateTestTimeOnLCD();
}
}
void increaseTestTime() {
if (testTime < maxTestTime) {
testTime += 100; // Increase test time by 500 ms
}
Serial.print("Test time increased to: ");
Serial.print(testTime);
Serial.println(" ms");
}
void decreaseTestTime() {
if (testTime > minTestTime) {
testTime -= 100; // Decrease test time by 500 ms
}
Serial.print("Test time decreased to: ");
Serial.print(testTime);
Serial.println(" ms");
}
void updateTestTimeOnLCD() {
lcd.setCursor(9, 1);
lcd.print("T");
delay(300);
lcd.print(testTime);
lcd.print("ms "); // Extra spaces to clear any leftover digits
}
//LCDtoALARM------------------------------------------------------------------------------------------------
void displayLowSignalMessage(const String& lowSignals) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("FOUND LOW SIGNAL");
lcd.setCursor(0, 1);
lcd.print(lowSignals);
updatingLCD = true;
lcdUpdateTime = millis();
delay(LCD_time);
}
void displayMultipleBinMessage(const String& lowBins) {
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("MULTIPLE BIN");
lcd.setCursor(0, 1);
lcd.print(lowBins);
updatingLCD = true;
lcdUpdateTime = millis();
delay(LCD_time);
}
void displayNoBINMessage() {
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("NO BIN");
updatingLCD = true;
lcdUpdateTime = millis();
delay(LCD_time);
}
void updateLCDt() {
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("TEST TIMEOUT");
updatingLCD = true;
lcdUpdateTime = millis();
delay(LCD_time);
}
//LCDtoSOT,EOT,BINS-----------------------------------------------------------------------------------------
void updateLCDs() {
lcd.setCursor(9, 0);
if (digitalRead(sotPin) == HIGH) {
lcd.print("S:H");
} else {
lcd.print("S:L");
}
}
void updateLCDb(int binIndex) {
// Set the cursor based on the BIN index
switch (binIndex) {
case 0: // BIN1
lcd.setCursor(0, 0);
break;
case 1: // BIN2
lcd.setCursor(0, 1);
break;
case 2: // BIN3
lcd.setCursor(5, 0);
break;
case 3: // BIN4
lcd.setCursor(5, 1);
break;
}
// Display the BIN status
lcd.print("B");
lcd.print(binIndex + 1); // Print BIN index as 1-4
if (digitalRead(binPins[binIndex]) == HIGH) {
lcd.print(":H");
} else {
lcd.print(":L");
}
}
void updateLCDe() {
lcd.setCursor(13, 0);
if (digitalRead(eotPin) == HIGH) {
lcd.print("E:H");
} else {
lcd.print("E:L");
}
}
//AlltestTime-----------------------------------------------------------------------------------------------
void calculateTestTime() {
unsigned long endTime = millis();
unsigned long elapsedTestTime = endTime - startTestTime;
// Check the state of the BIN pins
int activeBinCount = 0;
for (int i = 0; i < 4; i++) {
if (digitalRead(binPins[i]) == LOW) { // Assuming LOW indicates an active BIN
activeBinCount++;
}
}
// Only display test time if exactly one BIN is active
if (activeBinCount == 1) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("TestTime: ");
lcd.print(elapsedTestTime);
lcd.print("ms");
Serial.print("Test Time: ");
Serial.print(elapsedTestTime);
Serial.println(" ms");
}
}