Skip to content

Commit 37f933a

Browse files
committed
Hourly strike; automatic tube cleaning; rename fn "Cleaner" to "Tube tester"
1 parent 077d357 commit 37f933a

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ _In these instructions, **Select** is the main pushbutton, and **Adjust** can be
2020
| **Timer** | `__ __ _0` | A countdown timer, in hours, minutes, and seconds; or `0` when stopped. Can be set to the minute, up to 18 hours. Begins running as soon as you set it, and will continue to run in the background if you change to a different function. To cancel while running, hold **Select**. When timer runs out, press **Select** to silence. If power is lost, the timer will reset to `0`. |
2121
| **Day counter** | `_1 23 __` | Shows the number of days until/since a date you specify. Set the same way as **Date.** |
2222
| **Thermometer** | `__ 38 25` | Shows the temperature of the onboard DS3231 chip (e.g. 38.25°C – I think). May not be very useful as it tends to read higher than ambient temperature and its tolerance is low. |
23-
| **Cleaner** | `88 88 88` | Cycles all the digits on all the tubes. A quick and dirty anti-cathode-poisoning mode, until automatic digit cycling is implemented. |
23+
| **Tube tester** | `88 88 88` | Cycles through all the digits on all the tubes. |
2424

2525
### Options Menu
2626

