Alexgyver's nixie clock

Hello!
I am a beginner in arduino and have been at this for hours. I double checked the github page incase I missed anything and I tried searching google for help aswell but no luck.
My problem is that I am missing the timer2minim.h library file. The github has a folder with the exact library file name but exporting it to arduino libraries did nothing. Do I need to make a library file from this code shown in the screenshot myself or is there some other way.
Thank you!

Github website GitHub - AlexGyver/NixieClock_v2: Часы на газоразрядных индикаторах и Arduino версия 2

You need to copy the timer2minim.h file into your sketch's folder.
Then include it with

#include "timer2minim.h"

Welcome to the forum

As your topic does not relate directly to the installation or operation of the IDE it has been moved to the Programming category of the forum

Hi, @850nixie
Welcome to the forum.

This will show you how to post your code in a post.

Tom.... :smiley: :+1: :coffee: :australia:

Alright thanks!

Thank you!
I did that and that worked, no library error anymore, but inspired by your idea, I tried running the different files in the same ide. After doing that and then compiling, it gives me declaration errors, which I tried to fix with some success. Should I try uploading the code here?

Any code you (still) need help with shoukd def be posted here in its entirety. We needa see it, read it and maybe even try it for ourselves.

Use the IDE Autoformat tool first, then use the IDE Copy for Forum tool and paste it here.

a7

Show this in a code block. The sketch, too.

I am going to put the files as I got them. Comments are translated from russian

BRIGHT.ino

void backlBrightTick() {
  if (BACKL_MODE == 0 && backlBrightTimer.isReady()) {
    if (backlMaxBright > 0) {
      if (backlBrightDirection) {
        if (!backlBrightFlag) {
          backlBrightFlag = true;
          backlBrightTimer.setInterval((float)BACKL_STEP / backlMaxBright / 2 * BACKL_TIME);
        }
        backlBrightCounter += BACKL_STEP;
        if (backlBrightCounter >= backlMaxBright) {
          backlBrightDirection = false;
          backlBrightCounter = backlMaxBright;
        }
      } else {
        backlBrightCounter -= BACKL_STEP;
        if (backlBrightCounter <= BACKL_MIN_BRIGHT) {
          backlBrightDirection = true;
          backlBrightCounter = BACKL_MIN_BRIGHT;
          backlBrightTimer.setInterval(BACKL_PAUSE);
          backlBrightFlag = false;
        }
      }
      setPWM(BACKL, getPWM_CRT(backlBrightCounter));
    } else {
      digitalWrite(BACKL, 0);
    }
  }
}

void dotBrightTick() {
  if (dotBrightFlag && dotBrightTimer.isReady()) {
    if (dotBrightDirection) {
      dotBrightCounter += dotBrightStep;
      if (dotBrightCounter >= dotMaxBright) {
        dotBrightDirection = false;
        dotBrightCounter = dotMaxBright;
      }
    } else {
      dotBrightCounter -= dotBrightStep;
      if (dotBrightCounter <= 0) {
        dotBrightDirection = true;
        dotBrightFlag = false;
        dotBrightCounter = 0;
      }
    }
    setPWM(DOT, getPWM_CRT(dotBrightCounter));
  }
}

void changeBright() {
#if (NIGHT_LIGHT == 1)
  // setting the brightness of all lights depending on the time of day
  if ((hrs >= NIGHT_START && hrs <= 23)
      || (hrs >= 0 && hrs < NIGHT_END)) {
    indiMaxBright = INDI_BRIGHT_N;
    dotMaxBright = DOT_BRIGHT_N;
    backlMaxBright = BACKL_BRIGHT_N;
  } else {
    indiMaxBright = INDI_BRIGHT;
    dotMaxBright = DOT_BRIGHT;
    backlMaxBright = BACKL_BRIGHT;
  }
  for (byte i = 0; i < 4; i++) {
    indiDimm[i] = indiMaxBright;
  }

  dotBrightStep = ceil((float)dotMaxBright * 2 / DOT_TIME * DOT_TIMER);
  if (dotBrightStep == 0) dotBrightStep = 1;

  if (backlMaxBright > 0)
    backlBrightTimer.setInterval((float)BACKL_STEP / backlMaxBright / 2 * BACKL_TIME);
  indiBrightCounter = indiMaxBright;

  //change PWM to apply backlMaxBright in case of maximum bright mode
  if (BACKL_MODE == 1) setPWM(BACKL, backlMaxBright);
#endif
}

buttonSettings.ino

void settingsTick() {
  if (curMode == 1) {
    if (blinkTimer.isReady()) {
      sendTime(changeHrs, changeMins);
      lampState = !lampState;
      if (lampState) {
        anodeStates[0] = 1;
        anodeStates[1] = 1;
        anodeStates[2] = 1;
        anodeStates[3] = 1;
      } else {
        if (!currentDigit) {
          anodeStates[0] = 0;
          anodeStates[1] = 0;
        } else {
          anodeStates[2] = 0;
          anodeStates[3] = 0;
        }
      }
    }
  }
}

