Introduction: Location Reporting Clock

This instructable was created in fulfillment of the project requirement of the Makecourse at the University of South Florida (www.makecourse.com)

Introducing a clock for the perpetually misplaced and habitually late. Partially inspired by the location tracking clock the Weasley family owns in Harry Potter - I wanted to make a simple location "reporting/tracking" clock with an interesting design.

This project uses an Arduino Uno integrated with Keuwlsoft's Bluetooth Electronics Android app to let you set your intended destination before you leave your house, so whoever's still at home can see where you (probably) wandered off to. It keeps track of the time, as well, if (much like its creator) your answer to "What time is it?" is normally something like "Well... it's about 2:45ish, I suppose."

Step 1: Materials and Tools

Parts and Materials List

Hardware

#PartSource
1xArduino Uno Microcontroller

Amazon

2xAdafruit Motor Shield V2.3 + included headers

Amazon

1xHC-05 Bluetooth module

Amazon

3x Nema-17 bipolar stepper motor (200 step/rev, 12V)

Amazon

1xPower supply (12V)

-

1xShort breadboard

Amazon

1xPlastic electronics enclosure box

Amazon

-- Assorted male-male wires

-

1x4.7k ohm resistor

Resistor kit on Amazon

1x2.2k ohm resistor

-

2x8-pin stackable header

Header pin kit on Amazon

1x6-pin stackable header

-

1x10-pin stackable header

-



Materials

#PartSource
1x1 kg 1.75mm spool PLA for 3D printing

Hatchbox Brand (Amazon), 3DSolutech Brand(Amazon)

--Solder

-

--Assorted grit sand paper/ sanding blocks

-

1xBondo

-

1xSpray primer (matte gray or white)

-

2-3xSpray paint (each a different color)

-

--Small tube acrylic hobby paint

-

2x2 oz. Oven bake-able modelling clay (different colors) (optional)

Gold (Amazon), White (Amazon)



Tools

Part
3D printer
Soldering iron
Small electronics screw driver set
Dremel + cutting bit
Set of files


Additional Tools (may be necessary)

Part
Needlenose pliers
Wire cutters
Wire stripper

Step 2: Modelling and Physical Design

Parts

3D Printed Parts

Part
Base
Location dial
Hour dial
Minute dial
Location name plates (x6)


Optional Parts

Part
Figure to sit in the "front door"

Assembly

1) Base

This is the main exterior of the print. It can be whatever shape you'd like - I went for a simple round tower with an opening in the front to leave open the option to add a cuckoo clock spring feature in the future (as of the current version, there's just a little bird figure sitting in the opening).

For this version, the base is 300mm tall and about 180mm wide at it's widest point.

Key points for designing your own:

  • The base should be long and wide enough to fit two rows of motors with room for the hour and minute dials to slot inside.
  • The inside of mine is left hollow so more features can be added later and to save on print time
  • The electronics will be housed in a plastic enclosure recessed into the back, which dictates the minimum height the motors can be placed at, depending on how you want to orient the enclosure

2) Location dial and location name plates

The .stl provided and the subsequent code provided in the programming step are for a dial with 6 options, but the code can be modified if you choose to design yours with a different number. For the version shown, the locations are painted on individual name plates that are attached to each spot so they can be changed out.



Key points for designing your own:

  • This is the front dial, so size the overall radius accordingly - it should be large enough to read your locations
  • Each location spot should be spaced at equal angles around the center
  • You can either design the location text into the dial, or leave them blank so they can be switched out down the line
  • Connecting the dial to the motor:
    • Option 1: A hollow shaft on the back to slide over the motor shaft, such as in this design
    • Option 2: A solid shaft that attaches with shaft collars
      • If you choose this option, make sure the center hole in the base is wide enough to accommodate

3) Hour dial

The hour dial has 12 teeth, one positioned for the top of each hour.


4) Minute dial

For this particular design, I decided to go with a dial that completes one full rotation every two hours. The circular face narrows starting at the top of the hour (hour 1 - minute zero) until it reaches the end of the hour (minute 59) over 180 degrees, then spikes back up to the widest point again at the next minute zero (hour 2 - minute zero), with marks at the 15, 30 and 45 minute points.

Key points for designing your own:

  • The dial can be designed like the hour dial above to give a more accurate reading, or slightly less readable like the one provided
  • Additional size constraints for designing the hour/minute dials: if the two back motors are mounted on the same place:
    • i) If the dial faces will be sitting on the same plane, the radii will need to be small enough to allow them to move freely next to each other, and the shafts attached to the motor will be the same length
    • ii) If the faces will be off set, there's more room in size variation, but the shafts will need to be different lengths

