Archive

Arduino time machine

Introduction

One of the outreach demonstrations I give takes the audience through Einstein’s special and general relativity (very gently) and finishes with the idea of a time machine. One of the steps along the way is a  demonstration showing what would happen if we could see the effects of time dilation. While this can be done with atomic clocks and aeroplanes, I wanted a less expensive way of getting the concept across. To achieve this I built two special clocks, one of which stays stationary with the audience while the other goes on a “high speed” journey, usually courtesy of a student/audience member jogging around with it for a few minutes. My original clocks were built in 1995 using PIC controllers. This year I decided to make a new pair using two Arduino boards. Here’s how I did it – hope you enjoy, and please do emulate for your physics classes!

Parts:

  • 2x Arduino boards
  • 2x model servos
  • 2x stripboard: 20×11 holes.
  • single row pin headers
  • 2x 3.5mm jack sockets
  • 3.5mm to 3.5mm jack lead
  • 4x switches
  • 2x 150mm x 80mm x 50mm plastic boxes
  • 8x 4mm machine screws and nuts
  • 2x A4 5mm foam board
  • stiff card
  • 2x 4AA battery holders and clip leads

1. Making the Arduino shields

To connect the Arduino to the various switches and the servo you first need to build a suitable shield. This is a simple plug in that is made with a piece of 20×11 strip-board upon which will be soldered pin headers and wires. This shield does not require anything more complicated than wire as all the passive components are build into the Arduino board.  It is best if you can buy the strip board pre-cut as cutting the board produces dust that can be extremely hazardous if inhaled. Failing this, seek out an experienced professional who can safely cut the board for you.

There are two shields, one for the master clock and a second for the slave clock (see later). Both start life as the same piece of strip board. Use a track cutting tool to cut the tracks as shown below left.

BareBoard2

To mount on the Arduino, modify a strip of single pin headers by pushing the pins all the way down using long-nose pliers. Two strips are needed – one 11 pins long, another 7 pins long.

pins2

Solder the strips in place on the edge of the board. It should be obvious that the 7 pin header goes on the side with the 2×4 block of copper removed. The image below also marks up the “L” shaped cut out in the tracks below and the holes that will be used for wiring and the 3-pin servo header. This image shows the Master header, the Slave header has a slightly different layout.

BoardWithPins

The shield sits at the bottom of the Arduino board. Notice that the cut tracks at the top-left prevent a direct connection of power and ground to input/output pins.

shieldPos1

The connections for the master and slave shields are shown below.

MasterSlave

Make sure that you keep the order of the wires when you solder the jack sockets into place (i.e. top wire on the master schematic connects to top wire on the slave schematic, etc.)

The finished version should look something like this.

FinBoard

2. The software

To run this project you need software for the Arduinos. The basic design of the software is:

  • The master will count time in the stationary frame of reference. As each second ticks it will move the servo accordingly and send a sync pulse as output to the slave.
  • The slave will detect whether it is connected to the master. If it is it will listen for the sync pulse and keep time with it. If it is not connected it will keep its own time (which will be slower as the assumption will be that the clock is moving).

Before doing all this though, you need to work out what the servos range of motion is and which direction it measures angles! The following sketch can be downloaded to either of the boards to determine your servo characteristics. To prevent accidental damage to my computer’s USB by accidentally trying drawing too much current, I prefer to disconnect the board from the computer and run servo-based applications on batteries.

On the sketch, if the switch to pin 3 is open, the servo will assume the zero position. When you close the switch the servo rotates to the 180 degree position. Some servos do this by rotating clockwise, other by rotating counter-clockwise. Note which way the servo turns as you want your finished clock to follow the clockwise convention. You also need to note how long the pulses sent to the servo should be to give the zero and 180 degree positions. To do this, follow the instructions in the code comments to set PULSEMIN and PULSEMAX values.

// clock servo range calibration
// COMPILE WITH ARDUINO 1.0.1 OR HIGHER
// when connected, the servo will try to take the zero degree
// (PULSEMIN) position
// ground pin 3 to test the 180 degree (PULSEMAX) position

