This project Instructable is a build of a multi function Timer.
This timer is capable of functioning as:
- A general purpose alarm with selectable times between 1 second and +90 hours. Having a count down with audible alarm and/or control of external device till finished then a count-up indication of time since alarm.
- A nap timer with 7 selectable times, count-down and alarm on completion.
- A meditation timer with 4 selectable times, with count-down and a short chirp on completion, count-up with another chirp at 5 minutes after that .
This project may ether be built as described here or modified to suit. I previously built a timer with this functionality and used it in my first Instructable to control the UV exposure box.
I thought I could just publish the original program and board designs. However, for some reason I could not find the code. I also wanted to make improvements to the hardware to make the control circuits more flexible and reduce battery drain. The resulting redesign of the main circuit board and re-write of the code provides an opportunity to discuss the programming and hardware design approach.
Whenever I create a circuit board I often find that there are flaws in the design or placement of components, The boards I build are also one of two offs. Plus, I just like to be involved in a all aspects of a project from start to finish. These are some of the reasons I make my own circuit boards rather than send the Gerber files overseas for manufacture. Maybe I'm just old and stuck in my ways. This project reflects this bias. Since I make my own circuit boards, my designs and my Gerber files do not meet manufacturing standards, I have not included these files. Those who do not wish to etch and finish the boards are welcome to prepare their own designs and post the Gerber files in the comments section. Please have your boards manufactured and tested before posting.
Step 1: Hardware Elements Overview
The device is powered by 4 AAA batteries and is controlled by an Arduino Pro Mini 5V.
A small buzzer/speaker provides an audible alarm.
A miniature 5v relay provides control voltages to external devices. Flexibility is provided in the source of this control voltage output.
A rotary encoder with push button provides menu selection.
An OLED display and momentary start/stop switch completes the user interface.
Additional electronic hardware consists of a SPDT power switch and a miniature phone jack to connect to external devices.
In addition, files to assist you in this project are provided:
STL files for a 3D printed project case.
Copper and solder mask images for the etching and finishing of the control circuit board and rotary encoder .
Schematic and board images as a reference for those who wish to modify my design.
You may wish to review my Instructable on creating double sided circuit boards as an example of circuit board production how-to.
Step 2: Software Overview
Along with the Arduino source files, some additional information that may be helpful..
Hardware control libraries are used when available (button de-bounce, OLED control, rotary encoder reading).
The program implements a simple finite state machine (FSM) to control code execution as a switch statement in the loop function..
A Menu class is defined to allow selection of displayed options on the OLED and selection using the rotary encoder.
Input is implemented by direct polling ( non-interrupt driven) since it is not time critical and makes the code clearer.
Print statements to Serial are used to aid in tracing code execution and debugging
Various types of program structure elements including:
- Multiple code tabs to isolate some of the hardware control functions and variables.
- Switch statements to set the state value (FSM) and control variables.
- Structure definition
- Enumerations to allow assignment of state values as text.
- #define pre-processor definitions for hardware pin and standard values.
Step 3: Parts List
You will need the following parts to build the project as designed. Consumables, additional materials and tools are not listed. Refer to the above photo to ensure that your parts & purchases will integrate with the hardware and software..
AAA x 4 Battery Holder provides 6V output (ebay)
Rotary Encoder w PB switch (ebay)
Miniature Buzzer (23mm) w/ mounting ears (ebay)
OLED display module white or blue I2C .96 inches 128x64 (ebay)
Small momentary switch NO - Radio Shack used to sell these (ebay).
SPDT miniature slide switch (mounting holes .75 inch between centers).
3.5mm phone jack panel mount (ebay)
Miniature relay JQC-3F(T73) (ebay)
Pro Mini Enhancement ATMEGA328P 5V with FTDI header or built in USB connector (ebay)
Main Control Circuit board ( make it yourself)
Encoder break-out board ( make it yourself)
Project Enclosure (make it yourself )
Pin Headers & Jumpers (optional)
Dupont female crimp connectors & Housings (optional)
Stranded hookup wire 28 or 30 gage
Misc small screws machine (4-40) & plastic 2.5mm
Additional materials, non-parts.
FTDI programmer (not needed if Arduino has USB)
3D printer( optional ) and filament.
4-40 Tap for back attachment screws. (or 4-40 threaded inserts)
WEIERLI SN-48B Crimping pliers (optional - for Dupont connectors)
A general note about project builds. Gathering materials for a particular project can often take months. Some items you may already have, some must be ordered, some you may need to make. I find it helpful to create a project box at the start of a project to hold all the materials. That way you can add materials as they become available and they are all at hand at build time.
Step 4: Circuit Board Design
Main Circuit Board - Schematic
The central player in this design is the Arduino Pro Mini. Its I/O pins connects all the hardware components. These components are powered directly or indirectly by 4 AAA batteries providing 6V to components where the voltage level is not critical. The OLED display V+ is provided by the Arduino 5V output.
The Battery + and ground is connected to the pin header PWR . The V+ pin is connected to the SWPWR header and through that to an external SPDT switch to provide 6V to the Arduino and optionally the relay. The relay circuit provides flexible control to external devices. One end of the relay coil is connected to the ground other end is connected to pin 6 of the Arduino. Bring this pin high powers the relay. The JACK pin header is connected to an external device phone jack. Additional pin headers provide flexible control of the voltage sent to the external device.
The COMN header allows the selection of the voltage source provided to the external device. If the pin 3 is connected (jumpers?) to pin 2, the external device provides its own power, if pin 1 is connected to pin 2 6V from the battery is provided to the external device. Note when this option is chosen you also must provide a Ground return by connecting the two pins of the GNDS header. The NONC header is used to select which voltage is sent when the relay is powered (NO) or not powered (NC). If NO is chosen there will be a drain on the battery whenever the timer is turned on (ie. the external device is powered by the timer's battery), only use this option if you device needs voltage to be turned off to activate.
The ROTENC (rotary encoder) header is connected to Arduino pins 2,3 & 4 in INPUT PULLUP mode. Header pin 1 is connected to ground, header pin 5 is not used in this design. PIN 4 is connected to the encoder push button, Pins 2 & 3 to the encoder's A & B switches.
The Arduino provides 5V power and ground to the OLED header. I2C protocol is used to control this display with Arduino A4 (SDA) and A5 (SCL) signals.
The Start/Stop momentary switch is connected to header START , Arduino pin 10. The other end is connected to ground.
The Alarm buzzer/speaker is connected to header SPKR, Arduino pin 11 and to ground.
You may either use pin headers & jumpers to allow flexibility and connection of external components or solder permanent jumpers between pads.
Main Board - Layout
The above circuit board layout image indicates the physical location of the components on the control board. I have positioned the Arduino so that the FTDI programming pins are facing the edge of the board to make programming easier. My copper image can therefore be used with an Arduino that uses these pins or are programmed via a USB connector with modification for your Arduino?.
The coppers & solder mask images are provided on a 8 1/2 x 11 master sheet in several formats.
Rotary Encoder - Schematic & Layout
We will be using a breakout board for the rotary encoder. This allows flexibility in its physical placement within the enclosure. This board is designed to allow it to be used in different projects.
The pin header JP1 has connections for a common signal (pin 5 either V+ or ground) at one end and at the other (pin 1) a pull up or down voltage source that may be connected to the rotary encoder through optional resistors ( R1 - R3 ). JP1 - 2 is connected to the encoder's push button and JP1 - 2 & 3 are connected to the encoders A & B signals. Again Copper & solder mask master sheet for this breakout are provided. To recap this design only uses encoder pins 2 -5, connect wiring or cables to these pins only, pullup is handled by the Arduino (see setup function.)
Step 5: Circuit Board Manufacture
Prepare and Etch the boards
Cut the boards to rough shape and clean thoroughly.
Prepare your copper images and print them out or use my master PDF files (attached).
Double check your work and transfer images to double sided boards for the main control and single sided for the encoder board.
Etch the boards and inspect.
This is an optional step but using a mask will improve the longevity of the project and look more professional. My circuit board tutorial explains this process. Note I did not use a solder mask for my encoder board but rather painted the back after soldering in the components.
Step 6: Populate the Boards
Since the component count is low this step is straight forward, There is one complication to my board design. I have included vias that connect copper traces on the top of the board to the bottom. I have found that I am not able to solder pin headers on to the top pads so these vias will connect signal bearing top pads to the bottom. I bridge these via between the top and bottom with thin gage solid wire. To facilitate holding the wire in place I crimp one end of a short piece of wire with pliers then drop it through the hole before bending the other end over. They should be secure enough to fill all the vias before soldering.
There are also two decisions to consider:
- Pin headers or no pin headers. Pin headers allow the timer components to be detached for testing and replacement. They do however increase the component count and require building connection cables with female Dupont crimp connectors and housings. Direct wiring is quicker in the short run but the wires tend to break with handling over time. I suggest using pin headers and Jumpers.
- Socket the Arduino or solder it directly. Solder directly is a more compact solution, the Arduino sits closer to the Main board and may result in fewer problems. Soldering female pin header sockets to the board adds to the part count, is less compact and may be less reliable but it does allow the Arduino to be removed for replacement or programming. In this case I feel it is a tossup.
Solder the vias first, then the relay. After that, either solder the Arduino directly or use female sockets for the Arduino to plug into ( don't forget the A4 & A5 pin sockets.) Lastly solder the Pin headers . If using direct wiring delay soldering into the header pads till after unit testing and assembly to minimize straining the wires.
Step 7: Unit Testing
Before connecting the individual components to the main board I suggest that you test them. I have gotten bad or marginal components from vendors and spent many hours trying to diagnose faulty software only to find the problem was in the hardware. Complex components may appear to work only to fail to work in some manner when exercised. Wiring and connectors are also a source of failure that need to be tested. If you are using Dupont connectors, now would be a good time to attach the female crimp-ons and housings. Crimpers are not mandatory, I survived a couple of years using needle nose pliers, but crimpers make for faster and more reliable connections once you get the hang of them. I have identified a crimper that I purchased in the parts list step.
Some components can be easily tested with a multimeter (switches, battery, external jack) others (rotary encoder, OLED) may require using the example Arduino programs associated with their libraries. Still others like the speaker and relay can be tested by writing a simple Arduino programs. As a result of my testing I discovered a problem with the wiring of the pin header to the rotary encoder. My design and program used Arduino pins 2 & 3 for the encoder A & B and Arduino pin 4 for the push button. There is a mis-match when using a ribbon cable to connect the encoder to the main board. Encoder A&B were connecting to Arduino pins 3 & 4 and the encoder push button to pin 2. As a result I changed the ribbon cable at one end (for my prototype board) to fix this problem. I did go back and change the board design to fix this problem for you! I suggest that you use the main circuit board and Arduino to perform these tests since it will also test out the Arduino and the circuit board. An hour of time performing these tests may save you several hours of debug time later.
Step 8: Create the Enclosure
I was not sure where to put this step since it can be done at almost any point. I used a 3D printed enclosure box. You may not have access to a 3D printer or prefer another type of enclosure such as Aluminum box, Laser Cut plastic, Hand Carved Wood or other type you use for your electronic projects. I have included the STL files for the top, bottom, rotary encoder knob and OLED bezel. Use these files and the slicer of your choice to create gcode files for your printer.
I print out all parts using PLA filament, one color for the enclosure top and bottom, another contrasting one for the knob and bezel (which is glued to the top.) I am not going to specify all my slicer settings but, use a Tri-Hexagon infill at least 35% to allow for tapping of the corner screws and a "no support" setting for the incised lettering to be read. I printed the box using my printers "normal" layer height.
Step 9: Design and Writing Code
This step is optional but suggested for better understanding.
The bulk of the effort in terms of hours is the writing of the code. You can skip this step if you use the attached program as -is. It is ,however, suggested you take the time to review the code for better understanding or modification to meet your needs.
The following comments may be helpful in understanding this process.
- Comments- Comment extensively as you go - I often write the comments before I write the code.
- Divide & conquer - use functions, classes, and modules(tabs.) Use frequent compiles (Verify) to check syntax. Debug - Use print statements to verify flow and test values and hardware interfaces. Don't be afraid to work through the problems as you go, no one writes code that is bug-free!
- Constants - #define pre-compiler instructions assign names to pin numbers. Const variable definitions with comments reduce or eliminate "Magic" numbers. The use of constants located at the start of a program or function allow changing the parameters without rewriting code
- Predefined Libraries - Using predefined Libraries reduces programming burden and debug time.
- Design Blocks - Created using functions, Isolating code in separate tabs (associated programs & .hfiles), enumerations, classes and structures. Focus you attention on each one to understand how they work in relation to the rest of the code.
- State Machine(s) - This is a programming pattern that works great with Arduinos or any programs that is used to control outputs or react inputs. Several flavors of state machines exist. This code uses a state machine based on the switch statement in the loop function. This form is easy to understand and debug.
- Display & Menus - The OLED output is terse but provides enough feedback for casual users and supports option selection. It integrates well with the state machine (almost all states have an associated OLED screen). The Menu class was helpful in isolating code to display and select menu options
Please read the program several times. It helps to take one function or section at a time. I often don't understand code that I have written unless I have read it at least twice!
Step 10: Install the Program
Copy the attached file to your computer then unzip it into your Sketches directory
Connect the Arduino to your computer and download the program code in the normal manner. Open the Arduino IDE serial monitor to verify that the program is running and aid in debugging.
Step 11: Assemble the Timer
Once the top and bottom parts of the case are printed and cleaned up the components can be attached using small self-tapping plastic screws. First the battery holder is snapped into the back . The rest of the parts are attached to the enclosure top in the following order:
- OLED and cable
- Start/Stop switch & wiring
- Rotary Encoder and cable
- Speaker / Buzzer & wiring
- External control jack and wiring
- On/Off slide switch and wiring ( double check orientation so that on is in the direction you want
If you are soldering the cables directly to your circuit board, do this after all the parts are attached to your enclosure to reduce wire breakage. You to wait till the cables are wired to the main board before you screw that board to the back.
If you are using pin headers and Dupont connectors, first attach the main board to the back using screws then plug the components in. Be careful when you connect the battery to the main board and observe the correct polarity. You should also set up the relay control jumpers or wiring at this time.
The bottom of the enclosure connects to the top via using 4-40 round head machine screws, one in each corner. The four holes in the top should either be tapped with a 4/40 tap or if you use 4-40 threaded inserts, you will need to drill the holes to accept them. The 4 holes for the main circuit board mounting on the bottom also need to be drilled. Snug up this board to the snap-in battery mount and mark the locations of the holes. Drill as appropriate for your mounting screws.
Step 12: Integration Testing
Final (integration) testing is accomplished by trying all the menu options and verify they work with the hardware as designed. For the code I provided, that should sufficient. If you wrote your own code or modified mine your testing will need to be more extensive. I don't believe all the timing selections need to be exercised but you need to try all standard alarm options and validate Nap and Meditation alarms work as designed.
Step 13: Final Thoughts
Congratulations on your successful, I hope, project. I'm sure you encountered problems along the way that you needed to solve. I am also sure that some of my instructions could have been more complete or clearer. Please let me know through the comments section what your results were and provided suggestions on how these instructions may be improved.
Thanks for your time viewing and/or building this project.