latest
This commit is contained in:
175
arduino/wwvb/floats.csv
Normal file
175
arduino/wwvb/floats.csv
Normal file
@@ -0,0 +1,175 @@
|
||||
94.34
|
||||
39.62
|
||||
67.36
|
||||
48.64
|
||||
71.57
|
||||
78.93
|
||||
86.80
|
||||
37.59
|
||||
41.87
|
||||
76.45
|
||||
65.54
|
||||
70.19
|
||||
77.87
|
||||
73.15
|
||||
70.13
|
||||
33.27
|
||||
27.52
|
||||
87.68
|
||||
74.66
|
||||
49.75
|
||||
74.90
|
||||
68.83
|
||||
69.74
|
||||
58.10
|
||||
49.23
|
||||
61.75
|
||||
94.63
|
||||
85.94
|
||||
46.70
|
||||
68.18
|
||||
48.62
|
||||
75.80
|
||||
50.17
|
||||
52.28
|
||||
66.22
|
||||
68.36
|
||||
70.89
|
||||
46.68
|
||||
71.96
|
||||
90.99
|
||||
74.44
|
||||
97.34
|
||||
22.63
|
||||
25.14
|
||||
54.39
|
||||
47.70
|
||||
80.27
|
||||
75.28
|
||||
73.23
|
||||
63.09
|
||||
71.75
|
||||
73.39
|
||||
29.64
|
||||
60.99
|
||||
78.13
|
||||
73.29
|
||||
52.33
|
||||
68.42
|
||||
71.71
|
||||
60.31
|
||||
54.13
|
||||
76.60
|
||||
58.99
|
||||
75.99
|
||||
85.64
|
||||
74.30
|
||||
77.69
|
||||
79.76
|
||||
79.61
|
||||
60.93
|
||||
54.99
|
||||
45.50
|
||||
81.65
|
||||
74.05
|
||||
67.01
|
||||
85.79
|
||||
83.92
|
||||
76.03
|
||||
72.04
|
||||
32.79
|
||||
33.62
|
||||
67.26
|
||||
71.17
|
||||
78.02
|
||||
63.84
|
||||
67.86
|
||||
58.04
|
||||
71.88
|
||||
72.92
|
||||
72.11
|
||||
68.45
|
||||
68.71
|
||||
93.77
|
||||
65.92
|
||||
78.33
|
||||
63.78
|
||||
58.41
|
||||
48.74
|
||||
71.87
|
||||
53.10
|
||||
80.33
|
||||
58.18
|
||||
72.19
|
||||
79.94
|
||||
85.44
|
||||
78.55
|
||||
82.78
|
||||
71.12
|
||||
63.79
|
||||
62.94
|
||||
63.66
|
||||
58.44
|
||||
50.59
|
||||
91.02
|
||||
89.28
|
||||
68.35
|
||||
86.34
|
||||
31.90
|
||||
69.33
|
||||
65.45
|
||||
76.41
|
||||
83.79
|
||||
73.95
|
||||
73.08
|
||||
60.52
|
||||
51.60
|
||||
59.42
|
||||
82.91
|
||||
82.62
|
||||
64.72
|
||||
69.13
|
||||
67.46
|
||||
71.94
|
||||
78.55
|
||||
73.33
|
||||
70.58
|
||||
80.87
|
||||
77.23
|
||||
75.79
|
||||
87.83
|
||||
88.32
|
||||
79.55
|
||||
60.92
|
||||
71.68
|
||||
69.79
|
||||
83.03
|
||||
89.25
|
||||
76.60
|
||||
55.45
|
||||
67.67
|
||||
82.52
|
||||
77.72
|
||||
65.99
|
||||
60.15
|
||||
73.46
|
||||
68.14
|
||||
61.96
|
||||
85.54
|
||||
64.17
|
||||
83.86
|
||||
61.66
|
||||
79.66
|
||||
64.02
|
||||
45.70
|
||||
76.10
|
||||
63.10
|
||||
64.77
|
||||
94.71
|
||||
76.37
|
||||
75.78
|
||||
76.00
|
||||
35.66
|
||||
65.96
|
||||
68.23
|
||||
91.41
|
||||
|
1086
arduino/wwvb/output.txt
Normal file
1086
arduino/wwvb/output.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,110 +1,405 @@
|
||||
/*
|
||||
ESP8266 Blink by Simon Peter
|
||||
Blink the blue LED on the ESP-01 module
|
||||
This example code is in the public domain
|
||||
|
||||
The blue LED on the ESP-01 module is connected to GPIO1
|
||||
(which is also the TXD pin; so we cannot use Serial.print() at the same time)
|
||||
|
||||
Note that this sketch uses LED_BUILTIN to find the pin with the internal LED
|
||||
*/
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
LiquidCrystal_I2C lcd(0x27, 16, 2);
|
||||
|
||||
#define SERIAL_RATE 115200
|
||||
#define WWV_SIGNAL_PIN 14
|
||||
#define PPS_OUTPUT_PIN 16
|
||||
#define LOSC_INPUT_PIN 0
|
||||
#define DEBUG1_OUTPUT_PIN 15
|
||||
|
||||
void ICACHE_RAM_ATTR readLevel();
|
||||
#define ONEBIT 1
|
||||
#define ZEROBIT 2
|
||||
#define MARKBIT 3
|
||||
|
||||
volatile byte wwvbInState; // store receiver signal level
|
||||
#define NUM_SAMPLES_PER_FRAME 32000
|
||||
#define CLOCKS_PER_MS 32
|
||||
|
||||
byte prevWwvbInState; // store previous signal level
|
||||
unsigned int prevEdgeMillis; // store time signal was read
|
||||
byte bitVal; // bit decoded 0, 1 or Mark
|
||||
byte badBit; // bad bit, noise detected
|
||||
byte prevMark; // store previous mark bit
|
||||
char statusString[25] = "LOS";
|
||||
|
||||
volatile unsigned int lowLatencyInState;
|
||||
volatile unsigned int wwvbInState;
|
||||
volatile unsigned int lastWWVBInState;
|
||||
|
||||
volatile unsigned int stateStableCounter = 0;
|
||||
volatile unsigned int stateStableMillis = 0;
|
||||
volatile unsigned int lastStateStableMillis = 0;
|
||||
|
||||
volatile unsigned int secondCounter = 0;
|
||||
volatile unsigned int milliCounter = 0;
|
||||
volatile unsigned int clockCounter = 0;
|
||||
|
||||
volatile unsigned int timeToTick = 0;
|
||||
volatile unsigned int frameReadyToStart = 0;
|
||||
volatile unsigned int beginFrameSearch = 0;
|
||||
volatile unsigned int frameSamples = 0;
|
||||
volatile unsigned int lossOfSignal = 1;
|
||||
volatile unsigned int displayUpdateRequired = 1;
|
||||
volatile unsigned int frameSearch = 0;
|
||||
volatile unsigned int frameStart = 0;
|
||||
volatile unsigned int frameStartTime = 0;
|
||||
volatile unsigned int frameHigh = 0;
|
||||
volatile unsigned int frameHighReadOut = 0;
|
||||
volatile unsigned int frameLow = 0;
|
||||
volatile unsigned int frameLowReadOut = 0;
|
||||
volatile unsigned int frameCounter = 0;
|
||||
volatile unsigned int frameReadyForRead = 0;
|
||||
volatile unsigned int lastBitReceived = 0;
|
||||
volatile unsigned int millisSinceBoot = 0;
|
||||
volatile unsigned int ppsActivationTime;
|
||||
volatile unsigned int millisSinceSignalStateChange = 0;
|
||||
volatile unsigned int minuteSync = 0;
|
||||
|
||||
void ICACHE_RAM_ATTR WWVFallingEdge();
|
||||
void ICACHE_RAM_ATTR OSCEdge();
|
||||
void ICACHE_RAM_ATTR MilliEdge();
|
||||
void ICACHE_RAM_ATTR SecondEdge();
|
||||
|
||||
void setup() {
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
|
||||
pinMode(WWV_SIGNAL_PIN, INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(WWV_SIGNAL_PIN), readLevel, CHANGE); // fire interrupt on edge detected
|
||||
Serial.begin(9600);
|
||||
Serial.print("herro booted\n");
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
pinMode(PPS_OUTPUT_PIN, OUTPUT);
|
||||
pinMode(DEBUG1_OUTPUT_PIN, OUTPUT);
|
||||
pinMode(WWV_SIGNAL_PIN, INPUT);
|
||||
pinMode(LOSC_INPUT_PIN, INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(LOSC_INPUT_PIN), OSCEdge, RISING);
|
||||
lcd.init();
|
||||
lcd.backlight();
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print("booting");
|
||||
Serial.begin(SERIAL_RATE);
|
||||
Serial.print("\n\n************\n\nherro booted\n");
|
||||
ppsActivationTime = millis();
|
||||
}
|
||||
|
||||
void OSCEdge() {
|
||||
clockCounter++;
|
||||
if(clockCounter > CLOCKS_PER_MS) {
|
||||
clockCounter -= CLOCKS_PER_MS;
|
||||
|
||||
// *****************************************************************************
|
||||
// LOW LATENCY HACK to respond in 1/32nd of a ms to a falling
|
||||
// start-of-second edge
|
||||
// respond really fast to a falling edge if in the frameReadyToStart
|
||||
// state
|
||||
lowLatencyInState = digitalRead(WWV_SIGNAL_PIN);
|
||||
if(!lowLatencyInState && frameReadyToStart && !lossOfSignal && !frameStart) {
|
||||
// TICK!
|
||||
// falling edge, beginning of a new frame and second
|
||||
digitalWrite(PPS_OUTPUT_PIN, 1);
|
||||
timeToTick = 1;
|
||||
frameStart = 1;
|
||||
frameStartTime = millisSinceBoot;
|
||||
frameReadyToStart = 0;
|
||||
frameSearch = 0;
|
||||
}
|
||||
// *****************************************************************************
|
||||
MilliEdge();
|
||||
}
|
||||
}
|
||||
|
||||
void SecondEdge() {
|
||||
secondCounter++;
|
||||
displayUpdateRequired = 1;
|
||||
}
|
||||
|
||||
void MilliEdge() {
|
||||
digitalWrite(DEBUG1_OUTPUT_PIN, 1);
|
||||
wwvbInState = digitalRead(WWV_SIGNAL_PIN);
|
||||
|
||||
milliCounter++;
|
||||
millisSinceBoot++;
|
||||
|
||||
if(milliCounter > 1000) {
|
||||
milliCounter -= 1000;
|
||||
SecondEdge();
|
||||
}
|
||||
|
||||
if(wwvbInState == lastWWVBInState) {
|
||||
stateStableMillis++;
|
||||
|
||||
if(stateStableMillis > 1000) {
|
||||
stateStableMillis = 1000;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
//edge of some sort.
|
||||
lastStateStableMillis = stateStableMillis;
|
||||
// if it's a falling edge
|
||||
if(!wwvbInState && (stateStableMillis > 100) && (stateStableMillis < 2000)) {
|
||||
// main screen turn on
|
||||
lossOfSignal = 0;
|
||||
frameSearch = 1;
|
||||
}
|
||||
stateStableMillis = 0;
|
||||
}
|
||||
|
||||
lastWWVBInState = wwvbInState; // copy/save for next loop
|
||||
|
||||
if((stateStableMillis > 2000) && !lossOfSignal) {
|
||||
// we have received nothing for 2 seconds, loss of signal:
|
||||
lossOfSignal = 1;
|
||||
frameStart = 0;
|
||||
frameCounter = 0;
|
||||
minuteSync = 0;
|
||||
digitalWrite(DEBUG1_OUTPUT_PIN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(frameSearch && wwvbInState) {
|
||||
// if we have been high for 100ms (frameSearch) we are ready to start a new frame on the mark
|
||||
frameHigh = 0;
|
||||
frameLow = 0;
|
||||
frameReadyToStart = 1;
|
||||
digitalWrite(DEBUG1_OUTPUT_PIN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (frameStart && (frameSamples < NUM_SAMPLES_PER_FRAME)) {
|
||||
//begin sampling
|
||||
if (wwvbInState) {
|
||||
frameHigh++;
|
||||
} else {
|
||||
frameLow++;
|
||||
}
|
||||
frameSamples++;
|
||||
digitalWrite(DEBUG1_OUTPUT_PIN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(frameStart && (frameSamples >= NUM_SAMPLES_PER_FRAME)) {
|
||||
frameReadyForRead = 1;
|
||||
frameHighReadOut = frameHigh;
|
||||
frameLowReadOut = frameLow;
|
||||
frameStart = 0;
|
||||
frameHigh = 0;
|
||||
frameLow = 0;
|
||||
frameSamples = 0;
|
||||
}
|
||||
digitalWrite(DEBUG1_OUTPUT_PIN, 0);
|
||||
}
|
||||
|
||||
char pb[255];
|
||||
// the loop function runs over and over again forever
|
||||
void loop() {
|
||||
if (wwvbInState != prevWwvbInState) {
|
||||
pulseValue();
|
||||
prevWwvbInState = wwvbInState;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
digitalWrite(LED_BUILTIN, !wwvbInState);
|
||||
|
||||
void pulseValue() {
|
||||
unsigned int edgeMillis = millis(); // save current time
|
||||
badBit = 0; // set noise counter to zero
|
||||
if (wwvbInState == 1) { // rising edge
|
||||
prevEdgeMillis = edgeMillis; // set previous time to current
|
||||
}
|
||||
else { // falling edge
|
||||
int pulseLength = edgeMillis - prevEdgeMillis; // calculate pulse length millis
|
||||
if (pulseLength < 100) { // less than 100ms, noise pulses
|
||||
badBit = 1;
|
||||
}
|
||||
else if (pulseLength < 400) { // 800ms carrier drop mark
|
||||
bitVal = 2;
|
||||
}
|
||||
else if (pulseLength < 700) { // 500ms carrier drop one
|
||||
bitVal = 1;
|
||||
}
|
||||
else { // 200ms carrier drop zero
|
||||
bitVal = 0;
|
||||
if(timeToTick) {
|
||||
Serial.println("*** TICK in loop()");
|
||||
timeToTick = 0;
|
||||
TickSecond();
|
||||
}
|
||||
if (badBit == 0) {
|
||||
printBitVal();
|
||||
|
||||
yield();
|
||||
|
||||
if(frameReadyForRead) {
|
||||
Serial.println("*** processFrame() in loop()");
|
||||
frameReadyForRead = 0;
|
||||
processFrame();
|
||||
}
|
||||
|
||||
yield();
|
||||
|
||||
PPSLowIfRequired();
|
||||
|
||||
yield();
|
||||
|
||||
if (displayUpdateRequired) {
|
||||
Serial.println("*** updateDisplay() in loop()");
|
||||
sprintf(pb,"*** secondCounter=%d\n", secondCounter);
|
||||
Serial.print(pb);
|
||||
updateDisplay();
|
||||
displayUpdateRequired = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetPPSHigh() {
|
||||
digitalWrite(PPS_OUTPUT_PIN, 1);
|
||||
}
|
||||
|
||||
void readLevel() {
|
||||
wwvbInState = digitalRead(WWV_SIGNAL_PIN); // read signal level
|
||||
digitalWrite(LED_BUILTIN, !wwvbInState); // flash WWVB receiver indicator pin
|
||||
yield();
|
||||
void SetPPSLow() {
|
||||
digitalWrite(PPS_OUTPUT_PIN, 0);
|
||||
}
|
||||
|
||||
void SendPPS() {
|
||||
unsigned int tickInterval = millisSinceBoot - ppsActivationTime;
|
||||
ppsActivationTime = millisSinceBoot;
|
||||
SetPPSHigh();
|
||||
}
|
||||
|
||||
void PPSLowIfRequired() {
|
||||
if ((millisSinceBoot - ppsActivationTime) > 500) {
|
||||
SetPPSLow();
|
||||
}
|
||||
}
|
||||
|
||||
void TickSecond() {
|
||||
char buf[255];
|
||||
sprintf(buf, "TICK(%d): WWVB going low after %d ms high\n", frameCounter, lastStateStableMillis);
|
||||
SendPPS();
|
||||
Serial.print(buf);
|
||||
}
|
||||
|
||||
void processFrame() {
|
||||
char buf[255];
|
||||
sprintf(buf, "end of frame summary: frameHigh: %d, frameLow: %d\n", frameHighReadOut, frameLowReadOut);
|
||||
Serial.print(buf);
|
||||
float rawVal = (float)frameHighReadOut / frameLowReadOut;
|
||||
rawVal *= 1000;
|
||||
unsigned int intRawVal = (int)rawVal;
|
||||
if (intRawVal > 100000) {
|
||||
intRawVal = 100000;
|
||||
}
|
||||
displayUpdateRequired++;
|
||||
registerBit(convertDutyCycleToBit(intRawVal));
|
||||
}
|
||||
|
||||
int convertDutyCycleToBit(unsigned int rawVal) {
|
||||
char buf[255];
|
||||
/*
|
||||
|
||||
20% - marker
|
||||
50% - one bit
|
||||
80% - zero bit
|
||||
our cutoff points will be 50% and 80%
|
||||
*/
|
||||
char bitbuf[20];
|
||||
|
||||
int output = 0;
|
||||
output = ZEROBIT;
|
||||
sprintf(bitbuf, "ZERO");
|
||||
|
||||
if (rawVal > 20000) {
|
||||
output = MARKBIT;
|
||||
sprintf(bitbuf, "MARK");
|
||||
}
|
||||
|
||||
if (rawVal > 30000) {
|
||||
output = ONEBIT;
|
||||
sprintf(bitbuf, "ONE");
|
||||
}
|
||||
|
||||
sprintf(buf, "frame rawVal=%d, bit=%s\n", rawVal, bitbuf);
|
||||
Serial.print(buf);
|
||||
return output;
|
||||
}
|
||||
|
||||
void registerBit(int doot) {
|
||||
if (minuteSync) {
|
||||
frameCounter++;
|
||||
}
|
||||
|
||||
if (doot == MARKBIT) {
|
||||
if (lastBitReceived == MARKBIT) {
|
||||
// two mark bits in a row means we are in the first second of the minute
|
||||
frameCounter = 0;
|
||||
minuteSync = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!minuteSync) {
|
||||
frameCounter = 0;
|
||||
}
|
||||
|
||||
sanityCheckFrame(doot);
|
||||
lastBitReceived = doot;
|
||||
logBit(doot);
|
||||
}
|
||||
|
||||
void logBit(int doot) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void printBitVal() {
|
||||
if ((bitVal == 2) && (prevMark == 0)) {
|
||||
Serial.print(" : ");
|
||||
|
||||
prevMark = 1;
|
||||
}
|
||||
else if ((bitVal == 2) && (prevMark == 1)) {
|
||||
Serial.print("\nBit Value: ");
|
||||
Serial.print("| ");
|
||||
|
||||
prevMark = 0;
|
||||
}
|
||||
else {
|
||||
Serial.print(bitVal, DEC);
|
||||
prevMark = 0;
|
||||
}
|
||||
void lossOfSync(int errorFrame) {
|
||||
char buf[255];
|
||||
sprintf(buf, "ERROR: %d bit incorrect for framing, loss of sync!\n", errorFrame);
|
||||
Serial.print(buf);
|
||||
minuteSync = 0;
|
||||
displayUpdateRequired++;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Time display functions
|
||||
*****************************************************************************/
|
||||
|
||||
void printTime() {
|
||||
Serial.print("?x00?y0?f"); // movie cursor to line 1 char 1, clear screen
|
||||
void sanityCheckFrame(int doot) {
|
||||
if (
|
||||
(
|
||||
(frameCounter == 9)
|
||||
||
|
||||
(frameCounter == 19)
|
||||
||
|
||||
(frameCounter == 29)
|
||||
||
|
||||
(frameCounter == 39)
|
||||
||
|
||||
(frameCounter == 49)
|
||||
)
|
||||
&& doot != MARKBIT) {
|
||||
lossOfSync(frameCounter);
|
||||
}
|
||||
|
||||
if (
|
||||
(doot == MARKBIT)
|
||||
&&
|
||||
(
|
||||
(frameCounter != 0)
|
||||
&&
|
||||
(frameCounter != 9)
|
||||
&&
|
||||
(frameCounter != 19)
|
||||
&&
|
||||
(frameCounter != 29)
|
||||
&&
|
||||
(frameCounter != 39)
|
||||
&&
|
||||
(frameCounter != 49)
|
||||
)
|
||||
) {
|
||||
lossOfSync(frameCounter);
|
||||
}
|
||||
}
|
||||
|
||||
// LCD routines to initialize LCD and clear screen
|
||||
void lcdInit() { // using P H Anderson Serial LCD driver board
|
||||
Serial.print("?G216"); // configure driver for 2 x 16 LCD
|
||||
delay(300);
|
||||
Serial.print("?BDD"); // set backlight brightness
|
||||
delay(300);
|
||||
Serial.print("?f"); // clear screen
|
||||
Serial.print("?c0"); // set cursor off
|
||||
void updateDisplay() {
|
||||
//Serial.print("updateDisplay()\n");
|
||||
|
||||
if (frameStart) {
|
||||
// don't do anything if we are currently sampling.
|
||||
return;
|
||||
}
|
||||
|
||||
if (lossOfSignal) {
|
||||
sprintf(statusString, "LOS");
|
||||
}
|
||||
|
||||
if (millisSinceBoot - frameStartTime < 10000) {
|
||||
sprintf(statusString, "RX(syncing)");
|
||||
}
|
||||
if (minuteSync) {
|
||||
sprintf(statusString, "RX(bit %d)", frameCounter);
|
||||
}
|
||||
|
||||
char d[20];
|
||||
|
||||
if (lastBitReceived == MARKBIT) {
|
||||
sprintf(d, "%d=MARK", frameCounter);
|
||||
}
|
||||
if (lastBitReceived == ONEBIT) {
|
||||
sprintf(d, "%d=ONE ", frameCounter);
|
||||
}
|
||||
if (lastBitReceived == ZEROBIT) {
|
||||
sprintf(d, "%d=ZERO", frameCounter);
|
||||
}
|
||||
|
||||
lcd.clear();
|
||||
lcd.setCursor(0, 0);
|
||||
char msg[20];
|
||||
sprintf(msg, "up:%03d", millisSinceBoot/1000);
|
||||
lcd.print(msg);
|
||||
lcd.setCursor(0, 1);
|
||||
sprintf(msg, "s:%s", statusString);
|
||||
lcd.print(msg);
|
||||
|
||||
|
||||
if (minuteSync) {
|
||||
lcd.setCursor(10, 0);
|
||||
lcd.print(d);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user