// Panik Web Form Demo // define network constants #define MAC_DAVID { 0x90, 0xA2, 0xDA, 0x0D, 0xF4, 0x63 } #define MAC_PANIK { 0x90, 0xA2, 0xDA, 0x00, 0x9A, 0x94 } #define MAC_PANIK2 { 0x90, 0xA2, 0xDA, 0x0E, 0xF3, 0x77 } #define MAC_ADDRESS MAC_PANIK // include Arduino libraries #include #include #include #include // include third party libraries #include "WebServer.h" // include in-house libs #include "PanikSwitch.h" // contains variable types for panik switch // define SD and Ethernet select ports #define SD_SELECT 4 #define ETHERNET_SELECT 10 // define machine variables #define DEBOUNCE_TRESHOLD 10 // 10 milliseconds #define ABORT_TRESHOLD 3000L // 3 seconds #define PULSE_TRESHOLD 50 // 50 milliseconds #define BLINK_TRESHOLD 100 // 100 milliseconds // output pins #define RELAY_BUTTON_LEDS 5 // Button LED indicator #define RELAY_GREEN_LEDS 6 // ``Non-Stop`` LED indicator #define RELAY_RED_LEDS 8 // ``Studio 1`` LED indicator #define RELAY_YELLOW_LEDS 7 // ``Studio 2`` LED indicator #define RELAY_NONSTOP_OR_STUD 4 // Relay : Non-stop or Studio #define RELAY_STUD1_OR_STUD2 9 // Relay : Studio 1 or Studio 2 // input pins #define BUTTON1 2 // ``Select`` button #define BUTTON2 3 // ``Confirm`` button #define NONSTOP_VIA_STUD1 14 // is nonstop coming out of studio 1 #define NONSTOP_VIA_STUD2 15 // is nonstop coming out of studio 2 /* define an array with led pins, indexes in that array correspond to the values of possible selections i.e.: RELAY_GREEN_LEDS: nonstop, RELAY_RED_LEDS: studio1, RELAY_YELLOW_LEDS: studio2 */ const int ledsArray[] = { RELAY_GREEN_LEDS, RELAY_RED_LEDS, RELAY_YELLOW_LEDS }; /* activeSelection is the variable that holds the active output of the switch it is declared as an attribute that keeps its value between arduino resets */ switchSelection_t activeSelection __attribute__ ((section (".noinit"))); // variables and timers for blinking selection (selected but not confirmed) switchSelection_t blinkingSelection = nonstop; bool blinkingLedState = RELAY_STATE_CLOSED; unsigned long blinkingStartTime = 0, blinkingAbortTime = 0; // declaration of possible button states as enum type typedef enum { nochange, pressed, released } buttonEvent_t; // button event timers unsigned long button1LastEventTime = 0, button2LastEventTime = 0; // variables holding the state of each button // these are used during the debouncing process uint8_t button1State = LOW, button2State = LOW; // variables holding the non-stop status from studios 1 & 2 bool nonstop_via_stud1, nonstop_via_stud2; // declare functions buttonEvent_t debounce( const uint8_t buttonPin, uint8_t *buttonState, unsigned long *buttonLastEventTime ); static uint8_t mac[] = MAC_ADDRESS; #define PREFIX "" // instanciate web server WebServer webserver(PREFIX, 80); #define NAMELEN 4 #define VALUELEN 4 typedef enum responseStatus { NO_POST, POST_OK, POST_ERROR }; // web resource void webCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete) { server.httpSuccess("application/json"); if (type == WebServer::HEAD) return; responseStatus response_status = NO_POST; if (type == WebServer::POST) { return; char name[NAMELEN]; int name_len; char value[VALUELEN]; int value_len; response_status = POST_ERROR; while (server.readPOSTparam(name, NAMELEN, value, VALUELEN)) { if (strcmp(name, "s") == 0) { digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED); blinkingSelection = static_cast(atoi(value)); activeSelection = static_cast(atoi(value)); response_status = POST_OK; } } } server.println(F("{")); server.print(" \"response\": "); server.print(response_status); server.print(",\n \"active\": "); server.print(activeSelection); server.print(",\n \"nonstop-via-stud1\": "); server.print(nonstop_via_stud1); server.print(",\n \"nonstop-via-stud2\": "); server.println(nonstop_via_stud2); server.println(F("}")); } // setup function void setup() { // make sure that activeSelection holds something valid // if (!(activeSelection > nonstop) || !(activeSelection < _NbrSwitchSelections)) // activeSelection = nonstop; blinkingSelection = activeSelection = nonstop; // open serial communication for debugging Serial.begin(9600); Serial.println(F("Startup")); // disable SD and Ethernet ports before setup pinMode(SD_SELECT, OUTPUT); digitalWrite(SD_SELECT, HIGH); // disable SD card pinMode(ETHERNET_SELECT, OUTPUT); digitalWrite(ETHERNET_SELECT, HIGH); // disable Ethernet // start SPI (because Ethernet shield needs it) SPI.begin(); // start SPI // start Ethernet if (!(Ethernet.begin(mac) == 0)) // start network Serial.println(Ethernet.localIP()); else { Serial.println(F("Network Error")); while (1) ; } // set mode for used pins pinMode(RELAY_RED_LEDS, OUTPUT); digitalWrite(RELAY_RED_LEDS, RELAY_STATE_CLOSED); pinMode(RELAY_YELLOW_LEDS, OUTPUT); digitalWrite(RELAY_YELLOW_LEDS, RELAY_STATE_CLOSED); pinMode(RELAY_GREEN_LEDS, OUTPUT); digitalWrite(RELAY_GREEN_LEDS, RELAY_STATE_CLOSED); pinMode(RELAY_BUTTON_LEDS, OUTPUT); digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED); pinMode(RELAY_NONSTOP_OR_STUD, OUTPUT); digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED); pinMode(RELAY_STUD1_OR_STUD2, OUTPUT); digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED); pinMode(BUTTON1, INPUT); pinMode(BUTTON2, INPUT); pinMode(NONSTOP_VIA_STUD1, INPUT); pinMode(NONSTOP_VIA_STUD2, INPUT); // configure web server pages webserver.setDefaultCommand(&webCmd); // start web server webserver.begin(); } // loop function void loop() { // update variables indicating if non-stop is selected in studios 1&2 nonstop_via_stud1 = digitalRead(NONSTOP_VIA_STUD1); if (nonstop_via_stud1 == 0) nonstop_via_stud1 = 1; else nonstop_via_stud1 = 0; nonstop_via_stud2 = digitalRead(NONSTOP_VIA_STUD2); if (nonstop_via_stud2 == 0) nonstop_via_stud2 = 1; else nonstop_via_stud2 = 0; // check if we have a HTTP request (and respond) webserver.processConnection(); // handle button 1 (select button) switch ( debounce(BUTTON1, &button1State, &button1LastEventTime) ) { case nochange: break; case pressed: //Serial.println(F("Button 1 pressed")); digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED); blinkingSelection++; blinkingStartTime = millis(), blinkingAbortTime = millis(); blinkingLedState = RELAY_STATE_OPEN; break; case released: //Serial.println(F("Button 1 released")); break; } // handle button 2 (confirm button) switch ( debounce(BUTTON2, &button2State, &button2LastEventTime) ) { case nochange: break; case pressed: //Serial.println(F("Button 2 pressed")); blinkingAbortTime = 0; // disable blinking auto abort break; case released: //Serial.println(F("Button 2 released")); if (activeSelection != blinkingSelection) { digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED); activeSelection = blinkingSelection; // relay states must be changed now Serial.print(F("Active Selection: ")); Serial.println(activeSelection); break; } } // handle auto abort for blinking led (if any) if ( (blinkingAbortTime != 0) && ((millis() - blinkingAbortTime) >= ABORT_TRESHOLD) ) { digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED); blinkingAbortTime = 0; blinkingSelection = activeSelection; } // handle blinking led (if selected is not current state) if (activeSelection != blinkingSelection) { if ((millis() - blinkingStartTime) >= BLINK_TRESHOLD) { digitalWrite(ledsArray[blinkingSelection], blinkingLedState); digitalWrite(RELAY_BUTTON_LEDS, !blinkingLedState); blinkingStartTime = millis(); blinkingLedState = !blinkingLedState; } } else { digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED); } digitalWrite(ledsArray[activeSelection], RELAY_STATE_OPEN); // update audio channel relays if (activeSelection == nonstop) { digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED); digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED); } else if (activeSelection == studio1) { digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN); digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED); } else if (activeSelection == studio2) { digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN); digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_OPEN); } } buttonEvent_t debounce( const uint8_t buttonPin, uint8_t *buttonState, unsigned long *buttonLastEventTime ) { uint8_t buttonLastState = *buttonState; uint8_t buttonReading = digitalRead(buttonPin); if ( (*buttonLastEventTime == 0) && (*buttonState != buttonReading) ) { // something happened, start the debouncing process *buttonLastEventTime = millis(); } if (*buttonLastEventTime != 0) { long buttonEventTimer = millis() - *buttonLastEventTime; if ( (buttonEventTimer < DEBOUNCE_TRESHOLD) && (*buttonState == buttonReading) ) { // noise or bouncing, abort *buttonLastEventTime = 0; } if ( (buttonEventTimer >= DEBOUNCE_TRESHOLD) && (buttonReading != *buttonState) ) { // new button state was maintained *buttonLastEventTime = 0; *buttonState = buttonReading; } } // debouncing finished, return button state if (*buttonLastEventTime == 0) { // comparing buttonState and buttonLastState tells whether the // button is pressed or released if ( (*buttonState == HIGH) && (buttonLastState == LOW) ) { // button just pressed buttonLastState = *buttonState; return pressed; } if ( (*buttonState == LOW) && (buttonLastState == HIGH) ) { // button just released buttonLastState = *buttonState; return released; } } return nochange; }