@@ -44,12 +44,12 @@ _In these instructions, **Select** is the main pushbutton, and **Adjust** can be
4444
| 9. Alarm tone pitch | [Note number on a piano keyboard](https://en.wikipedia.org/wiki/Piano_key_frequencies), from 49 (A4) to 88 (C8). Some are louder than others! |
4545
| 10. Timer interval mode | What happens when the timer reaches 0.<br/>0 = stop and sound continuously<br/>1 = restart and sound a single tone (interval timer) |
4646
| 11. Timer tone pitch | Set the same way as the alarm tone pitch, above. |
47-
| 12. Hourly strike | _Not yet implemented._<br/>0 = off<br/>1 = double tone<br/>2 = pips<br/>3 = strike the hour<br/>4 = ship's bell<br/>(Clocks without radio/timer control only. Will not sound during day-off or night-off.) |
47+
| 12. Hourly strike | 0 = off<br/>1 = single beep<br/>2 = pips<br/>3 = strike the hour<br/>4 = ship's bell<br/>(Clocks without radio/timer control only. Will not sound during day-off or night-off.) |
4848
| 13. Hourly strike pitch | Set the same way as the alarm tone pitch, above. |
4949
| | **Night-off and day-off** |
5050
| 14. Night-off | To save tube life and/or preserve your sleep, dim or shut off tubes nightly when you're not around or sleeping.<br/>0 = none (tubes fully on at night)<br/>1 = dim tubes at night<br/>2 = shut off tubes at night<br/>When off, you can press **Select** to illuminate the tubes briefly. |
5151
| 15. Night starts at | Time of day. |
52-
| 16. Night ends at | Time of day. Set to 0:00 to use the alarm time. At this time (whether night-off/alarm is enabled or not), all tubes will briefly cycle through all digits at full brightness to help prevent [cathode poisoning](http://www.tube-tester.com/sites/nixie/different/cathode%20poisoning/cathode-poisoning.htm) _(not yet implemented)_. |
52+
| 16. Night ends at | Time of day. Set to 0:00 to use the alarm time. At this time (whether night-off/alarm is enabled or not), all tubes will briefly cycle through all digits at full brightness to help prevent [cathode poisoning](http://www.tube-tester.com/sites/nixie/different/cathode%20poisoning/cathode-poisoning.htm). |
5353
| 17. Day-off | To further save tube life, shut off tubes during the day when you're not around.<br/>0 = none (tubes fully on during the day)<br/>1 = clock at work (shut off all day on weekends)<br/>2 = clock at home (shut off during work hours)<br/>When off, you can press **Select** to illuminuate the tubes briefly. |
5454
| 18. First day of work week | 0–6 (Sunday–Saturday) |
5555
| 19. Last day of work week | 0–6 (Sunday–Saturday) |

sixtube_lm/sixtube_lm.ino

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ const byte fnIsAlarm = 2;
3232
const byte fnIsTimer = 3;
3333
const byte fnIsDayCount = 4;
3434
const byte fnIsTemp = 5;
35-
const byte fnIsCleaner = 6;
35+
const byte fnIsTubeTester = 6; //cycles all digits on all tubes 1/second, similar to anti-cathode-poisoning cleaner
3636
// functions enabled in this clock, in their display order. Only fnIsTime is required
37-
const byte fnsEnabled[] = {fnIsTime, fnIsDate, fnIsAlarm, fnIsTimer, fnIsDayCount, fnIsTemp, fnIsCleaner};
37+
const byte fnsEnabled[] = {fnIsTime, fnIsDate, fnIsAlarm, fnIsTimer, fnIsDayCount, fnIsTemp, fnIsTubeTester};
3838

3939
// These are the RLB board connections to Arduino analog input pins.
4040
// S1/PL13 = Reset
@@ -171,6 +171,8 @@ word timerRemain = 0; //timer actual counter
171171
word unoffRemain = 0; //un-off (briefly turn on tubes during full night-off or day-off) timeout counter, seconds
172172
byte displayNext[6] = {15,15,15,15,15,15}; //Internal representation of display. Blank to start. Change this to change tubes.
173173
byte displayDim = 2; //dim per display or function: 2=normal, 1=dim, 0=off
174+
byte cleanRemain = 11; //anti-cathode-poisoning clean timeout counter, increments at cleanSpeed ms (see loop()). Start at 11 to run at clock startup
175+
word cleanSpeed = 300; //ms
174176

175177

176178
////////// Main code control //////////
@@ -183,9 +185,18 @@ void setup(){
183185
if(readInput(mainSel)==LOW) initEEPROM();
184186
}
185187

186-
unsigned long pollLast = 0;
188+
unsigned long pollLast = 0; //every 50ms
189+
unsigned long pollCleanLast = 0; //every cleanSpeed ms
187190
void loop(){
188191
unsigned long now = millis();
192+
//Handle tube cleaning. A special case since it runs at a speed outside the normal cycles as below
193+
if(cleanRemain) {
194+
if(pollCleanLast<now+cleanSpeed) {
195+
pollCleanLast=now;
196+
cleanRemain--;
197+
updateDisplay();
198+
}
199+
}
189200
//Things done every 50ms - avoids overpolling(?) and switch bounce(?)
190201
if(pollLast<now+50) {
191202
pollLast=now;
@@ -623,8 +634,8 @@ void checkRTC(bool force){
623634
if(fnSetPg || fn>=fnOpts){
624635
if(pollLast-inputLast>120000) { fnSetPg = 0; fn = fnIsTime; force=true; } //Time out after 2 mins
625636
}
626-
//Temporary-display mode timeout: if we're *not* in a permanent one (time, day counter, or running timer)
627-
else if(fn!=fnIsTime && fn!=fnIsCleaner && fn!=fnIsDayCount && !(fn==fnIsTimer && (timerRemain>0 || signalRemain>0))){
637+
//Temporary-display mode timeout: if we're *not* in a permanent one (time, day counter, tester, or running/signaling timer)
638+
else if(fn!=fnIsTime && fn!=fnIsTubeTester && fn!=fnIsDayCount && !(fn==fnIsTimer && (timerRemain>0 || signalRemain>0))){
628639
if(pollLast>inputLast+5000) { fnSetPg = 0; fn = fnIsTime; force=true; }
629640
}
630641
}
@@ -649,11 +660,37 @@ void checkRTC(bool force){
649660
fnSetPg = 0; fn = fnIsTime; signalPitch = getHz(readEEPROM(39,false)); signalRemain = signalDur*60;
650661
} //end toddow check
651662
} //end alarm trigger
652-
//checkDigitCycle();
663+
//if it's the top or bottom of the hour, maybe do some striking
664+
//TODO some of these could do with better timing than once per second (e.g. strike/2s and ship's bells in pairs)
665+
if((tod.minute()==0 || tod.minute()==30) && signalType<2 && readEEPROM(21,false)>0 && fn==fnIsTime && fnSetPg==0 && displayDim==2) {
666+
signalPitch = getHz(readEEPROM(41,false));
667+
byte hr; hr = tod.hour(); hr = (hr==0?12:(hr>12?hr-12:hr));
668+
switch(readEEPROM(21,false)) {
669+
case 1: //single beep via normal signal cycle
670+
if(tod.minute()==0) signalRemain = 1; break;
671+
case 2: //pips - directly play 500ms hour pip
672+
if(tod.minute()==0 && signalType==0) tone(signalPin, signalPitch, 500); break;
673+
case 3: //hour strike via normal signal cycle
674+
if(tod.minute()==0) {
675+
signalRemain = hr; break;
676+
}
677+
case 4: //ship's bell at :00 and :30 mins
678+
hr = ((hr%4)*2)+(tod.minute()==30?1:0);
679+
default: break;
680+
} //end strike type
681+
} //end striking
682+
//check if we should trigger the cleaner (at night end time, or alarm time if night end is 0:00)
683+
if(tod.hour()*60+tod.minute()==(readEEPROM(30,true)==0?readEEPROM(0,true):readEEPROM(30,true))) {
684+
cleanRemain = 11; //loop() will pick this up
685+
} //end cleaner check
653686
}
654-
if(tod.second()==30 && fn==fnIsTime && fnSetPg==0) { //At bottom of minute, on fn time (not setting), maybe show date
687+
if(tod.second()==30 && fn==fnIsTime && fnSetPg==0) { //At bottom of minute, maybe show date
655688
if(readEEPROM(18,false)==2) { fn = fnIsDate; inputLast = pollLast; }
656689
}
690+
if(tod.minute()==59 && tod.second()>=55 && signalType<2 && readEEPROM(21,false)==2 && fn==fnIsTime && fnSetPg==0 && displayDim==2) {
691+
//In last 5 seconds of hour, maybe do pips - directly play 100ms seconds pip
692+
if(signalType==0) tone(signalPin, signalPitch, 100);
693+
}
657694

658695
//Things to do every natural second (decrementing real-time counters)
659696
if(!force) {
@@ -770,7 +807,17 @@ void getHz(byte note){
770807
void updateDisplay(){
771808
//Run as needed to update display when the value being shown on it has changed
772809
//This formats the new value and puts it in displayNext[] for cycleDisplay() to pick up
773-
if(fnSetPg) { //setting value, for either fn or option
810+
if(cleanRemain) { //cleaning tubes
811+
displayDim = 2;
812+
byte digit = (11-cleanRemain)%10;
813+
editDisplay(digit,0,0,true);
814+
editDisplay(digit,1,1,true);
815+
editDisplay(digit,2,2,true);
816+
editDisplay(digit,3,3,true);
817+
editDisplay(digit,4,4,true);
818+
editDisplay(digit,5,5,true);
819+
}
820+
else if(fnSetPg) { //setting value, for either fn or option
774821
displayDim = 2;
775822
blankDisplay(4, 5);
776823
if(fnSetValMax==1439) { //Time of day (0-1439 mins, 0:00–23:59): show hrs/mins
@@ -789,7 +836,8 @@ void updateDisplay(){
789836
displayDim = 2;
790837
editDisplay(fn-fnOpts+1,0,1,0); //display option number (1-index) on hour tubes
791838
blankDisplay(2,5);
792-
} else { //fn running
839+
}
840+
else { //fn running
793841
//Set displayDim per night-off and day-off settings - fnIsAlarm may override this
794842
word todmins = tod.hour()*60+tod.minute();
795843
if(unoffDur > 0) {
@@ -852,7 +900,7 @@ void updateDisplay(){
852900
editDisplay(abs(temp)/100,1,3,(temp<0?true:false)); //leading zeros if negative
853901
editDisplay(abs(temp)%100,4,5,true);
854902
break;
855-
case fnIsCleaner:
903+
case fnIsTubeTester:
856904
editDisplay(tod.second(),0,0,true);
857905
editDisplay(tod.second(),1,1,true);
858906
editDisplay(tod.second(),2,2,true);

0 commit comments

Comments
 (0)