void buttonsTick() {
  btnSet.tick();
  btnL.tick();
  btnR.tick();

  if (curMode == 1) {
    if (btnR.isClick()) {
      if (!currentDigit) {
        changeHrs++;
        if (changeHrs > 23) changeHrs = 0;
      } else {
        changeMins++;
        if (changeMins > 59) {
          changeMins = 0;
          changeHrs++;
          if (changeHrs > 23) changeHrs = 0;
        }
      }
      sendTime(changeHrs, changeMins);
    }
    if (btnL.isClick()) {
      if (!currentDigit) {
        changeHrs--;
        if (changeHrs < 0) changeHrs = 23;
      } else {
        changeMins--;
        if (changeMins < 0) {
          changeMins = 59;
          changeHrs--;
          if (changeHrs < 0) changeHrs = 23;
        }
      }
      sendTime(changeHrs, changeMins);
    }
  } else if (curMode == 0) {
    // switching digital effects
    if (btnR.isClick()) {
      if (++FLIP_EFFECT >= FLIP_EFFECT_NUM) FLIP_EFFECT = 0;
      EEPROM.put(0, FLIP_EFFECT);
      flipTimer.setInterval(FLIP_SPEED[FLIP_EFFECT]);
      for (byte i = 0; i < 4; i++) {
        indiDimm[i] = indiMaxBright;
        anodeStates[i] = 1;
      }
      // show effect
      newTimeFlag = true;
      for (byte i = 0; i < 4; i++) indiDigits[i] = FLIP_EFFECT;
    }

    // switching backlight effects
    if (btnL.isClick()) {
      if (++BACKL_MODE >= 3) BACKL_MODE = 0;
      EEPROM.put(1, BACKL_MODE);
      if (BACKL_MODE == 1) {
        setPWM(BACKL, backlMaxBright);
      } else if (BACKL_MODE == 2) {
        digitalWrite(BACKL, 0);
      }
    }

    // glitch switch
    if (btnL.isHolded()) {
      GLITCH_ALLOWED = !GLITCH_ALLOWED;
      EEPROM.put(2, GLITCH_ALLOWED);
    }
  }

  if (btnSet.isHolded()) {
    anodeStates[0] = 1;
    anodeStates[1] = 1;
    anodeStates[2] = 1;
    anodeStates[3] = 1;
    currentDigit = false;
    if (++curMode >= 2) curMode = 0;
    switch (curMode) {
      case 0:
        hrs = changeHrs;
        mins = changeMins;
        secs = 0;
        rtc.adjust(DateTime(2019, 12, 05, hrs, mins, 0));
        changeBright();
        break;
      case 1:
        changeHrs = hrs;
        changeMins = mins;
        break;
    }
  }
  if (btnSet.isClick()) {
    if (curMode == 1) currentDigit = !currentDigit;  // time settings
  }
}

effects.ino