#include <Servo.h>

#define PULSEMIN 680 // set to smallest value that does not cause judder
#define PULSEMAX 2400 // set to value that turns servo by 180 degrees

Servo servoClk;

// the setup routine runs once when you press reset:

 void setup()
 {
  servoClk.attach(6);

// Using writeMicroseconds allows higher resolution control of position
   servoClk.writeMicroseconds(PULSEMIN);
// input for position - use internal pull-up so natural state is HIGH
   pinMode(3, INPUT_PULLUP);
 }

// the loop routine runs over and over again forever:
 void loop()
 {
  int isZeroDeg = digitalRead(3);
  if(isZeroDeg == HIGH)
   {
   // increase PULSEMIN if the servo judders
   servoClk.writeMicroseconds(PULSEMIN);
   }
   else
   {
 // ground pin 3 - this is the 180 degree position
 // change PULSEMAX until you get the right amount of servo travel from
 // the zero degree position
 // as you do this note which sense the servo rotates
 // as this determines how the Master/Slave sketches should map time to
 // pulse width
     servoClk.writeMicroseconds(PULSEMAX);
   }
// delay to prevent sending data to the servo too quickly
   delay(20);
 }

The master code

The master sketch is given below. Note that my servos turn clockwise so I have the line

#define CLOCKWISESERVO true

You would change the true to false if your servo went counter-clockwise. Also, set the  PULSEMIN/PULSEMAX values as appropriate.

The full listing is:

// clock master

// COMPILE WITH ARDUINO 1.0.1 OR HIGHER

// this version uses
// Pin 2 tick out
// Pin 3 tick/no tick
// Pin 6 servo signal
// 
// additional
// GND

// switch 1, power - on/off. Switch off then on to reset
// switch 2, pin 2 - start/stop ticking
// outputs are ground, and pin 2.
// ground is common ground and connected to slave pin 3 (separately to avoid auto-pull down)
// pin 2 is the tick - driven low, change on leading edge
// start-up sequence
//
// connect slave to master
// turn master to STOP
// turn slave to STOP
// turn master on
// turn slave on
//
// to start:
// turn slave to START
// turn master to START
// ticks will be synchronous
//
// separate - ticks will not be synchronous
//
// re-attach - ticks should be synchrous but time will be different
// STOP master and slave to halt the motion
// conection using sereo phone plug
// 1. ground
// 2. connected pull down
// 3. tick

// COMPILE WITH ARDUINO 1.0.1 OR HIGHER
#include <Servo.h>
#define PULSEMIN 680
#define PULSEMAX 2400
#define CLOCKWISESERVO true
Servo servoClk;
int time=0;
int WriteTime=PULSEMIN;
// the setup routine runs once when you press reset:
void setup() 
{ 
 // initialize the digital pin as an output.
 pinMode(2, OUTPUT); 
 pinMode(13, OUTPUT); //visual signa

 servoClk.attach(6);
 // higher resolution control 
 servoClk.writeMicroseconds(WriteTime);

 // input to ticking or not - pulled up so high = not ticking
 pinMode(3, INPUT_PULLUP);

}
// the loop routine runs over and over again forever:
void loop() 
{

 int isOn = digitalRead(3);
// if input is grounded then start ticking 
 if(isOn == LOW)
 {
 if (time<300) time++;

 // 4 mins run time to 180 deg position
 // 4 mins = 4*60=240 sec

 if (CLOCKWISESERVO) WriteTime=map(time,0,240,PULSEMIN,PULSEMAX);
 else WriteTime=map(time,0,240,PULSEMAX,PULSEMIN);

 servoClk.writeMicroseconds(WriteTime); 

 digitalWrite(2, LOW); // take 2 low for 100 ms to signal an external tick
 digitalWrite(13, LOW); // take 13 low for 100 ms for visual signal
 }
delay(100);
 digitalWrite(2, HIGH); // bring back high to signal end of tick
 digitalWrite(13, HIGH); // bring back high for visual signal
 delay(900); 
}

The Slave code

The Slave code is given below. Again set the servo direction and PULSEMIN/PULSEMAX values as appropriate.

