Make your own MAGIC SWITH BOX

Hi, This is my version of the MAGIC SWITH BOX !!!!
Please comment and give new ideas.
Also ideas for improvement is wellcome.

Have fun/ Hans

/

// This software uses an ARDUINO NANO to make a "MAGIC SWITCH BOX".
// 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!  Try.. http://www.youtube.com/watch?v=0lGP8nQLANU
// 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 turned off is 1 you get the new order seq = 1-2-3-4. 
// Last off = 2 gets seq = 2-1-3-4. 3 gets seq = 3-4-1-2. and 4 gets seq = 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. 

#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 sw1_la =0;   // lamp related to switch one, (to be lerned in program run).
int sw2_la =0;
int sw3_la =0;
int sw4_la =0;

int stat_sw1=1;  // present status of switch one, active low.
int stat_sw2=1;
int stat_sw3=1;
int stat_sw4=1;
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;   
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_swi1, CHANGE); // call Int_swi1 when pin_sw1 changes status.
  PCintPort::attachInterrupt (pin_sw2, Int_swi2, CHANGE);
  PCintPort::attachInterrupt (pin_sw3, Int_swi3, CHANGE); 
  PCintPort::attachInterrupt (pin_sw4, Int_swi4, 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(); 
  
        Serial.println ("Running main loop"); 
  
do {     
       latest_interrupted_pin=PCintPort::arduinoPin ;
       last_off = latest_interrupted_pin-1;
       
     if (seq<1) {seq=1;}
     
        Serial.print ("sw1_la: ");        // comment out all Serial.print when serial monitor not in use.
        Serial.print (sw1_la); 
        Serial.print (stat_sw1);        
        Serial.print ("    sw2_la: ");  
        Serial.print (sw2_la); 
        Serial.print (stat_sw2);         
        Serial.print ("    sw3_la: ");  
        Serial.print (sw3_la); 
        Serial.print (stat_sw3); 
        Serial.print ("    sw4_la: ");  
        Serial.print (sw4_la); 
        Serial.println (stat_sw4); 
        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_sw1==1) && (stat_sw2==1) && (stat_sw3==1) && (stat_sw4==1)&& (done>0)){
        
        Serial.println ("Running reset");
        
       seq=latest_interrupted_pin-1;  
   if (seq<1) {seq=1;}
       sw1_la =0;           // lamp related to switch one.
       sw2_la =0;
       sw3_la =0;
       sw4_la =0;
       done=0; 
 } 
     }                      // end of main loop.
  
//______________________________________________________________________  

void Int_swi1()    // interrupt trigged by swith 1, CHANGE.   
{  

  time_out = millis();
 // Serial.println ("Running Int_swi1");   // used for debug run.   

if (sw1_la > 0)  { stat_sw1 = !stat_sw1; digitalWrite(sw1_la,stat_sw1); 
}

  else {
if ((done==0) && (seq==1)) { sw1_la = 10;}  
if ((done==1) && (seq==1)) { sw1_la = 11;}
if ((done==2) && (seq==1)) { sw1_la = 12;}
if ((done==3) && (seq==1)) { sw1_la = 13;}  

if ((done==0) && (seq==2)) { sw1_la = 11;}  
if ((done==1) && (seq==2)) { sw1_la = 10;}
if ((done==2) && (seq==2)) { sw1_la = 13;}
if ((done==3) && (seq==2)) { sw1_la = 12;}

if ((done==0) && (seq==3)) { sw1_la = 12;}  
if ((done==1) && (seq==3)) { sw1_la = 13;}
if ((done==2) && (seq==3)) { sw1_la = 10;}
if ((done==3) && (seq==3)) { sw1_la = 11;} 

if ((done==0) && (seq==4)) { sw1_la = 13;}  
if ((done==1) && (seq==4)) { sw1_la = 12;}
if ((done==2) && (seq==4)) { sw1_la = 11;}
if ((done==3) && (seq==4)) { sw1_la = 10;} 

  digitalWrite (sw1_la,LOW); stat_sw1 = !stat_sw1;
  ++done;   // increment counter for switch learned.
  } 
      }
//______________________________________________________________________

void Int_swi2()   // interrupt trigged by swith 2, CHANGE.
    {
  time_out = millis();  

if (sw2_la > 0)  {  stat_sw2 = !stat_sw2; digitalWrite(sw2_la,stat_sw2); }

  else {
if ((done==0) && (seq==1)) { sw2_la = 10;}  
if ((done==1) && (seq==1)) { sw2_la = 11;}
if ((done==2) && (seq==1)) { sw2_la = 12;}
if ((done==3) && (seq==1)) { sw2_la = 13;}  

if ((done==0) && (seq==2)) { sw2_la = 11;}  
if ((done==1) && (seq==2)) { sw2_la = 10;}
if ((done==2) && (seq==2)) { sw2_la = 13;}
if ((done==3) && (seq==2)) { sw2_la = 12;} 

if ((done==0) && (seq==3)) { sw2_la = 12;}  
if ((done==1) && (seq==3)) { sw2_la = 13;}
if ((done==2) && (seq==3)) { sw2_la = 10;}
if ((done==3) && (seq==3)) { sw2_la = 11;} 

if ((done==0) && (seq==4)) { sw2_la = 13;}  
if ((done==1) && (seq==4)) { sw2_la = 12;}
if ((done==2) && (seq==4)) { sw2_la = 11;}
if ((done==3) && (seq==4)) { sw2_la = 10;}

  digitalWrite (sw2_la,LOW); stat_sw2 = !stat_sw2;
  ++done;          // increment counter for switch learned.
  }  
     }