void flipTick() {
  if (FLIP_EFFECT == 0) {
    sendTime(hrs, mins);
    newTimeFlag = false;
  } else if (FLIP_EFFECT == 1) {
    if (!flipInit) {
      flipInit = true;
      // We remember which numbers have changed and will change their brightness.
      for (byte i = 0; i < 4; i++) {
        if (indiDigits[i] != newTime[i]) flipIndics[i] = true;
        else flipIndics[i] = false;
      }
    }
    if (flipTimer.isReady()) {
      if (!indiBrightDirection) {
        indiBrightCounter--;           // reduce brightness
        if (indiBrightCounter <= 0) {  // if the brightness is less than zero
          indiBrightDirection = true;  // change the direction of change
          indiBrightCounter = 0;       // reset the brightness
          sendTime(hrs, mins);         // change numbers
        }
      } else {
        indiBrightCounter++;                       // increase brightness
        if (indiBrightCounter >= indiMaxBright) {  // reached the limit
          indiBrightDirection = false;             // change direction
          indiBrightCounter = indiMaxBright;       // set the maximum
          // exit the cycle of change
          flipInit = false;
          newTimeFlag = false;
        }
      }
      for (byte i = 0; i < 4; i++)
        if (flipIndics[i]) indiDimm[i] = indiBrightCounter;  // apply brightness
    }
  } else if (FLIP_EFFECT == 2) {
    if (!flipInit) {
      flipInit = true;
      // We remember which numbers have changed and will change them.
      for (byte i = 0; i < 4; i++) {
        if (indiDigits[i] != newTime[i]) flipIndics[i] = true;
        else flipIndics[i] = false;
      }
    }

    if (flipTimer.isReady()) {
      byte flipCounter = 0;
      for (byte i = 0; i < 4; i++) {
        if (flipIndics[i]) {
          indiDigits[i]--;
          if (indiDigits[i] < 0) indiDigits[i] = 9;
          if (indiDigits[i] == newTime[i]) flipIndics[i] = false;
        } else {
          flipCounter++;  // a counter of numbers that do not need to be changed
        }
      }
      if (flipCounter == 4) {  // If none of the 4 digits need to be changed, // exit the change loop.
        flipInit = false;
        newTimeFlag = false;
      }
    }

    //byte cathodeMask[] = {1, 0, 2, 9, 3, 8, 4, 7, 5, 6};  //
order of cathodes in14 tube
  } else if (FLIP_EFFECT == 3) {
    if (!flipInit) {
      flipInit = true;
      // We remember which numbers have changed and will change them.
      for (byte i = 0; i < 4; i++) {
        if (indiDigits[i] != newTime[i]) {
          flipIndics[i] = true;
          for (byte c = 0; c < 10; c++) {
            if (cathodeMask[c] == indiDigits[i]) startCathode[i] = c;
            if (cathodeMask[c] == newTime[i]) endCathode[i] = c;
          }
        } else flipIndics[i] = false;
      }
    }

    if (flipTimer.isReady()) {
      byte flipCounter = 0;
      for (byte i = 0; i < 4; i++) {
        if (flipIndics[i]) {
          if (startCathode[i] > endCathode[i]) {
            startCathode[i]--;
            indiDigits[i] = cathodeMask[startCathode[i]];
          } else if (startCathode[i] < endCathode[i]) {
            startCathode[i]++;
            indiDigits[i] = cathodeMask[startCathode[i]];
          } else {
            flipIndics[i] = false;
          }
        } else {
          flipCounter++;
        }
      }
      if (flipCounter == 4) {  // If none of the 4 digits need to be changed, // exit the change loop.
        flipInit = false;
        newTimeFlag = false;
      }
    }
  }
  // --- train --- //
  else if (FLIP_EFFECT == 4) {
    if (!flipInit) {
      flipInit = true;
      currentLamp = 0;
      trainLeaving = true;
      flipTimer.reset();
    }
    if (flipTimer.isReady()) {
      if (trainLeaving) {
        for (byte i = 3; i > currentLamp; i--) {
          indiDigits[i] = indiDigits[i - 1];
        }
        anodeStates[currentLamp] = 0;
        currentLamp++;
        if (currentLamp >= 4) {
          trainLeaving = false;  //coming
          currentLamp = 0;
          //sendTime(hrs, mins);
        }
      } else {  //trainLeaving == false
        for (byte i = currentLamp; i > 0; i--) {
          indiDigits[i] = indiDigits[i - 1];
        }
        indiDigits[0] = newTime[3 - currentLamp];
        anodeStates[currentLamp] = 1;
        currentLamp++;
        if (currentLamp >= 4) {
          flipInit = false;
          newTimeFlag = false;
        }
      }
    }
  }

  // --- elastic band --- //
  else if (FLIP_EFFECT == 5) {
    if (!flipInit) {
      flipInit = true;
      flipEffectStages = 0;
      flipTimer.reset();
    }
    if (flipTimer.isReady()) {
      switch (flipEffectStages++) {
        case 1:
          anodeStates[3] = 0;
          break;
        case 2:
          anodeStates[2] = 0;
          indiDigits[3] = indiDigits[2];
          anodeStates[3] = 1;
          break;
        case 3:
          anodeStates[3] = 0;
          break;
        case 4:
          anodeStates[1] = 0;
          indiDigits[2] = indiDigits[1];
          anodeStates[2] = 1;
          break;
        case 5:
          anodeStates[2] = 0;
          indiDigits[3] = indiDigits[1];
          anodeStates[3] = 1;
          break;
        case 6:
          anodeStates[3] = 0;
          break;
        case 7:
          anodeStates[0] = 0;
          indiDigits[1] = indiDigits[0];
          anodeStates[1] = 1;
          break;
        case 8:
          anodeStates[1] = 0;
          indiDigits[2] = indiDigits[0];
          anodeStates[2] = 1;
          break;
        case 9:
          anodeStates[2] = 0;
          indiDigits[3] = indiDigits[0];
          anodeStates[3] = 1;
          break;
        case 10:
          anodeStates[3] = 0;
          //sendTime(hrs,mins);
          break;
        case 11:
          indiDigits[0] = newTime[3];
          anodeStates[0] = 1;
          break;
        case 12:
          anodeStates[0] = 0;
          indiDigits[1] = newTime[3];
          anodeStates[1] = 1;
          break;
        case 13:
          anodeStates[1] = 0;
          indiDigits[2] = newTime[3];
          anodeStates[2] = 1;
          break;
        case 14:
          anodeStates[2] = 0;
          indiDigits[3] = newTime[3];
          anodeStates[3] = 1;
          break;
        case 15:
          indiDigits[0] = newTime[2];
          anodeStates[0] = 1;
          break;
        case 16:
          anodeStates[0] = 0;
          indiDigits[1] = newTime[2];
          anodeStates[1] = 1;
          break;
        case 17:
          anodeStates[1] = 0;
          indiDigits[2] = newTime[2];
          anodeStates[2] = 1;
          break;
        case 18:
          indiDigits[0] = newTime[1];
          anodeStates[0] = 1;
          break;
        case 19:
          anodeStates[0] = 0;
          indiDigits[1] = newTime[1];
          anodeStates[1] = 1;
          break;
        case 20:
          indiDigits[0] = newTime[0];
          anodeStates[0] = 1;
          break;
        case 21:
          flipInit = false;
          newTimeFlag = false;
      }
    }
  }
}


