Here is my final optimised code version.
Have fun!
// This software uses an ARDUINO NANO to make a "MAGIC SWITCH BOX". A great magic illusion trick.
// If you using other type of ARDUINO board, please adjust for used light- and switch- pins.
// What is a "MAGIC SWITCH BOX"?? .... check on youtube! http://www.youtube.com/watch?v=0lGP8nQLANU
// My verion have the function for user to secretly select 4 versions of lamp-light sequense.
// Written by Hans Naesstroem Stockholm SWEDEN jun 2014. The program is free to use by anyone.
// The order of lamps is default 1-2-3-4 and after that set by last switch turned off and time out.
// If last switch off = 2 gets seq 2 = 2-1-3-4. 3 gets seq 3 = 3-4-1-2. and 4 gets seq 4 = 4-3-2-1.
// Condition for reset is: All switches off AND done>0 AND reset_time elapsed --- then resets to new
// seq determent by last switch off, 1-2-3 or 4.
// Remember to start unit with all switches in OFF (open) state.
#include <PinChangeInt.h> // multi interrupt pins handler. download if you dont have it installed.
#define pin_sw1 2 // defines for interrups.
#define pin_sw2 3 // pin_sw2 (switch 2) is connected to digital pin 3 and Ground. Switch NO.
#define pin_sw3 4
#define pin_sw4 5
// #define NO_PORTB_PINCHANGES ( Port B is all needed for this project).
#define NO_PORTC_PINCHANGES // not used, so save time and memory.
#define NO_PORTD_PINCHANGES
uint8_t latest_interrupted_pin;
// `latest_interrupted_pin` will allways show what pin that trigged the latest interrupt
const int pin_la1 = 10; // pin_la1 (lamp 1) connected to digital pin 10 and Ground.
const int pin_la2 = 11;
const int pin_la3 = 12;
const int pin_la4 = 13;
int swi[]={0,0,0,0}; // switches related to lamps, (to be lerned in program run).
int stat[]={1,1,1,1}; // initiate status of switches, active low.
int seq=1; // sequence to lit lamps, 1=1234, 2=2143, 3=3412, 4=4321.
int done=0; // lerned number of switches.
int last_off=1;
unsigned long time_out = millis(); // to calculate time_out.
void setup()
{
pinMode(pin_sw1,INPUT_PULLUP); // pin_sw1 (switch 1) connected to digital pin 2 and ground.
pinMode(pin_sw2,INPUT_PULLUP); // internal pullup used.
pinMode(pin_sw3,INPUT_PULLUP);
pinMode(pin_sw4,INPUT_PULLUP);
PCintPort::attachInterrupt (pin_sw1, Int_swi, CHANGE); // call Int_swi when pin_sw1 changes status.
PCintPort::attachInterrupt (pin_sw2, Int_swi, CHANGE);
PCintPort::attachInterrupt (pin_sw3, Int_swi, CHANGE);
PCintPort::attachInterrupt (pin_sw4, Int_swi, CHANGE);
pinMode(pin_la1,OUTPUT); // lamp pin is an output.
pinMode(pin_la2,OUTPUT);
pinMode(pin_la3,OUTPUT);
pinMode(pin_la4,OUTPUT);
digitalWrite(pin_la1,LOW); // turn off all lamps.
digitalWrite(pin_la2,LOW);
digitalWrite(pin_la3,LOW);
digitalWrite(pin_la4,LOW);
Serial.begin(9600); // enable serial monitor for debugging.
}
uint8_t i;
void loop() // MAIN LOOP ---------------------------
{
time_out=millis();
do {
latest_interrupted_pin=PCintPort::arduinoPin ;
last_off = latest_interrupted_pin-1;
if (seq<1) {seq=1;} // You may comment out all Serial.print when serial monitor not in use.
Serial.print ("swi[0]: "); Serial.print (swi[0]); Serial.print (" stat[0]: "); Serial.println (stat[0]);
Serial.print ("swi[1]: "); Serial.print (swi[1]); Serial.print (" stat[1]: "); Serial.println (stat[1]);
Serial.print ("swi[2]: "); Serial.print (swi[2]); Serial.print (" stat[2]: "); Serial.println (stat[2]);
Serial.print ("swi[3]: "); Serial.print (swi[3]); Serial.print (" stat[3]: "); Serial.println (stat[3]);
Serial.print (" done: ");
Serial.println (done);
Serial.print (" seq: ");
Serial.println (seq);
Serial.println ("------------------------------------------------");
delay (1000);
}
while (millis()<((time_out)+4000)); // set to preferred time out (4 sec).
Serial.println ("Timed out !!! ...");
if ((stat[0]==1) && (stat[1]==1) && (stat[2]==1) && (stat[3]==1)&& (done>0)){
Serial.println ("Running reset");
latest_interrupted_pin=PCintPort::arduinoPin ;
seq=latest_interrupted_pin-1;
if (seq<1) {seq=1;}
swi[0] =0; swi[1] =0; swi[2] =0; swi[3] =0; // lamps related to switches.
done=0;
}
} // END MAIN LOOP. -------------------------------
void Int_swi() // interrupt trigged by switches, CHANGE. ---------------------------------------
{
time_out = millis();
latest_interrupted_pin=PCintPort::arduinoPin ;
int sw = latest_interrupted_pin-2; // sw = 0,1,2 or 3
if (swi[sw] > 0) {stat[sw] = !stat[sw]; digitalWrite(swi[sw],stat[sw]); } // turn on/off lamp
else {
switch (seq){
case 1: {swi[sw] = done+10;} break;
case 2: {{swi[sw] = 11-done;}
if (swi[sw]<10) {swi[sw]= (10+done);}} break;
case 3: {{swi[sw] = 12+done;}
if (swi[sw]>13) {swi[sw] = (8+done);}} break;
case 4: {swi[sw] = 13-done;} break;
}
digitalWrite (swi[sw],LOW); stat[sw] = !stat[sw]; // turn on lamp
++done; // increment counter for switches learned.
}
}