//______________________________________________________________________

void Int_swi3()   // interrupt trigged by swith 3, CHANGE.    
{  
  time_out = millis();

if (sw3_la > 0)  { stat_sw3 = !stat_sw3; digitalWrite(sw3_la,stat_sw3);}

  else {
if ((done==0) && (seq==1)) { sw3_la = 10;}  
if ((done==1) && (seq==1)) { sw3_la = 11;}
if ((done==2) && (seq==1)) { sw3_la = 12;}
if ((done==3) && (seq==1)) { sw3_la = 13;}  

if ((done==0) && (seq==2)) { sw3_la = 11;}  
if ((done==1) && (seq==2)) { sw3_la = 10;}
if ((done==2) && (seq==2)) { sw3_la = 13;}
if ((done==3) && (seq==2)) { sw3_la = 12;} 

if ((done==0) && (seq==3)) { sw3_la = 12;}  
if ((done==1) && (seq==3)) { sw3_la = 13;}
if ((done==2) && (seq==3)) { sw3_la = 10;}
if ((done==3) && (seq==3)) { sw3_la = 11;} 

if ((done==0) && (seq==4)) { sw3_la = 13;}  
if ((done==1) && (seq==4)) { sw3_la = 12;}
if ((done==2) && (seq==4)) { sw3_la = 11;}
if ((done==3) && (seq==4)) { sw3_la = 10;} 

  digitalWrite (sw3_la,LOW); stat_sw3 = !stat_sw3;
  ++done;          // increment counter for switch learned.
  }
    }
//______________________________________________________________________

void Int_swi4()   // interrupt trigged by swith 4, CHANGE.    
{ 
  time_out = millis(); 

if (sw4_la > 0)  { stat_sw4 = !stat_sw4; digitalWrite(sw4_la,stat_sw4); }

  else {
if ((done==0) && (seq==1)) { sw4_la = 10;}  
if ((done==1) && (seq==1)) { sw4_la = 11;}
if ((done==2) && (seq==1)) { sw4_la = 12;}
if ((done==3) && (seq==1)) { sw4_la = 13;}  

if ((done==0) && (seq==2)) { sw4_la = 11;}  
if ((done==1) && (seq==2)) { sw4_la = 10;}
if ((done==2) && (seq==2)) { sw4_la = 13;}
if ((done==3) && (seq==2)) { sw4_la = 12;} 

if ((done==0) && (seq==3)) { sw4_la = 12;}  
if ((done==1) && (seq==3)) { sw4_la = 13;}
if ((done==2) && (seq==3)) { sw4_la = 10;}
if ((done==3) && (seq==3)) { sw4_la = 11;} 

if ((done==0) && (seq==4)) { sw4_la = 13;}  
if ((done==1) && (seq==4)) { sw4_la = 12;}
if ((done==2) && (seq==4)) { sw4_la = 11;}
if ((done==3) && (seq==4)) { sw4_la = 10;} 

  digitalWrite (sw4_la,LOW); stat_sw4 = !stat_sw4;
  ++done;        // increment counter for switch learned.
  }
    }

/[Code]

[/code]

Use unsigned long for timing with millis().
The function millis() returns an unsigned long, and if you do every calculation careful and with unsigned long, you can avoid the rollover trouble.

When I see all those : if ((done==0) && (seq==1)) { sw1_la = 10;}
then I see a 2 dimensional array.
There is nothing wrong with all those if statements, but using an array makes you look like a software designer.

line 41: long time_out = millis(); // to calculate time_out.

Your ide for a Array is fine, but it is more to it then then first meets the eye.
But it would be nice with a version using array, please go for it!!
best regards/ Hans

[code]Here is a bit more optimised version of code.

// This software uses an ARDUINO NANO to make a "MAGIC SWITCH BOX".
// 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! Try.. The Magic Switchboard - YouTube
// 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 turned off is 1 you get the new order seq = 1-2-3-4.
// Last off = 2 gets seq = 2-1-3-4. 3 gets seq = 3-4-1-2. and 4 gets seq = 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.

#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 sw1_la =0; // lamp related to switch one, (to be lerned in program run).
int sw2_la =0;
int sw3_la =0;
int sw4_la =0;