func.ino



void burnIndicators() {
  for (byte k = 0; k < BURN_LOOPS; k++) {
    for (byte d = 0; d < 10; d++) {
      for (byte i = 0; i < 4; i++) {
        indiDigits[i]--;
        if (indiDigits[i] < 0) indiDigits[i] = 9;
      }
      delay(BURN_TIME);
    }
  }
}

glitch.ino

void glitchTick() {
  if (!glitchFlag && secs > 7 && secs < 55) {
    if (glitchTimer.isReady()) {
      glitchFlag = true;
      indiState = 0;
      glitchCounter = 0;
      glitchMax = random(2, 6);
      glitchIndic = random(0, 4);
      glitchTimer.setInterval(random(1, 6) * 20);
    }
  } else if (glitchFlag && glitchTimer.isReady()) {
    indiDimm[glitchIndic] = indiState * indiMaxBright;
    indiState = !indiState;
    glitchTimer.setInterval(random(1, 6) * 20);
    glitchCounter++;
    if (glitchCounter > glitchMax) {
      glitchTimer.setInterval(random(GLITCH_MIN * 1000L, GLITCH_MAX * 1000L));
      glitchFlag = false;
      indiDimm[glitchIndic] = indiMaxBright;
    }
  }
}

isr.ino

// dynamic indication in timer interrupt 2
ISR(TIMER2_COMPA_vect) {
  indiCounter[curIndi]++;                         // indicator counter
  if (indiCounter[curIndi] >= indiDimm[curIndi])  // if the dimming threshold has been reached
    setPin(opts[curIndi], 0);                     // turn off the current indicator

  if (indiCounter[curIndi] > 25) {    // reached the threshold of 25 units
    indiCounter[curIndi] = 0;         // nixie lamp counter reset
    if (++curIndi >= 4) curIndi = 0;  // nixie lamp change loop

    // send a digit from the indiDigits array according to the lamp type
    if (indiDimm[curIndi] > 0) {
      byte thisDig = digitMask[indiDigits[curIndi]];
      setPin(DECODER3, bitRead(thisDig, 0));
      setPin(DECODER1, bitRead(thisDig, 1));
      setPin(DECODER0, bitRead(thisDig, 2));
      setPin(DECODER2, bitRead(thisDig, 3));
      setPin(opts[curIndi], anodeStates[curIndi]);  // turn on the anode to the current lamp
    }
  }
}

nixieClock_2_v2.5.ino

/*
  Sketch for the project "Clock on GRI version 2"
  Project page (diagrams, descriptions): https://alexgyver.ru/nixieclock_v2/
  Sources on GitHub: https://github.com/AlexGyver/NixieClock_v2
  Like the way the code is written? Support the author! https://alexgyver.ru/support_alex/
  Author: AlexGyver Technologies, 2018
  https://AlexGyver.ru/
*/

/*
  Control:
  - Time setting:
    - Left button - selection, the rest are "greater" and "less"
    - Hold "select" - time setting
    - Click on "select" - change hour/minute setting
    - Click "more" and "less" - change the time
    - Hold "select" - return to clock mode

  - Effect control IN CLOCK MODE:
    - Holding the central button turns on and off the "glitches"
    - Click on the central button to switch the lighting modes of the lamps
      - Breath
      - Permanent glow
      - Disabled
    - Clicking on the right button toggles the number scrolling modes
      - no effect
      - Smooth fade
      - Rewind in numerical order
      - Rewind on cathodes
      - Train
      - Elastic
*/
/*
  Version 2.0 (together with Pavel Smelov):
  - Fixed jambs with backlight
  - Added switching effects "train" and "gum"
  - Optimized code

  Version 2.1:
  - Fixed a bug with the passage of time

  Version 2.2:
  - Reset seconds when setting time
  
  Version 2.3:
  - Added advanced brightness settings
  - Fixed freezes at zero values ​​of some settings

  Version 2.4:
  - We continue to fix bugs with zero settings

  Version 2.5 ***THIS VERSION***:
  - Demonstration of the effect when selected
*/

// ************************** SETTINGS **************************
#define BOARD_TYPE 0
// clock board type:
// 0 - IN-12 turned (indicators are correct)
// 1 - IN-12 (indicators are upside down)
// 2 - IN-14 (regular and neon dot)
// 3 other indicators

#define DUTY 200  // PWM duty cycle. The voltage depends on the duty cycle! I have 175 volts at 180 and 145 volts at 120

