Skip to content

Commit 5b6151d

Browse files
authored
Merge pull request #8 from clockspot/dev
Dev
2 parents 5856a44 + 22bb160 commit 5b6151d

File tree

8 files changed

+71
-37
lines changed

8 files changed

+71
-37
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ The calendar cycles through several displays, before returning to the time of da
3030
* **The date.** [Several formats](#optionsgeneral) are available. When setting, it will ask for the year, then the month, then the date.
3131
* **Day counter.** This will count down to, or up from, a date of your choice, repeating every year. When setting, it will ask for the month, then the date, then the direction (0 = count down, 1 = count up).
3232
* TIP: To display the day of the year, set it to count up from December 31.
33-
* **Sunrise/sunset.** These two displays show the previous and next apparent sunrise/sunset times (indicated by `1` or `0` on the seconds tubes – during the day, it shows sunrise then sunset; at night, sunset then sunrise). The times are calculated using the latitude, longitude, UTC offset, and auto DST rule specified in the [options](#optionsgeography), and shown in the same 12h/24h format as the time of day.
33+
* **Sunrise/sunset.** These two displays show the previous and next apparent sunrise/sunset times (indicated by `1` or `0` on the seconds tubes – during the day, it shows sunrise then sunset; at night, sunset then sunrise), in the same 12h/24h format as the time of day.
34+
* Specify your latitude, longitude, and UTC offset in the [options menu](#optionsgeography). (From v1.8.1, sunrise/sunset is not displayed if latitude/longitude are left at 0.)
3435
* NOTE: At this writing, the times may be incorrect by a few minutes, depending on [your longitude and time of year](https://docs.google.com/spreadsheets/d/1dYchVCJAuhvosrCdtEeHLT3ZXcLZK8X0UtENItZR32M/edit#gid=0). I believe this to be a rounding error(s) in the [Dusk2Dawn library](https://github.com/dmkishi/Dusk2Dawn) (compared to the [NOAA Solar Calculator](https://www.esrl.noaa.gov/gmd/grad/solcalc/) it’s based on) and plan to investigate.
3536

3637
## Alarm
@@ -90,7 +91,7 @@ This feature can count up (chrono) or down (timer), up to 100 hours each way. Wh
9091
| 3 | Display date during time? | 0 = never<br/>1 = date instead of seconds<br/>2 = full date each minute at :30 seconds<br/>3 = same as 2, but scrolls in and out |
9192
| 4 | Leading zeros | 0 = no<br/>1 = yes |
9293
| 5 | Digit fade | 0–20 (in hundredths of a second) |
93-
| 6 | Auto DST | Add 1h for daylight saving time between these dates (at 2am):<br/>0 = off<br/>1 = second Sunday in March to first Sunday in November (US/CA)<br/>2 = last Sunday in March to last Sunday in October (UK/EU)<br/>3 = first Sunday in April to last Sunday in October (MX)<br/>4 = last Sunday in September to first Sunday in April (NZ)<br/>5 = first Sunday in October to first Sunday in April (AU)<br/>6 = third Sunday in October to third Sunday in February (BZ)<br/>If the clock is not powered at the time, it will correct itself when powered up. |
94+
| 6 | Auto DST | Add 1h for daylight saving time between these dates (at 2am):<br/>0 = off<br/>1 = second Sunday in March to first Sunday in November (US/CA)<br/>2 = last Sunday in March to last Sunday in October (UK/EU)<br/>3 = first Sunday in April to last Sunday in October (MX)<br/>4 = last Sunday in September to first Sunday in April (NZ)<br/>5 = first Sunday in October to first Sunday in April (AU)<br/>6 = third Sunday in October to third Sunday in February (BZ)<br/>If the clock is not powered at the time, it will correct itself when powered up.<br/>If you observe DST but your locale’s rules are not represented here, leave this set to 0 and set the clock manually (and the [DST offset](#optionsgeography) if applicable). |
9495
| 7 | LED behavior | 0 = always off<br/>1 = always on<br/>2 = on, but follow night/away shutoff if enabled<br/>3 = off, but on when alarm/timer sounds</br>4 = off, but on with switched relay (if equipped)<br/>(Clocks with LED lighting only) |
9596
| 8 | Anti-cathode poisoning | Briefly cycles all digits to prevent [cathode poisoning](http://www.tube-tester.com/sites/nixie/different/cathode%20poisoning/cathode-poisoning.htm)<br/>0 = once a day, either at midnight or when night shutoff starts (if enabled)<br/>1 = at the top of every hour<br/>2 = at the top of every minute<br/>(Will not trigger during night/away shutoff) |
9697
| | <a name="optionsalarm"></a>**Alarm** | |
@@ -121,7 +122,7 @@ This feature can count up (chrono) or down (timer), up to 100 hours each way. Wh
121122
| | <a name="optionsgeography"></a>**Geography** | |
122123
| 50 | Latitude | Your latitude, in tenths of a degree; negative (south) values are indicated with leading zeroes. (Example: Dallas is at 32.8°N, set as `328`.) |
123124
| 51 | Longitude | Your longitude, in tenths of a degree; negative (west) values are indicated with leading zeroes. (Example: Dallas is at 96.7°W, set as `00967`.) |
124-
| 52 | UTC offset | Your time zone’s offset from UTC (non-DST), in hours and minutes; negative (west) values are indicated with leading zeroes. (Example: Dallas is UTC–6, set as `0600`.) |
125+
| 52 | UTC offset | Your time zone’s offset from UTC (non-DST), in hours and minutes; negative (west) values are indicated with leading zeroes. (Example: Dallas is UTC–6, set as `0600`.)<br/>If you observe DST but set the clock manually rather than using the [auto DST feature](#optionsgeneral), you must add an hour to the UTC offset during DST, or the sunrise/sunset times will be an hour early. |
125126

126127
To reset the clock to “factory” defaults, hold **Select** while powering up the clock.
127128

arduino-nixie/arduino-nixie.ino

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
////////// Software version //////////
1313
const byte vMajor = 1;
1414
const byte vMinor = 8;
15-
const byte vPatch = 0;
15+
const byte vPatch = 1;
1616

1717
////////// Other includes, global consts, and vars //////////
1818
#include <Wire.h> //Arduino - GNU LPGL
@@ -150,7 +150,7 @@ unsigned long millisAtLastCheck = 0;
150150
word unoffRemain = 0; //un-off (briefly turn on tubes during full night/away shutoff) timeout counter, seconds
151151
byte displayDim = 2; //dim per display or function: 2=normal, 1=dim, 0=off
152152
byte cleanRemain = 0; //anti-cathode-poisoning clean timeout counter, increments at cleanSpeed ms (see loop()). Start at 11 to run at clock startup
153-
byte scrollRemain = 0; //"frames" of scroll – 0=not scrolling, >0=coming in, <0=going out, -128=scroll out at next change
153+
int8_t scrollRemain = 0; //"frames" of scroll – signed byte - 0=not scrolling, >0=coming in, <0=going out, -128=scroll out at next change.
154154
byte versionRemain = 3; //display version at start
155155

156156

@@ -198,28 +198,9 @@ void setup(){
198198
initOutputs(); //depends on some EEPROM settings
199199
}
200200

201-
unsigned long pollCleanLast = 0; //every cleanSpeed ms
202-
unsigned long pollScrollLast = 0; //every scrollSpeed ms
203201
void loop(){
204-
unsigned long now = millis();
205-
//If we're running a tube cleaning, advance it every cleanSpeed ms.
206-
if(cleanRemain && (unsigned long)(now-pollCleanLast)>=cleanSpeed) { //account for rollover
207-
pollCleanLast=now;
208-
cleanRemain--;
209-
if(cleanRemain<1) calcSun(tod.year(),tod.month(),tod.day()); //take this opportunity to perform a calculation that blanks the display for a bit
210-
updateDisplay();
211-
}
212-
//If we're scrolling an animation, advance it every scrollSpeed ms.
213-
else if(scrollRemain!=0 && scrollRemain!=-128 && (unsigned long)(now-pollScrollLast)>=scrollSpeed) {
214-
pollScrollLast=now;
215-
if(scrollRemain<0) {
216-
scrollRemain++; updateDisplay();
217-
} else {
218-
scrollRemain--; updateDisplay();
219-
if(scrollRemain==0) scrollRemain=-128;
220-
}
221-
}
222202
//Every loop cycle, check the RTC and inputs (previously polled, but works fine without and less flicker)
203+
checkEffects(false); //cleaning and scrolling display effects - not handled by checkRTC since they have their own timing
223204
checkRTC(false); //if clock has ticked, decrement timer if running, and updateDisplay
224205
millisApplyDrift();
225206
checkInputs(); //if inputs have changed, this will do things + updateDisplay as needed
@@ -334,6 +315,25 @@ void ctrlEvt(byte ctrl, byte evt){
334315
updateDisplay();
335316
return;
336317
}
318+
//If a scroll is waiting to scroll out, cancel it, and let the button event do what it will
319+
if(scrollRemain==-128 && evt==1){
320+
scrollRemain = 0;
321+
}
322+
//If a scroll is going, fast-forward to end of scroll in/out - see also checkRTC
323+
else if(scrollRemain!=0 && evt==1){
324+
btnStop();
325+
if(scrollRemain>0) scrollRemain = 1;
326+
else scrollRemain = -1;
327+
checkEffects(true);
328+
return;
329+
}
330+
//If the version display is going, any press should cancel it, with a display update
331+
if(versionRemain>0 && evt==1){
332+
versionRemain = 0;
333+
btnStop();
334+
updateDisplay();
335+
return;
336+
}
337337

338338
//Is it a press for an un-off?
339339
unoffRemain = unoffDur; //always do this so continued button presses during an unoff keep it alive
@@ -757,10 +757,10 @@ void initEEPROM(bool hard){
757757
btnCur = mainSel; btnStop();
758758
//If a hard init, set the clock
759759
if(hard) {
760-
ds3231.setYear(18);
760+
ds3231.setYear(20);
761761
ds3231.setMonth(1);
762762
ds3231.setDate(1);
763-
ds3231.setDoW(1); //2018-01-01 is Monday. DS3231 will keep count from here
763+
ds3231.setDoW(3); //2020-01-01 is Wednesday. DS3231 will keep count from here
764764
ds3231.setHour(0);
765765
ds3231.setMinute(0);
766766
ds3231.setSecond(0);
@@ -774,7 +774,7 @@ void initEEPROM(bool hard){
774774
if(hard) writeEEPROM(7,0,false); //7: Alt function preset
775775
//8: TODO functions/pages enabled (bitmask)
776776
//9: free
777-
//15: DST on flag (will be set at first RTC check)
777+
if(hard) writeEEPROM(15,0,false); //15: last known DST on flag - clear on hard reset (to match the reset RTC/auto DST/anti-poisoning settings to trigger midnight tubes as a tube test)
778778
//then the options menu defaults
779779
bool isInt = false;
780780
for(byte opt=0; opt<sizeof(optsLoc); opt++) {
@@ -845,9 +845,18 @@ void checkRTC(bool force){
845845
}
846846
//Paged-display function timeout //TODO change fnIsDate to consts? //TODO timeoutPageFn var
847847
else if(fn==fnIsDate && (unsigned long)(now-inputLast)>=3000) { //3sec per date page
848+
//If a scroll in is going, fast-forward to end - see also ctrlEvt
849+
if(scrollRemain>0) {
850+
scrollRemain = 1;
851+
checkEffects(true);
852+
}
848853
//Here we just have to increment the page and decide when to reset. updateDisplay() will do the rendering
849854
fnPg++; inputLast+=3000; //but leave inputLastTODMins alone so the subsequent page displays will be based on the same TOD
850-
if(fnPg >= fnDatePages){ fnPg = 0; fn = fnIsTime; }
855+
while(fnPg<fnDatePages && fnPg<200 && ( //skip inapplicable date pages. The 200 is an extra failsafe
856+
(!readEEPROM(10,true) && !readEEPROM(12,true) && //if no lat+long specified, skip weather/rise/set
857+
(fnPg==fnDateWeathernow || fnPg==fnDateWeathernext || fnPg==fnDateSunlast || fnPg==fnDateSunnext))
858+
)) fnPg++;
859+
if(fnPg >= fnDatePages){ fnPg = 0; fn = fnIsTime; } // when we run out of pages, go back to time. When the half-minute date is triggered, fnPg is set to 254, so it will be 255 here and be cancelled after just the one page.
851860
force=true;
852861
}
853862
//Temporary-display function timeout: if we're *not* in a permanent one (time, or running/signaling timer)
@@ -918,7 +927,7 @@ void checkRTC(bool force){
918927
} //end alarm trigger
919928
}
920929
//At bottom of minute, see if we should show the date
921-
if(tod.second()==30 && fn==fnIsTime && fnSetPg==0 && unoffRemain==0) {
930+
if(tod.second()==30 && fn==fnIsTime && fnSetPg==0 && unoffRemain==0 && cleanRemain==0 && scrollRemain==0 && versionRemain==0) {
922931
if(readEEPROM(18,false)>=2) { fn = fnIsDate; inputLast = now; inputLastTODMins = tod.hour()*60+tod.minute(); fnPg = 254; updateDisplay(); }
923932
if(readEEPROM(18,false)==3) { startScroll(); }
924933
}
@@ -1288,6 +1297,30 @@ byte displayNext[6] = {15,15,15,15,15,15}; //Internal representation of display.
12881297
byte displayLast[6] = {11,11,11,11,11,11}; //for noticing changes to displayNext and fading the display to it
12891298
byte scrollDisplay[6] = {15,15,15,15,15,15}; //For animating a value into displayNext from right, and out to left
12901299

1300+
unsigned long pollCleanLast = 0; //every cleanSpeed ms
1301+
unsigned long pollScrollLast = 0; //every scrollSpeed ms
1302+
void checkEffects(bool force){
1303+
//control the cleaning/scrolling effects - similar to checkRTC but it has its own timings
1304+
unsigned long now = millis();
1305+
//If we're running a tube cleaning, advance it every cleanSpeed ms.
1306+
if(cleanRemain && (unsigned long)(now-pollCleanLast)>=cleanSpeed) { //account for rollover
1307+
pollCleanLast=now;
1308+
cleanRemain--;
1309+
if(cleanRemain<1) calcSun(tod.year(),tod.month(),tod.day()); //take this opportunity to perform a calculation that blanks the display for a bit
1310+
updateDisplay();
1311+
}
1312+
//If we're scrolling an animation, advance it every scrollSpeed ms.
1313+
else if(scrollRemain!=0 && scrollRemain!=-128 && ((unsigned long)(now-pollScrollLast)>=scrollSpeed || force)) {
1314+
pollScrollLast=now;
1315+
if(scrollRemain<0) {
1316+
scrollRemain++; updateDisplay();
1317+
} else {
1318+
scrollRemain--; updateDisplay();
1319+
if(scrollRemain==0) scrollRemain = -128;
1320+
}
1321+
}
1322+
}
1323+
12911324
void updateDisplay(){
12921325
//Run as needed to update display when the value being shown on it has changed
12931326
//This formats the new value and puts it in displayNext[] for cycleDisplay() to pick up
@@ -1323,7 +1356,7 @@ void updateDisplay(){
13231356
*/
13241357
else if(scrollRemain>0) { //scrolling display: value coming in - these don't use editDisplay as we're going array to array
13251358
for(byte i=0; i<displaySize; i++) {
1326-
byte isrc = i-scrollRemain;
1359+
int8_t isrc = i-scrollRemain; //needs to support negative
13271360
displayNext[i] = (isrc<0? 15: scrollDisplay[isrc]); //allow to fade
13281361
}
13291362
}

arduino-nixie/configs/v5-4tube.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const word velThreshold = 0; //ms
6767

6868
// What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms
6969
const word cleanSpeed = 200; //ms
70-
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 - to give the illusion of a slow scroll that doesn't pause, use (timeoutTempFn*1000)/(displaySize+1) - e.g. 714 for displaySize=6 and timeoutTempFn=5
70+
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30
7171

7272
// What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec
7373
const unsigned long timeoutSet = 300; //sec

arduino-nixie/configs/v5-6tube.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const word velThreshold = 0; //ms
6767

6868
// What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms
6969
const word cleanSpeed = 200; //ms
70-
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 - to give the illusion of a slow scroll that doesn't pause, use (timeoutTempFn*1000)/(displaySize+1) - e.g. 714 for displaySize=6 and timeoutTempFn=5
70+
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30
7171

7272
// What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec
7373
const unsigned long timeoutSet = 300; //sec

arduino-nixie/configs/v8-4tube.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const word velThreshold = 0; //ms
7373

7474
// What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms
7575
const word cleanSpeed = 200; //ms
76-
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 - to give the illusion of a slow scroll that doesn't pause, use (timeoutTempFn*1000)/(displaySize+1) - e.g. 714 for displaySize=6 and timeoutTempFn=5
76+
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30
7777

7878
// What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec
7979
const unsigned long timeoutSet = 300; //sec

arduino-nixie/configs/v8-6tube.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const word velThreshold = 0; //ms
7373

7474
// What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms
7575
const word cleanSpeed = 200; //ms
76-
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 - to give the illusion of a slow scroll that doesn't pause, use (timeoutTempFn*1000)/(displaySize+1) - e.g. 714 for displaySize=6 and timeoutTempFn=5
76+
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30
7777

7878
// What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec
7979
const unsigned long timeoutSet = 300; //sec

arduino-nixie/configs/v9-6tube-relay.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const word velThreshold = 0; //ms
7474

7575
// What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms
7676
const word cleanSpeed = 200; //ms
77-
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 - to give the illusion of a slow scroll that doesn't pause, use (timeoutTempFn*1000)/(displaySize+1) - e.g. 714 for displaySize=6 and timeoutTempFn=5
77+
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30
7878

7979
// What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec
8080
const unsigned long timeoutSet = 300; //sec

arduino-nixie/configs/v9-6tube.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const word velThreshold = 0; //ms
7474

7575
// What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms
7676
const word cleanSpeed = 200; //ms
77-
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 - to give the illusion of a slow scroll that doesn't pause, use (timeoutTempFn*1000)/(displaySize+1) - e.g. 714 for displaySize=6 and timeoutTempFn=5
77+
const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30
7878

7979
// What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec
8080
const unsigned long timeoutSet = 300; //sec

0 commit comments

Comments
 (0)