One component radio clock time transmitter
Believe it or not, you can generate a time signal to set your WWVB controlled radio clocks with just an attiny45, wire antenna, and a battery. Upload the code to an attiny45, put a 20" or so wire on pin 6 and power with 5v. You'll need to put your radio clock close to pick up the signal best.



Step 1: The WWVB time signal and 60Khz carrier

One component radio clock time transmitter
The WWVB time signal is a 60khz carrier modulated by reducing the carrier in a particular sequence to encode the time. Wikipedia has a good article which I used to design this project: https://en.wikipedia.org/wiki/WWVB

The attiny45/85 has a fast timer that can be set to generate a square wave at 60khz like this:

/* Initalize Fast PWM on OCR1A*/
DDRB |= _BV(PB1); // Set PWM pin as output
PLLCSR |= _BV(PLLE); // Start PLL
_delay_us(100); // Wait till PLL stablizes p. 9
PLLCSR |= _BV(PCKE); // Set Clock source to PLL
OCR1C = 132; // Set OCR1C to top p. 91 (60kkHz)
OCR1A = 66; // Set beginning OCR1A value (50% duty cycle)
TCCR1 |= _BV(CS12); /* Set clock prescaler to 8 */
TCCR1 |= _BV(PWM1A) /* Enable PWM based on OCR1A */ \
| _BV(COM1A0) /* Set PWM compare mode p. 89 */ \
;


Step 2: Modulating the 60khz Carrier

One component radio clock time transmitter
To modulated the carrier, just reduce the duty cycle of the wave by changing OCR1A to less than 66. I set the other timer on the attiny45 to fire an interrupt 61 times a second like this:

/* Initalize CTC interupt on timer0 at 61hz */
TCCR0A |= _BV(WGM01); //pg. 82 Mode 2 CTC OCR0A TOP
OCR0A |= 127; // 8mhz / ((127+1) * 1024 prescale) = 61hz
TCCR0B |= _BV(CS00) | _BV(CS02); // set prescaler to 1024
TIMSK |= _BV(OCIE0A);// enable compare match interrupt
sei(); // Enable interupts

This gives 61 times slices in each second to reduce the power of the carrier for modulation.

Step 3: Encoding the modulation with a time signal

One component radio clock time transmitter
Next I wrote a routine which would keep track of the 61 time slices of each second and change to duty cycle of the carrier to encode the time signal. Each case represents a second of the minute long time signal. Each parameter can be set. I have a few defines that can be used to easily change the hour and minutes. You can add other defines too.

ISR(TIMER0_COMPA_vect){

switch (slot) {

case 0 : { signal = 2;break;}

case 1 : { signal = ((minute_tens >> 2) & 1);break;} // min 40
case 2 : { signal = ((minute_tens >> 1) & 1);break;} // min 20
case 3 : { signal = ((minute_tens >> 0) & 1);break;} // min 10

case 5 : { signal = ((minute_ones >> 4) & 1);break;} // min 8
case 6 : { signal = ((minute_ones >> 2) & 1);break;} // min 4
case 7 : { signal = ((minute_ones >> 1) & 1);break;} // min 2
case 8 : { signal = (minute_ones & 1);break;} // min 1

case 9 : { signal = 2;break;}

case 12 : { signal = ((hour_tens >> 1) & 1);break;} // hour 20
case 13 : { signal = ((hour_tens >> 0) & 1);break;} // hour 10

case 15 : { signal = ((hour_ones >> 4) & 1);break;} // hour 8
case 16 : { signal = ((hour_ones >> 2) & 1);break;} // hour 4
case 17 : { signal = ((hour_ones >> 1) & 1);break;} // hour 2
case 18 : { signal = (hour_ones & 1);break;} // hour 1

case 19: { signal = 2;break;}

case 26: { signal = 1;break;} //
case 27: { signal = 1;break;} // Day of year 60
case 29: { signal = 2;break;} //

case 31: { signal = 1;break;} //
case 32: { signal = 1;break;} // Day of year 6
case 37: { signal = 1;break;} //
case 39: { signal = 2;break;}

case 42: { signal = 1;break;} //
case 43: { signal = 1;break;} // DUT1 = 0.3
case 49: { signal = 2;break;}

case 50: { signal = 1;break;} // Year = 08
case 55: { signal = 1;break;} // Leap year = True
case 59: { signal = 2;break;}

default: { signal = 0;break;}
}

switch (signal) {

case 0: {
// 0 (0.2s reduced power)
if (timer < 12) {OCR1A = 6;}
else {OCR1A = 66;}
} break;
case 1: {
// 1 (0.5s reduced power)
if (timer < 30) {OCR1A = 6;}
else {OCR1A = 66;}
} break;
case 2: {
// Marker (0.8s reduced power)
if (timer < 48) {OCR1A = 6;}
else {OCR1A = 66;}
} break;
}

timer++; // Advance timer
if (timer == 61) { // Check to see if at end of second
timer = 0; // If so reset timer
slot++; // Advance data slot in minute data packet
if (slot == 60) {
slot = 0; // Reset slot to 0 if at 60 seconds
minute_ones++; // Advance minute count
}
}
}

Step 4: The hex files and c code

One component radio clock time transmitter
The hex files for direct uploading of your microcontroller can be downloaded below. Also included is the C source file.

Have fun!
One component radio clock time transmitter
pwm.hex1 KB
One component radio clock time transmitter
pwm.c3 KB
 
 

Tag cloud

make build easy simple arduino making homemade solar laser printed portable cheap mini building custom cardboard wooden create super lego turn paracord chocolate your paper light intel