This commit is contained in:
2022-01-10 04:58:59 -08:00
parent ac052d190a
commit ae9c16e405
4 changed files with 2493 additions and 84 deletions

175
arduino/wwvb/floats.csv Normal file
View 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
1 94.34
2 39.62
3 67.36
4 48.64
5 71.57
6 78.93
7 86.80
8 37.59
9 41.87
10 76.45
11 65.54
12 70.19
13 77.87
14 73.15
15 70.13
16 33.27
17 27.52
18 87.68
19 74.66
20 49.75
21 74.90
22 68.83
23 69.74
24 58.10
25 49.23
26 61.75
27 94.63
28 85.94
29 46.70
30 68.18
31 48.62
32 75.80
33 50.17
34 52.28
35 66.22
36 68.36
37 70.89
38 46.68
39 71.96
40 90.99
41 74.44
42 97.34
43 22.63
44 25.14
45 54.39
46 47.70
47 80.27
48 75.28
49 73.23
50 63.09
51 71.75
52 73.39
53 29.64
54 60.99
55 78.13
56 73.29
57 52.33
58 68.42
59 71.71
60 60.31
61 54.13
62 76.60
63 58.99
64 75.99
65 85.64
66 74.30
67 77.69
68 79.76
69 79.61
70 60.93
71 54.99
72 45.50
73 81.65
74 74.05
75 67.01
76 85.79
77 83.92
78 76.03
79 72.04
80 32.79
81 33.62
82 67.26
83 71.17
84 78.02
85 63.84
86 67.86
87 58.04
88 71.88
89 72.92
90 72.11
91 68.45
92 68.71
93 93.77
94 65.92
95 78.33
96 63.78
97 58.41
98 48.74
99 71.87
100 53.10
101 80.33
102 58.18
103 72.19
104 79.94
105 85.44
106 78.55
107 82.78
108 71.12
109 63.79
110 62.94
111 63.66
112 58.44
113 50.59
114 91.02
115 89.28
116 68.35
117 86.34
118 31.90
119 69.33
120 65.45
121 76.41
122 83.79
123 73.95
124 73.08
125 60.52
126 51.60
127 59.42
128 82.91
129 82.62
130 64.72
131 69.13
132 67.46
133 71.94
134 78.55
135 73.33
136 70.58
137 80.87
138 77.23
139 75.79
140 87.83
141 88.32
142 79.55
143 60.92
144 71.68
145 69.79
146 83.03
147 89.25
148 76.60
149 55.45
150 67.67
151 82.52
152 77.72
153 65.99
154 60.15
155 73.46
156 68.14
157 61.96
158 85.54
159 64.17
160 83.86
161 61.66
162 79.66
163 64.02
164 45.70
165 76.10
166 63.10
167 64.77
168 94.71
169 76.37
170 75.78
171 76.00
172 35.66
173 65.96
174 68.23
175 91.41

1086
arduino/wwvb/output.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
}