Setting radio controlled clocks using WWVB

I am working on an project to try and set our WWVB radio controlled clock using an Uno.

I was inspired by this project using an attiny chip. http://www.instructables.com/id/WWVB-radio-time-signal-generator-for-ATTINY45-or-A/.

I am using this PWM frequency library, http://forum.arduino.cc/index.php?topic=117425.0 to get a 60kHz wave.

I am modifying the duty cycle of the waveform in a similar fashion as the attiny project. I have about a 4 foot wire acting as my antenna connected to pin 9. I have verified that I do get a 60kHz wave on an oscilloscope. But my clock won’t set. Here is my sketch.

#include <PWM.h>

int led = 9;               // the pin that the LED is attached to
int32_t frequency = 60000; //frequency (in Hz)
unsigned long previous_time ;
int frame = 0 ;

void setup() {
  //initialize all timers except for 0, to save time keeping functions
  InitTimersSafe(); 

  //sets the frequency for the specified pin
  bool success = SetPinFrequencySafe(led, frequency);
  
  uint16_t frequency = Timer1_GetFrequency();
  uint16_t decimalResolution = Timer1_GetTop() + 1;
  uint16_t binaryResolution = GetPinResolution(led);

  char strOut[75];
  sprintf(strOut, "Frequency: %u Hz\r\n Number of Possible Duties: %u\r\n Resolution: %u bit\r\n", frequency, decimalResolution, binaryResolution );
  Serial.begin(115200);
  Serial.println(strOut);

  // Use built-in LED to for visual confirmation of output signal.
  pinMode(13, OUTPUT);

  pwmWrite( led , 128 ) ;
  digitalWrite(13, HIGH);
    
  previous_time = millis() ;
  
}

// flash LED to mirror output signal.
void reduce_power( long time ) {
    pwmWrite(led , 5 ) ;
    digitalWrite(13, LOW);
    delay( time ) ;
    pwmWrite(led , 128 ) ;
    digitalWrite(13, HIGH);
}

// Fake time and date
int hours = 6 ;
int minutes = 12 ;
int days_of_year = 267 ;
int year = 14 ;

