Timer Circuit to Drive the Automata

colonel-a04Each of the automata in the Archive Project will be mounted on a plinth. There is an electric motor that drives the model and in the end we decided to use a token to set off the motion rather than a simple push button.
The theory is that having tokens or using coins gives value to each ‘performance’

In this picture you can see the coin slot mechanism. When the correct coin is inserted into the slot the mechanism emits a short electrical pulse. Too short to be used directly but long enough to be used to start a timer circuit . I managed to source the coin reader slot mechanism from eBay in the UK.

Here’s the breadboard based final design set up and plugged into one of the coin slot mechanism.
timercircuit12

The timer circuit is based around the Arduino micro-controller.
Specification:  A switch to start the timer.
An emergency cancel switch.
Adjustable time from one second to at least a couple of minutes in one second steps.
A reasonably high current relay to switch the electric motor on the model which will be driven from a 12v lead acid battery.

I settled on a DIP switch as the easiest way to preset the time. The switch works like a binary number. Each switch is worth twice the time as its neighbour: Make up the number of seconds you want by adding together the numbers. timercircuit11For example:timercircuit10
Here’s the final layout of the breadboard and Arduino.
timerfritz_bb

…and the code used to drive the Arduino. You can download the code here.


/*
Timer circuit to drive relay for preset amount of time.
(cc) Rob Ives 2015 www.robives.com www.thearchiveproject.net
*/
// constants
//the pins to read the eight switches of the dip switch
const int dip00 = 2;
const int dip01 = 3;
const int dip02 = 4;
const int dip03 = 5;
const int dip04 = 6;
const int dip05 = 7;
const int dip06 = 8;
const int dip07 = 9;

const int start = 11; // pin for the input pulse
const int cancel = 12; // emergency cancel button

const int relay = 13; // output to relay

//variables
int runtime = 0; // the variable where the time set on the dip switch will be stored
int startstate = 0; //variable for reading start pulse
int cancelstate = 0; //variable for reading emergency cancel button
int timeractive = 0; // is the timer timing?

unsigned long currentMillis = 0;  // start time store
unsigned long timeInMillis = 0; //runtime in milliseconds
unsigned long endInMillis = 0; //runtime in milliseconds

void setup() {
   // set the digital pin:
  pinMode(dip00, INPUT);
  pinMode(dip01, INPUT);
  pinMode(dip02, INPUT);
  pinMode(dip03, INPUT);
  pinMode(dip04, INPUT);
  pinMode(dip05, INPUT);
  pinMode(dip06, INPUT);
  pinMode(dip07, INPUT);

  pinMode(relay, OUTPUT); // set relay pin to output

  pinMode(start, INPUT); // input for coin slot
  pinMode(cancel, INPUT); //input for emergency stop

  digitalWrite(relay, LOW); //turn off relay

}

void loop() {
  timeractive = 0; 

  if (digitalRead(start)){
    timeractive = 1; //start the timer
    digitalWrite(relay, HIGH); // turn on the relay
    runtime = readDip(); // get preset time from dip switch
    timeInMillis = (unsigned long)runtime * 1000; //convert time to milliseconds
    currentMillis = millis(); //get the start time of switch press
    endInMillis = currentMillis + timeInMillis;
  }
  while (timeractive == 1){// timer loop
    currentMillis = millis();
    if(currentMillis > endInMillis)  {
      timeractive = 0;
    }
    cancelstate = digitalRead(cancel);
    if (cancelstate == HIGH){
         timeractive = 0;
    }
  }  // end of timer while loop
  digitalWrite(relay, LOW); //turn off relay
}

int readDip()
{
  // dip00 is LSD
  int dipState00 = !!(digitalRead(dip00) == HIGH);
  int dipState01 = !!(digitalRead(dip01) == HIGH);
  int dipState02 = !!(digitalRead(dip02) == HIGH);
  int dipState03 = !!(digitalRead(dip03) == HIGH);
  int dipState04 = !!(digitalRead(dip04) == HIGH);
  int dipState05 = !!(digitalRead(dip05) == HIGH);
  int dipState06 = !!(digitalRead(dip06) == HIGH);
  int dipState07 = !!(digitalRead(dip07) == HIGH);

  int dipTotal = 0;
  dipTotal += dipState00;
  dipTotal += dipState01 * 2;
  dipTotal += dipState02 * 4;
  dipTotal += dipState03 * 8;
  dipTotal += dipState04 * 16;
  dipTotal += dipState05 * 32;
  dipTotal += dipState06 * 64;
  dipTotal += dipState07 * 128;

  return dipTotal;
}

A note about the code: The readDip function is used to read the value of the dip switch and return a duration in seconds. It uses digitalRead(val) to read each of the pins on each of the dip switch. To be sure that the returned value for an on switch is 1 and not some other non-zero value I have added a double not (!!) to the front of the digital read.

int dipState00 = !!(digitalRead(dip00) == HIGH);

If the pin read is zero it will return 0, if it is any other value it will return 1

Here are the various parts of the circuit as circuit diagrams. It’s sometime easier using them to set up a circuit rather than the layout picture.

First the wiring for the DIP switch:timercircuit01Next, the start and cancel switches:
timercircuit03

And finally the parts that drives the relay. I’ve used a transistor as a switch to turn on the relay and a diode to protect the circuit when the magnetic field in the coil collapses. The LED is there as an indicator to show when the relay is activated.
timercircuit02b

Here’s how it all fits together.timercircuit05

The relay is a 5V model with a 10A switch, plenty to drive the electric motors I’m using.

timercircuit07

The underside of the relay shows how the pins are laid out. Not what I was expecting! timercircuit09

The circuit works a treat. I’m going to need to make quite a few of them so my next/final step will be to make up some printed circuit boards to make a more permanent version of the timer circuit.

(Thanks to Mike for coding advice 🙂