// clock slave

// COMPILE WITH ARDUINO 1.0.1 OR HIGHER

// this version uses
// Pin 13 tick out (LED signal only) - lead not required
// Pin 6 servo signal
// Pin 3 tick/no tick
// Pin 4 is connected to master (connect to ground on master)
// Pin 2 tick signal from master (connect to 13 on master)
// 
// additional
// GND

// switch 1, power - on/off. Switch off then on to reset
// switch 2, pin 2 - start/stop ticking
// inputs from master
// common ground connection
// ground line to 4 to signal is connected
// tick line from master pin 2 to slave pin 2 to indicate tick
// COMPILE WITH ARDUINO 1.0.1 OR HIGHER
#include <Servo.h>
#define PULSEMIN 680
#define PULSEMAX 2400
#define CLOCKWISESERVO true
Servo servoClk;
int time=0;
int WriteTime=PULSEMIN;

// the setup routine runs once when you press reset:
void setup() 
{
// initialize the digital pin as an output.
 pinMode(13, OUTPUT);
servoClk.attach(6);
 // higher resolution control 
 servoClk.writeMicroseconds(WriteTime);

 // input to ticking or not - pulled up so high = not ticking
 pinMode(3, INPUT_PULLUP);

 // is connected to master - pulled up so high = not connected
 pinMode(4, INPUT_PULLUP);

 // tick from master
 pinMode(2, INPUT_PULLUP);

}
// the loop routine runs over and over again forever:
void loop() 
{

 int isOn = digitalRead(3);
 int isNotConnected=digitalRead(4);
// if input is grounded then start ticking 
 if(isOn == LOW)
 {
 if (isNotConnected)
 {
 if (time<300) time++;

 // 4 mins run time to 180 deg position
 // 4 mins = 4*60=240 sec
if (CLOCKWISESERVO) WriteTime=map(time,0,240,PULSEMIN,PULSEMAX);
 else WriteTime=map(time,0,240,PULSEMAX,PULSEMIN);

 servoClk.writeMicroseconds(WriteTime);
 digitalWrite(13, LOW);
 delay(200); // slow time down!
 digitalWrite(13, HIGH);
 delay(1000); // slow time down!
 }
 else
 {
 while (digitalRead(2)==HIGH && !isNotConnected)
 {
 isNotConnected=digitalRead(4);
 }

 if (time<300) time++;
 // 4 mins run time to 180 deg position
 // 4 mins = 4*60=240 sec
if (CLOCKWISESERVO) WriteTime=map(time,0,240,PULSEMIN,PULSEMAX);
 else WriteTime=map(time,0,240,PULSEMAX,PULSEMIN);

servoClk.writeMicroseconds(WriteTime);
 digitalWrite(13, LOW);
 while (digitalRead(2)==LOW && !isNotConnected)
 {
 isNotConnected=digitalRead(4);
 }
 digitalWrite(13, HIGH);
 }
 }
}

3. Testing

Once the shield is in place and the software uploaded it’s time to test before housing the components. Make sure you download the right sketch to the right board! The testing set-up is shown below (note, disconnect the boards from your computer and run from batteries).

FullAssembly2

Assuming that you have download the sketches and mounted the boards on the Arduinos but not inserted batteries or connected anything else, the testing is as follows:

  1. Ensure the power switches and start/stop switches are in the off position.
  2. Connect the servos. Remember that the ground connection should line up with the ground connection from the battery pack. The central connection should be +6V and should line up with the positive connection. The bottom connection (relative to the image above) should be the signal.
  3. Connect the boards using the 3.5 mm jack to jack cable.
  4. Insert the batteries.
  5. Turn on the master. The servo may reset its position. The on-board LED will illuminate.
  6. Turn on the slave. The servo may reset its position. The on-board LED will not illuminate It is important that this sequence is carried out in this order as the Master determines whether the slave should tick or not.
  7. Turn on the slave start/stop tick switch. Nothing will happen.
  8. Turn on the master start/stop tick switch. Both LEDs will blink synchronously at 1 Hz. The servos will step together.
  9. Disconnect the jack plug from one of the boards. The master will tick as before. The slave will tick slower. This represents the slave going on a journey at near the speed of light.
  10. Reconnect the jack. The two units will now tick synchronously again. This represents returning from the journey.
  11. Turn the tick on the master to the off position. Do the same on the slave.
  12. Power off.

