Code Monkey home page Code Monkey logo

wwvb's People

Contributors

micooke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

wwvb's Issues

Thanks, this works perfectly for me

Not reporting an issue, but just sharing my experience.

I'm using an Arduino Micro and an Adafruit Ultimate GPS breakout.

I used one wire to connect GPS Tx ==> Arduino Micro Rx (pin 10)

I had to read up on what the sketch does and figure out the constructor for SoftwareSerial to see what pins were being used.

I didn't bother with connecting up the other direction (micro Tx => GPS Rx) since there are no commands going the other way.

I had a bit of difficulty with getting it working initially because I used a solid core 22AWG hookup wire as my antenna directly connected to pin 9, but I discovered it wasn't working, so then I did exactly as the diagram showed

pin 9 -> antenna
pin 9 -> R (110 ohm) -> LED -> GND
pin 9 -> C (1uF) -> GND

I think the capacitor might be helping convert the square wave coming out of pin 9 into a sine wave which is what my clock is looking for maybe?

The LED is properly blinking in it's (morse-code-ish) pattern.

I wanted to ask whether you have any recommendation on the antenna. Right now I'm using about a foot long 22AWG solid core hookup wire, I've coiled it up around a pencil but I need to have the clock right next to it in order for it to sync.

The way I know it all works is if I slightly modify the sketch to send day+1 over WWVB, I see my clock showing tomorrow's date instead of today after it's done synching. Thus proving that it's synching with my arduino instead of Colorado.

Thanks immensely for putting out this project.

Running on 3V logic

Hi Mark.
I recently tried to migrate my project to a sleeker Adafruit setup with a 32u4 Feather and a GPS FeatherWing.

There's only one problem with that. The 32u4 Feather runs on 3V logic.

I re-compiled the sketch and uploaded it and everything went fine but the signal is not getting picked up with the desk clock now. I can see that pin 9 is pulsing a wwvb signal properly. Here's my setup:

Pin 9 --> 110 ohm --> 1uF & LED --> GND
|
+---> Antenna

How should I change my circuit, weaker resistors/capacitors? to achieve the same goal with 3V instead of 5V?

Thanks in advance.

No output with nano

I'm using the wrong interrupt and forgot to make isr accessed variables volatile to ensure they don't get cached.

AD9850 DDS as a RF generator