5) Figure (Optional)

For this project, I just modelled a little bird out of some sculpey modelling clay and baked it per the package instructions (225 degrees fahrenheit for 15 minutes per 1/2 inch of thickness).

If you don't want to go the clay route, you can either 3D model or find a cute print off thingiverse to suite your needs.

Step 3: Motor Shield Set Up

Before you assemble everything, you'll want to make sure all your electronics and code are working smoothly while you can easily pull things apart. We'll start with the motor shields:

Parts and Materials

#Part
1x Arduino Uno microcontroller
2xAdafruit Motor Shield V2.3 + included headers
2x 8-pin stackable header
1x 6-pin stackable header
1x 10-pin stackable header
-- Soldering iron
--Solder

Steps

The first thing you'll need to do is connect the headers to the motor shields and solder

  1. First motor shield headers (bottom shield) - stackable headers:
    • Fit a stackable header with appropriate number pins in each of the four sections noted below through the top of the motor shield (these will connect to the arduino below and the additional shield stacked above)
    • Flip the motor shield over so it's resting on the pins, front side facing down
    • Solder one pin from each header to hold them in place, then go back and solder the rest of the pins
  2. First motor shield - jumper
    • Solder the right most jumper as pictured below
  3. Second motor shield (top shield) - use headers included with kit
    • This time using the pins provided with the motor shield, solder as you did with the previous motor shield
  4. Second motor shield - jumper
    • Leave all jumpers unsoldered; this shield will use the default address

Step 4: Wiring

Parts and Materials

#Part
1x Arduino Uno microcontroller
2xAdafruit Motor Shield V2.3
1x HC-05 Bluetooth module
3x Nema-17 bipolar stepper motor (200 step/rev, 12V)
--USB 2.0 to 3.0 cable
-- Breadboard
--Assorted male-male wires
1x4.7k ohm resistor
1x2.2k ohm resistor
-- Screwdriver with small flat head

Steps

  1. First hook up one of the motors to the M1/M2 terminals of the motor shield with the soldered jumper, as in the photo below:
    • *Note the wire order: red, yellow, gray, green*

    • Use the flat head screw driver to loosen/tighten the screw clamps

  2. Next, hook up the remaining two motors to the other motor shield in the same manner, one on the M1/M2 terminals and the other on the M3/M4 terminals
  3. Now wire the HC-05 bluetooth module to the bread board, and wire the breadboard to the motor shield with the two motors attached:
    • Wire the positive rail of the breadboard to the 5V pin of the motor shield, and the negative rail to the ground pin of the motor shield
    • Place the 2.2k ohm and 4.7k ohm resistors in series on the breadboard
    • Insert the bluetooth module into the breadboard and wire the following connections:
      • VCC pin to the positive rail of the breadboard
      • GND pin to the negative rail of the breadboard
      • TXD pin to pin 0 (RX pin) of the motor shield
      • RXD pin to the junction where the 2 resistors meet
    • Connect the end of one of the resistors to the negative rail of the breadboard
    • Connect the end of the other resistor to pin 1 (TX pin) of the motor shield
  4. Attach the motor shields to the arduino:
    • Fit the pins on the bottom of the motor shield with the single motor attached into the headers of the arduino board and gently press until the pins are seated
    • Fit the pins on the bottom of the other motor shield into the the headers of the motor shield now attached to the arduino

Step 5: Programming

The code for this project was done using the Arduino IDE. The full sketch is available for download.

Overview

Dials

The front dial is set to turn clockwise back to the home location, and then turn from there to which ever location was chosen.

The minute dial turns one half of a full rotation per hour, and it moves forward 5 steps every 3 minutes. The hour dial turns one full rotation over the course of 12 hours, and it moves forward 5 steps approximately every 18 minutes. The time is kept synced to the actual time passing by tracking the milliseconds that have passed through the milli() function.

Bluetooth integration

The Arduino receives command data through the serial connection between the bluetooth module and the Arduino. Then, Keuwlsoft's Bluetooth Electronics app is able to connect to the HC-05 bluetooth module attached to the board. In the location tracking section of the Arduino sketch's void loop, the characters that can be received via the app are each assigned a function. A-F are assigned to move the location dial, and G-J reset the time.

  • Location (A-F):
    • Each time a character is received, the dial turns back to the home location
      • Set this location by moving the dial to the desired home position each time the project is turned on
    • Then the dial will move the necessary number of steps to reach the location the app user requested
  • Resetting time (G-J):
    • When the pause button is pressed, the motors for the time dials stop moving
    • The user must then turn the hour and minute dial so the clock reads 12:00
    • Integers can then be entered into the bluetooth app and sent to the arduino
    • When the resume button is pressed, the motors turn to the entered time and resume regular function
      • Since the user might enter a time in between "periods" for the dials to turn, code has been added to calculate this partial period (the remainder variables in the sketch), turn when the number of milliseconds has elapsed, and then resume regular function