// ======================= EFFECTS ========================
// clock flip effects
byte FLIP_EFFECT = 0;
// The selected one is active at the first start and is changed by buttons. Memorized in memory
// 0 - no effect
// 1 - fade in and out (recommended speed: 100-150)
// 2 - rewind in numerical order (recommended speed: 50-80)
// 3 - rewind in order of the cathodes in the lamp (recommended speed: 30-50)
// 4 - train (recommended speed: 50-170)
// 5 - elastic band (recommended speed: 50-150)


// ======================= BRIGHTNESS =======================
#define NIGHT_LIGHT 1   // Change brightness from time of day (1 on, 0 off)
#define NIGHT_START 23  // hour of transition to night illumination (BRIGHT_N)
#define NIGHT_END 7     // hour of transition to daylight (BRIGHT)

#define INDI_BRIGHT 23   // the brightness of the digits is daytime (1 - 24)! 24 may create burn-in!
#define INDI_BRIGHT_N 8  // night brightness (1 - 24)

#define DOT_BRIGHT 35    // dot brightness daytime (1 - 255)
#define DOT_BRIGHT_N 15  // dot brightness at night (1 - 255)

#define BACKL_BRIGHT 250     // Max. daytime lamp brightness (0 - 255)
#define BACKL_BRIGHT_N 50    // Max. lamp backlight brightness at night (0 - 255, 0 - backlight off)
#define BACKL_MIN_BRIGHT 20  // min. brightness of lamp illumination in breathing mode (0 - 255)
#define BACKL_PAUSE 400      // "darkness" interval between flashes of lamp illumination in breathing mode, ms

// ======================= Glitches =======================
#define GLITCH_MIN 30   // minimum time between glitches, seconds
#define GLITCH_MAX 120  // maximum time between glitches, seconds

// ======================  BLINK =======================
#define DOT_TIME 500  // dot flashing time, ms
#define DOT_TIMER 20  // dot brightness step, ms

#define BACKL_STEP 2     // backlight flashing step
#define BACKL_TIME 5000  // backlight period, ms

// ==================  ANTI BURN-IN ====================
#define BURN_TIME 10    // indicator bypass period in cleaning mode, ms
#define BURN_LOOPS 3    // number of cleaning cycles for each period
#define BURN_PERIOD 15  // anti-burn-in period, minutes


// *********************** FOR DEVELOPERS ***********************
byte BACKL_MODE = 0;                             // The selected one is active at startup and can be changed with buttons
byte FLIP_SPEED[] = { 0, 130, 50, 40, 70, 70 };  // effects speed, ms (do not change the number)
byte FLIP_EFFECT_NUM = sizeof(FLIP_SPEED);       // number of effects
boolean GLITCH_ALLOWED = 1;                      // 1 - enable, 0 - disable glitches. Button controlled

// --------- ALARM ---------
#define ALM_TIMEOUT 30  // alarm timeout
#define FREQ 900        // alarm frequency

// pins
#define PIEZO 2   // alarm
#define KEY0 3    // hours
#define KEY1 4    // hours
#define KEY2 5    // minutes
#define KEY3 6    // minutes
#define BTN1 7    // button 1
#define BTN2 8    // button 2
#define GEN 9     // generator
#define DOT 10    // point
#define BACKL 11  // backlight
#define BTN3 12   // button 3

// decoder
#define DECODER0 A0
#define DECODER1 A1
#define DECODER2 A2
#define DECODER3 A3

// lamp pinout
#if (BOARD_TYPE == 0)
const byte digitMask[] = { 7, 3, 6, 4, 1, 9, 8, 0, 5, 2 };    // board decoder mask IN-12-turned (normal numbers)
const byte opts[] = { KEY0, KEY1, KEY2, KEY3 };               // order of indicators from left to right
const byte cathodeMask[] = { 1, 6, 2, 7, 5, 0, 4, 9, 8, 3 };  // cathode order IN-12

#elif (BOARD_TYPE == 1)
const byte digitMask[] = { 2, 8, 1, 9, 6, 4, 3, 5, 0, 7 };    // board decoder mask IN-12 (numbers upside down)
const byte opts[] = { KEY3, KEY2, KEY1, KEY0 };               // order of indicators from right to left (for IN-12 turned) and IN-14
const byte cathodeMask[] = { 1, 6, 2, 7, 5, 0, 4, 9, 8, 3 };  // cathode order IN-12

#elif (BOARD_TYPE == 2)
const byte digitMask[] = { 9, 8, 0, 5, 4, 7, 3, 6, 2, 1 };    // IN-14 board decoder mask
const byte opts[] = { KEY3, KEY2, KEY1, KEY0 };               // order of indicators from right to left (for IN-12 turned) and IN-14
const byte cathodeMask[] = { 1, 0, 2, 9, 3, 8, 4, 7, 5, 6 };  // cathode order IN-14

