Skip to content

Commit

Permalink
Merge pull request #8 from clockspot/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
clockspot authored Sep 6, 2020
2 parents 5856a44 + 22bb160 commit 5b6151d
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 37 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<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 |
| 4 | Leading zeros | 0 = no<br/>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):<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. |
| 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). |
| 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) |
| 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) |
| | <a name="optionsalarm"></a>**Alarm** | |
Expand Down Expand Up @@ -121,7 +122,7 @@ This feature can count up (chrono) or down (timer), up to 100 hours each way. Wh
| | <a name="optionsgeography"></a>**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`.)<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. |

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

Expand Down
89 changes: 61 additions & 28 deletions arduino-nixie/arduino-nixie.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Wire.h> //Arduino - GNU LPGL
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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)
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<sizeof(optsLoc); opt++) {
Expand Down Expand Up @@ -845,9 +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
if(fnPg >= fnDatePages){ fnPg = 0; fn = fnIsTime; }
while(fnPg<fnDatePages && fnPg<200 && ( //skip inapplicable date pages. The 200 is an extra failsafe
(!readEEPROM(10,true) && !readEEPROM(12,true) && //if no lat+long specified, skip weather/rise/set
(fnPg==fnDateWeathernow || fnPg==fnDateWeathernext || fnPg==fnDateSunlast || fnPg==fnDateSunnext))
)) fnPg++;
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)
Expand Down Expand Up @@ -918,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(); }
}
Expand Down Expand Up @@ -1288,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
Expand Down Expand Up @@ -1323,7 +1356,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<displaySize; i++) {
byte isrc = i-scrollRemain;
int8_t isrc = i-scrollRemain; //needs to support negative
displayNext[i] = (isrc<0? 15: scrollDisplay[isrc]); //allow to fade
}
}
Expand Down
2 changes: 1 addition & 1 deletion arduino-nixie/configs/v5-4tube.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion arduino-nixie/configs/v5-6tube.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion arduino-nixie/configs/v8-4tube.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion arduino-nixie/configs/v8-6tube.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion arduino-nixie/configs/v9-6tube-relay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion arduino-nixie/configs/v9-6tube.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5b6151d

Please sign in to comment.