diff --git a/Script/common.py b/Script/common.py index 14b02da..9d128ee 100644 --- a/Script/common.py +++ b/Script/common.py @@ -31,3 +31,13 @@ CONFIG_UPDATE_AVAILABLE = True NO_CONFIG_UPDATE = False + +SWT_MODEL_SINGLE_TYPE_A = "Type-A" +SWT_MODEL_SINGLE_TYPE_D = "Type-D" +SWT_MODEL_DOUBLE_TYPE_B = "Type-B" +SWT_MODEL_DOUBLE_TYPE_C = "Type-C" +SWT_MODEL_DOUBLE_TYPE_E = "Type-E" + +LOOP_RTN_TYPE_ERROR = "error" +LOOP_RTN_TYPE_SW_CHANGE = "switch" + diff --git a/Script/doubleSwitch.py b/Script/doubleSwitch.py new file mode 100644 index 0000000..bfabd10 --- /dev/null +++ b/Script/doubleSwitch.py @@ -0,0 +1,318 @@ +from datetime import datetime +import time + +from lcd20x4 import Lcd20x4 +from rpigpio import RpiGpio + +from utility import * +from common import * +from pinDescription import * + + +# global hardware module library initilization +lcd = Lcd20x4(LCD_MODULE_ADDRESS, LCD_MODULE_NO_OF_COLUMN, LCD_MODULE_NO_OF_ROW) +gpio = RpiGpio() + + +# global variables +cycleIndexPos = 0 +cycleCounter = 0 +TotalCounter = 0 + +previousPosition = None +currentPosition = None + +ResetBtnReading = None +buttonState = None + +ResetTrigger = False +isConfigReadNeed = True +cycleIndexPosMiddle = False + +lastButtonState = HIGH +debounceDelay = 5000 +lastDebounceTime = 0 + + +# Introduction banner print +def startIntroPrint(): + lcd.write("SPRING LOADED", row = ROW_NO_0, center = True) + lcd.write("SWITCH TESTER", row = ROW_NO_1, center = True) + appVersion = getAppVersion() + print(f"Application version: {appVersion}") + lcd.write(f"Version: {appVersion}", row = ROW_NO_3, padding = True) + time.sleep(3) + lcd.clean() + time.sleep(0.5) + lcd.turnOffBacklight() + time.sleep(1) + lcd.turnOnBacklight() + time.sleep(1) + + +# This is the gpio initialization +def gpioInitialization(): + gpio.pinMode(ON_BOARD_LED_PIN, OUTPUT) + gpio.pinMode(GPIO_3V3_1_PIN, OUTPUT) + gpio.pinMode(GPIO_3V3_2_PIN, OUTPUT) + + gpio.pinMode(MICRO_SWITCH_S1_NC_PIN, INPUT, PULL_DOWN) + gpio.pinMode(MICRO_SWITCH_S1_NO_PIN, INPUT, PULL_DOWN) + gpio.pinMode(MICRO_SWITCH_S2_NC_PIN, INPUT, PULL_DOWN) + gpio.pinMode(MICRO_SWITCH_S2_NO_PIN, INPUT, PULL_DOWN) + + gpio.pinMode(POSITION_RIGHT_LED_PIN, OUTPUT) + gpio.pinMode(POSITION_MIDDLE_LED_PIN, OUTPUT) + gpio.pinMode(POSITION_LEFT_LED_PIN, OUTPUT) + + gpio.pinMode(MOTOR_ON_OFF_PIN, OUTPUT) + + gpio.pinMode(RESET_PUSH_SWITCH_PIN, INPUT) + + gpio.digitalWrite(GPIO_3V3_1_PIN, HIGH) + gpio.digitalWrite(GPIO_3V3_2_PIN, HIGH) + + gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) + + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + + +# Time print function +def printCurrentTime(row: int): + lcd.write(datetime.now().strftime('%I:%M:%S %p %d/%m/%y'), row = row, padding = True) + + +# Print the count value +def printCountValue(row: int, currentCount: int, totalCount: int): + lcd.write(f"Test:{currentCount}/{totalCount}", row = row, padding = True) + + +# Turn on only the position LED +def showPositionLED(position: int|None): + if position == POSITION_LEFT: + gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, HIGH) + + elif position == POSITION_RIGHT: + gpio.digitalWrite(POSITION_RIGHT_LED_PIN, HIGH) + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) + + elif position == POSITION_MIDDLE: + gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, HIGH) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) + + else: + gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) + + +# This is the void Setup() function just like Arduino code +def doubleSwitchSetup(model: str): + global cycleIndexPos + global previousPosition + global cycleCounter + global TotalCounter + + startIntroPrint() + print("Intro print done!") + gpioInitialization() + print("GPIO initialization done!") + + lcd.write(f"Model: {model}", row = ROW_NO_1, center = True) + + ################################################# + ## S1_NO S1_NC S2_NO S2_NC ## + ## LEFT 0 1 1 0 ## + ## MID 1 0 1 0 ## + ## RIGHT 1 0 0 1 ## + ################################################# + + if gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): + previousPosition = POSITION_LEFT + cycleIndexPos = POSITION_LEFT + print("Initial position: LEFT") + + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): + previousPosition = POSITION_MIDDLE + cycleIndexPos = POSITION_MIDDLE + print("Initial position: MIDDLE") + + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN): + previousPosition = POSITION_RIGHT + cycleIndexPos = POSITION_RIGHT + print("Initial position: RIGHT") + + ########## TEST BEGIN ############### + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN) and\ + gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN) and\ + gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): + previousPosition = POSITION_MIDDLE + cycleIndexPos = POSITION_MIDDLE + print("Probably No switch found; All pin are HIGH ... !!") + + if previousPosition == None and cycleIndexPos == None: + raise Exception("Something Wrong!! Not able to read switch position!!") + + ########## TEST END## ############### + + cycleCounter = getCycleCount() + TotalCounter = getTotalCount() + print(f"Current Counter: {cycleCounter}") + print(f"Max Counter : {TotalCounter}") + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + setCycleCount(cycleCounter) + + gpio.digitalWrite(ON_BOARD_LED_PIN, LOW) + + +# This is the void loop() function just like Arduino code +def doubleSwitchLoop(model: str): + global isConfigReadNeed + global previousPosition + global cycleIndexPos + global currentPosition + global cycleCounter + global TotalCounter + global cycleIndexPosMiddle + global ResetBtnReading + global lastButtonState + global debounceDelay + global buttonState + global ResetTrigger + global lastDebounceTime + + rtn = LOOP_RTN_TYPE_ERROR + switchModel = None + + while True: + motorStatus = getMotorControlStatus() + gpio.digitalWrite(MOTOR_ON_OFF_PIN, motorStatus) + printCurrentTime(ROW_NO_0) + + ################################################# + ## S1_NO S1_NC S2_NO S2_NC ## + ## LEFT 0 1 1 0 ## + ## MID 1 0 1 0 ## + ## RIGHT 1 0 0 1 ## + ################################################# + + # Reading the gpio pin for the switchs + if gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): + currentPosition = POSITION_LEFT + lcd.write("Position Left ", row = ROW_NO_2) + print("Position Left") + + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): + currentPosition = POSITION_MIDDLE + lcd.write("Position Middle", row = ROW_NO_2) + print("Position Middle") + + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN): + currentPosition = POSITION_RIGHT + lcd.write("Position Right ", row = ROW_NO_2) + print("Position Right") + + print("S1_NO:", gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN), end="\t") + print("S1_NC:", gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN), end="\t") + print("S2_NO:", gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN), end="\t") + print("S2_NC:", gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN)) + + # Turn on the postion LED + showPositionLED(currentPosition) + + # According to the position, update the count number + countUpdate = False + if currentPosition != previousPosition: + if currentPosition == POSITION_LEFT or currentPosition == POSITION_RIGHT: + if cycleIndexPos == currentPosition: + cycleCounter += 1 + countUpdate = True + elif currentPosition == POSITION_MIDDLE: + if cycleIndexPosMiddle and (cycleIndexPos == currentPosition): + cycleCounter += 1 + countUpdate = True + cycleIndexPosMiddle = not cycleIndexPosMiddle + else: + pass + + previousPosition = currentPosition + + # update current and total count value if config update avaialabe + if getConfigUpdateStatus() == CONFIG_UPDATE_AVAILABLE: + cycleCounter = getCycleCount() + TotalCounter = getTotalCount() + motorStatus = getMotorControlStatus() + switchModel = getSwitchModel() + setConfigUpdateStatus(NO_CONFIG_UPDATE) + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + gpio.digitalWrite(MOTOR_ON_OFF_PIN, motorStatus) + if switchModel != model: + # Switch model has changed + print("Switch model change detected.") + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + rtn = LOOP_RTN_TYPE_SW_CHANGE + break + + # Update the count in the LCD + if countUpdate: + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + setCycleCount(cycleCounter) + countUpdate = False + + # If reach the full count number then turn on the Finish LED + if cycleCounter >= TotalCounter: + gpio.digitalWrite(ON_BOARD_LED_PIN, HIGH) + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + setMotorControlStatus(LOW) + lcd.write("Count Finished!", row = ROW_NO_3, padding = True) + print("Count Finished!") + cycleCounter = 0 + + # Reset button debounce logic + ResetBtnReading = gpio.digitalRead(RESET_PUSH_SWITCH_PIN) + + if ResetBtnReading != lastButtonState: + lastDebounceTime = time.time() + + if ((time.time() - lastDebounceTime) * 1000) > debounceDelay: + if ResetBtnReading != buttonState: + buttonState = ResetBtnReading + + if buttonState == LOW: + lcd.write("Count Reseting...", row = ROW_NO_3, padding = True) + ResetTrigger = True + + lastButtonState = ResetBtnReading + + # If reset button pressed then clean the old stuffs + if ResetTrigger: + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + setMotorControlStatus(LOW) + cycleCounter = 0 + gpio.digitalWrite(ON_BOARD_LED_PIN, LOW) + setCycleCount(cycleCounter) + ResetTrigger = False + time.sleep(2) + lcd.write(" "*LCD_MODULE_NO_OF_COLUMN, row = ROW_NO_3) + time.sleep(1) + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + + # Return the loop status + return rtn, switchModel + +# Entry point main function +def main(): + print("Entering initial setup.") + doubleSwitchSetup(SWT_MODEL_DOUBLE_TYPE_B) + print("Entering main loop.") + doubleSwitchLoop(SWT_MODEL_DOUBLE_TYPE_B) + + +if __name__ == "__main__": + main() diff --git a/Script/lcd20x4.py b/Script/lcd20x4.py index cbcbab2..321bbff 100644 --- a/Script/lcd20x4.py +++ b/Script/lcd20x4.py @@ -1,4 +1,8 @@ -from RPLCD.i2c import CharLCD +try: + from RPLCD.i2c import CharLCD +except ImportError: + print("RPLCD module not found. Please install it using 'pip install RPLCD'.") + CharLCD = None class Lcd20x4: def __init__(self, i2cAddress: int, column: int, row: int): @@ -12,21 +16,27 @@ def __init__(self, i2cAddress: int, column: int, row: int): def init(self): - self._lcd = CharLCD( - i2c_expander = 'PCF8574', - address = self.i2cAddress, - port = self.port, - cols = self.columns, - rows = self.rows, - dotsize = self.dotSize) + try: + self._lcd = CharLCD( + i2c_expander = 'PCF8574', + address = self.i2cAddress, + port = self.port, + cols = self.columns, + rows = self.rows, + dotsize = self.dotSize) + except Exception as e: + print(f"Error initializing LCD: {e}") + self._lcd = None self.clean() def clean(self): - self._lcd.clear() + if self._lcd: + self._lcd.clear() def setLcdCursor(self, row: int, column: int): - self._lcd.cursor_pos = (row, column) + if self._lcd: + self._lcd.cursor_pos = (row, column) def write(self, @@ -54,13 +64,17 @@ def write(self, if row != -1: self.setLcdCursor(row, column) - - self._lcd.write_string(text) + if self._lcd: + self._lcd.write_string(text) + else: + print(f"LCD: {text}") def turnOffBacklight(self): - self._lcd.backlight_enabled = False + if self._lcd: + self._lcd.backlight_enabled = False def turnOnBacklight(self): - self._lcd.backlight_enabled = True + if self._lcd: + self._lcd.backlight_enabled = True diff --git a/Script/main.py b/Script/main.py index ad5b019..5a1ae19 100644 --- a/Script/main.py +++ b/Script/main.py @@ -1,303 +1,54 @@ -from datetime import datetime -import time +from common import * +from utility import * +from doubleSwitch import * +from singleSwitch import * -from lcd20x4 import Lcd20x4 -from rpigpio import RpiGpio - -from utility import * -from common import * -from pinDescription import * - - -# global hardware module library initilization -lcd = Lcd20x4(LCD_MODULE_ADDRESS, LCD_MODULE_NO_OF_COLUMN, LCD_MODULE_NO_OF_ROW) -gpio = RpiGpio() - - -# global variables -cycleIndexPos = 0 -cycleCounter = 0 -TotalCounter = 0 - -previousPosition = None -currentPosition = None - -ResetBtnReading = None -buttonState = None - -ResetTrigger = False -isConfigReadNeed = True -cycleIndexPosMiddle = False - -lastButtonState = HIGH -debounceDelay = 5000 -lastDebounceTime = 0 - - -# Introduction banner print -def startIntroPrint(): - lcd.write("SPRING LOADED", row = ROW_NO_0, center = True) - lcd.write("SWITCH TESTER", row = ROW_NO_1, center = True) - appVersion = getAppVersion() - print(f"Application version: {appVersion}") - lcd.write(f"Version: {appVersion}", row = ROW_NO_3, padding = True) - time.sleep(3) - lcd.clean() - time.sleep(0.5) - lcd.turnOffBacklight() - time.sleep(1) - lcd.turnOnBacklight() - time.sleep(1) - - -# This is the gpio initialization -def gpioInitialization(): - gpio.pinMode(ON_BOARD_LED_PIN, OUTPUT) - gpio.pinMode(GPIO_3V3_1_PIN, OUTPUT) - gpio.pinMode(GPIO_3V3_2_PIN, OUTPUT) - - gpio.pinMode(MICRO_SWITCH_S1_NC_PIN, INPUT, PULL_DOWN) - gpio.pinMode(MICRO_SWITCH_S1_NO_PIN, INPUT, PULL_DOWN) - gpio.pinMode(MICRO_SWITCH_S2_NC_PIN, INPUT, PULL_DOWN) - gpio.pinMode(MICRO_SWITCH_S2_NO_PIN, INPUT, PULL_DOWN) - - gpio.pinMode(POSITION_RIGHT_LED_PIN, OUTPUT) - gpio.pinMode(POSITION_MIDDLE_LED_PIN, OUTPUT) - gpio.pinMode(POSITION_LEFT_LED_PIN, OUTPUT) - - gpio.pinMode(MOTOR_ON_OFF_PIN, OUTPUT) - - gpio.pinMode(RESET_PUSH_SWITCH_PIN, INPUT) - - gpio.digitalWrite(GPIO_3V3_1_PIN, HIGH) - gpio.digitalWrite(GPIO_3V3_2_PIN, HIGH) - - gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) - gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) - gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) - - gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) - - -# Time print function -def printCurrentTime(row: int): - lcd.write(datetime.now().strftime('%I:%M:%S %p %d/%m/%y'), row = row, padding = True) - # time.sleep(0.1) - - -# Print the count value -def printCountValue(row: int, currentCount: int, totalCount: int): - lcd.write(f"Test:{currentCount}/{totalCount}", row = row, padding = True) - - -# Turn on only the position LED -def showPositionLED(position: int|None): - if position == POSITION_LEFT: - gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) - gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) - gpio.digitalWrite(POSITION_LEFT_LED_PIN, HIGH) - - elif position == POSITION_RIGHT: - gpio.digitalWrite(POSITION_RIGHT_LED_PIN, HIGH) - gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) - gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) - - elif position == POSITION_MIDDLE: - gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) - gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, HIGH) - gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) +def app_setup(switchModel): + if switchModel == SWT_MODEL_DOUBLE_TYPE_B or switchModel == SWT_MODEL_DOUBLE_TYPE_C or switchModel == SWT_MODEL_DOUBLE_TYPE_E: + doubleSwitchSetup(switchModel) + elif switchModel == SWT_MODEL_SINGLE_TYPE_A or switchModel == SWT_MODEL_SINGLE_TYPE_D: + singleSwitchSetup(switchModel) else: - gpio.digitalWrite(POSITION_RIGHT_LED_PIN, LOW) - gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) - gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) - - -# This is the void setup() function just like Arduino code -def setup(): - global cycleIndexPos - global previousPosition - global cycleCounter - global TotalCounter - - startIntroPrint() - print("Intro print done!") - gpioInitialization() - print("GPIO initialization done!") - createRtDbFile() - print("Database creation done!") - - lcd.write("Model: Type-D", row = ROW_NO_1, center = True) - - ################################################# - ## S1_NO S1_NC S2_NO S2_NC ## - ## LEFT 0 1 1 0 ## - ## MID 1 0 1 0 ## - ## RIGHT 1 0 0 1 ## - ################################################# - - if gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): - previousPosition = POSITION_LEFT - cycleIndexPos = POSITION_LEFT - print("Initial position: LEFT") - - if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): - previousPosition = POSITION_MIDDLE - cycleIndexPos = POSITION_MIDDLE - print("Initial position: MIDDLE") - - if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN): - previousPosition = POSITION_RIGHT - cycleIndexPos = POSITION_RIGHT - print("Initial position: RIGHT") - - ########## TEST BEGIN ############### - if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN) and\ - gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN) and\ - gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): - previousPosition = POSITION_MIDDLE - cycleIndexPos = POSITION_MIDDLE - print("Probably No switch found; All pin are HIGH ... !!") - - if previousPosition == None and cycleIndexPos == None: - raise Exception("Someting Wrong!! Not able to read switch posiiton!!") - - ########## TEST END## ############### - - cycleCounter = getCycleCount() - TotalCounter = getTotalCount() - print(f"Current Counter: {cycleCounter}") - print(f"Max Counter : {TotalCounter}") - printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) - setCycleCount(cycleCounter) - - gpio.digitalWrite(ON_BOARD_LED_PIN, LOW) - - -# This is the void loop() function just like Arduino code -def loop(): - global isConfigReadNeed - global previousPosition - global cycleIndexPos - global currentPosition - global cycleCounter - global TotalCounter - global cycleIndexPosMiddle - global ResetBtnReading - global lastButtonState - global debounceDelay - global buttonState - global ResetTrigger - global lastDebounceTime - - while True: - gpio.digitalWrite(MOTOR_ON_OFF_PIN, HIGH) - printCurrentTime(ROW_NO_0) - - ################################################# - ## S1_NO S1_NC S2_NO S2_NC ## - ## LEFT 0 1 1 0 ## - ## MID 1 0 1 0 ## - ## RIGHT 1 0 0 1 ## - ################################################# - - # Reading the gpio pin for the switchs - if gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): - currentPosition = POSITION_LEFT - lcd.write("Position Left ", row = ROW_NO_2) - print("Position Left") + print("Unknown switch model. Exiting.") + exit(1) - if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN): - currentPosition = POSITION_MIDDLE - lcd.write("Position Middle", row = ROW_NO_2) - print("Position Middle") - if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN): - currentPosition = POSITION_RIGHT - lcd.write("Position Right ", row = ROW_NO_2) - print("Position Right") - - print("S1_NO:", gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN), end="\t") - print("S1_NC:", gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN), end="\t") - print("S2_NO:", gpio.digitalRead(MICRO_SWITCH_S2_NO_PIN), end="\t") - print("S2_NC:", gpio.digitalRead(MICRO_SWITCH_S2_NC_PIN)) - - # Turn on the postion LED - showPositionLED(currentPosition) - - # According to the position, update the count number - countUpdate = False - if currentPosition != previousPosition: - if currentPosition == POSITION_LEFT or currentPosition == POSITION_RIGHT: - if cycleIndexPos == currentPosition: - cycleCounter += 1 - countUpdate = True - elif currentPosition == POSITION_MIDDLE: - if cycleIndexPosMiddle and (cycleIndexPos == currentPosition): - cycleCounter += 1 - countUpdate = True - cycleIndexPosMiddle = not cycleIndexPosMiddle - else: - pass - - previousPosition = currentPosition - - # update current and total count value if config update avaialabe - if getConfigUpdateStatus() == CONFIG_UPDATE_AVAILABLE: - cycleCounter = getCycleCount() - TotalCounter = getTotalCount() - setConfigUpdateStatus(NO_CONFIG_UPDATE) - printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) - - # Update the count in the LCD - if countUpdate: - printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) - setCycleCount(cycleCounter) - countUpdate = False - - # If reach the full count number then turn on the Finish LED - if cycleCounter >= TotalCounter: - gpio.digitalWrite(ON_BOARD_LED_PIN, HIGH) - gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) - lcd.write("Count Finished!", row = ROW_NO_3, padding = True) - print("Count Finished!") - cycleCounter = 0 - - # Reset button debounce logic - ResetBtnReading = gpio.digitalRead(RESET_PUSH_SWITCH_PIN) - - if ResetBtnReading != lastButtonState: - lastDebounceTime = time.time() - - if ((time.time() - lastDebounceTime) * 1000) > debounceDelay: - if ResetBtnReading != buttonState: - buttonState = ResetBtnReading - - if buttonState == LOW: - lcd.write("Count Reseting...", row = ROW_NO_3, padding = True) - ResetTrigger = True - - lastButtonState = ResetBtnReading +def app_loop(switchModel): + if switchModel == SWT_MODEL_DOUBLE_TYPE_B or switchModel == SWT_MODEL_DOUBLE_TYPE_C or switchModel == SWT_MODEL_DOUBLE_TYPE_E: + rtn, model = doubleSwitchLoop(switchModel) + elif switchModel == SWT_MODEL_SINGLE_TYPE_A or switchModel == SWT_MODEL_SINGLE_TYPE_D: + rtn, model = singleSwitchLoop(switchModel) + else: + print("Unknown switch model. Exiting.") + rtn = LOOP_RTN_TYPE_ERROR + model = None - # If reset button pressed then clean the old stuffs - if ResetTrigger: - gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) - cycleCounter = 0 - gpio.digitalWrite(ON_BOARD_LED_PIN, LOW) - setCycleCount(cycleCounter) - ResetTrigger = False - time.sleep(2) - lcd.write(" "*LCD_MODULE_NO_OF_COLUMN, row = ROW_NO_3) - time.sleep(1) - printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + return rtn, model # Entry point main function -def main(): +def main(ForceDbCreation = False, newSwModel = None): + print(f"Starting Spring Loaded Switch application. {getAppVersion()}") + createRtDbFile(ForceDbCreation) + print("Database creation done!") + if newSwModel: + print("Updating new Switch Model...") + setSwitchModel(newSwModel) + print("Getting Switch Model...") + switchModel = getSwitchModel() + print(f"Detected Switch Model: {switchModel}") print("Entering initial setup.") - setup() + app_setup(switchModel) print("Entering main loop.") - loop() + rtn, model = app_loop(switchModel) + print(f"Main loop returned: {rtn}") + if rtn == LOOP_RTN_TYPE_SW_CHANGE: + print("Switch model change detected. Restarting application...") + main(ForceDbCreation = True, newSwModel = model) + else: + print("Exiting application.") + exit(-1) if __name__ == "__main__": diff --git a/Script/rpigpio.py b/Script/rpigpio.py index 4300154..458aa1d 100644 --- a/Script/rpigpio.py +++ b/Script/rpigpio.py @@ -1,4 +1,8 @@ -import RPi.GPIO as GPIO # type: ignore +try: + import RPi.GPIO as GPIO # type: ignore +except ImportError: + print("RPi.GPIO module not found. Please install it using 'pip install RPi.GPIO'.") + GPIO = None from common import * class RpiGpio: @@ -7,15 +11,22 @@ def __init__(self): def init(self): + if GPIO is None: + print("RPi.GPIO module is not available.") + return GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) def deinit(self): - GPIO.cleanup() + if GPIO: + GPIO.cleanup() def pinMode(self, pin: int, state: bool, pullUpDown: bool|None = None): + if GPIO is None: + print("RPi.GPIO module is not available.") + return _state = None _pullUpDown = None @@ -44,11 +55,15 @@ def pinMode(self, pin: int, state: bool, pullUpDown: bool|None = None): def digitalRead(self, pin: int): + if GPIO is None: + return LOW state = GPIO.input(pin) return state def digitalWrite(self, pin: int, state: bool): + if GPIO is None: + return _state = None # Mapping with HIGH LOW macro with GPIO.HIGH GPIO.LOW diff --git a/Script/singleSwitch.py b/Script/singleSwitch.py new file mode 100644 index 0000000..1445f59 --- /dev/null +++ b/Script/singleSwitch.py @@ -0,0 +1,284 @@ +from datetime import datetime +import time + +from lcd20x4 import Lcd20x4 +from rpigpio import RpiGpio + +from utility import * +from common import * +from pinDescription import * + + +# global hardware module library initilization +lcd = Lcd20x4(LCD_MODULE_ADDRESS, LCD_MODULE_NO_OF_COLUMN, LCD_MODULE_NO_OF_ROW) +gpio = RpiGpio() + + +# global variables +cycleIndexPos = 0 +cycleCounter = 0 +TotalCounter = 0 + +previousPosition = None +currentPosition = None + +ResetBtnReading = None +buttonState = None + +ResetTrigger = False +isConfigReadNeed = True +cycleIndexPosMiddle = False + +lastButtonState = HIGH +debounceDelay = 5000 +lastDebounceTime = 0 + + +# Introduction banner print +def startIntroPrint(): + lcd.write("SPRING LOADED", row = ROW_NO_0, center = True) + lcd.write("SWITCH TESTER", row = ROW_NO_1, center = True) + appVersion = getAppVersion() + print(f"Application version: {appVersion}") + lcd.write(f"Version: {appVersion}", row = ROW_NO_3, padding = True) + time.sleep(3) + lcd.clean() + time.sleep(0.5) + lcd.turnOffBacklight() + time.sleep(1) + lcd.turnOnBacklight() + time.sleep(1) + + +# This is the gpio initialization +def gpioInitialization(): + gpio.pinMode(ON_BOARD_LED_PIN, OUTPUT) + gpio.pinMode(GPIO_3V3_1_PIN, OUTPUT) + gpio.pinMode(GPIO_3V3_2_PIN, OUTPUT) + + gpio.pinMode(MICRO_SWITCH_S1_NC_PIN, INPUT, PULL_DOWN) + gpio.pinMode(MICRO_SWITCH_S1_NO_PIN, INPUT, PULL_DOWN) + + gpio.pinMode(POSITION_MIDDLE_LED_PIN, OUTPUT) + gpio.pinMode(POSITION_LEFT_LED_PIN, OUTPUT) + + gpio.pinMode(MOTOR_ON_OFF_PIN, OUTPUT) + + gpio.pinMode(RESET_PUSH_SWITCH_PIN, INPUT) + + gpio.digitalWrite(GPIO_3V3_1_PIN, HIGH) + gpio.digitalWrite(GPIO_3V3_2_PIN, HIGH) + + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) + + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + + +# Time print function +def printCurrentTime(row: int): + lcd.write(datetime.now().strftime('%I:%M:%S %p %d/%m/%y'), row = row, padding = True) + + +# Print the count value +def printCountValue(row: int, currentCount: int, totalCount: int): + lcd.write(f"Test:{currentCount}/{totalCount}", row = row, padding = True) + + +# Turn on only the position LED +def showPositionLED(position: int|None): + if position == POSITION_LEFT: + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, HIGH) + + elif position == POSITION_MIDDLE: + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, HIGH) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) + + else: + gpio.digitalWrite(POSITION_MIDDLE_LED_PIN, LOW) + gpio.digitalWrite(POSITION_LEFT_LED_PIN, LOW) + + +# This is the void setup() function just like Arduino code +def singleSwitchSetup(model: str): + global cycleIndexPos + global previousPosition + global cycleCounter + global TotalCounter + + startIntroPrint() + print("Intro print done!") + gpioInitialization() + print("GPIO initialization done!") + + lcd.write(f"Model: {model}", row = ROW_NO_1, center = True) + + ############################## + ## S1_NO S1_NC ## + ## LEFT 0 1 ## + ## MID 1 0 ## + ############################## + + if gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN): + previousPosition = POSITION_LEFT + cycleIndexPos = POSITION_LEFT + print("Initial position: LEFT") + + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN): + previousPosition = POSITION_MIDDLE + cycleIndexPos = POSITION_MIDDLE + print("Initial position: MIDDLE") + + ########## TEST BEGIN ############### + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN) and gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN): + previousPosition = POSITION_MIDDLE + cycleIndexPos = POSITION_MIDDLE + print("Probably No switch found; All pin are HIGH ... !!") + + if previousPosition == None and cycleIndexPos == None: + raise Exception("Something Wrong!! Not able to read switch position!!") + + ########## TEST END## ############### + + cycleCounter = getCycleCount() + TotalCounter = getTotalCount() + print(f"Current Counter: {cycleCounter}") + print(f"Max Counter : {TotalCounter}") + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + setCycleCount(cycleCounter) + + gpio.digitalWrite(ON_BOARD_LED_PIN, LOW) + + +# This is the void loop() function just like Arduino code +def singleSwitchLoop(model: str): + global isConfigReadNeed + global previousPosition + global cycleIndexPos + global currentPosition + global cycleCounter + global TotalCounter + global cycleIndexPosMiddle + global ResetBtnReading + global lastButtonState + global debounceDelay + global buttonState + global ResetTrigger + global lastDebounceTime + + rtn = LOOP_RTN_TYPE_ERROR + switchModel = None + + while True: + motorStatus = getMotorControlStatus() + gpio.digitalWrite(MOTOR_ON_OFF_PIN, motorStatus) + printCurrentTime(ROW_NO_0) + + ############################## + ## S1_NO S1_NC ## + ## LEFT 0 1 ## + ## MID 1 0 ## + ############################## + + # Reading the gpio pin for the switchs + if gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN): + currentPosition = POSITION_LEFT + lcd.write("Position Left ", row = ROW_NO_2) + print("Position Left") + + if gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN): + currentPosition = POSITION_MIDDLE + lcd.write("Position Middle", row = ROW_NO_2) + print("Position Middle") + + print("S1_NO:", gpio.digitalRead(MICRO_SWITCH_S1_NO_PIN), end="\t") + print("S1_NC:", gpio.digitalRead(MICRO_SWITCH_S1_NC_PIN)) + + # Turn on the postion LED + showPositionLED(currentPosition) + + # According to the position, update the count number + countUpdate = False + if currentPosition != previousPosition: + # A full cycle is MIDDLE -> LEFT -> MIDDLE. + # Increment count when transitioning from MIDDLE to LEFT. + if currentPosition == POSITION_MIDDLE and previousPosition == POSITION_LEFT: + cycleCounter += 1 + countUpdate = True + + previousPosition = currentPosition + + # update current and total count value if config update avaialabe + if getConfigUpdateStatus() == CONFIG_UPDATE_AVAILABLE: + cycleCounter = getCycleCount() + TotalCounter = getTotalCount() + motorStatus = getMotorControlStatus() + switchModel = getSwitchModel() + setConfigUpdateStatus(NO_CONFIG_UPDATE) + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + gpio.digitalWrite(MOTOR_ON_OFF_PIN, motorStatus) + if switchModel != model: + # Switch model has changed + print("Switch model change detected.") + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + rtn = LOOP_RTN_TYPE_SW_CHANGE + break + + # Update the count in the LCD + if countUpdate: + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + setCycleCount(cycleCounter) + countUpdate = False + + # If reach the full count number then turn on the Finish LED + if cycleCounter >= TotalCounter: + gpio.digitalWrite(ON_BOARD_LED_PIN, HIGH) + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + setMotorControlStatus(LOW) + lcd.write("Count Finished!", row = ROW_NO_3, padding = True) + print("Count Finished!") + cycleCounter = 0 + + # Reset button debounce logic + ResetBtnReading = gpio.digitalRead(RESET_PUSH_SWITCH_PIN) + + if ResetBtnReading != lastButtonState: + lastDebounceTime = time.time() + + if ((time.time() - lastDebounceTime) * 1000) > debounceDelay: + if ResetBtnReading != buttonState: + buttonState = ResetBtnReading + + if buttonState == LOW: + lcd.write("Count Reseting...", row = ROW_NO_3, padding = True) + ResetTrigger = True + + lastButtonState = ResetBtnReading + + # If reset button pressed then clean the old stuffs + if ResetTrigger: + gpio.digitalWrite(MOTOR_ON_OFF_PIN, LOW) + setMotorControlStatus(LOW) + cycleCounter = 0 + gpio.digitalWrite(ON_BOARD_LED_PIN, LOW) + setCycleCount(cycleCounter) + ResetTrigger = False + time.sleep(2) + lcd.write(" "*LCD_MODULE_NO_OF_COLUMN, row = ROW_NO_3) + time.sleep(1) + printCountValue(row = ROW_NO_3, currentCount = cycleCounter, totalCount = TotalCounter) + + # Return the loop status + return rtn, switchModel + +# Entry point main function +def main(): + print("Entering initial setup.") + singleSwitchSetup(SWT_MODEL_SINGLE_TYPE_A) + print("Entering main loop.") + singleSwitchLoop(SWT_MODEL_SINGLE_TYPE_A) + + +if __name__ == "__main__": + main() diff --git a/Script/utility.py b/Script/utility.py index ce6bac4..e95f96b 100644 --- a/Script/utility.py +++ b/Script/utility.py @@ -33,10 +33,12 @@ def getAppVersion(): return "0.0.0.0000" -def createRtDbFile(): - if not os.path.exists(RT_DB_FILE): +def createRtDbFile(ForceDbCreation = False): + if not os.path.exists(RT_DB_FILE) or ForceDbCreation: blankData = { - "cycleCount": 0 + "cycleCount": 0, + "switchModel": SWT_MODEL_DOUBLE_TYPE_B, + "motorStatus": 1 } setYamlData(RT_DB_FILE, blankData) @@ -101,3 +103,41 @@ def setConfigUpdateStatus(status): if rtData: rtData["updateNeeded"] = status setYamlData(RT_DB_FILE, rtData) + + +def getSwitchModel(): + switchModel = SWT_MODEL_DOUBLE_TYPE_B + rtData = getYamlData(RT_DB_FILE) + if rtData: + switchModel = rtData.get("switchModel") + if switchModel == None: + switchModel = SWT_MODEL_DOUBLE_TYPE_B + + return switchModel + + +def setSwitchModel(switchModel): + rtData = getYamlData(RT_DB_FILE) + if rtData: + rtData["switchModel"] = switchModel + setYamlData(RT_DB_FILE, rtData) + + +def getMotorControlStatus(): + motorStatus = LOW + rtData = getYamlData(RT_DB_FILE) + if rtData: + motorStatus = rtData.get("motorStatus") + if motorStatus == None: + motorStatus = LOW + + return motorStatus + + +def setMotorControlStatus(status): + status = 1 if status == HIGH else 0 + + rtData = getYamlData(RT_DB_FILE) + if rtData: + rtData["motorStatus"] = status + setYamlData(RT_DB_FILE, rtData) diff --git a/Web/backend.php b/Web/backend.php index c629b24..17bc2d8 100644 --- a/Web/backend.php +++ b/Web/backend.php @@ -6,6 +6,12 @@ $yamlConfigFilePath = '../config.yaml'; $RtConfigFilePath = '../rtDb.json'; +$SWT_MODEL_SINGLE_TYPE_A = "Type-A"; +$SWT_MODEL_SINGLE_TYPE_D = "Type-D"; +$SWT_MODEL_DOUBLE_TYPE_B = "Type-B"; +$SWT_MODEL_DOUBLE_TYPE_C = "Type-C"; +$SWT_MODEL_DOUBLE_TYPE_E = "Type-E"; + // get yaml config data function getConfigData() @@ -88,4 +94,44 @@ function updateCurrentCountValue($count) $rtConfig["updateNeeded"] = 1; setRtConfig($rtConfig); } + + +// update switch model +function updateSwitchModel($model) +{ + $rtConfig = getRtConfig(); + $rtConfig["switchModel"] = $model; + $rtConfig["updateNeeded"] = 1; + setRtConfig($rtConfig); +} + + +// toggle motor state +function toggleMotorState() +{ + $rtConfig = getRtConfig(); + if (isset($rtConfig["motorStatus"])) { + $rtConfig["motorStatus"] = ($rtConfig["motorStatus"] == 1) ? 0 : 1; + } else { + $rtConfig["motorStatus"] = 1; // Default to ON if not set + } + $rtConfig["updateNeeded"] = 1; + setRtConfig($rtConfig); + return $rtConfig["motorStatus"]; +} + + +// get motor status +function getMotorStatus() +{ + $rtConfig = getRtConfig(); + return isset($rtConfig['motorStatus']) ? $rtConfig['motorStatus'] : 0; // Default to Off +} + +// get switch type +function getSwitchType() +{ + $rtConfig = getRtConfig(); + return isset($rtConfig['switchModel']) ? $rtConfig['switchModel'] : $SWT_MODEL_DOUBLE_TYPE_B; // Default to Type-B +} ?> diff --git a/Web/index.php b/Web/index.php index 7026228..64e9066 100644 --- a/Web/index.php +++ b/Web/index.php @@ -4,6 +4,9 @@ $appVersion = getAppVersion(); $currentCount = getCurrentCountValue(); $totalCount = getTotalCountValue(); +$motorStatus = getMotorStatus(); +$switchType = getSwitchType(); +$motorButtonText = $motorStatus == 1 ? "Turn Off" : "Turn On"; ?> @@ -28,6 +31,23 @@

