Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <ESP8266WiFi.h>
- #include <ESP8266WebServer.h>
- #include <ESP8266mDNS.h>
- // Project: Remote PC Power Control via Relay & Resistor Voltage Divider State Monitoring
- // Hardware components:
- // 1. Controller: NodeMCU ESP8266 V3 (CH340)
- // 2. Relay: 1-Channel 3.3V Low-Level Trigger Relay Module
- // 3. Resistors: 1x 1k Ohm, 1x 2k Ohm (Voltage divider for PLED sensing)
- // 4. Power: Micro-USB (5V)
- // 5. Connection:
- // - Power Control (Relay Output):
- // Relay VCC -> NodeMCU VIN (5V) or 3V3
- // Relay GND -> NodeMCU GND
- // Relay IN -> NodeMCU D1 (GPIO5)
- // Relay COM & NO -> PC Motherboard POWER SW pins
- // - Power LED Sense (Resistor Divider Input):
- // PC Motherboard PLED (+) -> 1k Ohm Resistor -> NodeMCU D2 (GPIO4)
- // NodeMCU D2 (GPIO4) -> 2k Ohm Resistor -> NodeMCU GND & PLED (-)
- //
- // Schematic Diagram:
- //
- // [ NodeMCU ] [ Relay Module ] [ Motherboard F_PANEL ]
- // Pin D1 (GPIO5) -------------------> IN
- // VIN (5V) -------------------------> VCC
- // GND ------------------------------> GND
- // COM ---------------------------> Pin 7 (POWER SW +)
- // NO ----------------------------> Pin 8 (POWER SW -)
- //
- // [ NodeMCU ] [ Voltage Divider ] [ Motherboard F_PANEL ]
- // Pin D2 (GPIO4) <----+-------------- [ 1kΩ Resistor ] --------------> Pin 1 (PLED +)
- // |
- // [ 2kΩ Resistor ]
- // |
- // GND ----------------+----------------------------------------------> Pin 3 (PLED -) / GND
- //
- // Features:
- // - Web-server for remote control via VPN
- // - Real-time power state sensing via resistor divider (5V to 3.3V)
- // - mDNS support (access via http://mainpc.local)
- // - Static IP configuration (192.168.0.133)
- // - Force Shutdown support (8s long press via /force)
- // - Physical FLASH button on board triggers the relay
- // - English UI with status indicator
- //
- // Hardware Notes:
- // - Relay module IN pin has built-in SMD resistors on PCB.
- // - The 1k/2k ohm divider steps motherboard 5V down to 3.3V safe for ESP8266 GPIO.
- // - Pin D2 uses standard INPUT logic. HIGH = PC ON, LOW = PC OFF.
- // Your network config
- const char* ssid = "WiFI_NAME_REGISTRY_DEPENDANT"; // Change this
- const char* password = "WiFI_PASSWORD"; // Change this
- const char* hostName = "mainpc"; // Access in browser with mainpc.local
- const int relayPin = 5; // D1 (GPIO5) -> Relay IN Pin (Control)
- const int sensePin = 4; // D2 (GPIO4) -> Resistor Divider Middle (PLED Sense)
- const int buttonPin = 0; // FLASH button (GPIO0)
- const int ledPin = 2; // Onboard LED (D4)
- // Static IP Configuration
- IPAddress local_IP(192, 168, 0, 133);
- IPAddress gateway(192, 168, 0, 1);
- IPAddress subnet(255, 255, 255, 0);
- IPAddress primaryDNS(192, 168, 0, 1);
- // Durations in milliseconds
- const int standardPress = 500;
- const int forcePress = 8000; // Force kill duration (8 sec)
- ESP8266WebServer server(80);
- void pressButton(int durationMs) {
- Serial.print("Action: pressing relay for ");
- Serial.print(durationMs);
- Serial.println("ms");
- digitalWrite(ledPin, LOW); // Onboard LED ON (active LOW)
- digitalWrite(relayPin, LOW); // Relay ON (Low-Level Trigger)
- delay(durationMs);
- digitalWrite(relayPin, HIGH); // Relay OFF
- digitalWrite(ledPin, HIGH); // Onboard LED OFF
- }
- // True if PC is ON (5V from PLED through divider yields HIGH on D2)
- bool isPcOn() {
- return digitalRead(sensePin) == HIGH;
- }
- void handleRoot() {
- String html = "<html><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1'>";
- html += "<style>body{text-align:center;font-family:Arial,sans-serif;background:#f4f4f4;padding:20px;}";
- html += "h1{display:flex;align-items:center;justify-content:center;margin-bottom:30px;color:#2c3e50;}";
- html += ".indicator{display:inline-block;width:22px;height:22px;border-radius:50%;margin-left:15px;background:#2ecc71;box-shadow: 0 0 10px #2ecc71;transition: 0.3s;}";
- html += ".btn{width:100%;max-width:300px;height:80px;font-size:20px;font-weight:bold;color:white;border:none;border-radius:15px;margin:15px 0;cursor:pointer;display:block;margin-left:auto;margin-right:auto;transition:0.2s;}";
- html += ".btn:active{transform:scale(0.98);}";
- html += ".on{background:#2ecc71;box-shadow:0 5px #27ae60;} .off{background:#e74c3c;box-shadow:0 5px #c0392b;}";
- html += "p{color:#7f8c8d;margin-top:20px;font-size:14px;}</style>";
- html += "<script>";
- html += "setInterval(function(){ fetch('/status').then(r => r.text()).then(status => {";
- html += "var ind = document.querySelector('.indicator');";
- html += "if(status==='ON'){ind.style.background='#2ecc71'; ind.style.boxShadow='0 0 10px #2ecc71';}";
- html += "else{ind.style.background='#e74c3c'; ind.style.boxShadow='0 0 10px #e74c3c';}";
- html += "});}, 2000);";
- html += "function safeToggle() { fetch('/status').then(r => r.text()).then(status => {";
- html += "if (status === 'ON') { if (confirm('PC is already ON. Power action?')) location.href='/power'; }";
- html += "else { location.href='/power'; }";
- html += "});}";
- html += "</script></head>";
- html += "<body><h1>PC Remote <span class='indicator'></span></h1>";
- html += "<button class='btn on' onclick='safeToggle()'>POWER ON/OFF</button>";
- html += "<button class='btn off' onclick=\"if(confirm('Are you sure you want to FORCE SHUTDOWN?')){location.href='/force';}\">FORCE SHUTDOWN</button>";
- html += "<p>Network name: http://" + String(hostName) + ".local</p></body></html>";
- server.send(200, "text/html", html);
- }
- void handleStatus() {
- server.send(200, "text/plain", isPcOn() ? "ON" : "OFF");
- }
- void handlePower() {
- server.send(200, "text/html", "<h1>OK! Standard press sent.</h1><script>setTimeout(function(){window.location.href='/';},2000);</script>");
- pressButton(standardPress);
- }
- void handleForce() {
- server.send(200, "text/html", "<h1>OK! Force shutdown sent.</h1><script>setTimeout(function(){window.location.href='/';},4000);</script>");
- pressButton(forcePress);
- }
- void setup() {
- Serial.begin(115200);
- pinMode(relayPin, OUTPUT);
- pinMode(ledPin, OUTPUT);
- pinMode(sensePin, INPUT); // Standard input mode for reading divider voltage
- pinMode(buttonPin, INPUT_PULLUP);
- digitalWrite(relayPin, HIGH); // Keep Low-Level Relay OFF initially
- digitalWrite(ledPin, HIGH); // Onboard LED OFF initially
- if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
- Serial.println("STA Failed to configure static IP!");
- }
- WiFi.mode(WIFI_STA);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
- Serial.println("\nWiFi Connected!");
- Serial.print("IP Address: ");
- Serial.println(WiFi.localIP());
- if (MDNS.begin(hostName)) {
- Serial.println("mDNS responder started: http://" + String(hostName) + ".local");
- }
- server.on("/", handleRoot);
- server.on("/status", handleStatus);
- server.on("/power", handlePower);
- server.on("/force", handleForce);
- server.begin();
- MDNS.addService("http", "tcp", 80);
- }
- void loop() {
- MDNS.update();
- server.handleClient();
- if (digitalRead(buttonPin) == LOW) {
- delay(50);
- if (digitalRead(buttonPin) == LOW) {
- pressButton(standardPress);
- while(digitalRead(buttonPin) == LOW) delay(10);
- }
- }
- }
Advertisement