From 6fb9b6370034cd4ff37e923b142802529c26ffaf Mon Sep 17 00:00:00 2001 From: Luke McKenzie Date: Sun, 6 Sep 2020 09:41:10 -0500 Subject: [PATCH 1/7] Scrolling display bugfix Had previously converted char to byte, but it needed to support negative --- arduino-nixie/arduino-nixie.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arduino-nixie/arduino-nixie.ino b/arduino-nixie/arduino-nixie.ino index 7cc9199..b9b7323 100644 --- a/arduino-nixie/arduino-nixie.ino +++ b/arduino-nixie/arduino-nixie.ino @@ -150,7 +150,7 @@ unsigned long millisAtLastCheck = 0; word unoffRemain = 0; //un-off (briefly turn on tubes during full night/away shutoff) timeout counter, seconds byte displayDim = 2; //dim per display or function: 2=normal, 1=dim, 0=off byte cleanRemain = 0; //anti-cathode-poisoning clean timeout counter, increments at cleanSpeed ms (see loop()). Start at 11 to run at clock startup -byte scrollRemain = 0; //"frames" of scroll – 0=not scrolling, >0=coming in, <0=going out, -128=scroll out at next change +int8_t scrollRemain = 0; //"frames" of scroll – signed byte - 0=not scrolling, >0=coming in, <0=going out, -128=scroll out at next change. byte versionRemain = 3; //display version at start @@ -1323,7 +1323,7 @@ void updateDisplay(){ */ else if(scrollRemain>0) { //scrolling display: value coming in - these don't use editDisplay as we're going array to array for(byte i=0; i Date: Sun, 6 Sep 2020 11:03:32 -0500 Subject: [PATCH 2/7] On hard reset, clear eeprom dst flag --- arduino-nixie/arduino-nixie.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino-nixie/arduino-nixie.ino b/arduino-nixie/arduino-nixie.ino index b9b7323..42792d0 100644 --- a/arduino-nixie/arduino-nixie.ino +++ b/arduino-nixie/arduino-nixie.ino @@ -774,7 +774,7 @@ void initEEPROM(bool hard){ if(hard) writeEEPROM(7,0,false); //7: Alt function preset //8: TODO functions/pages enabled (bitmask) //9: free - //15: DST on flag (will be set at first RTC check) + writeEEPROM(15,0,false); //15: DST on flag - will be set at first RTC check, but set to off to trigger tube display //then the options menu defaults bool isInt = false; for(byte opt=0; opt Date: Sun, 6 Sep 2020 11:11:23 -0500 Subject: [PATCH 3/7] Skip rise/set/weather if no coords; readme notes on UTC offset --- README.md | 7 ++++--- arduino-nixie/arduino-nixie.ino | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8a0570b..423d1c1 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ The calendar cycles through several displays, before returning to the time of da * **The date.** [Several formats](#optionsgeneral) are available. When setting, it will ask for the year, then the month, then the date. * **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). * TIP: To display the day of the year, set it to count up from December 31. -* **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. +* **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. + * 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.) * 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. ## Alarm @@ -90,7 +91,7 @@ This feature can count up (chrono) or down (timer), up to 100 hours each way. Wh | 3 | Display date during time? | 0 = never
1 = date instead of seconds
2 = full date each minute at :30 seconds
3 = same as 2, but scrolls in and out | | 4 | Leading zeros | 0 = no
1 = yes | | 5 | Digit fade | 0–20 (in hundredths of a second) | -| 6 | Auto DST | Add 1h for daylight saving time between these dates (at 2am):
0 = off
1 = second Sunday in March to first Sunday in November (US/CA)
2 = last Sunday in March to last Sunday in October (UK/EU)
3 = first Sunday in April to last Sunday in October (MX)
4 = last Sunday in September to first Sunday in April (NZ)
5 = first Sunday in October to first Sunday in April (AU)
6 = third Sunday in October to third Sunday in February (BZ)
If the clock is not powered at the time, it will correct itself when powered up. | +| 6 | Auto DST | Add 1h for daylight saving time between these dates (at 2am):
0 = off
1 = second Sunday in March to first Sunday in November (US/CA)
2 = last Sunday in March to last Sunday in October (UK/EU)
3 = first Sunday in April to last Sunday in October (MX)
4 = last Sunday in September to first Sunday in April (NZ)
5 = first Sunday in October to first Sunday in April (AU)
6 = third Sunday in October to third Sunday in February (BZ)
If the clock is not powered at the time, it will correct itself when powered up.
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). | | 7 | LED behavior | 0 = always off
1 = always on
2 = on, but follow night/away shutoff if enabled
3 = off, but on when alarm/timer sounds
4 = off, but on with switched relay (if equipped)
(Clocks with LED lighting only) | | 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)
0 = once a day, either at midnight or when night shutoff starts (if enabled)
1 = at the top of every hour
2 = at the top of every minute
(Will not trigger during night/away shutoff) | | | **Alarm** | | @@ -121,7 +122,7 @@ This feature can count up (chrono) or down (timer), up to 100 hours each way. Wh | | **Geography** | | | 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`.) | | 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`.) | -| 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`.) | +| 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`.)
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. | To reset the clock to “factory” defaults, hold **Select** while powering up the clock. diff --git a/arduino-nixie/arduino-nixie.ino b/arduino-nixie/arduino-nixie.ino index 42792d0..10d6997 100644 --- a/arduino-nixie/arduino-nixie.ino +++ b/arduino-nixie/arduino-nixie.ino @@ -847,6 +847,10 @@ void checkRTC(bool force){ else if(fn==fnIsDate && (unsigned long)(now-inputLast)>=3000) { //3sec per date page //Here we just have to increment the page and decide when to reset. updateDisplay() will do the rendering fnPg++; inputLast+=3000; //but leave inputLastTODMins alone so the subsequent page displays will be based on the same TOD + while(fnPg= fnDatePages){ fnPg = 0; fn = fnIsTime; } force=true; } From f483a3241ea2923e4865b08f9332b29e4732fb93 Mon Sep 17 00:00:00 2001 From: Luke McKenzie Date: Sun, 6 Sep 2020 11:11:52 -0500 Subject: [PATCH 4/7] Hard reset date in 2020 --- arduino-nixie/arduino-nixie.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arduino-nixie/arduino-nixie.ino b/arduino-nixie/arduino-nixie.ino index 10d6997..bba5ea8 100644 --- a/arduino-nixie/arduino-nixie.ino +++ b/arduino-nixie/arduino-nixie.ino @@ -757,10 +757,10 @@ void initEEPROM(bool hard){ btnCur = mainSel; btnStop(); //If a hard init, set the clock if(hard) { - ds3231.setYear(18); + ds3231.setYear(20); ds3231.setMonth(1); ds3231.setDate(1); - ds3231.setDoW(1); //2018-01-01 is Monday. DS3231 will keep count from here + ds3231.setDoW(3); //2020-01-01 is Wednesday. DS3231 will keep count from here ds3231.setHour(0); ds3231.setMinute(0); ds3231.setSecond(0); From e27c11669d906411ee42d1d3790c9891fde21119 Mon Sep 17 00:00:00 2001 From: Luke McKenzie Date: Sun, 6 Sep 2020 13:01:57 -0500 Subject: [PATCH 5/7] Bugfix to hard reset eeprom dst flag clear --- arduino-nixie/arduino-nixie.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino-nixie/arduino-nixie.ino b/arduino-nixie/arduino-nixie.ino index bba5ea8..c8c02d0 100644 --- a/arduino-nixie/arduino-nixie.ino +++ b/arduino-nixie/arduino-nixie.ino @@ -774,7 +774,7 @@ void initEEPROM(bool hard){ if(hard) writeEEPROM(7,0,false); //7: Alt function preset //8: TODO functions/pages enabled (bitmask) //9: free - writeEEPROM(15,0,false); //15: DST on flag - will be set at first RTC check, but set to off to trigger tube display + 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) //then the options menu defaults bool isInt = false; for(byte opt=0; opt Date: Sun, 6 Sep 2020 13:08:09 -0500 Subject: [PATCH 6/7] Bugfix/enhancements to half-minute date triggering and scrolling --- arduino-nixie/arduino-nixie.ino | 73 ++++++++++++++++++-------- arduino-nixie/configs/v5-4tube.h | 2 +- arduino-nixie/configs/v5-6tube.h | 2 +- arduino-nixie/configs/v8-4tube.h | 2 +- arduino-nixie/configs/v8-6tube.h | 2 +- arduino-nixie/configs/v9-6tube-relay.h | 2 +- arduino-nixie/configs/v9-6tube.h | 2 +- 7 files changed, 57 insertions(+), 28 deletions(-) diff --git a/arduino-nixie/arduino-nixie.ino b/arduino-nixie/arduino-nixie.ino index c8c02d0..4041b42 100644 --- a/arduino-nixie/arduino-nixie.ino +++ b/arduino-nixie/arduino-nixie.ino @@ -198,28 +198,9 @@ void setup(){ initOutputs(); //depends on some EEPROM settings } -unsigned long pollCleanLast = 0; //every cleanSpeed ms -unsigned long pollScrollLast = 0; //every scrollSpeed ms void loop(){ - unsigned long now = millis(); - //If we're running a tube cleaning, advance it every cleanSpeed ms. - if(cleanRemain && (unsigned long)(now-pollCleanLast)>=cleanSpeed) { //account for rollover - pollCleanLast=now; - cleanRemain--; - if(cleanRemain<1) calcSun(tod.year(),tod.month(),tod.day()); //take this opportunity to perform a calculation that blanks the display for a bit - updateDisplay(); - } - //If we're scrolling an animation, advance it every scrollSpeed ms. - else if(scrollRemain!=0 && scrollRemain!=-128 && (unsigned long)(now-pollScrollLast)>=scrollSpeed) { - pollScrollLast=now; - if(scrollRemain<0) { - scrollRemain++; updateDisplay(); - } else { - scrollRemain--; updateDisplay(); - if(scrollRemain==0) scrollRemain=-128; - } - } //Every loop cycle, check the RTC and inputs (previously polled, but works fine without and less flicker) + checkEffects(false); //cleaning and scrolling display effects - not handled by checkRTC since they have their own timing checkRTC(false); //if clock has ticked, decrement timer if running, and updateDisplay millisApplyDrift(); checkInputs(); //if inputs have changed, this will do things + updateDisplay as needed @@ -334,6 +315,25 @@ void ctrlEvt(byte ctrl, byte evt){ updateDisplay(); return; } + //If a scroll is waiting to scroll out, cancel it, and let the button event do what it will + if(scrollRemain==-128 && evt==1){ + scrollRemain = 0; + } + //If a scroll is going, fast-forward to end of scroll in/out - see also checkRTC + else if(scrollRemain!=0 && evt==1){ + btnStop(); + if(scrollRemain>0) scrollRemain = 1; + else scrollRemain = -1; + checkEffects(true); + return; + } + //If the version display is going, any press should cancel it, with a display update + if(versionRemain>0 && evt==1){ + versionRemain = 0; + btnStop(); + updateDisplay(); + return; + } //Is it a press for an un-off? unoffRemain = unoffDur; //always do this so continued button presses during an unoff keep it alive @@ -845,13 +845,18 @@ void checkRTC(bool force){ } //Paged-display function timeout //TODO change fnIsDate to consts? //TODO timeoutPageFn var else if(fn==fnIsDate && (unsigned long)(now-inputLast)>=3000) { //3sec per date page + //If a scroll in is going, fast-forward to end - see also ctrlEvt + if(scrollRemain>0) { + scrollRemain = 1; + checkEffects(true); + } //Here we just have to increment the page and decide when to reset. updateDisplay() will do the rendering fnPg++; inputLast+=3000; //but leave inputLastTODMins alone so the subsequent page displays will be based on the same TOD while(fnPg= fnDatePages){ fnPg = 0; fn = fnIsTime; } + 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. force=true; } //Temporary-display function timeout: if we're *not* in a permanent one (time, or running/signaling timer) @@ -922,7 +927,7 @@ void checkRTC(bool force){ } //end alarm trigger } //At bottom of minute, see if we should show the date - if(tod.second()==30 && fn==fnIsTime && fnSetPg==0 && unoffRemain==0) { + if(tod.second()==30 && fn==fnIsTime && fnSetPg==0 && unoffRemain==0 && cleanRemain==0 && scrollRemain==0 && versionRemain==0) { if(readEEPROM(18,false)>=2) { fn = fnIsDate; inputLast = now; inputLastTODMins = tod.hour()*60+tod.minute(); fnPg = 254; updateDisplay(); } if(readEEPROM(18,false)==3) { startScroll(); } } @@ -1292,6 +1297,30 @@ byte displayNext[6] = {15,15,15,15,15,15}; //Internal representation of display. byte displayLast[6] = {11,11,11,11,11,11}; //for noticing changes to displayNext and fading the display to it byte scrollDisplay[6] = {15,15,15,15,15,15}; //For animating a value into displayNext from right, and out to left +unsigned long pollCleanLast = 0; //every cleanSpeed ms +unsigned long pollScrollLast = 0; //every scrollSpeed ms +void checkEffects(bool force){ + //control the cleaning/scrolling effects - similar to checkRTC but it has its own timings + unsigned long now = millis(); + //If we're running a tube cleaning, advance it every cleanSpeed ms. + if(cleanRemain && (unsigned long)(now-pollCleanLast)>=cleanSpeed) { //account for rollover + pollCleanLast=now; + cleanRemain--; + if(cleanRemain<1) calcSun(tod.year(),tod.month(),tod.day()); //take this opportunity to perform a calculation that blanks the display for a bit + updateDisplay(); + } + //If we're scrolling an animation, advance it every scrollSpeed ms. + else if(scrollRemain!=0 && scrollRemain!=-128 && ((unsigned long)(now-pollScrollLast)>=scrollSpeed || force)) { + pollScrollLast=now; + if(scrollRemain<0) { + scrollRemain++; updateDisplay(); + } else { + scrollRemain--; updateDisplay(); + if(scrollRemain==0) scrollRemain = -128; + } + } +} + void updateDisplay(){ //Run as needed to update display when the value being shown on it has changed //This formats the new value and puts it in displayNext[] for cycleDisplay() to pick up diff --git a/arduino-nixie/configs/v5-4tube.h b/arduino-nixie/configs/v5-4tube.h index 0ad8905..5d95fa4 100644 --- a/arduino-nixie/configs/v5-4tube.h +++ b/arduino-nixie/configs/v5-4tube.h @@ -67,7 +67,7 @@ const word velThreshold = 0; //ms // What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms const word cleanSpeed = 200; //ms -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 +const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 // What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec const unsigned long timeoutSet = 300; //sec diff --git a/arduino-nixie/configs/v5-6tube.h b/arduino-nixie/configs/v5-6tube.h index 02fcf13..b433838 100644 --- a/arduino-nixie/configs/v5-6tube.h +++ b/arduino-nixie/configs/v5-6tube.h @@ -67,7 +67,7 @@ const word velThreshold = 0; //ms // What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms const word cleanSpeed = 200; //ms -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 +const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 // What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec const unsigned long timeoutSet = 300; //sec diff --git a/arduino-nixie/configs/v8-4tube.h b/arduino-nixie/configs/v8-4tube.h index 866e033..edc30b3 100644 --- a/arduino-nixie/configs/v8-4tube.h +++ b/arduino-nixie/configs/v8-4tube.h @@ -73,7 +73,7 @@ const word velThreshold = 0; //ms // What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms const word cleanSpeed = 200; //ms -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 +const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 // What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec const unsigned long timeoutSet = 300; //sec diff --git a/arduino-nixie/configs/v8-6tube.h b/arduino-nixie/configs/v8-6tube.h index 9b11b08..8a9bbf6 100644 --- a/arduino-nixie/configs/v8-6tube.h +++ b/arduino-nixie/configs/v8-6tube.h @@ -73,7 +73,7 @@ const word velThreshold = 0; //ms // What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms const word cleanSpeed = 200; //ms -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 +const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 // What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec const unsigned long timeoutSet = 300; //sec diff --git a/arduino-nixie/configs/v9-6tube-relay.h b/arduino-nixie/configs/v9-6tube-relay.h index bd03c22..f28e18a 100644 --- a/arduino-nixie/configs/v9-6tube-relay.h +++ b/arduino-nixie/configs/v9-6tube-relay.h @@ -74,7 +74,7 @@ const word velThreshold = 0; //ms // What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms const word cleanSpeed = 200; //ms -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 +const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 // What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec const unsigned long timeoutSet = 300; //sec diff --git a/arduino-nixie/configs/v9-6tube.h b/arduino-nixie/configs/v9-6tube.h index 39aa815..a82424e 100644 --- a/arduino-nixie/configs/v9-6tube.h +++ b/arduino-nixie/configs/v9-6tube.h @@ -74,7 +74,7 @@ const word velThreshold = 0; //ms // What is the "frame rate" of the tube cleaning and display scrolling? up to 65535 ms const word cleanSpeed = 200; //ms -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 +const word scrollSpeed = 100; //ms - e.g. scroll-in-and-out date at :30 // What are the timeouts for setting and temporarily-displayed functions? up to 65535 sec const unsigned long timeoutSet = 300; //sec From 22bb160179df9e506efc81193eecc63dca5e6de1 Mon Sep 17 00:00:00 2001 From: Luke McKenzie Date: Sun, 6 Sep 2020 13:09:16 -0500 Subject: [PATCH 7/7] v1.8.1 --- arduino-nixie/arduino-nixie.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino-nixie/arduino-nixie.ino b/arduino-nixie/arduino-nixie.ino index 4041b42..1226468 100644 --- a/arduino-nixie/arduino-nixie.ino +++ b/arduino-nixie/arduino-nixie.ino @@ -12,7 +12,7 @@ ////////// Software version ////////// const byte vMajor = 1; const byte vMinor = 8; -const byte vPatch = 0; +const byte vPatch = 1; ////////// Other includes, global consts, and vars ////////// #include //Arduino - GNU LPGL