diff --git a/icbm.ino b/icbm.ino
index cb83fd8509e4a18a140a06e539773f54c7535da9..102c5fcaae279455a3148a6cf73ad7ddecb569fa 100644
--- a/icbm.ino
+++ b/icbm.ino
@@ -7,6 +7,9 @@ unsigned long start;
 extern bool eth_connected;
 extern SNMP::Manager snmp;
 
+TaskHandle_t restServerTask;
+TaskHandle_t powerProcedureTask;
+
 void setup() {
     Serial.begin(115200);
 
@@ -20,8 +23,15 @@ void setup() {
     PINS.last_triggered = millis();
     PINS.stage = "";
     PINS.ramping = false;
+    PINS.canDoPowerFromREST = false;
 
     start = millis();
+
+    // Run the web interface on core 0
+    xTaskCreatePinnedToCore(webInterfaceLoop, "Web Interface", 10000, NULL, 1, &restServerTask, 0);
+    // Run the power procedure and interrupt handling on core 1, the default core
+    xTaskCreatePinnedToCore(mainLoop, "PowerProcedure Task", 10000, NULL, 1, &powerProcedureTask,
+                            1);
 }
 
 enum {
@@ -37,13 +47,51 @@ void serialLoop() {
     }
 }
 
-void loop() {
-    isr_check_loop();
-    snmp.loop();
-    restServer.handleClient();
-    toggle_status_led();
-    serialLoop();
-    if (eth_connected) {  // We may be triggered, but disconnected from the network.
-        powerOffCheckLoop();
+void waitEnvOk() {
+    // Poll port expander on initialiation to wait until environment all ok
+    // If the ICBM is booted before the detector is up, as it should be,
+    // then the environment will always be incorrect, creating a power down
+    PINS.stage = "Waiting for environment to be okay first time";
+
+    uint32_t lastIteration = millis();
+    while (true) {
+        serialLoop();
+        if (millis() - lastIteration >= 200) {  // ms, faster polling makes for erroneous readings.
+            poll_port_expander();
+            if (PINS.sib && PINS.plc && PINS.ups) {
+                break;
+            }
+            lastIteration = millis();
+        }
+    }
+
+    PINS.stage = "";
+    PINS.canDoPowerFromREST = true;
+}
+
+void webInterfaceLoop(void* pvParameters) {
+    Serial.print("Web loop running on core ");
+    Serial.println(xPortGetCoreID());
+    while (true) {
+        restServer.handleClient();
+    }
+}
+
+void mainLoop(void* pvParameters) {
+    Serial.print("Main loop running on core ");
+    Serial.println(xPortGetCoreID());
+
+    waitEnvOk();
+
+    while (true) {
+        isr_check_loop();
+        snmp.loop();
+        toggle_status_led();
+        serialLoop();
+        if (eth_connected) {  // We may be triggered, but disconnected from the network.
+            powerOffCheckLoop();
+        }
     }
 }
+
+void loop() {}
diff --git a/mpod.cpp b/mpod.cpp
index c119546e72a021eb50293a0d15bd8fada38c6519..08ec1a0a3bc82dce49052d3b80cca910dc9b7e2b 100644
--- a/mpod.cpp
+++ b/mpod.cpp
@@ -260,6 +260,12 @@ void setChannelStateAndWait(const IPAddress *ipAddr, const uint16_t channel, con
 
         delay(MPOD_UPDATE_LATENCY);
         snmp.loop();
+        if (mpod.getChannel() != channel) {
+            // We have stale information, because MPOD swallowed UDP request.
+            // Skip this update check and go for next iteration, where data will be requested
+            // or request resent.
+            continue;
+        }
         loopCount += 1;
         ramping = (mpod.isRampingUp() || mpod.isRampingDown());
         if (!ramping) {
@@ -267,7 +273,7 @@ void setChannelStateAndWait(const IPAddress *ipAddr, const uint16_t channel, con
                 settingChannelState = false;
             } else if (loopCount >= 5) {
                 // There were no changes in 5 reads, it might be that the command (UDP)
-                // got swallowed by the MPOD controller while doing something else.
+                // got swallowed by the MPOD controller while it was doing something else.
                 Serial.print("!Resend command to ");
                 Serial.println(channel);
                 SNMP::Message *snmp_msg = mpod.setChannelState(channel, output);
diff --git a/pins.cpp b/pins.cpp
index 03a94ccebd9cbf5ef6bff9fca4021c4694b8c2d9..f689b3b3ca86f482a49aeaae01f943ec1ac43bda 100644
--- a/pins.cpp
+++ b/pins.cpp
@@ -72,6 +72,7 @@ void isr_check_loop() {
     // If not all ok, set the power down flag, later handled.
     if (!(PINS.sib && PINS.plc && PINS.ups)) {
         PERFORM_PROCEDURE_FROM_INTERRUPT = 1;
+        PINS.canDoPowerFromREST = true;
     }
 }
 
diff --git a/pins.hpp b/pins.hpp
index e1efb053f3824ff5eeb9d3b30c7312e44c2caec9..70a5ff37690a2998755db03a39bd308342e9194f 100644
--- a/pins.hpp
+++ b/pins.hpp
@@ -26,6 +26,7 @@ struct pins {
    int last_triggered;
    String stage;
    bool ramping;
+   bool canDoPowerFromREST;
 };
 extern struct pins PINS;
 
diff --git a/rest.cpp b/rest.cpp
index c6536cc54d3bd9401416f7f988e43894e2623180..3a73c7f3ecaa6a83c2bf1c8943357ca80da360d7 100644
--- a/rest.cpp
+++ b/rest.cpp
@@ -25,6 +25,8 @@ void initializeRoutes() {
     restServer.on("/", panel);
     restServer.on("/poll", pollMPODChannel);
 
+    restServer.on("/mpodstatus", getMpodStatus);
+
     restServer.on("/power", powerGroup);
     restServer.on("/alloff", powerAllOff);
 
@@ -82,9 +84,9 @@ void identify() {
     message += "\"ramping\":";
     message += PINS.ramping;
     message += ",\n";
-    message += "\"stage\":";
+    message += "\"stage\": \"";
     message += PINS.stage;
-    message += ",\n";
+    message += "\"\n";
     message += "\n}";
 
     message += "\n}";
@@ -131,6 +133,10 @@ enum {
 };
 
 void sendSNMP() {
+    if (PINS.ramping) {
+        restServer.send(403, "text/json", "{\"success\": 0, \"reason\": \"ramping ongoing\"}");
+        return;
+    }
     uint8_t output = NONE;
     uint16_t channel = 0;
     bool success = false;
@@ -177,7 +183,20 @@ void sendSNMP() {
     restServer.send(success ? 200 : 406, "text/json", http_msg);
 }
 
+void getMpodStatus() {
+    if (PINS.ramping) {
+        restServer.send(403, "text/json", "{\"success\": 0, \"reason\": \"ramping ongoing\"}");
+        return;
+    }
+
+    restServer.send(200, "text/json", pproc.toJSON());
+}
+
 void powerGroup() {
+    if (PINS.ramping) {
+        restServer.send(403, "text/json", "{\"success\": 0, \"reason\": \"ramping ongoing\"}");
+        return;
+    }
     String output;
     String group;
     String ret;
@@ -202,11 +221,19 @@ void powerGroup() {
     }
 
     if (output && group) {
+        PINS.ramping = true;
+        PINS.stage = group;
+
         if (output == "on") {
+            PINS.stage += " going up";
             success = pproc.powerOn(group);
         } else if (output == "off") {
+            PINS.stage += " going down";
             success = pproc.powerOff(group);
         }
+
+        PINS.ramping = false;
+        PINS.stage = "";
     }
 
     String http_msg = "{\n";
@@ -224,6 +251,10 @@ void powerGroup() {
 }
 
 void powerAllOff() {
+    if (PINS.ramping) {
+        restServer.send(403, "text/json", "{\"success\": 0, \"reason\": \"ramping ongoing\"}");
+        return;
+    }
     String group;
     String groups;
     bool success = false;
diff --git a/rest.hpp b/rest.hpp
index aab65f0e39d167aff2b2ca94e6fbe5a51a8ea192..8206b58b32915c3f35f047651124d91e8b785fd2 100644
--- a/rest.hpp
+++ b/rest.hpp
@@ -13,3 +13,4 @@ void panel(); // / show a status page
 void pollMPODChannel();  // /poll?ch=1
 void powerGroup(); // /power?group=ASICS&output=on
 void powerAllOff(); // /alloff?token=CWH
+void getMpodStatus();  // /mpodstatus