If you don’t see the above check your wiring, batteries, coding, etc.

The above represents the full experiment. Had pointers been attached to the servos you would have seen that the slave pointer had turned less.  Steps (5) onwards will be the exact sequence of events for the finalised version.

4. Making the clocks

To make the clocks I used a 50mm x 80mm x 50mm plastic box to house the electronics and an A4 piece of 5mm foam board as the face. The cutouts, drill holes and clock face for the design are given in this pdf

TimeMachineDrawings

The hole and mount are sized for a 40mm x 20mm servo. The two circles with arrows on will be the clock hands in the final version.

The servo is mounted inside the box and protrudes through the cut-out in the box and foam board.

ServoFix

To get the servo to be flush against the inside of the box you may have to remove some plastic, as I did for the servos I used.

ServoLug

The board is secured to the foam board using double-sided adhesive strips as shown below (each of these can support about 3kg).

tape1

I provided cut-outs for the switches on the top and drilled a hole for the jack plugs in the side. Notice the slot to allow the wires to be fed through for mounting. I have also used different switch types for the start/stop ticking and the power. You can screw/glue these items in place. During use the battery may rattle around a little. To avoid this pack it with bubble-wrap or foam. Also note that the Arduino board has not been forced to lay flat (it’s a little too large). You will find that in sits quite snug at a slight angle.

inbox2You will find it convenient in use if you mount the jack socket on one side for the master and the other for the slave. This will allow easy connection of the clocks using a short lead, see below. Also note how the mounting is such that the case forms a stand for the clocks.

clocksBack

Each clock has a single hand. I cut this out of card and laminated it for extra stiffness. Make a hole at the centre and attach to the servo using the servo’s screw. Make sure both tick switches are in the off position and turn on both devices. Wait until they move to the zero position then alter the clock hands so that the pointer coincides with zero. You’re now ready to demonstrate time dilation!

5. The experiment

Ensure both clocks are powered off and have the tick switch in the off position. Ensure they are connected together with the jack lead.

  1. Turn on the master. The servo may reset its position.
  2. Turn on the slave. The servo may reset its position.
  3. Turn on the slave start/stop tick switch. Nothing will happen.

In the introduction you want to show that clocks in the same frame of reference tick at the same rate. Turn on the master start/stop tick switch and watch for about 45 seconds to convince yourself that this is the case.

clocks1

4. Disconnect the slave from the master and give it to a volunteer to run around with. Get them to hold the clock at the left and right edges so they don’t interfere with the movement (and ask that they take reasonable care with the clock).

5. Keep the volunteer running until the master clock shows about 3:30.

6. Bring the clocks back together and reconnect the slave to the master. There are two things to note. First, that because both clocks are now in the same reference frame they tick at the same rate. You will see this clearly. Second, that because one clock started moving around (we assume the volunteer can run at near the speed of light), time for it, and the volunteer, passed more slowly. You will see this as the slave clock will have lost time with respect to the master, see below (slave on the left).

clocks27. You can freeze the action by turning the tick switch in the master to off. (Then do the same on the slave. You can also power off at this stage.)

You should explain that this is only a simulation as the real effect is very small. However, I find that this simple hands-on demonstration really starts people thinking and provides a good starting point for showing real examples (decay of high energy cosmic rays, atomic clock experiments, etc.).

The way this becomes a time machine is that if you can manage to travel near the speed of light your clock will slow down relative to the rest of us. If it slows enough, then 100 years could have passed for the world, while you only experience say, 1 hour; you’ve effectively travelled 100 years into the future.  Of course, this explanation needs a caveat to explain the twins paradox. It should also be pointed out that this trip is one way. Once you’re 100 years into the future you have no way of getting back – that’s another relativity demonstration!