From 4a2d2162797e4a0ac7161008b3cb8d2be144e2a2 Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 20 Sep 2021 21:57:10 -0400 Subject: [PATCH] Add Adjust topic and improve state handling Add adjusting topic to allow for tweaking the open/close endpoints. Improved the state handling/transitions so that it will only change states when IDLE. --- blinds.ino | 135 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 101 insertions(+), 34 deletions(-) diff --git a/blinds.ino b/blinds.ino index bedf293..420d9f8 100644 --- a/blinds.ino +++ b/blinds.ino @@ -6,9 +6,16 @@ WiFiClient net; MQTTClient client; AccelStepper stepper(AccelStepper::HALF4WIRE, D0, D2, D1, D3); +// Config const char ssid[] = ""; -const char pw[] = ""; -const char mqtt_addr[] = "192.168.10.30"; +const char wifi_pw[] = ""; +const char mqtt_user[] = ""; +const char mqtt_pw[] = ""; +const char mqtt_addr[] = ""; +const char client_name[] = ""; + + +// End Config unsigned long lastMillis = 0; @@ -18,69 +25,103 @@ const int SLACK = 1; const int OPENING_BLINDS = 2; const int CLOSING_BLINDS = 3; const int IDLE = 4; +const int ADJUSTING = 5; int state = SETUP; int previousState = SETUP; bool blindsOpen = false; +long fullyOpenPosition = -14000; +long fullyClosedPosition = 0; + void connect() { - Serial.print("checking wifi..."); + Serial.println("checking wifi..."); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(1000); } - Serial.print("\nconnecting..."); - while (!client.connect("bedroom-blinds-1", "cameron", pw)) { + Serial.println("\nconnecting..."); + while (!client.connect(client_name, mqtt_user, mqtt_pw)) { Serial.print("."); delay(1000); } Serial.println("\nconnected!"); - client.subscribe("/blinds/bedroom/1"); + client.subscribe("/bedroom/blinds/2"); + client.subscribe("/bedroom/blinds/2/adjust"); } void messageReceived(String &topic, String &payload) { Serial.println("incoming: " + topic + " - " + payload); - // Note: Do not use the client in the callback to publish, subscribe or - // unsubscribe as it may cause deadlocks when other things arrive while - // sending and receiving acknowledgments. Instead, change a global variable, - // or push to a queue and handle it in the loop after calling `client.loop()`. - if (payload.indexOf("open") != -1) { - openBlinds(); - } else if (payload.indexOf("close") != -1) { - closeBlinds(); + if (topic.endsWith("adjust")) { + int adjustment; + sscanf(payload.c_str(), "%d", &adjustment); + adjustClosedPosition(adjustment); } else { - Serial.println(payload); + if (payload.indexOf("open") != -1) { + openBlinds(); + } else if (payload.indexOf("close") != -1) { + closeBlinds(); + } else if (payload.indexOf("reset") != -1) { + Serial.println("Resetting current position and setting blinds state to closed"); + stepper.setCurrentPosition(0); + blindsOpen = false; + } else { + Serial.println(payload); + } + } +} + +void updateState(int newState) { + previousState = state; + state = newState; + + if(newState == IDLE) { + Serial.println("Transitioning to idle"); + } else { + Serial.print("Moving "); + Serial.print(previousState); + Serial.print(" -> "); + Serial.println(newState); } } void openBlinds() { - if (!blindsOpen) { + if (!blindsOpen && state == IDLE) { Serial.println("Opening Blinds"); - previousState = state; - state = OPENING_BLINDS; + updateState(OPENING_BLINDS); stepper.enableOutputs(); - stepper.moveTo(-14000); + stepper.moveTo(fullyOpenPosition); } } void closeBlinds() { - if (blindsOpen) { + if (blindsOpen && state == IDLE) { Serial.println("Closing Blinds"); - previousState = state; - state = CLOSING_BLINDS; + updateState(CLOSING_BLINDS); stepper.enableOutputs(); - stepper.moveTo(0); + stepper.moveTo(fullyClosedPosition); } } +void adjustClosedPosition(int offset) { + if(offset == 0 || state != IDLE) return; + + Serial.print("Adjust by: "); + Serial.println(offset); + + updateState(ADJUSTING); + stepper.enableOutputs(); + stepper.move(offset); +} + void setup() { Serial.begin(115200); - WiFi.begin(ssid, pw); + WiFi.begin(ssid, wifi_pw); client.begin(mqtt_addr, 1883, net); client.onMessage(messageReceived); @@ -112,15 +153,14 @@ void loop() { } else if (previousState == CLOSING_BLINDS) { stepper.move(-3000); } else if (stepper.distanceToGo() == 0) { - state = IDLE; + updateState(IDLE); stepper.disableOutputs(); - Serial.println("Transitioning to IDLE"); return; - } else { - stepper.run(); } - // Update previous to SLACK until we take up the slack + stepper.run(); + + // Update previous to SLACK until we take up the slack to prevent the stepper from moving forever previousState = state; break; case OPENING_BLINDS: @@ -139,19 +179,46 @@ void loop() { bool open = state == OPENING_BLINDS; blindsOpen = open; sendBlindsUpdate(open); - previousState = state; - state = SLACK; + updateState(SLACK); } + break; + case ADJUSTING: + if (millis() - lastMillis > 1000) { + Serial.println("Adjusting..."); + lastMillis = millis(); + } + + stepper.run(); + + if (stepper.distanceToGo() == 0) { + Serial.print("Finished adjusting to: "); + Serial.println(stepper.currentPosition()); + + updateState(IDLE); + stepper.disableOutputs(); + + if(blindsOpen) { + fullyOpenPosition = stepper.currentPosition(); + + Serial.print("New open position: "); + Serial.println(fullyOpenPosition); + } else { + fullyClosedPosition = stepper.currentPosition(); + + Serial.print("New closed position: "); + Serial.println(fullyClosedPosition); + } + } + break; } } void setup_stepper() { - previousState = state; - state = IDLE; + updateState(IDLE); stepper.setCurrentPosition(-3000); } void sendBlindsUpdate(bool isOpen) { - client.publish("/blinds/bedroom/1/status", isOpen ? "true" : "false", true); + client.publish("/bedroom/blinds/2/status", isOpen ? "true" : "false", true); }