#elif (BOARD_TYPE == 3)
const byte digitMask[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };    // here enter your order of pins
const byte opts[] = { KEY0, KEY1, KEY2, KEY3 };               // own order of indicators
const byte cathodeMask[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  // and its order of cathodes

#endif

/*
  ард ног ном
  А0  7   4
  А1  6   2
  А2  4   8
  А3  3   1
*/

timeFunctions.ino

// send to indicators
void sendTime(byte hours, byte minutes) {
  indiDigits[0] = (byte)hours / 10;
  indiDigits[1] = (byte)hours % 10;

  indiDigits[2] = (byte)minutes / 10;
  indiDigits[3] = (byte)minutes % 10;
}

// for effects
void setNewTime() {
  newTime[0] = (byte)hrs / 10;
  newTime[1] = (byte)hrs % 10;

  newTime[2] = (byte)mins / 10;
  newTime[3] = (byte)mins % 10;
}
}

timer2Minim.h

// Mini Timer Class, Version 2.0
// An improved millisecond timer algorithm was used
// The algorithm is slightly slower, but provides multiple intervals and protection against gaps and overflows

class timerMinim {
public:
  timerMinim(uint32_t interval);        // timer declaration with interval specification
  void setInterval(uint32_t interval);  // setting the timer interval
  boolean isReady();                    // Returns true when the time has come. Resets to false automatically (AUTO) or manually (MANUAL)
  void reset();                         // manual reset of the timer to a set interval

private:
  uint32_t _timer = 0;
  uint32_t _interval = 0;
};

timerMinim::timerMinim(uint32_t interval) {
  _interval = (interval != 0) ? interval : 5;
  _timer = millis();
}

void timerMinim::setInterval(uint32_t interval) {
  _interval = (interval != 0) ? interval : 5;
  _interval = interval;
}

boolean timerMinim::isReady() {
  uint32_t thisMls = millis();
  if (thisMls - _timer >= _interval) {
    do {
      _timer += _interval;
      if (_timer < _interval) break;         // uint32_t overflow
    } while (_timer < thisMls - _interval);  // step skip protection
    return true;
  } else {
    return false;
  }
}

void timerMinim::reset() {
  _timer = millis();
}

timeTicker.ino

byte minsCount = 0;
void calculateTime() {
  dotFlag = !dotFlag;
  if (dotFlag) {
    dotBrightFlag = true;
    dotBrightDirection = true;
    dotBrightCounter = 0;
    secs++;
    if (secs > 59) {
      newTimeFlag = true;  // flag that the time needs to be changed
      secs = 0;
      mins++;
      minsCount++;

      if (minsCount >= 15) {  // every 15 minutes
        minsCount = 0;
        DateTime now = rtc.now();  // synchronization with RTC
        secs = now.second();
        mins = now.minute();
        hrs = now.hour();
      }

      if (mins % BURN_PERIOD == 0) burnIndicators();  // we're cleaning, we're cleaning!

      /*if (!alm_flag && alm_mins == mins && alm_hrs == hrs && true) {
        mode = 0;
        alm_flag = true;
        almTimer.start();
        almTimer.reset();
        }*/
    }
    if (mins > 59) {
      mins = 0;
      hrs++;
      if (hrs > 23) hrs = 0;
      changeBright();
    }
    if (newTimeFlag) setNewTime();  // updating the time array

    /*
        if (mode == 0) sendTime(hrs, mins);

        if (alm_flag) {
          if (almTimer.isReady() || true ) {
            alm_flag = false;
            almTimer.stop();
            mode = 0;
            noTone(PIEZO);
          }
        }
    */
  }

  /*
    // blink on the alarm clock
    if (alm_flag) {
      if (!dotFlag) {
        noTone(PIEZO);
        for (byte i = 1; i < 7; i++) digitsDraw[i] = 10;
      } else {
        tone(PIEZO, FREQ);
        sendTime(hrs, mins);
      }
    }
  */
}

0_data.ino


// libraries
#include "timer2Minim.h"
#include <GyverButton.h>
#include <Wire.h>
#include <RTClib.h>
#include <EEPROM.h>

RTC_DS3231 rtc;

// timers
timerMinim dotTimer(500);                // half-second timer for a watch
timerMinim dotBrightTimer(DOT_TIMER);    // dot brightness step timer
timerMinim backlBrightTimer(30);         // backlight brightness step timer
timerMinim almTimer((long)ALM_TIMEOUT * 1000);
timerMinim flipTimer(FLIP_SPEED[FLIP_EFFECT]);
timerMinim glitchTimer(1000);
timerMinim blinkTimer(500);

// buttons
GButton btnSet(BTN1, HIGH_PULL, NORM_OPEN);
GButton btnL(BTN2, HIGH_PULL, NORM_OPEN);
GButton btnR(BTN3, HIGH_PULL, NORM_OPEN);

// variables
volatile int8_t indiDimm[4];      // dimming value (0-24)
volatile int8_t indiCounter[4];   // counter of each indicator (0-24)
volatile int8_t indiDigits[4];    // the numbers that the indicators should show(0-10)
volatile int8_t curIndi;          // current indicator (0-3)