Full details of the bluetooth app will be outlined in the next step.

Code

/////////////////////////////////////// ///////Location Tracking Clock///////////////////////////////////////////////include the following libraries#include #include #include "utility\Adafruit_MS_PWMServoDriver.h"//initialze motor shieldsAdafruit_MotorShield AFMSbot(0x61); // bottom shield, 0x61 jumper solderedAdafruit_MotorShield AFMStop(0x60); // top shield, default address, no jumpers//initialize stepper motors on shieldsAdafruit_StepperMotor *stepperLoc = AFMSbot.getStepper(200, 1);   //location stepperAdafruit_StepperMotor *stepperMin = AFMStop.getStepper(200, 1);   //minute hand stepperAdafruit_StepperMotor *stepperHour = AFMStop.getStepper(200, 2);  //hour hand stepper char BluetoothData; //Bluetooth data received //variables to hold/ track bluetooth location statesint currLoc = 0;  //# of steps from home    int homeLoc = 0;  //# of steps back to home //variables to track time during normal clock movementint minPeriod = 180000;   //ms bw minute hand movement   /* Calculation:    (36000 ms/step)*(100 total steps)* (5 steps/period) = 180000 steps per period */int hourPeriod = 1080000;   //ms bw hour hand movement   /* Calculation:    (4320000 ms/12hr)*(216000 ms/step)*(5 steps/period)=1080000 steps per period */long minNow = 0;  // current minute (20 total steps)long hourNow = 0;   //current hour (40 total steps)//variables to set user input timeint changeTime = 0; // 0=regular time, 1=change timeint setTime = 0;  // 0=regular movement, 1= pause clock movementint userHour = 0;   //user input hour from bluetooth appint userMin = 0;    //user input minutes from bluetooth applong newHourMilli = 0;  //user input time in mslong newMinMilli = 0;   //user input minutes in msint newHourPeriod;  //# of hour dial periods to set timeint newMinPeriod;   //# of minute dial periods to set timelong hourRem; //ms to wait before resuming hour dial motionlong minRem;  //ms to wait before resuming minute dial motionvoid setup() {  Serial.begin(9600); //begin serial communication  AFMStop.begin(); //start the top shield  AFMSbot.begin(); //start bottom shield//set motor speeds  stepperLoc->setSpeed(5);  //5 rpm     stepperHour->setSpeed(5); //5 rpm     stepperMin->setSpeed(5);  //5 rpm   }void loop() {//////////////////////Clock dial movement (hours/minutes) and time set///////////////////  if (changeTime == 0){ //default state    if(millis() > minNow + minPeriod){    //Check until millis reaches next marked period for minute dial     minNow=millis();                  //replace with new current minute state    stepperMin->step(5,FORWARD,SINGLE);   //move minute dial forward    }        if (millis() > hourNow + hourPeriod){ //Check until millis reaches next marked period for hour dial       hourNow = millis();                 //replace with new current hour state    stepperHour->step(5,BACKWARD,SINGLE); //move hour dial forward    }  }  if(changeTime==1){    //pause normal clock movement    //read user entered hour/minute to set time and match up with code dictated periods        if(setTime==1){    newMinMilli = long(userMin)*60*1000;          //calculate hour milliseconds from user input    newHourMilli = long(userHour)*60*60*1000 + newMinMilli; //calculate overall ms based on user time input        newMinPeriod = int(newMinMilli/minPeriod)*5;          //steps to move beyond zero minute point      newHourPeriod = int(newHourMilli/hourPeriod)*5;       //steps to move beyong zero hour point        hourRem = (newHourMilli % hourPeriod)*hourPeriod;     //calculate remaining ms to wait before next addtional move of hour dial    minRem = (newMinMilli % minPeriod)*minPeriod;       //calculate remaining ms to wait before next additional move of minute dial    }        if(newMinMilli != 0 && newHourMilli != 0){        newHourPeriod = int(newHourMilli / 1080000)*5;  //move to new hour    newMinPeriod = int(newMinMilli / 180000)*5;   //move to new minute        stepperHour->step(newHourPeriod,BACKWARD,SINGLE);    stepperMin->step(newMinPeriod,FORWARD,SINGLE);          if (millis()>millis()+hourRem){ //wait hour ms remainder before moving to next hour period      stepperHour->step(5,BACKWARD,SINGLE);      }            if (millis()>millis()+minRem){  //wait minute ms remainder before moving to next minute period        stepperMin->step(5,FORWARD,SINGLE);      }  //reset variables and resume regular clock movement    newMinMilli = 0;    newHourMilli = 0;    userMin=0;    userHour=0;    setTime=0;     changeTime=0;       }  }    //////////////////////Location tracking and time update via bluetooth app///////////////////  if (Serial.available()){  BluetoothData=Serial.read(); //Get next character from bluetooth    ////location tracking - characters A - F      if(BluetoothData=='A'){ // Location 1 pressed    homeLoc = 200-currLoc;                                //calculate steps to home dial (location 1)                            stepperLoc->step(homeLoc, BACKWARD, SINGLE);          //move dial to home location    currLoc = 0;                                          //set new current location    }    if(BluetoothData=='B'){ // Location 2 pressed    homeLoc = 200-currLoc;                               //calculate steps to home dial (location 1)                 stepperLoc->step(homeLoc+34, BACKWARD, SINGLE);      //move stepper home then to desired location     currLoc = 34;                                        //set new current location    }    if(BluetoothData=='C'){ // Location 3 pressed    homeLoc = 200-currLoc;                 stepperLoc->step(homeLoc+67, BACKWARD, SINGLE);     currLoc = 67;    }    if(BluetoothData=='D'){ // Location 4 pressed    homeLoc = 200-currLoc;    stepperLoc->step(homeLoc+100, BACKWARD, SINGLE);     currLoc = 100;    }    if(BluetoothData=='E'){ // Location 5 pressed    homeLoc = 200-currLoc;                 stepperLoc->step(homeLoc+134, BACKWARD, SINGLE);     currLoc = 134;    }    if(BluetoothData=='F'){ // Location 6 pressed    homeLoc = 200-currLoc;                 stepperLoc->step(homeLoc+167, BACKWARD, SINGLE);     currLoc = 167;    }      ////time update G - J     if(BluetoothData=='G'){ //pause clock movement    changeTime=1;    }      if(BluetoothData=='H'){ //set time, resume movement    setTime=1;    }            if(BluetoothData=='I'){ //user input - minutes    userMin=Serial.parseInt();    }        if(BluetoothData=='J'){ //user input - hours    userHour=Serial.parseInt();         }  }//close void loop() }  

