Jump to content
43oh

Keeping Track of Time?


Recommended Posts

I am about to start a project with the msp430 launchpad, and my goal is to make a digital clock. I was wondering if anyone knew how to keep track of time inside the microcontroller? For example, when it powers on, it would start at some arbitrary time (like 12:00), and then keep track of the time continuously as it's running. Does anyone know how to do this?

 

Thanks for your help,

 

Matthew

Link to post
Share on other sites

First off, Welcome to the forums! Take a minute to introduce yourself in the New Users section!

 

These projects should help:

 

Doug Paradis' MSP430-based "chronulator" (great info on calibrating the external crystal)

 

simpleavr's 3-part, 4-wire clock (should be especially helpful; it's a clock with extra functions and low parts count)

 

-Doc

Link to post
Share on other sites

Thanks for the reply! However, those are a bit more complicated than I was looking for. I am new to microcontrollers, but I have gained some experience using them in a lab for one of my classes. We used the M430F2012, and did some basic things like a blinking LED, an introduction to the ADC, and using a touch sensor. (A copy of the lab is here: http://ucbfeedback.com/assignments/166/pdf if you're interested).

 

Perhaps I should explain my project a little better. I am planning on making a 4-digit digital clock, where each digit is made up of 20 LEDs. Each of the digits will be controlled by a separate microcontroller. I found a way to display all the numbers properly using 9 of the 10 I/O pins. (Note: I based this off the M430F2012, but it looks like I can easily adapt it to the microcontroller that comes with the launch kit). Here is what I came up with:

 

digitalclockdisplay.png

 

My plan is to use 1 microcontroller for each digit of the clock, and then use another microcontroller to keep track of the time and send a voltage to the free I/O pin on the other microcontrollers displaying the digits so they know what number to display. The thing that I do not know how to do is keep track of the time (especially in a digit-by-digit form). Are there any other simple examples that could lead me on the right track?

 

Thanks again for your help,

 

Matthew

Link to post
Share on other sites

Rather than using a separate microcontroller on each digit, you might want to go the route this guy did for his scoreboard project. He uses 8-bit, constant current, LED drivers with cascadable latch registers, and just runs what looks like a 5-wire bus between digits (SPI, Vcc, latch). Takes care of driving the LEDs and handling communication with digits in one part!

 

-Doc

 

EDIT: Just noticed you want 9 bits on your display. Still, worth looking into...

Link to post
Share on other sites

may i ask what is your project objective?

 

if you want a simplest solution that requires fewest component and cost, u could

. use 32Khz crystal to keep accurate timing. this reduce your usable io pins to 8

. employ charlieplexing to drive all your segments (9x4=36)

. charlixplex can drive 42 segments w/ 7 io pins

. u don't need any additional components, just leds and a MSP430G2211

. will need to work harder on the wiring and led timing

 

if this is a architecture showcase project, i.e. u need to demonstrate certain things (MCU to MCU comms, etc)

. employ your existing MCU per digit design.

. have one io pin as interrupt pin.

. program your "slave" MCUs to advance digit (from 0 to 9 or 0 to 6, etc) per interrupt trigger.

. consecutive triggering (i.e. 16 triggers in less than, say 100ms) can be view by "slaves" as reset counter to 0.

. your "'master" mcu will have 4 io pins to drive each interrupt pins of the 4 "slaves".

. you keep time via timer_a interrupts and at each minute / second toggle the related io pins to trigger individual "slave" digit advances.

. you can also implement software i2c between the master and slave MCUs to showcase as special design feature, more complicated but your design will be more flexible.

 

either case the following is a good read, it shows you how to make 430 MCU act as a RTC, may be this is just what u originally asked for

 

http://focus.ti.com/lit/an/slaa076a/slaa076a.pdf

 

hope this help.

Link to post
Share on other sites
may i ask what is your project objective?

 

if you want a simplest solution that requires fewest component and cost, u could

. use 32Khz crystal to keep accurate timing. this reduce your usable io pins to 8

. employ charlieplexing to drive all your segments (9x4=36)

. charlixplex can drive 42 segments w/ 7 io pins

. u don't need any additional components, just leds and a MSP430G2211

. will need to work harder on the wiring and led timing

 

if this is a architecture showcase project, i.e. u need to demonstrate certain things (MCU to MCU comms, etc)

. employ your existing MCU per digit design.

. have one io pin as interrupt pin.

. program your "slave" MCUs to advance digit (from 0 to 9 or 0 to 6, etc) per interrupt trigger.

. consecutive triggering (i.e. 16 triggers in less than, say 100ms) can be view by "slaves" as reset counter to 0.

. your "'master" mcu will have 4 io pins to drive each interrupt pins of the 4 "slaves".

. you keep time via timer_a interrupts and at each minute / second toggle the related io pins to trigger individual "slave" digit advances.

. you can also implement software i2c between the master and slave MCUs to showcase as special design feature, more complicated but your design will be more flexible.

 

either case the following is a good read, it shows you how to make 430 MCU act as a RTC, may be this is just what u originally asked for

 

http://focus.ti.com/lit/an/slaa076a/slaa076a.pdf

 

hope this help.

 

The objective is to create something with the knowledge I've gained so far in the course. It is a course on circuit theory, not programming microcontrollers, so I think the original design is more what my professor is looking for. I like your idea for the interrupt trigger, originally I was thinking of using the ADC to send each of the other microcontrollers a certain voltage, and based on that voltage they would determine which number to display. I think I will go with your soultion instead.

 

The document you provided is somewhat what I am looking for. However, I would prefer not to use the crystal, so I can keep as many free pins as possible on the master controller, and because I have no idea how to solder, and the project has to be fully implemented on a breadboard. Is there a way to keep time without the crystal? It doesn't need to be horribly accurate, since this project is more about proof of concept than anything else.

 

Thanks again for all the input

-Matthew

Link to post
Share on other sites
Is there a way to keep time without the crystal? It doesn't need to be horribly accurate, since this project is more about proof of concept than anything else.

Sure. The internal oscillator is fairly accurate (1MHz) for short-term timekeeping.

What GeekDoc said. To set the DCO (which runs the MCKL and SMCLK by default) to 1MHz, use the following two lines of code (in c):

   // setup DCO for 1MHz ticks
   BCSCTL1 = CALBC1_1MHZ;
   DCOCTL = CALDCO_1MHZ;

 

The MSP430G2xxx chips come with a pre-calibrated set of values for setting the DCO to 1MHz. This value varies for each individual chip, but can be accessed by the CALBC1_1MHZ and CALDCO_1MHZ registers.

 

Hope this helps! And good luck fitting all of that on a breadboard... :P

Link to post
Share on other sites

the time keeping is the least thing u should worry about, i would worry about how to put the circuit together on a breadboard.

 

here is the code needed to keep a no-so-accurate time (may be off a few minutes a day)

 

it's taken and modified from the ti 2xx examples (slac080h.zip i think) msp430x20x3_ta_02.c

 

i tried it on a EZ430 dongle and it's working as expected. i build w/ msg430-gcc but it should built under windows w/ CCS also.

 

. use SMCLK at 1Mhz as based

. use calibrated value for clock to maximize accuracy.

. count to 50,000 to get a timer interrupt (20 times/sec)

. another counter counts the clicks to 20 and resets it (we got one second here)

. update a system 'clock' (ticks), this contains the seconds since midnight

. also update a flag so that your main loop got signal to do something (advance slave digit counters?)

. u need to add your own logic to get seconds, hours, etc by deriving them from the 'clock' ticks.

 

 

//  use timer_a to generate one second ticks
//  built with msg430-gcc, flash w/ mspdebug
//

#ifdef MSP430
#include "signal.h"
#endif
#include 

volatile unsigned char second_passed=0;	// advance indicator
volatile unsigned long ticks=0;	// 'clock' in seconds

void main(void) {
 WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
 BCSCTL1 = CALBC1_1MHZ;		// Set DCO to 1MHz factory calibration value
 DCOCTL = CALDCO_1MHZ;
 P1DIR |= 0x01;                            // P1.0 output
 CCTL0 = CCIE;                             // CCR0 interrupt enabled
 CCR0 = 50000;
 TACTL = TASSEL_2 + MC_1;                  // SMCLK, upmode
 _BIS_SR(GIE);                 // enable interrupt

 while (1) {
 	if (second_passed) {
	//____ do something w/ ticks
	//     ? trigger via io slave MCUs etc
	second_passed = 0;
}//if
 }//while

 //_BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}

// Timer A0 interrupt service routine
#ifdef MSP430
interrupt(TIMERA0_VECTOR) Timer_A(void)

#else
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)

#endif
{
 static unsigned int clicks=0;
 // we will get called at 1Mhz/50k = 20 times a seconds
 clicks++;
 if (clicks >= 20) {
 	clicks = 0;
ticks++;		// advance clock for each second
second_passed = 1; // have a flag to tell back main loop
 }//if
 // the followng can be a HHMM colon seperator led
 // take them out if not needed
 if (clicks >= 10)
  P1OUT |=  0x01;               // half second on
 else
  P1OUT &= ~0x01;               // half second off
 //P1OUT ^= 0x01;                  // Toggle P1.0
}

 

if you are not to solder, i think u will need a very big breadboard or several smaller ones. either way, it will be bad hair day w/ all the jumpers (and almost impossible to debug).

 

the design of using single leds will make it almost impossible to do a proper layout, also w/ some segment have 2/3 leds in series will requires u to have different resistor values (or different refresh rates if u do not use resistors).

 

if u can replace them w/ 7-segment LEDs you will save yourself a lot of trouble.

 

[EDIT] just noticed i forgot to enable interrupt (but it did worked anyway)

Link to post
Share on other sites

Thanks simpleavr! That is exactly the type of code I was looking for.

 

I have a couple quick questions to help me understand fully how it works:

 

-What makes this method of keeping the time inaccurate? Is it that the processor isn't perfectly calibrated to 1MHz?

-Is the mcu asleep while it is waiting for a click to occur?

-Will the mcu interrupt whatever it's doing every 50k cycles to increase the clicks counter? What if it's in the middle of processing another function? Will it pause, increment clicks, and then go back to it?

 

If I understand the code correctly, the main loop waits for the variable second_passed to equal 1, and then if it does equal one, it does whatever actions are necessary (in this case, it will take the necessary steps to increase the time), and then second_passed gets set back to zero and it waits for it to be 1 again. What happens if another second passes and it's still in the middle of the instructions for second_passed? Is this where the time inaccuracy occurs?

 

Also, is there a way to make the output of a pin on the mcu a fraction of Vdd?

 

Thanks for all the help and advice! Also, for your concern about the breadboard, I think what I will do is have each digit on a small breadboard and try to wire everything as neatly as possible. (I do agree that it will still be pretty messy).

Link to post
Share on other sites
Also, is there a way to make the output of a pin on the mcu a fraction of Vdd?

To answer the part that I do know: No, you cannot set a voltage other than Vcc on an output pin.

 

What you are looking for is a Digital to Analog Converter (DAC) function, which the MSP430G2231/2211 do not have. The LaunchPad does have a nice ADC (Analog to Digital Converter), but that is obviously the opposite direction.

 

I believe there are other MSP430 models with DAC functions, but I'm not sure if they are compatible with the LaunchPad. Others here are more familiar with the rest of the MSP430 line and may be able to help.

Link to post
Share on other sites

-What makes this method of keeping the time inaccurate? Is it that the processor isn't perfectly calibrated to 1MHz?

if it can be made perfect, there will be no need to calibrate. from the datasheet the MSP430G2231 has a typical accuracy of plus/minus 3%, at idea case it's plus/minus 0.5%. if u can keep constant voltage and constant temperature, it will be more accurate. even crystals have some drifts and for accuracy u can match capacitors or even oven control them (for temperature).

 

-Is the mcu asleep while it is waiting for a click to occur?

no, but u can make it happen by entering various LPM modes, for more power saving (LPM3) you will need to use VLO (or 32Khz crystal) as the DCO is also shut down.

if u really want to showcase this, u can

. inside the while loop, go to sleep LPM?, etc.

. inside your timer interrupt do _BIC_SR_IRQ(LPM?_bits) to exit LPM when u got a second tick (actually u could remove the "second_passed" flag in this case as system would be asleep unless it passes a second.

. you should use clock divider (divide by 8 at most) so that the system gets fewer interrupts and thus further power save.

. i had made the quick example simple so that it's easy to understand. and if u can gain by showcasing more features in your project you should implement them (clock dividing, power saving, etc) once the basics is going OK.

 

-Will the mcu interrupt whatever it's doing every 50k cycles to increase the clicks counter? What if it's in the middle of processing another function? Will it pause, increment clicks, and then go back to it?

if an interrupt occurs, your processing will be suspended after the interrupts have been served. for multiple interrupts at the same time, there is also a defined priority list based on interrupt types (u can find them in datasheet).

typically inside your interrupt routine u should disable further interrupts to avoid race conditions / re-entrance problems.

and u should disable them during your critical processing (trigger slaves, etc).

in this case we need the interrupts on all times to keep the time right and the logic processing is not that critical (triggering the slave is still safe if interrupted). but u surely can experiment w/ them, or showcase such consideration in your code.

What happens if another second passes and it's still in the middle of the instructions for second_passed? Is this where the time inaccuracy occurs?

it won't happen, or u have to make it not happen, if your core logic requires that much cycles (like 1million cycles), u should revise them. (or setup to run faster).

 

another note, if u implement LPM u may want to check the datasheet as there may be delays here and there when some MCU features are brought back from sleep, these may affects accuracy.

Link to post
Share on other sites

Thanks for the helpful replies!

 

I was really hoping I could set the output to a certain fraction of Vcc so I could showcase my knowledge of ADC's in the other four mcus (since ADC and DAC were covered in the course). I guess this means I am stuck using interrupts for the other four mcus controlling the other digits?

Link to post
Share on other sites

to demonstrate adc in your current design, u can

 

. capture and show temperature via the in-built adc10 channel, this is a very cheap addition (a dozen lines of code)

. divide your vcc in two resistor and feed it to a adc input and show supply voltage on slave displays (kind of a low-battery detect)

. attach a variable resistor to an adc channel and make it as input for advancing / decreasing the clock values

 

dac is kind of out unless u are willing to expand your circuit.

 

focus.ti.com/lit/an/slaa116/slaa116.pdf show how to use PWM to do DAC.

 

or google for "r-2r dac"

 

either way, i don't know how much time u have to construct this, i would start simple and get the basics working and then add one feature at a time. if u try to implement all feature at once it's difficult to debug what went wrong.

 

may be construct a "slave" digit control 1st. instead of tying the interrupt to the clock "master", u can just use a tactile button to test the digit advancing logic.

Link to post
Share on other sites

Thanks for the great ideas, the potentiometer changing the speed sounds like a really fun one to implement!

 

I'm trying to work through the logic of the individual digits in my head right now, and the simplest solution I can come up with to code would be:

 

    if(input voltage at pinx != 0){
     -increase digit, and depending on its position, determine whether it
       should be reset to 0 or off.
     -wait for input voltage at pinx to go back to zero
   }

 

The way it would work is if a digit is to be increased, the master turns on the pin connected to the digit for a brief period of time, and then turn it off. Then, the digit waits for this change in the input pin, increases the digit, resetting it back to its base value if necessary, and then waits for the voltage at the input pin to turn back off. This way, turning the voltage on and off at a certain pin of the master would be like operating a digital switch. The above code would be placed inside an infinite while loop inside main.

 

I am assuming there is a way to at least detect if the voltage at a certain input pin is zero or not? Does this procedure sound technically possible, or are there more limitations to the mcu's that I'm overlooking?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...