void loop() {

  unsigned long current_time = millis() ;

  if ( current_time - previous_time > 1000 ) {
      int signal ;
      int hours_tens, hours_ones ;
      int minutes_tens, minutes_ones ;
      int temp_days_of_year, days_of_year_hundreds , days_of_year_tens , days_of_year_ones ;
      int year_tens , year_ones ;
  
      hours_tens = hours / 10 ;
      hours_ones = hours - hours_tens * 10 ;
  
      minutes_tens = minutes / 10 ;
      minutes_ones = minutes - minutes_tens * 10 ;
  
      days_of_year_hundreds = days_of_year / 100 ;
      temp_days_of_year = days_of_year - days_of_year_hundreds * 100 ;
      days_of_year_tens = temp_days_of_year / 10 ;
      days_of_year_ones = temp_days_of_year - days_of_year_tens * 10 ;
  
      year_tens = year / 10 ;
      year_ones = year - year_tens * 10 ;
      
      switch (frame) {    
          case 0 : signal = 2; break; // marker
          case 1 : signal = (minutes_tens >> 2) & 1; break; // min 40
          case 2 : signal = (minutes_tens >> 1) & 1; break; // min 20
          case 3 : signal = (minutes_tens >> 0) & 1; break; // min 10
          case 4 : signal = 0; break; // unused
          case 5 : signal = (minutes_ones >> 3) & 1; break; // min 8
          case 6 : signal = (minutes_ones >> 2) & 1; break; // min 4
          case 7 : signal = (minutes_ones >> 1) & 1; break; // min 2
          case 8 : signal = (minutes_ones >> 0) & 1; break; // min 1
          case 9 : signal = 2; break; // marker
          case 10 : signal = 0; break; // unused
          case 11 : signal = 0; break; // unused
          case 12 : signal = (hours_tens >> 1) & 1; break; // hour 20
          case 13 : signal = (hours_tens >> 0) & 1; break; // hour 10
          case 14 : signal = 0; break; // unused
          case 15 : signal = (hours_ones >> 3) & 1; break; // hour 8
          case 16 : signal = (hours_ones >> 2) & 1; break; // hour 4
          case 17 : signal = (hours_ones >> 1) & 1; break; // hour 2
          case 18 : signal = (hours_ones >> 0) & 1; break; // hour 1
          case 19 : signal = 2; break; //marker
          case 20 : signal = 0; break; // unused
          case 21 : signal = 0; break; // unused
          case 22 : signal = (days_of_year_hundreds >> 1) & 1; break; // day 200
          case 23 : signal = (days_of_year_hundreds >> 0) & 1; break; // day 100
          case 24 : signal = 0; break; // unused
          case 25 : signal = (days_of_year_tens >> 3) & 1; break; // day 80
          case 26 : signal = (days_of_year_tens >> 2) & 1; break; // day 40
          case 27 : signal = (days_of_year_tens >> 1) & 1; break; // day 20
          case 28 : signal = (days_of_year_tens >> 0) & 1; break; // day 10
          case 29 : signal = 2; break ; // marker
          case 30 : signal = (days_of_year_ones >> 3) & 1; break; // day 8
          case 31 : signal = (days_of_year_ones >> 2) & 1; break; // day 4
          case 32 : signal = (days_of_year_ones >> 1) & 1; break; // day 2
          case 33 : signal = (days_of_year_ones >> 0) & 1; break; // day 1
          case 34 : signal = 0; break; // unused
          case 35 : signal = 0; break; // unused
          case 36 : signal = 0; break; // DUT1 +sign
          case 37 : signal = 1; break; // DUT1 -sign
          case 38 : signal = 0; break; // DUT1 +sign
          case 39 : signal = 2; break; // marker
          case 40 : signal = 0; break; // DUT1 0.8
          case 41 : signal = 0; break; // DUT1 0.4
          case 42 : signal = 1; break; // DUT1 0.2
          case 43 : signal = 1; break; // DUT1 0.1
          case 44 : signal = 0; break; // unused
          case 45 : signal = (year_tens >> 3) & 1; break; // year 80
          case 46 : signal = (year_tens >> 2) & 1; break; // year 40
          case 47 : signal = (year_tens >> 1) & 1; break; // year 20
          case 48 : signal = (year_tens >> 0) & 1; break; // year 10        
          case 49 : signal = 2; break; // marker
          case 50 : signal = (year_ones >> 3) & 1; break; // year 8
          case 51 : signal = (year_ones >> 2) & 1; break; // year 4
          case 52 : signal = (year_ones >> 1) & 1; break; // year 2
          case 53 : signal = (year_ones >> 0) & 1; break; // year 1
          case 54 : signal = 0; break; // unused
          case 55 : signal = 0; break; // leap year indicator
          case 56 : signal = 0; break; // leap second at end of month
          case 57 : signal = 1; break; // DST status 2
          case 58 : signal = 1; break; // DST status 1
          case 59 : signal = 2; break; // marker
          default : signal = 0; break; // unused (should not happen)
      }
 
      switch ( signal ) {
          case 0: reduce_power(200) ; break ;
          case 1: reduce_power(500) ; break ;
          case 2: reduce_power(800) ; break ;
      }
      
      previous_time += 1000 ;
      frame++ ;
      if ( frame >= 60 ) {
          frame = 0 ;
          minutes++ ;
      }
    }


}

I’m not sure if I’m modulating the wave in a way a radio clock can pick up and understand, or if I have an error in my sketch. Could someone take a look?

Been there , done that.
I did not analyze your switch , but here are some pointers.

  1. 4 feet of wire will work DEPENDING on normal parameters - distance from Colorado, time of day etc.
  2. The weak signal can get noisy and the timing gets screwed up.
  3. You need to monitor not only each second "tick" separately , but as 5 seconds (BCD code) block too.
  4. Don't forget "synch" pulses each 5 seconds on top of BCD.
    .
    I run my on Basic stamp and it needed lots of timing adjustements than.
    The code on Tiny , I thing 85 , run better, but I kept loosing the synch during daylight hours - I am in TX , Houston.
    I would have to search fo the code , if you are interested.

One interesting note - I never did figured out if the timing code represented CURRENT minute or was i minute behind, hence at the 60 seconds mark you clock was actually 1 minute behind. Or not ??

PS I do have some extra hardware - ferrite rod antennas tuned to 60 kHz and small RX board which demodulates the signal to low / high at proper time. If you interested, let me know. It was given to me free, so you can have it for same price.
It is very much fun project and in theory eliminates resetting the clock after power outage! In 1 minute !
Cheers Vaclav

Thanks for the response, but I think you are talking about a receiver for WWVB. I'm trying to emulate a transmitter. I work in a windowless room where the WWVB signal cannot penetrate. I'm looking to emulate and transmit the WWVB signal to periodically set the clock I have on the wall.

Also what a coincidence, I'm in Houston too!