]> git.0d.be Git - PanikSwitch.git/blob - FINAL2013V2.ino
notify selection change over udp
[PanikSwitch.git] / FINAL2013V2.ino
1 // Panik Web Form Demo
2
3
4
5 // define network constants
6 #define MAC_DAVID { 0x90, 0xA2, 0xDA, 0x0D, 0xF4, 0x63 }
7 #define MAC_PANIK { 0x90, 0xA2, 0xDA, 0x00, 0x9A, 0x94 }
8 #define MAC_PANIK2 { 0x90, 0xA2, 0xDA, 0x0E, 0xF3, 0x77 }
9 #define MAC_ADDRESS MAC_PANIK2
10
11 // include Arduino libraries
12 #include <Wire.h>
13 #include <SPI.h>
14 #include <SD.h>
15 #include <Ethernet.h>
16 #include <EthernetUdp.h>
17
18 // include third party libraries
19 #include "WebServer.h"
20
21 // include in-house libs
22 #include "PanikSwitch.h"    // contains variable types for panik switch
23
24 // define SD and Ethernet select ports
25 #define  SD_SELECT            4
26 #define  ETHERNET_SELECT     10
27
28 // define machine variables
29 #define DEBOUNCE_TRESHOLD     10   // 10 milliseconds
30 #define ABORT_TRESHOLD     3000L   // 3 seconds
31 #define PULSE_TRESHOLD        50   // 50 milliseconds
32 #define BLINK_TRESHOLD       100   // 100 milliseconds
33
34 // output pins
35 #define RELAY_BUTTON_LEDS        5   // Button LED indicator
36 #define RELAY_GREEN_LEDS         6   // ``Non-Stop`` LED indicator
37 #define RELAY_RED_LEDS           8   // ``Studio 1`` LED indicator
38 #define RELAY_YELLOW_LEDS        7   // ``Studio 2`` LED indicator
39
40 #define RELAY_NONSTOP_OR_STUD    4   // Relay : Non-stop or Studio
41 #define RELAY_STUD1_OR_STUD2     9   // Relay : Studio 1 or Studio 2
42
43 // input pins
44 #define BUTTON1                  2   // ``Select`` button
45 #define BUTTON2                  3   // ``Confirm`` button
46 #define NONSTOP_VIA_STUD1       14   // is nonstop coming out of studio 1
47 #define NONSTOP_VIA_STUD2       15   // is nonstop coming out of studio 2
48
49
50
51 /* define an array with led pins,
52    indexes in that array correspond to the values of possible selections
53    i.e.: RELAY_GREEN_LEDS: nonstop, RELAY_RED_LEDS: studio1, RELAY_YELLOW_LEDS: studio2
54 */
55 const int ledsArray[] = { RELAY_GREEN_LEDS, RELAY_RED_LEDS, RELAY_YELLOW_LEDS };
56
57
58 /* activeSelection is the variable that holds the active output of the switch
59    it is declared as an attribute that keeps its value between arduino resets
60 */
61 switchSelection_t activeSelection __attribute__ ((section (".noinit")));
62
63 // variables and timers for blinking selection (selected but not confirmed)
64 switchSelection_t blinkingSelection = nonstop;
65 bool blinkingLedState = RELAY_STATE_CLOSED;
66 unsigned long blinkingStartTime = 0, blinkingAbortTime = 0;
67
68
69 // declaration of possible button states as enum type
70 typedef enum { nochange, pressed, released } buttonEvent_t;
71
72 // button event timers
73 unsigned long button1LastEventTime = 0, button2LastEventTime = 0;
74
75 // variables holding the state of each button
76 // these are used during the debouncing process
77 uint8_t button1State = LOW, button2State = LOW;
78
79 // variables holding the non-stop status from studios 1 & 2
80 bool nonstop_via_stud1, nonstop_via_stud2;
81
82 // declare functions
83 buttonEvent_t debounce( const uint8_t buttonPin,
84                         uint8_t *buttonState,
85                         unsigned long *buttonLastEventTime );
86
87 static uint8_t mac[] = MAC_ADDRESS;
88 #define PREFIX ""
89
90 // instanciate web server
91 WebServer webserver(PREFIX, 80);
92
93 // and EthernetUDP instance to send notifications
94 EthernetUDP Udp;
95 IPAddress udp_remote_ip(192, 168, 17, 224);
96
97
98 #define NAMELEN 4
99 #define VALUELEN 4
100
101 typedef enum responseStatus { NO_POST, POST_OK, POST_ERROR };
102
103
104 // web resource
105 void webCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
106 {
107
108   server.httpSuccess("application/json");
109
110   if (type == WebServer::HEAD)
111     return;
112
113   responseStatus response_status = NO_POST;
114
115   if (type == WebServer::POST)
116   {
117     char name[NAMELEN];
118     int  name_len;
119     char value[VALUELEN];
120     int value_len;
121
122     response_status = POST_ERROR;
123
124     while (server.readPOSTparam(name, NAMELEN, value, VALUELEN))
125     {
126       if (strcmp(name, "s") == 0) {
127         digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED);
128         blinkingSelection = static_cast<switchSelection_t>(atoi(value));
129         activeSelection = static_cast<switchSelection_t>(atoi(value));
130         response_status = POST_OK;
131       }
132     }
133   }
134
135   server.println(F("{"));
136
137   server.print(" \"response\": ");
138   server.print(response_status);
139
140   server.print(",\n \"active\": ");
141   server.print(activeSelection);
142
143   server.print(",\n \"nonstop-via-stud1\": ");
144   server.print(nonstop_via_stud1);
145   server.print(",\n \"nonstop-via-stud2\": ");
146   server.println(nonstop_via_stud2);
147
148   server.println(F("}"));
149 }
150
151
152 // setup function
153 void setup()
154 {
155   // make sure that activeSelection holds something valid
156 //  if (!(activeSelection > nonstop) || !(activeSelection < _NbrSwitchSelections))
157 //    activeSelection = nonstop;
158   blinkingSelection = activeSelection = nonstop;
159
160   // open serial communication for debugging
161   Serial.begin(9600);
162   Serial.println(F("Startup"));
163
164   // disable SD and Ethernet ports before setup
165   pinMode(SD_SELECT, OUTPUT);
166   digitalWrite(SD_SELECT, HIGH);                  // disable SD card
167   pinMode(ETHERNET_SELECT, OUTPUT);
168   digitalWrite(ETHERNET_SELECT, HIGH);           // disable Ethernet
169
170   // start SPI (because Ethernet shield needs it)
171   SPI.begin();                                          // start SPI
172
173   // start Ethernet
174   if (!(Ethernet.begin(mac) == 0))                    // start network
175     Serial.println(Ethernet.localIP());
176   else
177   {
178     Serial.println(F("Network Error"));
179     while (1) ;
180   }
181   if (! Udp.begin(1312)) {
182     Serial.println(F("Failed to initiate UDP"));
183   }
184
185   // set mode for used pins
186   pinMode(RELAY_RED_LEDS, OUTPUT);
187   digitalWrite(RELAY_RED_LEDS, RELAY_STATE_CLOSED);
188   pinMode(RELAY_YELLOW_LEDS, OUTPUT);
189   digitalWrite(RELAY_YELLOW_LEDS, RELAY_STATE_CLOSED);
190   pinMode(RELAY_GREEN_LEDS, OUTPUT);
191   digitalWrite(RELAY_GREEN_LEDS, RELAY_STATE_CLOSED);
192   pinMode(RELAY_BUTTON_LEDS, OUTPUT);
193   digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED);
194
195   pinMode(RELAY_NONSTOP_OR_STUD, OUTPUT);
196   digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED);
197   pinMode(RELAY_STUD1_OR_STUD2, OUTPUT);
198   digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
199
200   pinMode(BUTTON1, INPUT);
201   pinMode(BUTTON2, INPUT);
202   pinMode(NONSTOP_VIA_STUD1, INPUT);
203   pinMode(NONSTOP_VIA_STUD2, INPUT);
204
205   // configure web server pages
206   webserver.setDefaultCommand(&webCmd);
207
208   // start web server
209   webserver.begin();
210 }
211
212
213 // loop function
214 void loop()
215 {
216   // update variables indicating if non-stop is selected in studios 1&2
217   nonstop_via_stud1 = digitalRead(NONSTOP_VIA_STUD1);
218   if (nonstop_via_stud1 == 0)
219     nonstop_via_stud1 = 1;
220   else
221     nonstop_via_stud1 = 0;
222   nonstop_via_stud2 = digitalRead(NONSTOP_VIA_STUD2);
223   if (nonstop_via_stud2 == 0)
224     nonstop_via_stud2 = 1;
225   else
226     nonstop_via_stud2 = 0;
227
228   // check if we have a HTTP request (and respond)
229   webserver.processConnection();
230
231   // handle button 1 (select button)
232   switch ( debounce(BUTTON1, &button1State, &button1LastEventTime) )
233   {
234     case nochange:
235       break;
236     case pressed:
237       //Serial.println(F("Button 1 pressed"));
238       digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED);
239       blinkingSelection++;
240       blinkingStartTime = millis(),
241       blinkingAbortTime = millis();
242       blinkingLedState = RELAY_STATE_OPEN;
243       break;
244     case released:
245       //Serial.println(F("Button 1 released"));
246       break;
247   }
248
249   // handle button 2 (confirm button)
250   switch ( debounce(BUTTON2, &button2State, &button2LastEventTime) )
251   {
252     case nochange:
253       break;
254     case pressed:
255       //Serial.println(F("Button 2 pressed"));
256       blinkingAbortTime = 0;        // disable blinking auto abort
257       break;
258     case released:
259       //Serial.println(F("Button 2 released"));
260       if (activeSelection != blinkingSelection)
261       {
262         char str_selection[20];
263         digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED);
264         activeSelection = blinkingSelection;  // relay states must be changed now
265         Serial.print(F("Active Selection: "));
266         Serial.println(activeSelection);
267         // notify over UDP
268         snprintf(str_selection, 19, "{\"active\": %d}", activeSelection);
269         Udp.beginPacket(udp_remote_ip, 1312);
270         Udp.write(str_selection);
271         Udp.endPacket();
272         break;
273       }
274   }
275
276   // handle auto abort for blinking led (if any)
277   if ( (blinkingAbortTime != 0) &&
278        ((millis() - blinkingAbortTime) >= ABORT_TRESHOLD) ) {
279     digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED);
280     blinkingAbortTime = 0;
281     blinkingSelection = activeSelection;
282   }
283
284   // handle blinking led (if selected is not current state)
285   if (activeSelection != blinkingSelection) {
286     if ((millis() - blinkingStartTime) >= BLINK_TRESHOLD) {
287       digitalWrite(ledsArray[blinkingSelection], blinkingLedState);
288       digitalWrite(RELAY_BUTTON_LEDS, !blinkingLedState);
289       blinkingStartTime = millis();
290       blinkingLedState = !blinkingLedState;
291     }
292   }
293   else {
294     digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED);
295   }
296
297   digitalWrite(ledsArray[activeSelection], RELAY_STATE_OPEN);
298
299   // update audio channel relays
300   if (activeSelection == nonstop)
301   {
302     digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED);
303     digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
304   }
305   else if (activeSelection == studio1)
306   {
307     digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN);
308     digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
309   }
310   else if (activeSelection == studio2)
311   {
312     digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN);
313     digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_OPEN);
314   }
315 }
316
317 buttonEvent_t debounce( const uint8_t buttonPin,
318                         uint8_t *buttonState,
319                         unsigned long *buttonLastEventTime )
320 {
321   uint8_t buttonLastState = *buttonState;
322   uint8_t buttonReading = digitalRead(buttonPin);
323
324   if ( (*buttonLastEventTime == 0) &&
325        (*buttonState != buttonReading) ) {
326     // something happened, start the debouncing process
327     *buttonLastEventTime = millis();
328   }
329
330   if (*buttonLastEventTime != 0) {
331     long buttonEventTimer = millis() - *buttonLastEventTime;
332
333     if ( (buttonEventTimer < DEBOUNCE_TRESHOLD) &&
334          (*buttonState == buttonReading) ) {
335       // noise or bouncing, abort
336       *buttonLastEventTime = 0;
337     }
338
339     if ( (buttonEventTimer >= DEBOUNCE_TRESHOLD) &&
340          (buttonReading != *buttonState) ) {
341       // new button state was maintained
342       *buttonLastEventTime = 0;
343       *buttonState = buttonReading;
344     }
345   }
346
347   // debouncing finished, return button state
348   if (*buttonLastEventTime == 0) {
349     // comparing buttonState and buttonLastState tells whether the
350     // button is pressed or released
351     if ( (*buttonState == HIGH) &&
352          (buttonLastState == LOW) ) {
353       // button just pressed
354       buttonLastState = *buttonState;
355       return pressed;
356     }
357     if ( (*buttonState == LOW) &&
358          (buttonLastState == HIGH) ) {
359       // button just released
360       buttonLastState = *buttonState;
361       return released;
362     }
363   }
364   return nochange;
365 }
366