Final MAGIC SWITCH BOX a great magic illusion trick

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.
    }
        }

Thanks for the post,
You just need to do one more thing:

click the MODIFY button in the upper right of the post window.
Highlight all you code.
click the "#" CODE TAGS button on the toolbar above just to the left of the QUOTE button.
click SAVE (at the bottom).
When you post code on the forum, please make a habit of using the code tags "#" button.

Just a question,

How would we conenct up the lamps and switches?

Genuiely confused

Start your own post .
It is considered impolite to hijack someone else's thread.

raschemmel:
Start your own post .
It is considered impolite to hijack someone else's thread.

What is the impoliteness?

As I read it, the133448 is asking how the box is wired up?

I have build the box and used this code. Unfotunately it was not working. After a small change ( invert the digital write by adding a not ! !stat_sw1 ) it works like a charm!

and this

pouvez vous le faire sur ce site en émulation....

I am totally new to Arduino, but have been studying. Hope someone can help me here. I built the circuit and downloaded the code to my Arduino NANO, but my lights don't light. Two questions: Could my problem be that I used 6V incandescent bulbs instead of LED's? Also, one person said he had to add a "!" (not) in the code to make it work, but I can't see where in the code to try that. Can you be more specific for me? Thanks for any help.