/*
File : Digital Timer
Author : leveletech.com / wa 081214584114
Date : 2024 03 04
Description : Digital Timer
*/
//--------------------------------- Include Libraries-----------------------------------------------
#include <LiquidCrystal_I2C.h>
#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>
//--------------------------------- Include Libraries-----------------------------------------------
//--------------------------------- Hardware Setting------------------------------------------------
//--------------------------------- Hardware Setting------------------------------------------------
//--------------------------------- Define and Constant---------------------------------------------
//--------------------------------- Define and Constant---------------------------------------------
//--------------------------------- User Define Data Type-------------------------------------------
struct timer_data {
bool IN;
bool Q;
bool BP1; //button pressed
bool BP2; //button pressed
int PT; //preset time
int ET; //elapsed time
unsigned long TN; //time now
};
//--------------------------------- User Define Data Type-------------------------------------------
//----------------------------------Global Variable-------------------------------------------------
LiquidCrystal_I2C lcd(0X27, 20, 4);
// Assign push button pins
const int buttonPins[] = { 2, 3, 4, 5, 6, 7, 8 }; // Array of pins for buttons
const int numButtons = 7; // Number of buttons
bool lastButtonState[numButtons] = { false, false, false, false, false, false, false };
// Assign relay pins
const int relayPins[] = { 48, 49, 50, 51, 52, 53, 46 }; // Array of pins for relays
const int numRelays = 7; // Number of relays
bool S[8] = { false, false, false, false, false, false, false, false };
bool S_P[8] = { false, false, false, false, false, false, false, false };
bool R[8] = { false, false, false, false, false, false, false, false };
bool B[8] = { false, false, false, false, false, false, false, false };
bool BM[8] = { false, false, false, false, false, false, false, false };
unsigned long lastDebounceTime[numButtons]; // Array to store the last debounce time for each button
const unsigned long debounceDelay = 50; // Debounce delay in milliseconds
timer_data T[8]; //TON
char data = 0;
//modsbus
modbusDevice regBank;
modbusSlave slave;
//----------------------------------Global Variable-------------------------------------------------
//----------------------------------User Defined Function Stage 1-----------------------------------
void TON(timer_data& Var) { //Timer On delay function
if (Var.IN) {
if (!Var.BP1) {
Var.TN = millis();
Var.BP1 = true;
}
if (!Var.Q) {
Var.ET = (millis() - Var.TN) / 1000;
if (Var.ET >= Var.PT) Var.Q = true;
}
} else {
Var.Q = false;
Var.BP1 = false;
Var.ET = 0;
}
}
void DI_Update() {
for (int i = 0; i < numButtons; i++) {
// Read the current state of the button
int currentState = digitalRead(buttonPins[i]);
// Check if the button state has changed and debounce it
if (currentState != lastButtonState[i]) {
// Reset the debounce timer
lastDebounceTime[i] = millis();
}
// Check if enough time has passed to consider it a valid state change
if ((millis() - lastDebounceTime[i]) > debounceDelay) {
// If enough time has passed, update the state
S[i + 1] = !currentState;
}
// Store the current state for the next iteration
lastButtonState[i] = currentState;
}
}
void DO_Update() {
for (int i = 1; i < numRelays + 1; i++) {
digitalWrite(relayPins[i - 1], !R[i]);
}
}
void Timer_Update() {
for (int i = 1; i < numRelays + 1; i++) {
if (S[i] || B[i] || BM[i]) {
if (!S_P[i]) {
S_P[i] = true;
R[i] = !R[i];
LCD_Update();
}
} else {
S_P[i] = false;
}
T[i].IN = R[i];
TON(T[i]);
if (T[i].Q) {
R[i] = false;
LCD_Update();
}
}
}
String R_Status(bool status) {
if (status) {
return "ON ";
} else {
return "OFF";
}
}
void LCD_Update() {
lcd.setCursor(3, 0);
lcd.print("DIGITAL TIMER");
lcd.setCursor(0, 1);
lcd.print("R1:" + R_Status(R[1]) + " " + "R4:" + R_Status(R[4]) + " " + "R7:" + R_Status(R[7]));
lcd.setCursor(0, 2);
lcd.print("R2:" + R_Status(R[2]) + " " + "R5:" + R_Status(R[5]));
lcd.setCursor(0, 3);
lcd.print("R3:" + R_Status(R[3]) + " " + "R6:" + R_Status(R[6]));
}
void BT_Update() {
for (int i = 1; i < numRelays + 1; i++) {
B[i] = false;
}
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
for (int i = 1; i <= 7; i++) {
if (input == String(i)) {
B[i] = true;
break; // Exit the loop once the condition is met
}
// Check if input starts with "t1-"
if (input.startsWith(String("t") + String(i) + "-")) {
String valueStr = input.substring(3); // Extract numeric part after "t1-"
bool isNumeric = true;
// Check if all characters after "t1-" are numeric
for (size_t i = 0; i < valueStr.length(); i++) {
if (!isDigit(valueStr.charAt(i))) {
isNumeric = false;
break;
}
}
if (isNumeric) {
int value = valueStr.toInt(); // Convert the numeric part to an integer
// Do something with the value if needed
T[i].PT = value;
Serial.println(T[i].PT);
}
}
}
}
}
void Modbus_Update() {
for (int i = 1; i < numRelays + 1; i++) {
int DOx = regBank.get(i);
if (DOx <= 0) BM[i] = false;
if (DOx >= 1) BM[i] = true;
int myInt = R[i] ? 1 : 0;
regBank.set(10000 + i, myInt);
regBank.set(30000 + i, (T[i].PT) - T[i].ET);
word AOx = regBank.get(40000 + i);
T[i].PT = AOx;
//if (AOx != T[i].PT) {
// T[i].PT = AOx;
//regBank.set(40000 + i, T[i].PT);
// }
slave.run();
delay(10);
}
}
//----------------------------------User Defined Function Stage 1-----------------------------------
//----------------------------------User Defined Function Stage 2-----------------------------------
//----------------------------------User Defined Function Stage 2-----------------------------------
//----------------------------------User Defined Function Stage 3-----------------------------------
//----------------------------------User Defined Function Stage 3-----------------------------------
//----------------------------------Testing Function------------------------------------------------
//----------------------------------Testing Function------------------------------------------------
//--------------------------------- Setup----------------------------------------------
void setup() {
Serial.begin(9600);
//Serial1.begin(9600);
//Pin Initialization
// Initialize push button pins as inputs
for (int i = 0; i < numButtons; i++) {
pinMode(buttonPins[i], INPUT_PULLUP); // Using internal pull-up resistors
}
// Initialize relay pins as outputs
for (int i = 0; i < numRelays; i++) {
pinMode(relayPins[i], OUTPUT);
digitalWrite(relayPins[i], HIGH); // Turn off all relays initially Active Low
}
//Start Services
lcd.init();
lcd.backlight();
lcd.clear();
//Timer Initialization (dalam detik)
T[1].PT = 5; //
T[2].PT = 5; //
T[3].PT = 5; //
T[4].PT = 5; //
T[5].PT = 5; //
T[6].PT = 5; //
T[7].PT = 5; //
LCD_Update();
Serial.println("ok");
//modsbus
regBank.setId(1);
slave._device = ®Bank;
slave.setBaud(4800);
//Add Digital Output registers 00001-00016 to the register bank
//BM1-BM7
regBank.add(1);
regBank.add(2);
regBank.add(3);
regBank.add(4);
regBank.add(5);
regBank.add(6);
regBank.add(7);
//Add Digital Input registers 10001-10008 to the register bank
//R1-R7
regBank.add(10001);
regBank.add(10002);
regBank.add(10003);
regBank.add(10004);
regBank.add(10005);
regBank.add(10006);
regBank.add(10007);
//Add Analog Input registers 30001-30008 to the register bank
regBank.add(30001);
regBank.add(30002);
regBank.add(30003);
regBank.add(30004);
regBank.add(30005);
regBank.add(30006);
regBank.add(30007);
//Add Analog Output registers 40001-40020 to the register bank
//T[1].PT - T[7].PT
regBank.add(40001);
regBank.add(40002);
regBank.add(40003);
regBank.add(40004);
regBank.add(40005);
regBank.add(40006);
regBank.add(40007);
for (int i = 1; i < numRelays + 1; i++) {
regBank.set(40000 + i, T[i].PT);
}
}
//--------------------------------- Setup----------------------------------------------
//--------------------------------- Loop-----------------------------------------------
void loop() {
//Update Input
DI_Update();
BT_Update();
//Process Update
Timer_Update();
Modbus_Update();
//Update Output
DO_Update();
}
//--------------------------------- Loop-----------------------------------------------
//--------------------------------- Note-----------------------------------------------
/*
*/
//--------------------------------- Note-----------------------------------------------