boolean dotFlag;
int8_t hrs, mins, secs;
int8_t alm_hrs, alm_mins;
int8_t mode = 0;    // 0 clock, 1 temperature, 2 alarm setting, 3 clock setting, 4 alarm
boolean changeFlag;
boolean blinkFlag;
byte indiMaxBright = INDI_BRIGHT, dotMaxBright = DOT_BRIGHT, backlMaxBright = BACKL_BRIGHT;
boolean alm_flag;
boolean dotBrightFlag, dotBrightDirection, backlBrightFlag, backlBrightDirection, indiBrightDirection;
int dotBrightCounter, backlBrightCounter, indiBrightCounter;
byte dotBrightStep;
boolean newTimeFlag;
boolean flipIndics[4];
byte newTime[4];
boolean flipInit;
byte startCathode[4], endCathode[4];
byte glitchCounter, glitchMax, glitchIndic;
boolean glitchFlag, indiState;
byte curMode = 0;
boolean currentDigit = false;
int8_t changeHrs, changeMins;
boolean lampState = false;
boolean anodeStates[] = {1, 1, 1, 1};
byte currentLamp, flipEffectStages;
bool trainLeaving;

const uint8_t CRTgamma[256] PROGMEM = {
  0,    0,    1,    1,    1,    1,    1,    1,
  1,    1,    1,    1,    1,    1,    1,    1,
  2,    2,    2,    2,    2,    2,    2,    2,
  3,    3,    3,    3,    3,    3,    4,    4,
  4,    4,    4,    5,    5,    5,    5,    6,
  6,    6,    7,    7,    7,    8,    8,    8,
  9,    9,    9,    10,   10,   10,   11,   11,
  12,   12,   12,   13,   13,   14,   14,   15,
  15,   16,   16,   17,   17,   18,   18,   19,
  19,   20,   20,   21,   22,   22,   23,   23,
  24,   25,   25,   26,   26,   27,   28,   28,
  29,   30,   30,   31,   32,   33,   33,   34,
  35,   35,   36,   37,   38,   39,   39,   40,
  41,   42,   43,   43,   44,   45,   46,   47,
  48,   49,   49,   50,   51,   52,   53,   54,
  55,   56,   57,   58,   59,   60,   61,   62,
  63,   64,   65,   66,   67,   68,   69,   70,
  71,   72,   73,   74,   75,   76,   77,   79,
  80,   81,   82,   83,   84,   85,   87,   88,
  89,   90,   91,   93,   94,   95,   96,   98,
  99,   100,  101,  103,  104,  105,  107,  108,
  109,  110,  112,  113,  115,  116,  117,  119,
  120,  121,  123,  124,  126,  127,  129,  130,
  131,  133,  134,  136,  137,  139,  140,  142,
  143,  145,  146,  148,  149,  151,  153,  154,
  156,  157,  159,  161,  162,  164,  165,  167,
  169,  170,  172,  174,  175,  177,  179,  180,
  182,  184,  186,  187,  189,  191,  193,  194,
  196,  198,  200,  202,  203,  205,  207,  209,
  211,  213,  214,  216,  218,  220,  222,  224,
  226,  228,  230,  232,  233,  235,  237,  239,
  241,  243,  245,  247,  249,  251,  253,  255,
};

byte getPWM_CRT(byte val) {
  return pgm_read_byte(&(CRTgamma[val]));
}

// fast digitalWrite
void setPin(uint8_t pin, uint8_t x) {
  switch (pin) { // откл pwm
    case 3:  // 2B
      bitClear(TCCR2A, COM2B1);
      break;
    case 5: // 0B
      bitClear(TCCR0A, COM0B1);
      break;
    case 6: // 0A
      bitClear(TCCR0A, COM0A1);
      break;
    case 9: // 1A
      bitClear(TCCR1A, COM1A1);
      break;
    case 10: // 1B
      bitClear(TCCR1A, COM1B1);
      break;
    case 11: // 2A
      bitClear(TCCR2A, COM2A1);
      break;
  }

  if (pin < 8) bitWrite(PORTD, pin, x);
  else if (pin < 14) bitWrite(PORTB, (pin - 8), x);
  else if (pin < 20) bitWrite(PORTC, (pin - 14), x);
  else return;
}

// fast analogWrite
void setPWM(uint8_t pin, uint16_t duty) {
  if (duty == 0) setPin(pin, LOW);
  else {
    switch (pin) {
      case 5:
        bitSet(TCCR0A, COM0B1);
        OCR0B = duty;
        break;
      case 6:
        bitSet(TCCR0A, COM0A1);
        OCR0A = duty;
        break;
      case 10:
        bitSet(TCCR1A, COM1B1);
        OCR1B = duty;
        break;
      case 9:
        bitSet(TCCR1A, COM1A1);
        OCR1A = duty;
        break;
      case 3:
        bitSet(TCCR2A, COM2B1);
        OCR2B = duty;
        break;
      case 11:
        bitSet(TCCR2A, COM2A1);
        OCR2A = duty;
        break;
      default:
        break;
    }
  }
}