Step 6: Bluetooth Integration

Keuwlsoft's Bluetooth Electronics app can be downloaded from the Google Play store, and will connect to the HC-05 module. Additional information about the base app and its functionality can be found here on their website.

The Bluetooth Electrionics app will let you create panels with controls that will send serial data to the bluetooth module hooked up to the project. For this project, you'll want to create two different panels - one for controlling the location, and one for setting the time.


Creating the Panels

Panel One: Location Tracking

  1. Select a blank panel and touch edit to open up the panel editor
  2. You'll need six buttons, one for each location on the location dial of the physical project
    • To place a button: select "Buttons" from the menu on the right, and drag a button from the menu on the bottom onto the panel
  3. When your buttons are on the panel and arranged, select "Text" from the right-hand menu
    • Drag one of the four left-most text box options from the bottom menu to the panel for each of your locations and arrange accordingly
  4. Select one of the panels text boxes, and use the bottom right menu to edit the label text
  5. The character each button sends to the Arduino needs to be set:
    • Assign each location a different character (A-F) in the "Press Text" box; leave the "Release Text" box blank or clear it if there is a character already assigned

Panel Two - Set Time

  1. Return to the app's main screen and select a new blank panel to edit
  2. In this panel, add two buttons to the screen and label them - these will be the stop and start clock buttons
  3. For the stop button, assign 'G' to "Press Text", and nothing to "Release Text"
  4. For the start/ set new time button, assign 'H' to "Press Text", and nothing to "Release Text"
  5. Select "Terminals" from the right-hand menu, and from the bottom menu drag two of the top-left send boxes to the screen
    • Assign these labels for minute and hour
  6. For the send box labeled minute, assign 'I' to "Press Text", and nothing to "Release Text"
  7. For the send box labeled hour, assign 'J' to "Press Text", and nothing to "Release Text"

Your app now has everything it needs to function with the project!

Step 7: Assembly - Part 1 (Part Preparation)

Parts and Materials

3D Printed Parts

Part
Base
Location dial
Hour dial
Minute dial
Location name plates (x6)

Additional Supplies

Part
Glue
Small picture hanging adhesive strips
Bondo
Sand paper/ sanding blocks
Spray paint primer
Spray paint - assorted colors, minimum of 2
Black acrylic paint/small brush
Dremel with cutting bits
Plastic enclosure