int stat_sw1=1; // present status of switch one, active low.
int stat_sw2=1;
int stat_sw3=1;
int stat_sw4=1;
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_swi1, CHANGE); // call Int_swi1 when pin_sw1 changes status.
PCintPort::attachInterrupt (pin_sw2, Int_swi2, CHANGE);
PCintPort::attachInterrupt (pin_sw3, Int_swi3, CHANGE);
PCintPort::attachInterrupt (pin_sw4, Int_swi4, 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();

Serial.println ("Running main loop");
do {
latest_interrupted_pin=PCintPort::arduinoPin ;
last_off = latest_interrupted_pin-1;

if (seq<1) {seq=1;}

Serial.print ("sw1_la: "); // comment out all Serial.print when serial monitor not in use.
Serial.print (sw1_la);
Serial.print (stat_sw1);
Serial.print (" sw2_la: ");
Serial.print (sw2_la);
Serial.print (stat_sw2);
Serial.print (" sw3_la: ");
Serial.print (sw3_la);
Serial.print (stat_sw3);
Serial.print (" sw4_la: ");
Serial.print (sw4_la);
Serial.println (stat_sw4);
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_sw1==1) && (stat_sw2==1) && (stat_sw3==1) && (stat_sw4==1)&& (done>0)){

Serial.println ("Running reset");

seq=latest_interrupted_pin-1;
if (seq<1) {seq=1;}
sw1_la =0; // lamp related to switch one.
sw2_la =0;
sw3_la =0;
sw4_la =0;
done=0;
}
} // end of main loop.

void Int_swi1() // interrupt trigged by swith 1, CHANGE. ---------------------------------------
{
time_out = millis();
if (sw1_la > 0) {stat_sw1 = !stat_sw1; digitalWrite(sw1_la,stat_sw1); }
else {
switch (seq){
case 1: {sw1_la = done+10;} break;
case 2: {{sw1_la = 11-done;}
if (sw1_la<10) {sw1_la = (10+done);}} break;
case 3: {{sw1_la = 12+done;}
if (sw1_la>13) {sw1_la = (8+done);}} break;
case 4: {sw1_la = 13-done;} break;
}
digitalWrite (sw1_la,LOW); stat_sw1 = !stat_sw1;
++done; // increment counter for switch learned.
}
}

void Int_swi2() // interrupt trigged by swith 2, CHANGE. ---------------------------------------
{
time_out = millis();
if (sw2_la > 0) { stat_sw2 = !stat_sw2; digitalWrite(sw2_la,stat_sw2); }
else {
switch (seq){
case 1: {sw2_la = done+10;} break;
case 2: {{sw2_la = 11-done;}
if (sw2_la<10) {sw2_la = (10+done);}} break;
case 3: {{sw2_la = 12+done;}
if (sw2_la>13) {sw2_la = (8+done);}} break;
case 4: {sw2_la = 13-done;} break;
}
digitalWrite (sw2_la,LOW); stat_sw2 = !stat_sw2;
++done; // increment counter for switch learned.
}
}

void Int_swi3() // interrupt trigged by swith 3, CHANGE. ---------------------------------------
{
time_out = millis();
if (sw3_la > 0) { stat_sw3 = !stat_sw3; digitalWrite(sw3_la,stat_sw3);}
else {
switch (seq){
case 1: {sw3_la = done+10;} break;
case 2: {{sw3_la = 11-done;}
if (sw3_la<10) {sw3_la = (10+done);}} break;
case 3: {{sw3_la = 12+done;}
if (sw3_la>13) {sw3_la = (8+done);}} break;
case 4: {sw3_la = 13-done;} break;
}
digitalWrite (sw3_la,LOW); stat_sw3 = !stat_sw3;
++done; // increment counter for switch learned.
}
}

void Int_swi4() // interrupt trigged by swith 4, CHANGE. ---------------------------------------
{
time_out = millis();
if (sw4_la > 0) { stat_sw4 = !stat_sw4; digitalWrite(sw4_la,stat_sw4); }
else {
switch (seq){
case 1: {sw4_la = done+10;} break;
case 2: {{sw4_la = 11-done;}
if (sw4_la<10) {sw4_la = (10+done);}} break;
case 3: {{sw4_la = 12+done;}
if (sw4_la>13) {sw4_la = (8+done);}} break;
case 4: {sw4_la = 13-done;} break;
}
digitalWrite (sw4_la,LOW); stat_sw4 = !stat_sw4;
++done; // increment counter for switch learned.
}
}

[/code]

Hello Hans,

this is realy great. I love the idea and the realization,

reards, robert

and this

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

hehe, all standard "magic" trickery until the the best bit when the batteries are taken out. :slight_smile:

Notice that the underside of the box is never shown. :slight_smile:

Hello, I see your very interesting program for "Magic switch". I am a beginer with Arduino Uno from 73 years. I understand (+/-) the program but can I see a scheme (diagram) of the electronic from emplacement from switchs and lamps. Thanks
(sorry for my english)