CCCPaste

# I2C Relay Controller rev_02

/********* Pleasedontcode.com **********

	Pleasedontcode thanks you for automatic code generation! Enjoy your code!

	- Terms and Conditions:
	You have a non-exclusive, revocable, worldwide, royalty-free license
	for personal and commercial use. Attribution is optional; modifications
	are allowed, but you're responsible for code maintenance. We're not
	liable for any loss or damage. For full terms,
	please visit pleasedontcode.com/termsandconditions.

	- Project: # I2C Relay Controller
	- Source Code NOT compiled for: ESP8266 NodeMCU V1.0
	- Source Code created on: 2026-02-05 14:53:15

********* Pleasedontcode.com **********/

/****** SYSTEM REQUIREMENTS *****/
/****** SYSTEM REQUIREMENT 1 *****/
	/* add i2c gpio expander PCF8574 */
/****** END SYSTEM REQUIREMENTS *****/


/* START CODE */

/********* Pleasedontcode.com **********\n\n\tPleasedontcode thanks you for automatic code generation! Enjoy your code!\n\n\t- Terms and Conditions:\n\tYou have a non-exclusive, revocable, worldwide, royalty-free license\n\tfor personal and commercial use. Attribution is optional; modifications\n\tare allowed, but you're responsible for code maintenance. We're not\n\tliable for any loss or damage. For full terms,\n\tplease visit pleasedontcode.com/termsandconditions.\n\n\t- Project: Project_3913\n\t- SOURCE CODE NOT YET FINALIZED. STILL UNDER GENERATION PHASE.\n\t- Source Code created on: 2026-02-05 14:53:15\n\t- Source Code generated by: Sargo A\n\n********* Pleasedontcode.com **********/\n\n/****** SYSTEM REQUIREMENTS *****/\n/****** SYSTEM REQUIREMENT 1 *****/\n\t/* add i2c gpio expander PCF8574 */\n/****** END SYSTEM REQUIREMENTS *****/\n\n#include \"PCF8574.h\"\n#include \"Relay.h\"\n\n// Create PCF8574 instance with default I2C address 0x20\n// Address range: 0x20 to 0x27 depending on A0, A1, A2 pins\nPCF8574 expander(0x20);\n\n// Create Relay instance for managing 8 relays\nRelay relayController(&expander, 8);\n\n// Serial command buffer\nString commandBuffer = \"\";\n\n// Timestamp for periodic status monitoring\nunsigned long lastStatusTime = 0;\nunsigned long statusInterval = 5000;  // Print status every 5 seconds\n\n// Relay state change log\nstruct RelayLog {\n  uint32_t timestamp;\n  uint8_t relayNum;\n  bool state;  // true = ON, false = OFF\n  char action[20];\n};\n\n// Log buffer for relay state changes (last 10 changes)\nRelayLog relayLogs[10];\nuint8_t logIndex = 0;\n\n/****** FUNCTION PROTOTYPES *****/\nvoid setup(void);\nvoid loop(void);\nvoid processSerialCommand(String command);\nvoid handleRelayCommand(String command);\nvoid printAvailableCommands(void);\nvoid logRelayStateChange(uint8_t relayNum, bool newState, const char* action);\nvoid printRelayLogs(void);\nvoid printRelayStatusMonitoring(void);\n\nvoid setup(void)\n{\n  // Initialize Serial communication\n  Serial.begin(115200);\n  delay(100);\n  \n  Serial.println(\"\\n\\n================================================\");\n  Serial.println(\"     PCF8574 I2C GPIO Expander with Relays     \");\n  Serial.println(\"================================================\");\n  Serial.println();\n  \n  // Initialize PCF8574 with I2C address 0x20\n  // Using default ESP8266 pins: SDA=4 (D2), SCL=5 (D1)\n  Serial.println(\"Initializing PCF8574 I2C GPIO Expander...\");\n  \n  if (expander.begin()) {\n    Serial.println(\"[SUCCESS] PCF8574 initialized successfully!\");\n    Serial.print(\"[INFO] I2C Address: 0x\");\n    Serial.println(0x20, HEX);\n    Serial.println(\"[INFO] I2C Pins: SDA=4 (D2), SCL=5 (D1)\");\n    \n    // Initialize all relay pins to HIGH (default/inactive state)\n    expander.writePort(0xFF);\n    Serial.println(\"[INFO] All relay pins set to HIGH (inactive)\");\n    \n    delay(500);\n    \n    // Initialize Relay controller\n    Serial.println();\n    Serial.println(\"Initializing Relay Controller...\");\n    relayController.init();\n    \n    Serial.println();\n    Serial.println(\"[SUCCESS] System fully initialized and ready!\");\n    Serial.println();\n    \n    // Print help information\n    printAvailableCommands();\n    \n    // Initialize log timestamps\n    lastStatusTime = millis();\n    \n  } else {\n    Serial.println(\"[ERROR] Failed to initialize PCF8574!\");\n    Serial.println(\"[ERROR] Please check:\");\n    Serial.println(\"  - I2C connections (SDA=D2/GPIO4, SCL=D1/GPIO5)\");\n    Serial.println(\"  - PCF8574 I2C address (default 0x20, check A0/A1/A2 pins)\");\n    Serial.println(\"  - PCF8574 power supply (VCC and GND)\");\n    Serial.println();\n    Serial.println(\"System will continue but relay control may not work.\");\n  }\n  \n  delay(1000);\n}\n\n\nvoid loop(void)\n{\n  // Check for serial commands\n  if (Serial.available()) {\n    char inChar = Serial.read();\n    \n    // Handle enter key (carriage return or newline)\n    if (inChar == '\\r' || inChar == '\\n') {\n      if (commandBuffer.length() > 0) {\n        Serial.println();  // Echo newline\n        Serial.print(\"[COMMAND] \");\n        Serial.println(commandBuffer);\n        processSerialCommand(commandBuffer);\n        commandBuffer = \"\";  // Clear buffer\n      }\n    }\n    // Handle backspace\n    else if (inChar == '\\b') {\n      if (commandBuffer.length() > 0) {\n        commandBuffer.remove(commandBuffer.length() - 1);\n        Serial.print(inChar);  // Echo backspace\n      }\n    }\n    // Add character to buffer\n    else if (inChar >= 32 && inChar <= 126) {  // Printable ASCII characters\n      commandBuffer += inChar;\n      Serial.print(inChar);  // Echo character\n    }\n  }\n  \n  // Periodic status monitoring and logging\n  if (millis() - lastStatusTime >= statusInterval) {\n    lastStatusTime = millis();\n    printRelayStatusMonitoring();\n  }\n  \n  // Small delay to prevent watchdog timeout\n  delay(10);\n}\n\n\n// Process serial commands from user\nvoid processSerialCommand(String command) {\n  // Convert to lowercase for case-insensitive handling\n  command.toLowerCase();\n  \n  // Trim whitespace\n  command.trim();\n  \n  // Empty command\n  if (command.length() == 0) {\n    return;\n  }\n  \n  // Help command\n  if (command == \"help\" || command == \"?\") {\n    printAvailableCommands();\n    return;\n  }\n  \n  // Status command - print current relay states\n  if (command == \"status\" || command == \"s\") {\n    Serial.println();\n    relayController.printStatus();\n    Serial.println();\n    return;\n  }\n  \n  // Logs command - print relay change logs\n  if (command == \"logs\" || command == \"l\") {\n    Serial.println();\n    printRelayLogs();\n    Serial.println();\n    return;\n  }\n  \n  // Clear logs command\n  if (command == \"clrlogs\" || command == \"cl\") {\n    logIndex = 0;\n    Serial.println(\"[INFO] Relay logs cleared\");\n    Serial.println();\n    return;\n  }\n  \n  // Turn off all relays\n  if (command == \"alloff\" || command == \"off\") {\n    Serial.println();\n    relayController.turnOffAll();\n    logRelayStateChange(255, false, \"ALL OFF\");\n    relayController.printStatus();\n    Serial.println();\n    return;\n  }\n  \n  // Test mode - cycle through all relays\n  if (command == \"test\" || command == \"t\") {\n    Serial.println();\n    Serial.println(\"[TEST] Starting relay test sequence...\");\n    Serial.println(\"[TEST] Turning ON each relay for 1 second...\");\n    Serial.println();\n    \n    for (uint8_t i = 0; i < 8; i++) {\n      Serial.print(\"[TEST] Testing Relay \");\n      Serial.println(i);\n      relayController.turnOn(i);\n      delay(1000);\n      relayController.turnOff(i);\n      delay(200);\n    }\n    \n    Serial.println();\n    Serial.println(\"[TEST] Relay test sequence completed!\");\n    Serial.println();\n    return;\n  }\n  \n  // Relay control commands\n  if (command.startsWith(\"on \") || command.startsWith(\"off \") || \n      command.startsWith(\"toggle \") || command.startsWith(\"tog \")) {\n    handleRelayCommand(command);\n    return;\n  }\n  \n  // Check for single digit commands (quick on/off)\n  if (command.length() == 1 && isDigit(command[0])) {\n    uint8_t relayNum = command[0] - '0';\n    if (relayNum < 8) {\n      Serial.println();\n      relayController.toggle(relayNum);\n      logRelayStateChange(relayNum, relayController.getState(relayNum), \"TOGGLE\");\n      relayController.printStatus();\n      Serial.println();\n      return;\n    }\n  }\n  \n  // Unknown command\n  Serial.println(\"[ERROR] Unknown command. Type 'help' for available commands.\");\n  Serial.println();\n}\n\n\n// Handle relay-specific commands (on/off/toggle)\nvoid handleRelayCommand(String command) {\n  String action = \"\";\n  uint8_t relayNum = 255;\n  \n  Serial.println();\n  \n  // Parse \"on\" commands\n  if (command.startsWith(\"on \")) {\n    action = \"ON\";\n    command = command.substring(3);\n    command.trim();\n    \n    if (command.length() > 0 && isDigit(command[0])) {\n      relayNum = command[0] - '0';\n    }\n  }\n  // Parse \"off\" commands\n  else if (command.startsWith(\"off \")) {\n    action = \"OFF\";\n    command = command.substring(4);\n    command.trim();\n    \n    if (command.length() > 0 && isDigit(command[0])) {\n      relayNum = command[0] - '0';\n    }\n  }\n  // Parse \"toggle\" or \"tog\" commands\n  else if (command.startsWith(\"toggle \")) {\n    action = \"TOGGLE\";\n    command = command.substring(7);\n    command.trim();\n    \n    if (command.length() > 0 && isDigit(command[0])) {\n      relayNum = command[0] - '0';\n    }\n  }\n  else if (command.startsWith(\"tog \")) {\n    action = \"TOGGLE\";\n    command = command.substring(4);\n    command.trim();\n    \n    if (command.length() > 0 && isDigit(command[0])) {\n      relayNum = command[0] - '0';\n    }\n  }\n  \n  // Execute command if relay number is valid\n  if (relayNum < 8) {\n    if (action == \"ON\") {\n      relayController.turnOn(relayNum);\n      logRelayStateChange(relayNum, true, \"ON\");\n    }\n    else if (action == \"OFF\") {\n      relayController.turnOff(relayNum);\n      logRelayStateChange(relayNum, false, \"OFF\");\n    }\n    else if (action == \"TOGGLE\") {\n      relayController.toggle(relayNum);\n      logRelayStateChange(relayNum, relayController.getState(relayNum), \"TOGGLE\");\n    }\n    \n    relayController.printStatus();\n  } else {\n    Serial.print(\"[ERROR] Invalid relay number. Use 0-7. Got: \");\n    Serial.println(command);\n  }\n  \n  Serial.println();\n}\n\n\n// Print available commands\nvoid printAvailableCommands(void) {\n  Serial.println();\n  Serial.println(\"================================================\");\n  Serial.println(\"           Available Serial Commands            \");\n  Serial.println(\"================================================\");\n  Serial.println();\n  Serial.println(\"Relay Control Commands:\");\n  Serial.println(\"  on       - Turn ON relay n (0-7)\");\n  Serial.println(\"  off      - Turn OFF relay n (0-7)\");\n  Serial.println(\"  toggle   - Toggle relay n (0-7)\");\n  Serial.println(\"  tog      - Toggle relay n (0-7) [shorthand]\");\n  Serial.println(\"           - Quick toggle relay n (0-7)\");\n  Serial.println(\"  alloff      - Turn OFF all relays\");\n  Serial.println(\"  off         - Turn OFF all relays [shorthand]\");\n  Serial.println();\n  Serial.println(\"System Commands:\");\n  Serial.println(\"  status, s   - Display current relay status\");\n  Serial.println(\"  logs, l     - Display relay change log\");\n  Serial.println(\"  clrlogs, cl - Clear relay change log\");\n  Serial.println(\"  test, t     - Run relay test sequence\");\n  Serial.println(\"  help, ?     - Display this help message\");\n  Serial.println();\n  Serial.println(\"Example: Type 'on 0' to turn ON relay 0\");\n  Serial.println(\"Example: Type '3' to toggle relay 3\");\n  Serial.println(\"================================================\");\n  Serial.println();\n}\n\n\n// Log relay state changes\nvoid logRelayStateChange(uint8_t relayNum, bool newState, const char* action) {\n  // Special handling for \"ALL OFF\" action\n  if (relayNum == 255) {\n    // Log all relays being turned off\n    for (uint8_t i = 0; i < 8; i++) {\n      RelayLog& log = relayLogs[logIndex % 10];\n      log.timestamp = millis();\n      log.relayNum = i;\n      log.state = false;\n      strncpy(log.action, action, sizeof(log.action) - 1);\n      log.action[sizeof(log.action) - 1] = '\\0';\n      logIndex++;\n    }\n  } else {\n    RelayLog& log = relayLogs[logIndex % 10];\n    log.timestamp = millis();\n    log.relayNum = relayNum;\n    log.state = newState;\n    strncpy(log.action, action, sizeof(log.action) - 1);\n    log.action[sizeof(log.action) - 1] = '\\0';\n    logIndex++;\n  }\n}\n\n\n// Print relay state change logs\nvoid printRelayLogs(void) {\n  Serial.println(\"=== Relay Change Log (Last 10 changes) ===\");\n  \n  if (logIndex == 0) {\n    Serial.println(\"No relay changes recorded yet.\");\n  } else {\n    // Calculate start index for circular buffer\n    uint8_t startIdx = (logIndex >= 10) ? (logIndex % 10) : 0;\n    uint8_t count = (logIndex >= 10) ? 10 : logIndex;\n    \n    for (uint8_t i = 0; i < count; i++) {\n      uint8_t idx = (startIdx + i) % 10;\n      RelayLog& log = relayLogs[idx];\n      \n      Serial.print(\"[\");\n      Serial.print(log.timestamp / 1000);\n      Serial.print(\"s] Relay \");\n      Serial.print(log.relayNum);\n      Serial.print(\": \");\n      Serial.print(log.state ? \"ON\" : \"OFF\");\n      Serial.print(\" (\");\n      Serial.print(log.action);\n      Serial.println(\")\");\n    }\n  }\n  \n  Serial.println(\"===========================================\");\n}\n\n\n// Print relay status monitoring with periodic updates\nvoid printRelayStatusMonitoring(void) {\n  // Calculate uptime\n  uint32_t uptimeSeconds = millis() / 1000;\n  uint8_t hours = uptimeSeconds / 3600;\n  uint8_t minutes = (uptimeSeconds % 3600) / 60;\n  uint8_t seconds = uptimeSeconds % 60;\n  \n  Serial.println();\n  Serial.println(\"--------- Relay Status Monitor (Periodic) --------\");\n  Serial.print(\"Uptime: \");\n  \n  if (hours < 10) Serial.print(\"0\");\n  Serial.print(hours);\n  Serial.print(\":\");\n  \n  if (minutes < 10) Serial.print(\"0\");\n  Serial.print(minutes);\n  Serial.print(\":\");\n  \n  if (seconds < 10) Serial.print(\"0\");\n  Serial.println(seconds);\n  \n  // Print all relay states\n  Serial.println(\"Current Relay States:\");\n  for (uint8_t i = 0; i < 8; i++) {\n    Serial.print(\"  Relay \");\n    Serial.print(i);\n    Serial.print(\": \");\n    Serial.println(relayController.getState(i) ? \"ON \" : \"OFF\");\n  }\n  \n  // Print number of logged changes\n  Serial.print(\"Total logged changes: \");\n  Serial.println(logIndex);\n  \n  Serial.println(\"--------------------------------------------------\");\n  Serial.println();\n}\n

/* END CODE */