Hi!
I am new with programming, but I found your project really interesting.
I live in a country that does not have the time signal available, so I have no other choice but constructing a transmitter.
I tried your "minimal" project but it wasn't able to set my citizen watches. The Rx indicator shows some signal reception but it always fails.
Then I got a AD9850 DDS RF generator and it's really easy to create a sine 60khz carrier.
Changing a WWVB sample code from vinmarshall (https://github.com/vinmarshall/WWVB-Clock), I could generate a WWVB signal that was correctly received by the watches.
Now, I'm trying to combine the ad9850 code with your wwvb library, but with no sucess.
I would be very happy if you could help me with that, because I am new to programming.
I am using an arduino nano, a ublox 6 GPS module to get acurate time and the AD9850 to broadcast it.
Thanks in advance.

here is the code I used to generate the carrier.

/* WWVB Test Signal v 1.0
*

  • This code uses an Arduino to simulate the C-Max CMMR-6P TCO positive
  • output signal. This was written for debugging WWVB Clock
  • Receiver code.
  • This code is adapted from the WWVB Receiver Simulator provided by
  • Capt.Tagon at duinolab.blogspot.com. It expands on that code by
  • incrementing the time and date starting from that set in the
  • setup() routine. This also contains debugging code to display
  • this value on the Serial monitor.
  • This code supports the "Atomic Clock" article in the April 2010 issue
  • of Popular Science. There is also a schematic for this project. There
  • is also WWVB signal simulator code, to facilitate debugging and
  • hacking on this project when the reception of the WWVB signal
  • itself is less than stellar.
  • The code for both the clock and the WWVB simulator, and the schematic
  • are available online at:
  • http://www.popsci.com/diy/article/2010-03/build-clock-uses-atomic-timekeeping
  • and on GitHub at: http://github.com/vinmarshall/WWVB-Clock
  • Copyright (c) 2010 Vin Marshall ([email protected], www.2552.com)
  • Permission is hereby granted, free of charge, to any person
  • obtaining a copy of this software and associated documentation
  • files (the "Software"), to deal in the Software without
  • restriction, including without limitation the rights to use,
  • copy, modify, merge, publish, distribute, sublicense, and/or sell
  • copies of the Software, and to permit persons to whom the
  • Software is furnished to do so, subject to the following
  • conditions:
  • The above copyright notice and this permission notice shall be
  • included in all copies or substantial portions of the Software.
  • THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  • EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  • OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  • NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  • HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  • WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  • FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  • OTHER DEALINGS IN THE SOFTWARE.

*/

#include <AD9850.h>

const int W_CLK_PIN = 7;
const int FQ_UD_PIN = 8;
const int DATA_PIN = 10;
const int RESET_PIN = 11;

double freq = 60000;
double trimFreq = 124999500;

int phase = 0;

/* WWVB time format struct - acts as an overlay on wwvbRxBuffer to extract time/date data.

  • All this points to a 64 bit buffer wwvbRxBuffer that the bits get read from as the
  • sample data stream is transmitted. (Thanks to Capt.Tagon @ duinolab.blogspot.com)

*/

struct wwvbBuffer {
unsigned long long U12 :4; // no value, empty four bits only 60 of 64 bits used
unsigned long long Frame :1; // framing
unsigned long long Dst :2; // dst flags
unsigned long long Leapsec :1; // leapsecond
unsigned long long Leapyear :1; // leapyear
unsigned long long U11 :1; // no value
unsigned long long YearOne :4; // year (5 -> 2005)
unsigned long long U10 :1; // no value
unsigned long long YearTen :4; // year (5 -> 2050)
unsigned long long U09 :1; // no value
unsigned long long OffVal :4; // offset value
unsigned long long U08 :1; // no value
unsigned long long OffSign :3; // offset sign
unsigned long long U07 :2; // no value
unsigned long long DayOne :4; // day ones
unsigned long long U06 :1; // no value
unsigned long long DayTen :4; // day tens
unsigned long long U05 :1; // no value
unsigned long long DayHun :2; // day hundreds
unsigned long long U04 :3; // no value
unsigned long long HourOne :4; // hours ones
unsigned long long U03 :1; // no value
unsigned long long HourTen :2; // hours tens
unsigned long long U02 :3; // no value
unsigned long long MinOne :4; // minutes ones
unsigned long long U01 :1; // no value
unsigned long long MinTen :3; // minutes tens
unsigned long long U00 :1;
};

// We point the struct and the unsigned long long at the
// same memory space so we can access the bits using
// both paradigms.
struct wwvbBuffer * buffer = (struct wwvbBuffer *) malloc(sizeof(struct wwvbBuffer));
unsigned long long * timeBits = (unsigned long long *) buffer;

/*

  • setup
  • uC Initialization
    */

void setup() {

// Setup the Serial port out and the WWVB signal output pin

DDS.begin(W_CLK_PIN, FQ_UD_PIN, DATA_PIN, RESET_PIN);
DDS.calibrate(trimFreq);

    // Preset the time struct 
    *timeBits = 0x0000000000000000;
    buffer->MinTen = 5;
    buffer->MinOne = 7; 
    buffer->HourTen = 2;
    buffer->HourOne = 3;
    buffer->DayHun = 3;
    buffer->DayTen = 6;
    buffer->DayOne = 5;
    buffer->OffSign = 5;  // 2 -> -  5 -> +
    buffer->OffVal = 3;
    buffer->YearTen = 1;
    buffer->YearOne = 0;
    buffer->Dst = 3; // 0 no dst, 1 dst ending, 2 dst starting, 3 dst
    buffer->Leapyear = 0;
    buffer->Leapsec = 0;

}

/*

  • loop
  • Main program loop
    */

void loop() {

// Print the Date & Time to the Serial port for debugging.
int year = (buffer->YearTen * 10) + buffer->YearOne;
int day = (buffer->DayHun * 100) + (buffer->DayTen * 10) + buffer->DayOne;
int hour = (buffer->HourTen * 10) + buffer->HourOne;
int minute = (buffer->MinTen * 10) + buffer->MinOne;
char date[30];
sprintf(date, "%.2i:%.2i %.3i, 20%.2i\n", hour, minute, day, year);
Serial.print(date);

// Step through each bit in this frame
int position = 0;
for (int i = 63; i >= 4; i--) {
// Mask off all bits but the one in question.
// This singles out one bit, moving from MSB to LSB
unsigned long long mask = (unsigned long long) 1 << i;
unsigned long long masked = (*timeBits) & mask;

// Determine if there was a 1 in that bit position
int bit = ((*timeBits) & mask)?1:0;

            // Determine if we're at a Marker position
            int mark = 0;
            if ( (position == 0) || 
                 ((position + 1) % 10 == 0) ) {
                   mark = 1;
            }
            position++;

// Rattle off each bit

// Debug output to the Serial port
// Print in groups of 4. Makes cross ref to hex easier
if ( (i+1) % 4 == 0) {
  Serial.println("");
} 

            if (mark) { 
              Serial.print("M"); 
              sendMark();
            } else if (bit == 0) {
              Serial.print("0");
              sendUnweighted();
            } else if (bit == 1) {
              Serial.print("1");
              sendWeighted();
            }

}
Serial.println("");

// Increment the Time and Date
if (++(buffer->MinOne) == 10) {
buffer->MinOne = 0;
buffer->MinTen++;
}

if (buffer->MinTen == 6) {
buffer->MinTen = 0;
buffer->HourOne++;
}

    if (buffer->HourOne == 10) {
            buffer->HourOne = 0;
            buffer->HourTen++;
    }

    if ( (buffer->HourTen == 2) && (buffer->HourOne == 4) ) {
            buffer->HourTen = 0;
            buffer->HourOne = 0;
            buffer->DayOne++;
    }
    
    if (buffer->DayOne == 10) {
            buffer->DayOne = 0;
            buffer->DayTen++;
    }
    
    if (buffer->DayTen == 10) {
            buffer->DayTen = 0;
            buffer->DayHun++;
    }
    
    if ( (buffer->DayHun == 3) && 
         (buffer->DayTen == 6) &&
         (buffer->DayOne == (6 + (int) buffer->Leapyear)) ) {
             // Happy New Year.
             buffer->DayHun = 0;
             buffer->DayTen = 0;
             buffer->DayOne = 1;
             buffer->YearOne++;
     }
     
     if (buffer->YearOne == 10) {
       buffer->YearOne = 0;
       buffer->YearTen++;
     }
     
     if (buffer->YearTen == 10) {
       buffer->YearTen = 0;
     }

}

/*

  • sendMark
  • Output a Frame / Position marker bit
    */

void sendMark() {

// Send low for 0.8 sec
DDS.down();
delay(799);

// Send high for 0.2 sec
DDS.setfreq(freq, phase);
delay(199);

return;
}

/*

  • sendWeighted
  • Output a Weighted bit (1)
    */

void sendWeighted() {

// Send low for 0.5 sec
DDS.down();
delay(499);

// Send high for 0.5 sec
DDS.setfreq(freq, phase);
delay(499);

return;
}

/*

  • sendUnweighted
  • Output an Unweighted bit (0)
    */

void sendUnweighted() {

// Send low for 0.2 sec
DDS.down();
delay(199);

// Send high for 0.8 sec
DDS.setfreq(freq, phase);
delay(799);

return;
}

Difficult on the Casio watch

I'm finding that the Casio watch is listening to the WWVB for longer than 9 minutes without making a time update. I'd like to try 19 minutes between re-sync with GPS time and see if it works then.

Can we do re-sync at 0, 20, 40 minutes and TX start at 1, 21, 41 ??
MS

// Note
// * wwvb time is synced and wwvb transmission is started when minutes = 0,10,20,30,40 or 50
// * wwvb transmission is stopped when minutes = 9,19,29,39,49 or 59
//
// In other words, wwvb will transmit for 9 minutes, then turn off and sync for a minute
//
if ((wwvb_tx.mm() % 10 == 9) & wwvb_tx.is_active())

Nearly there but...

Got to report after doing more testing that there is still two minor bugs in the gps_time_sync_nokia5110.ino.

The setting for time zone offset for the WWVB is out by 12 hour (ahead). So a setting of (-6, 0) results in my desk clock being 12 hours ahead of local time (i.e. says AM instead of PM, date is 1 day ahead too). I can get it to be correct by setting the WWVB parameter to (-18, 0 ) though....

Also I still have the LCD text wrap issue even after using different PC today with a fresh grab of all the libraries (yours, and Adafruits GFX and 5110). Seems your system results in a slightly different compilation of the display code somehow. Arduino IDE version issue maybe ?

Timing issue

I measured the output using an arduino nano, and it consistently transmits the full 60s frame in 60.5s.

Ill need to investigate this, but i believe i was using minimum_no_interrupt.ino which is a concern.

Hours not correct on minimum.ino

Now the the excitement of a valid reading has settled I note that the hour value decoded by the clock is out by -6 hours. After a valid decode 10:30PM compile time, the clock reads 4:30PM (or really a bit later due to the few minutes the decode takes to happen). I'll try a recompile and try again to verify.
I set the time zone on the clock to CST, so there wouldn't be an offset...
Minutes, seconds, and date/year is OK.

Too many big words Charlie

Minimum.ino is working but Nano_with_gps.ino and nano_with_gps2.ino are all over the place with pulse widths and are unable to be calibrated.

The issue is the gps parsing overhead that was added. I need to look into this, it may mean a two chip solution is required?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.