This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I have a simple circuit where an MSP430G2152 is used to control a transistor. The intent is to briefly cut the power to a device once per day (the reason is a long story so I won't get into it). I'm trying to get as close to once per day as possible using a minimum of parts to keep the cost low. So, no external crystal, RTC, etc.).
I built three replicates of the same circuit, and programmed them with the same program in order to look at the variation between the three.
My test code is as follows:
#include <msp430.h> //***************************************************************************** // GLOBAL VARIABLES * //***************************************************************************** #define RED_BIT BIT7 #define GREEN_BIT BIT6 #define ENABLE_OUTPUT_BIT BIT0 #define THRESHOLD_0M 6646 // Estimated total counts for a 24 hour period #define RESET_DURATION 95541 // ~2 sec off time long CYC_COUNTER = 0; //***************************************************************************** // Set up device for specific clock rate, power configuration, and outputs * // before enabling the watchdog timer. * //***************************************************************************** int main(void) { // Stop the watchdog timer WDTCTL = WDTPW | WDTHOLD; // Setup the auxiliary clock (ACLK) // - DIVA_2 = /4 (~10.9s) BCSCTL1 = DIVA_2 | BCSCTL1; // Setup the master clock (MCLK): // - Run from DCOCLK (SELM_0) // - SMCLK from VLOCLK (SELS) BCSCTL2 = BCSCTL2 | SELM_0 | SELS; // - Set to use 12kHz VLOCLK since XTS = 0 (LFXT1S_2) BCSCTL3 = LFXT1S_2; // Setup the IO functions for the LED and output enable line P2SEL = P2SEL & (~RED_BIT) & (~GREEN_BIT); // Select IO function for P2.6 and P2.7 (LEDs) P1SEL = P1SEL & (~ENABLE_OUTPUT_BIT); // Select IO function for P1.0 (Power control) P2OUT = P2OUT | GREEN_BIT; // Pre-configure the output to turn on the GREEN LED P2DIR = P2DIR | RED_BIT | GREEN_BIT; // Set Port 2 direction to output. P1OUT = P1OUT | ENABLE_OUTPUT_BIT; // Turn on output enable P1DIR = P1DIR | ENABLE_OUTPUT_BIT; // Set Port 1 direction to output. // Turn on the GREEN LED and turn off the RED LED P2OUT = P2OUT & (~RED_BIT) | GREEN_BIT; // Configure watchdog/interval timer (WDT): // - From ACLK (WDTSSEL) // - Interval timer (WDTTMSEL) // - ACLK/32768 (WDTIS0 and WDTIS1 UNSET) // - Counter cleared (WDTCNTCL) WDTCTL = WDTPW + WDTSSEL + WDTTMSEL + WDTCNTCL; // Set the interrupt configuration // - Enable WDTIFG interrupt for interval timer mode (WDTIE) IE1 = IE1 | WDTIE; // Configure power mode // - LPM3 = CPU, MCLK, SMCLK, DCO are disabled. DC generator disabled. ACLK is active. _BIS_SR(LPM3_bits + GIE); // Original: Enter LPM3 with interrupts return 0; } //***************************************************************************** // The watchdog timer controls the counter and the visual display indicating * // to the user the amount of time remaining in a power cycle. This routine * // is entered based on the WDT interrupt, disabled, the count checked and the * // indication shown to the user and/or the power cycled, and then the watchdog* // is re-enabled for another loop. This continues until power is removed. The * // counter is volatile and resets upon power-up. * //***************************************************************************** #pragma vector=WDT_VECTOR __interrupt void WatchdogTimer(void) { volatile long i = 0; volatile long j = 0; volatile int blink = 0; CYC_COUNTER++; // Reset the watchdog timer WDTCTL = WDTHOLD + WDTPW; // Enable the LEDs P2DIR = P2DIR | GREEN_BIT | RED_BIT; if (CYC_COUNTER >= THRESHOLD_0M) { // 0M (RESET EVENT) P2OUT = P2OUT & (~GREEN_BIT) | RED_BIT ; // Turn on the RED LED and turn off the GREEN LED P1OUT = P1OUT & (~ENABLE_OUTPUT_BIT); // Turn off the output. for (i = RESET_DURATION; i >= 0; i--) {} // Delay P1OUT = P1OUT | ENABLE_OUTPUT_BIT; // Turn on the output. P2OUT = P2OUT | (~GREEN_BIT) | (~RED_BIT); // Turn off all LEDs CYC_COUNTER = 0; // Reset the cycle counter }
// Turn off the LEDs P2DIR = P2DIR & (~GREEN_BIT) & (~RED_BIT); // Configure WDT to run as interval timer again, restarting the whole process WDTCTL = WDTPW + WDTSSEL + WDTCNTCL + WDTTMSEL; return; }
The results are dramatically different looking at the actual time between power-on and the output cut event (intended to be close to 24:00:00):
Board 1 - 22:33:44
Board 2 - 24:01:22 (this was the board used to determine the value of THRESHOLD_0M
Board 3 - 25:28:32
The variation seems to be directly tied to the watchdog interval timer.
My questions:
1. Is this much variation expected from controller to controller within the watchdog when used as an interval timer?
2. What can I do to limit this variation? I do not want to add more parts, so software solutions are ideal. I also cannot leave the part active all the time since power consumption is a consideration for my application, although I'm not sure that would address the underlying cause anyway.
As a test, I also ran the same code using LPM2, LPM1, and LPM0 and the results are very similar.
Thanks for reading. Any help would be appreciated.
vlo can be off by 20%, time it using 1% dco calibration and it gets a little better.
I would try a on the fly calibration,
you use dco for the wdt for four cycle (8sec) once every 30 minutes and when you get back you check vlo value in T0AR
do not div aclk during this as that will give less rounding down error
~15KHz for 4seconds will fit in 64K timer, plus you can always check overflow flag.
You will now know what value 8sec is, you calculate so you sleep for 29min and 52 seconds with vlo
and then do next dco wdt calibration for 8sec again = 30min total.
But over a month or two it will still (probably) be off by hours,
unless you press a button at for say 9:00am once every two weeks or some other outside reference.
A 32K crystal cost 60cents and you will only be off a minute a year.
Ryan Smith46 said:...I'm trying to get as close to once per day as possible using a minimum of parts to keep the cost low...
Is 50/60Hz AC main available to your system?
If so, you may be able to derive a 50/60Hz clock cheaply. Depends on where you are, the accumulative clock frequency error can be much smaller than that from a watch crystal.
**Attention** This is a public forum