1
\$\begingroup\$

Alright so I learned all the fundamentals of the AVR and now I am thinking of building a clock as a project. I will use the ATMega328P along with the DS1307 RTC. The time will be shown on an LCD or OLED display. What I want to know is how the general structure of the overall program will be. I know that there will two modes; one to set the time and one in which the clock runs normally. I need some help as to how I will implement these modes and two switch between them using external buttons. It would be great if someone could shed light on this. Thank you.

\$\endgroup\$
1
\$\begingroup\$

When working with modes and states, I strongly advice you to use while loops.

So a start would be something like this:

#define up_button 0
#define down_button 1
#define set_button 2
#define leave_set_button 3

main_loop(){

    read_RTC_clock();
    //Through spi or i2c or what have you

    write_RTC_clock_to_display(); 
    //To the LCD or OLED display

    read_button_states(); 
    //Update the input_port variable

    if(input_port&set_time_button){
        while(!input_port&leave_set_button){//"and" out the leave button
            //If you are in this loop, then you will stay in here
            //until the user chooses to leave.

            //so we better make it possible for the user to leave by
            //reading the inputs and updating the button status

            read_button_states(); 
            //Update the input_port variable

            switch(input_port){
                case up_button|down_button: 
                //up_button|down_button means that
                // I press both simultaneously
                increment_step = 60/increment_step;
                //if increment_step is 60, then it's now 1 second
                //if increment_step is 1, then it's now 60 seconds
                break;
                case up_button: time+=increment_step; break;                    
                case down_button: time-=increment_step; break;
            }

            //and why not show the LED or OLED what we're doing
            write_settings_to_display();
        }
        write_time_to_RTC_clock();//update the RTC with the time we set
    }
}

I won't write more... but... this is how I would start the project. I would also debounce the buttons in software. I would also ask myself how many buttons I really want, the more buttons the easier it is to use. It could work with only 2 buttons, but then you need to use some timing so if you hold one button down for 1 second it means something different than if you just tap it for 10 milliseconds.

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Guidance? Sure... don't bring it to school.

In all seriousness, if you are using the RTC this is fairly simple, since you don't have to worry about actually keeping time. Displaying time could just be an at-convenience loop which queries the RTC and then updates the display. It sounds like your display is also command oriented rather than something you would need to explicitly multiplex like a 4-digit 7-segment LED.

In terms of setting the clock, one approach would be to consider the concept of a Finite State Machine.

However, at the simplest level, you could just have logic which checks to see if a single "adjust" button is pushed. If it is, then the time gets advanced by some faster-than-actual-time unit and displayed, a delay of some chunk of a second is waited then the cycle repeats.

That post-delay will have the benefit of both pacing things for the user, and of solving the contact bounce problem by simply ignoring the button for a bit after each time you conclude it is (still) pressed.

A more refined design might offer both a fast and slow button. Or you could build an accelerating button where the delay starts out long, and reduces towards a minimum the longer the button is held.

At an extreme you could provide individual up and down buttons for hours and minutes, or even for each digit of each.

Or your could build a more stateful scheme, where you have a digit select button that changes which digits flashes, and an increment button which increments the selected digit.

A more advanced project would be to do this all with MCU and its on-chip timers, without the RTC chip. Potentially you could even do it from the slow speed oscillator running off a watch crystal.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ I was looking forward to 3 buttons, UP, DOWN and SET that you can used to set up the seconds, minutes hours etc. The subroutine to set up the time would run once only when the watch is powered up and after that the watch would work normally until it is reset again to set the time. The main thing I would have to work with is how to increment,decrement the time since the RTC stores in BCD and not binary. \$\endgroup\$ – hacker804 Jul 13 '17 at 2:38
  • \$\begingroup\$ Something like the button count and BCD requirement really should be explicit in your question. It shouldn't be too hard to do addition, and implement carry logic - just think about how you would do it manually. Start without the down button so you can defer worrying about subtraction, and make an implicit rule that if both the up and set are pressed, one "wins" as this will allow you to consider everything in the same decide/delay loop with its implicit debounce. \$\endgroup\$ – Chris Stratton Jul 13 '17 at 2:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.