1_setup.ino

void setup() {
  //Serial.begin(9600);
  // random seed for a random number generator
  randomSeed(analogRead(6) + analogRead(7));

  // Setting up output pins
  pinMode(DECODER0, OUTPUT);
  pinMode(DECODER1, OUTPUT);
  pinMode(DECODER2, OUTPUT);
  pinMode(DECODER3, OUTPUT);
  pinMode(KEY0, OUTPUT);
  pinMode(KEY1, OUTPUT);
  pinMode(KEY2, OUTPUT);
  pinMode(KEY3, OUTPUT);
  pinMode(PIEZO, OUTPUT);
  pinMode(GEN, OUTPUT);
  pinMode(DOT, OUTPUT);
  pinMode(BACKL, OUTPUT);

  // we set the PWM frequency on pins 9 and 10 to 31 kHz
  TCCR1B = TCCR1B & 0b11111000 | 1;  // we put the divisor 1

  // turn on PWM
  setPWM(9, DUTY);

  // We reconfigure the PWM frequency on pins 3 and 11 to 7.8 kHz and enable COMPA interrupts.
  TCCR2B = (TCCR2B & B11111000) | 2;  // divisor 8
  TCCR2A |= (1 << WGM21);             // enable CTC mode for COMPA
  TIMSK2 |= (1 << OCIE2A);            // enable COMPA match interrupts

  // ---------- RTC -----------
  rtc.begin();
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  DateTime now = rtc.now();
  secs = now.second();
  mins = now.minute();
  hrs = now.hour();

  // EEPROM
  if (EEPROM.read(1023) != 100) {  // first launch
    EEPROM.put(1023, 100);
    EEPROM.put(0, FLIP_EFFECT);
    EEPROM.put(1, BACKL_MODE);
    EEPROM.put(2, GLITCH_ALLOWED);
  }
  EEPROM.get(0, FLIP_EFFECT);
  EEPROM.get(1, BACKL_MODE);
  EEPROM.get(2, GLITCH_ALLOWED);

  /*if (EEPROM.read(100) != 66) {   // First run check. 66 randomly
    EEPROM.write(100, 66);
    EEPROM.write(0, 0);     // alarm clock
    EEPROM.write(1, 0);     // alarm minutes
    }
    alm_hrs = EEPROM.read(0);
    alm_mins = EEPROM.read(1);*/

  sendTime(hrs, mins);  // send time to indicators
  changeBright();       // change brightness according to the time of day

  // set the brightness on the indicators
  for (byte i = 0; i < 4; i++)
    indiDimm[i] = indiMaxBright;

  // calculation of the brightness step of a point
  dotBrightStep = ceil((float)dotMaxBright * 2 / DOT_TIME * DOT_TIMER);
  if (dotBrightStep == 0) dotBrightStep = 1;

  // breathing backlight
  if (backlMaxBright > 0)
    backlBrightTimer.setInterval((float)BACKL_STEP / backlMaxBright / 2 * BACKL_TIME);

  // initial period of glitches
  glitchTimer.setInterval(random(GLITCH_MIN * 1000L, GLITCH_MAX * 1000L));
  indiBrightCounter = indiMaxBright;

  // mode speed at startup
  flipTimer.setInterval(FLIP_SPEED[FLIP_EFFECT]);
  //almTimer.stop();
}

2_loop.ino

void loop() {
  if (dotTimer.isReady()) calculateTime();        // every 500 ms recalculation and sending of time
  if (newTimeFlag && curMode == 0) flipTick();    // flipping numbers
  dotBrightTick();                                // smooth blinking of the dot
  backlBrightTick();                              // smooth blinking of lamp backlight
  if (GLITCH_ALLOWED && mode == 0) glitchTick();  // glitches
  buttonsTick();                                  // buttons
  settingsTick();                                 // settings

Very nice!

2_loop.ino is missing a close brace ( } ) and timeFunction.ino has one too many close braces.

You don’t need to create the library yourself — you just need to install it correctly. In the AlexGyver/NixieClock_v2 GitHub repository, the timer2minim folder is already the library, but Arduino IDE only recognizes a library if the folder contains the header (.h) and source (.cpp) files directly inside it. Make sure you download the repository as a ZIP, then extract it and copy the entire folder named timer2minim (not the whole repo, not a folder containing another folder) into your Documents/Arduino/libraries/ directory. After restarting Arduino IDE, you should see timer2minim listed under Sketch → Include Library. If it still doesn’t show up, open the folder and ensure the files are not stuck inside an extra nested directory.

I fixed those. Does the rest of the code look okay?
I'll try to put the code in order now

Compile it in your IDE. Does it do what you expect?

I got local help. The clock is now working! How do I post a thanks to everyone?

"@" followed by their user name like @850nixie

Thank you to @MaximoEsfuerzo @xfpd and everyone else who I coudlnt mention cause I am a new user who offered their help! I learned new things!
Have a nice morning/noon/evening/night!