Steps

First, the 3D printed parts need to prepped and painted.


Prep the Base

  1. If the base was printed in multiple pieces, assemble the pieces and glue together
  2. If you're happy with the quality of your print, you can skip further prep
  3. Start by sanding the base if the print came out particularly rough
  4. Wipe down with a wet cloth to clear of sanding debris and pat dry with a soft towel
  5. Apply a thin coat of bondo over the entire base, per instructions on container
  6. When dry, sand to an even finish
    • If you have a sanding bit for the dremel, you can (carefully) use this to quickly sand down any spots that are significantly thicker than others
  7. Reapply if necessary
  8. Wipe down with wet cloth when desired smoothness is reached, then pat dry

Prep the Enclosure

  1. Using the cutting bit of the dremel, cut out a ~2.5 inch slot near one of the short edges in the lid of the enclosure
  2. In the base of the enclosure, cut three holes where the motor wires will feed through:
    • A ~2 inch hole near the top of the main face of the enclosure
    • One hole on each of the two adjacent long edges

Prime and Paint

  1. Prime all printed pieces and the plastic enclosure/ lid with the spray primer
  2. When dry, use one color of spray paint for the base and the enclosure, and a separate color (or colors) for the dials and plaques. Apply multiple coats if necessary for better coverage.
  3. Location name plates:
    • Use the acrylic paint to write in the locations you chose in your app on the plaques
    • Cut the adhesive strips to fit the backs of the plaques and stick the plaques to the location dial
  4. Use the acrylic paint to apply numbers to the hour dial, and markers for 15/30/45 minutes on the minute dial
Once all paint is dry, it's time to start putting things together.

Step 8: Assembly - Part 2 (Part Assembly)

Parts and Materials

Part
Painted parts from previous step
3x Motors (remove from motor shield temporarily if already attached)
Tape

Steps

  1. Place one of the motors in the front motor bracket, wire edge down, and thread the wires through the bottom opening before fully setting the motor in place
  2. Slide the location dial shaft over the motor shaft through the hole in the face at the front, making sure it is snug and the motor shaft turns with the dial when spun
  3. Attach the minute dial and the hour dial to the remaining motors. Slide the minute dial motor into the back right motor bracket, and the hour dial into the back left motor bracket, again threading the wires through the bottom openings
  4. Place the enclosure up to the back of the project and thread the motor wires through their respective holes
    • Tape the wires to the inside of the enclosure for now, and keep track of which set goes to which motor
  5. Seat the enclosure fully in the base, but do not secure it until the Arduino is fully wired back up and the features are all running

Step 9: Assembly - Part 3 (Electrical Components)

Parts and Materials

Part
Assembled base
Arduino + shields
Picture hanging strips

Steps

  1. Bring your assembled project to a location that is close enough to hook up to a computer when the Arduino is inside the enclosure.
  2. Connect the motors to the appropriate motor shield location and make sure the motor shields are seated properly on the Arduino
    • The location dial motor connects to M1/M2 on the bottom shield
    • The minute dial motor connects to M1/M2 on the top shield
    • The hour dial motor connects to M3/M4 on the top shield
  3. Apply one or two of the adhesive strips to the back of the breadboard and stick it to one of the sides inside the enclosure
  4. Gently apply one adhesive strip to a blank spot on the back of the Arduino, and stick to the inside of the enclosure
  5. Turn the location dial so Home is facing upwards (or whatever was set to 'A' in your bluetooth app)
  6. Plug in the USB cable and upload code
    • **Note:** The RX/TX pins need to be disconnected before each upload, or the upload will fail; reconnect when done.
  7. If your cable is too short to keep comfortably plugged into the computer, either:
    • a) Hook up a small USB battery pack after code is uploaded, or,
    • b) Connect a power cable to the Arduino's barrel jack and plug into the wall
  8. Connect to bluetooth:
    • Open the Bluetooth Electronics app on your phone
    • Select "Connect"
    • Choose the HC-05 device - hit connect, and then done when it is connected
    • Navigate to either of your panels and play around to make sure everything is working as it should be

Step 10: Finishing Up

Final Adjustments

If your code has uploaded, the bluetooth is connecting and the app/ motors are working and moving like you want them to - great! It's time to finish up.

  1. Place two or three of the adhesive strips on the bottom of your enclosure and stick it in place on the base (or use a more permanent adhesive if you don't intend to remove it again).
  2. Thread whichever power cable you decided to go with through the hole you made in the lid of the enclosure before securing the lid with the screws it came with.
  3. Set up your completed project wherever you want to display it, and plug it in!

In Action