Count: /

+
+ + + +
+
+ + +
diff --git a/Web/postRequest.php b/Web/postRequest.php index aec2e43..2be2a5b 100644 --- a/Web/postRequest.php +++ b/Web/postRequest.php @@ -71,4 +71,29 @@ echo json_encode($response); } + +// update switch type +if (isset($_POST["updateSwitchType"])) { + $newSwitchType = $_POST['newSwitchType']; + updateSwitchModel($newSwitchType); + $response = [ + 'msg' => "Switch Type Updated to " . $newSwitchType, + 'status' => TRUE, + ]; + echo json_encode($response); +} + +// toggle motor +if (isset($_POST["toggleMotor"])) { + $newMotorState = toggleMotorState(); + $buttonText = $newMotorState == 1 ? "Turn Off" : "Turn On"; + $response = [ + 'msg' => "Motor Turned " . ($newMotorState == 1 ? "On" : "Off"), + 'status' => TRUE, + 'buttonText' => $buttonText, + 'motorStatus' => $newMotorState, + ]; + echo json_encode($response); +} + ?> diff --git a/Web/script.js b/Web/script.js index 90381b4..862febb 100644 --- a/Web/script.js +++ b/Web/script.js @@ -75,4 +75,68 @@ function updateCurrentCountValue() { } +function updateSwitchType() { + if (!confirm("Changing switch type will reset the current count to 0. Do you want to continue?")) { + return; + } + let valueElement = document.getElementById('switchType'); + let switchType = valueElement.value; + + $.ajax({ + url: "postRequest.php", + method: "POST", + data: { + updateSwitchType: 1, + newSwitchType: switchType, + }, + success: function(data) { + if(data['status']) + { + $('#switchTypeStatus').text(switchType); + alert(data['msg']); + } + else + { + alert(data['msg']); + } + } + }); +} + + +function toggleMotor() { + $.ajax({ + url: "postRequest.php", + method: "POST", + data: { + toggleMotor: 1, + }, + success: function(data) { + if(data['status']) + { + $('#motorToggle').text(data['buttonText']); + updateMotorStatus(data['motorStatus']); + alert(data['msg']); + } + else + { + alert(data['msg']); + } + } + }); +} + + +function updateMotorStatus(status) { + let statusElement = $('#motorStatus'); + let buttonElement = $('#motorToggle'); + statusElement.text(status == 1 ? 'ON' : 'OFF'); + if (status == 1) { + buttonElement.removeClass('motor-off').addClass('motor-on'); + } else { + buttonElement.removeClass('motor-on').addClass('motor-off'); + } +} + + setInterval(updateCountValues, 1000); diff --git a/Web/style.css b/Web/style.css index 44517c0..adbe7ae 100644 --- a/Web/style.css +++ b/Web/style.css @@ -42,6 +42,13 @@ main { width: 100%; } +.switchType { + padding: 6px 12px; + border-radius: 4px; + border: 1px solid #ccc; + font-size: 1em; +} + label { font-size: 1rem; } @@ -95,3 +102,27 @@ button:hover { .currentCountBtn:hover { background-color: coral; } + +#motorStatus { + font-weight: bold; +} + +.motor-on { + background-color: #d1240a; /* Red for on */ +} + +.motor-on:hover { + background-color: #b82009; +} + +.motor-off { + background-color: #4CAF50; /* Green for off */ +} + +.motor-off:hover { + background-color: #45a049; +} + +#switchTypeStatus { + font-weight: bold; +} diff --git a/config.yaml b/config.yaml index 88857ba..7d75f56 100644 --- a/config.yaml +++ b/config.yaml @@ -1,2 +1,2 @@ -appVersion: 1.8.1.1016 +appVersion: 1.9.1.1017 maxCount : 7500000