Skip to content
Snippets Groups Projects
Commit c8cde2a0 authored by Cyril Danilevski's avatar Cyril Danilevski :scooter:
Browse files

Perform power down sequence from port expander interrupt

parent 4d32668b
No related branches found
No related tags found
1 merge request!5Perform power down sequence from port expander trigger
Pipeline #166084 passed
......@@ -15,11 +15,13 @@ void setup() {
initializeRoutes();
initializeSNMP();
start = millis();
// Poll port expander to initialize the PINS struct.
poll_port_expander();
PINS.last_triggered = millis();
PINS.stage = "";
PINS.ramping = false;
start = millis();
}
enum {
......@@ -28,7 +30,7 @@ enum {
OFF,
};
void serial_loop() {
void serialLoop() {
if (millis() - start >= 1000) {
start = millis();
Serial.print(eth_connected ? "." : "-");
......@@ -40,5 +42,8 @@ void loop() {
snmp.loop();
restServer.handleClient();
toggle_status_led();
serial_loop();
serialLoop();
if (eth_connected) { // We may be triggered, but disconnected from the network.
powerOffCheckLoop();
}
}
#include "pins.hpp"
#include "powerproc.hpp"
MCP23S08 MCP(SS, MISO, MOSI, SCK);
volatile byte ISR_FLAG = 0;
// Semaphores for handling interrupts and power down events.
volatile byte MCP_ISR_FLAG = 0;
volatile byte PERFORM_PROCEDURE_FROM_INTERRUPT = 0;
struct pins PINS;
void IRAM_ATTR isr() { ISR_FLAG = 1; }
void IRAM_ATTR isr() { MCP_ISR_FLAG = 1; }
void initializeMCP() {
pinMode(ISR_PIN, INPUT_PULLUP);
......@@ -18,40 +24,54 @@ void initializeMCP() {
MCP.enableInterrupt(0, CHANGE);
MCP.enableInterrupt(1, CHANGE);
MCP.enableInterrupt(2, CHANGE);
// Inform SIB we're ready
MCP.write1(ALERT_SIB_PIN, HIGH);
Serial.println("MCP23S08 Started");
}
void isr_check_loop() {
if (ISR_FLAG == 1) {
PINS.sib = false;
PINS.plc = false;
PINS.ups = false;
PINS.last_triggered = millis();
Serial.print("Interrupt: ");
uint8_t regval = MCP.getInterruptCaptureRegister(); // INTCAP
Serial.print(regval, BIN);
uint8_t mask = 1 << 0;
if (!(regval & mask)) {
Serial.print(" UPS");
PINS.ups = true;
}
mask = 1 << 1;
if (!(regval & mask)) {
Serial.print(" PLC");
PINS.plc = true;
}
mask = 1 << 2;
if (!(regval & mask)) {
Serial.print(" SIB");
PINS.sib = true;
}
Serial.println();
ISR_FLAG = 0;
if (MCP_ISR_FLAG == 0) {
return;
}
// False means triggered (not ok).
PINS.sib = false;
PINS.plc = false;
PINS.ups = false;
PINS.last_triggered = millis();
// Get the pins status at the time of the interrupt, and check their statuses.
Serial.print("Interrupt: ");
uint8_t regval = MCP.getInterruptCaptureRegister(); // INTCAP
Serial.print(regval, BIN);
uint8_t mask = 1 << 0;
if (!(regval & mask)) {
Serial.print(" UPS");
PINS.ups = true;
}
mask = 1 << 1;
if (!(regval & mask)) {
Serial.print(" PLC");
PINS.plc = true;
}
mask = 1 << 2;
if (!(regval & mask)) {
Serial.print(" SIB");
PINS.sib = true;
}
Serial.println();
// This interrupt was handled
MCP_ISR_FLAG = 0;
// If not all ok, set the power down flag, later handled.
if (!(PINS.sib && PINS.plc && PINS.ups)) {
PERFORM_PROCEDURE_FROM_INTERRUPT = 1;
}
}
......@@ -59,7 +79,6 @@ void poll_port_expander() {
PINS.sib = false;
PINS.plc = false;
PINS.ups = false;
PINS.last_triggered = millis();
int regval = MCP.read8();
uint8_t mask = 1 << 0;
......@@ -92,3 +111,56 @@ void toggle_status_led() {
MCP.write1(STATUS_LED_PIN, on);
}
}
void powerOffCheckLoop() {
if (!PERFORM_PROCEDURE_FROM_INTERRUPT) {
return;
}
// Disable interrupts while performing power procedure.
// Once we've been triggered, we perform the power down procedure, uninterrupted,
// regardless of changes in the environment.
detachInterrupt(digitalPinToInterrupt(ISR_PIN));
// Update status on serial interface and status webpage.
PINS.ramping = true;
Serial.println("POWERING DOWN DUE TO TRIGGER.");
// Inform SIB that we're about to perform a procedure.
MCP.write1(ALERT_SIB_PIN, LOW);
Serial.println("asked sib down");
// Wait for SIB to acknowledge by checking its input (should go to triggered).
/* This require hardware changes, not implemented yet.
// TODO: apply a timeout and go ahead anyway?
do {
delay(200);
poll_port_expander();
} while(!(PINS.sib));
Serial.println("SIB ACK");
*/
// Iterate through each group and power down.
String group;
String groups;
for (int8_t groupIdx = pproc.stagesCount - 1; groupIdx >= 0; groupIdx--) {
group = pproc.stages[groupIdx].name;
groups += group;
groups += ",";
PINS.stage = group;
pproc.powerOff(group);
delay(1000);
}
// Clear statuses on webpage and serial interfaces.
PINS.ramping = false;
Serial.print("Finished powering down from interrupt: ");
Serial.println(groups);
PINS.stage = "Ramped down";
// This event has been handled.
PERFORM_PROCEDURE_FROM_INTERRUPT = 0;
// Inform SIB that we're done and it can take data again.
MCP.write1(ALERT_SIB_PIN, HIGH);
// Re-enable interrupts before exiting.
attachInterrupt(digitalPinToInterrupt(ISR_PIN), isr, CHANGE);
}
......@@ -13,9 +13,12 @@
//AlCon Logic Board interrupt
#define TRIGGER_SIGNAL 14
// LED pin on MCP23S08 extender
// LED pin on MCP23S08 expander
#define STATUS_LED_PIN 6
// Pin to inform SIB that a power down is about to happen, on MCP23S08 expander
#define ALERT_SIB_PIN 7
struct pins {
bool sib;
bool plc;
......@@ -32,3 +35,4 @@ void initializeMCP();
void isr_check_loop();
void poll_port_expander();
void toggle_status_led();
void powerOffCheckLoop();
......@@ -34,4 +34,6 @@ public:
String toJSON();
};
void powerOffCheckLoop();
extern PowerProcedure pproc;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment