micooke / wwvb Goto Github PK
View Code? Open in Web Editor NEWArduino WWVB Transmitter for Attiny85, nano, micro etc.
License: MIT License
Arduino WWVB Transmitter for Attiny85, nano, micro etc.
License: MIT License
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.
Hey, had success.
I just had a first success with minimum.ino in setting the time, date and year on a desk clock, then repeated again to make sure, with full success.
Will test with a CASIO watch now...
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.
I'm using the wrong interrupt and forgot to make isr accessed variables volatile to ensure they don't get cached.
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
*
*/
#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.
*/
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;
/*
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;
}
/*
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;
}
}
/*
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;
}
/*
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;
}
/*
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;
}
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())
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 ?
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.
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.
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.