Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Nixie Clock - How c...
 
Share:
Notifications
Clear all

[Solved] Nixie Clock - How can i add my desired function to this code

17 Posts
2 Users
5 Reactions
3,612 Views
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

hi guys and girls this is a link of instructable i am trying to modify its code , as you can see thats a nixie tube clock which it has a unique design the thing is it lacks a functionality to roll through numbers every 30 minutes so the tube remains undamaged from cathode poisoning i wanted to add the code to its original .ino code file but i couldn't do it myself so i provided you with the code to see what you think , can we add a function loop that forces clock to roll through all numbers sequentially for 2 cycle every 30 minutes ? can you please help me out here

//Youtube channel: engineer2you

#include

#include "DS3231.h"




RTClib RTC;

DS3231 Clock;




int hour;

int minute;

int second;




const int nixie_0 = 2;

const int nixie_1 = 3;

const int nixie_2 = 4;

const int nixie_3 = 5;  

const int nixie_4 = 6;

const int nixie_5 = 7;

const int nixie_6 = 8;

const int nixie_7 = 9;

const int nixie_8 = 10;

const int nixie_9 = 11;




const int row_1 = 0;

const int row_2 = 1;

const int row_3 = 14;

const int row_4 = 15;

const int row_5 = 16;

const int row_6 = 17;




const int button_up = 12;

const int button_dn = 13;

int button_up_value;

int button_dn_value;




boolean hour_blink, min_blink, sec_blink;

int blink_latch = 0;

int mode_step = 0;

int mode_counter = 0;

int change_counter = 0;




const int time_on = 2;  //time display each number of nixie tube




void setup() {

  pinMode(nixie_0, OUTPUT);

  pinMode(nixie_1, OUTPUT);

  pinMode(nixie_2, OUTPUT);

  pinMode(nixie_3, OUTPUT);

  pinMode(nixie_4, OUTPUT);

  pinMode(nixie_5, OUTPUT);

  pinMode(nixie_6, OUTPUT);

  pinMode(nixie_7, OUTPUT);

  pinMode(nixie_8, OUTPUT);

  pinMode(nixie_9, OUTPUT);

  pinMode(row_1, OUTPUT);

  pinMode(row_2, OUTPUT);

  pinMode(row_3, OUTPUT);

  pinMode(row_4, OUTPUT);

  pinMode(row_5, OUTPUT);

  pinMode(row_6, OUTPUT);

  pinMode(button_up, INPUT_PULLUP);

  pinMode(button_dn, INPUT_PULLUP);

  //Serial.begin(9600); //should NOT use seiral println, it will effect to output pin D0 & D1

  Wire.begin();

  hour_blink = false;

  min_blink = false;

  sec_blink = false;

}




void loop() {

    //-------------------get clock value---------------------------

    DateTime now = RTC.now();

    hour = now.hour();

    minute = now.minute();

    second = now.second();

    

    //-------------------show clock number ----------------------

    int j; //second number from right

    int k; //first number from right

    //-----------------------------------------------------------------------second number show

    j = second/10;

    k = second%10;

    if(sec_blink==false)

    {

      //-----------show first number of second

      off_all();

      on_number(0,k+2);

      delay(time_on);

      //-----------show second number of second

      off_all();

      on_number(1,j+2);

      delay(time_on);

    }

    else{

      if(blink_latch < 8){  //blink_latch: time for blinking

        off_all();

        delay(time_on);

        blink_latch++;

      }

      else{

        //-----------show first number of second/ blink display

        off_all();

        on_number(0,k+2);

        delay(time_on);

        //-----------show second number of second/ blink display

        off_all();

        on_number(1,j+2);

        delay(time_on);

        if (blink_latch < 16) blink_latch++;

        else blink_latch = 0;

      }

    }

    //-------------------------------------------------------------minute number show

    j = minute/10;

    k = minute%10;

    if(min_blink==false)

    {

      //-----------show first number of minute

      off_all();

      on_number(14,k+2);

      delay(time_on);

      //-----------show second number of minute

      off_all();

      on_number(15,j+2);

      delay(time_on);

    }

    else{

      if(blink_latch < 8){  //blink_latch: time for blinking

        off_all();

        delay(time_on);

        blink_latch++;

      }

      else{

        //-----------show first number of minute/ blink display

        off_all();

        on_number(14,k+2);

        delay(time_on);

        //-----------show second number of minute/ blink display

        off_all();

        on_number(15,j+2);

        delay(time_on);

        if (blink_latch < 16) blink_latch++;

        else blink_latch = 0;

      }

     }

    //-----------------------------------------------------------------hour number show

    j = hour/10;

    k = hour%10;

    if(hour_blink==false)

    {

      //-----------show first number of hour

      off_all();

      on_number(16,k+2);

      delay(time_on);

      //-----------show second number of hour

      off_all();

      on_number(17,j+2);

      delay(time_on);

    }

    else{

      if(blink_latch < 8){  //blink_latch: time for blinking

        off_all();

        delay(time_on);

        blink_latch++;

      }

      else{

        //-----------show first number of hour/ blink display

        off_all();

        on_number(16,k+2);

        delay(time_on);

        //-----------show second number of hour/ blink display

        off_all();

        on_number(17,j+2);

        delay(time_on);

        if (blink_latch < 16) blink_latch++;

        else blink_latch = 0;

      }

    }




  //---------------------------------------mode choosen: push two button same time

  button_up_value = digitalRead(button_up); //normal ON (1)

  button_dn_value = digitalRead(button_dn); //normal ON (1)




  if((button_up_value==0)&(button_dn_value==0)&(mode_step==0)){

    mode_step = 1;

  }

  //---------------------------allow to change second

  if(mode_step==1){

    if (mode_counter < 200){

      mode_counter++; // waiting time for changing value

    }

    else{

      mode_counter=0;

      mode_step=2;

      change_counter = 0;

    }

    sec_blink = true; // allow to change second

    min_blink = false;

    hour_blink = false;

  }

  //-------------------------allow to change minute

  if(mode_step==2){

    if (mode_counter < 200){

      mode_counter++; // waiting time for changing value

    }

    else{

      mode_counter=0;

      mode_step=3;

      change_counter = 0;

    }

    sec_blink = false;

    min_blink = true; // allow to change minute

    hour_blink = false;

  }

  //-------------------------allow to change hour

  if(mode_step==3){

    if (mode_counter < 200){

      mode_counter++; // waiting time for changing value

    }

    else{

      mode_counter=0;

      mode_step=4;

      change_counter = 0;

    }

    sec_blink = false;

    min_blink = false;

    hour_blink = true;  // allow to change hour

  }

  //--------------------------escape changing time

  if(mode_step==4){

    mode_step=0;  // escape changing time

    sec_blink = false;

    min_blink = false;

    hour_blink = false;

    change_counter = 0;

  }

  

  //----------------------------------------------------------------------change-second +/-

  if ((button_up_value==0)&(sec_blink==true)){

    second++;

    if (second>59) second = 0;

    change_counter++; //prevent value change too fast

    mode_counter = 0; //hold mode

    if(change_counter>5){

      Clock.setSecond(second);

      change_counter=0;

    }

  }

  if ((button_dn_value==0)&(sec_blink==true)){

    second--;

    if (second<0) second = 59;

    change_counter++; //prevent value change too fast

    mode_counter = 0; //hold mode

    if(change_counter>5){

      Clock.setSecond(second);

      change_counter=0;

    }

  }

  //----------------------------------------------------------------------change-minute +/-

  if ((button_up_value==0)&(min_blink==true)){

    minute++;

    if (minute>59) minute = 0;

    change_counter++; //prevent value change too fast

    mode_counter = 0; //hold mode

    if(change_counter>5){

      Clock.setMinute(minute);

      change_counter=0;

    }

  }

  if ((button_dn_value==0)&(min_blink==true)){

    minute--;

    if (minute<0) minute = 59;

    change_counter++; //prevent value change too fast

    mode_counter = 0; //hold mode

    if(change_counter>5){

      Clock.setMinute(minute);

      change_counter=0;

    }

  }

  //----------------------------------------------------------------------change-hour +/-

  if ((button_up_value==0)&(hour_blink==true)){

    hour++;

    if (hour>23) hour = 0;

    change_counter++; //prevent value change too fast

    mode_counter = 0; //hold mode

    if(change_counter>5){

      Clock.setHour(hour);

      change_counter=0;

    }

  }

  if ((button_dn_value==0)&(hour_blink==true)){

    hour--;

    if (hour<0) hour = 23;

    change_counter++; //prevent value change too fast

    mode_counter = 0; //hold mode

    if(change_counter>5){

      Clock.setHour(hour);

      change_counter=0;

    }

  }

}




void on_number(int row, int nixie){

  digitalWrite(row, HIGH);

  digitalWrite(nixie, HIGH);

}




void off_all(){

  digitalWrite(row_1, LOW);

  digitalWrite(row_2, LOW);

  digitalWrite(row_3, LOW);

  digitalWrite(row_4, LOW);

  digitalWrite(row_5, LOW);

  digitalWrite(row_6, LOW);

  digitalWrite(nixie_0, LOW);

  digitalWrite(nixie_1, LOW);

  digitalWrite(nixie_2, LOW);

  digitalWrite(nixie_3, LOW);

  digitalWrite(nixie_4, LOW);

  digitalWrite(nixie_5, LOW);

  digitalWrite(nixie_6, LOW);

  digitalWrite(nixie_7, LOW);

  digitalWrite(nixie_8, LOW);

  digitalWrite(nixie_9, LOW);




  delayMicroseconds(400);  //to prevent "ghost" effect to other tube

}


This topic was modified 4 years ago by pejman1998

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

I'm not an expert on Nixie tubes (love looking at them though).

When looking at the code, I'd probably look at this section:

//-------------------------------------------------------------minute number show

and add something like

if( (minute=0) || (minute=30) ) {
// rotate numbers
}

I just don't know how the numbers are being set.

 


   
pejman1998 reacted
ReplyQuote
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

@hans hi Hans , thanks for replying, the digits of each numbers actually are set by one anode and one cathode , the anode is common and by cathode the number changes ,  6 pieces of nixie tubes are representing hour minute and seconds ,in each tube there are 10 digits starting from 0 to 9 and a common anode, same digits from all 6 tubes are tide (connected) together but each anode of tubes are separated meaning that there are 6 anodes and 10 cathodes for 6 tube to show 6 digits , each time the circuit can only lit up one digit but human eye sees it as normal and constant. it uses SSR (optocouplers) to switch the numbers and anodes, pins assigned for anodes are A0, A1, A2, A3, D0, D1 and pins for numbers are assigned to pins D2,...,D11 the sequence is from number 0 to 9 , so Arduino sends a signal to each of 16 SSR relays to switch on the high voltage in one side and switch the respective digit cathode on the other side all i want is a piece of code that tells Arduino to run through all digits and for each digit for a 0.5 second with a loop that happens has 2 cycles every 30 minutes , do you think its  possible?


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

Thanks for the explanation! I;ve work with radio tubes before (like way back in the day) so the Anode/Cathode and High Voltage are not completely unfamiliar.
I have never worked with Nixie tubes though, so I hope I'm doing this right.

For now I'd stick with the approach I've mentioned before.
The "loop()" function is executed over and over again, so somewhere in the code there (maybe best at the beginning) we can check if minute = 0 or minute = 30.
If so then we can cycle through the numbers and when that is done, continue with the loop() code.

Note: I'm checking here if minute is either 0 or 30, and seconds=0. This to prevent that our action will be executed multiple times within a minute.
This may need some finetuning though, since I'm not 100% sure if you'd catch the exact "second = 0" moment.

Since the code is not entirely clear to me, and I have zero Nixie experience, I can only guess something like this:

if( ( (minute==0) || (minute==30) ) && (second==0) ) {

  off_all(); // all tubes OFF

on_number(row_1, nixie_0);
digitalWrite(row_1, LOW);

on_number(row_1, nixie_1);
digitalWrite(row_1, LOW);

  on_number(row_1, nixie_2);
digitalWrite(row_1, LOW);

...

on_number(row_1, nixie_9);
  digitalWrite(row_1, LOW);

  ...

on_number(row_6, nixie_0);
  digitalWrite(row_6, LOW);

on_number(row_6, nixie_1);
  digitalWrite(row_6, LOW);

on_number(row_6, nixie_2);
  digitalWrite(row_6, LOW);

  ...

on_number(row_6, nixie_9);
digitalWrite(row_6, LOW);
}

We need to do this for every row, and for every nixie. And this is just turning everything OFF, and one at a time every number ON and OFF again.
A delay between turning one ON and OFF again may be desired, I cannot imagine it to be great for the nixies to be turned on only for a fraction of a second.

Now, you do see a ton of repeated code, and this can be done much more efficient.

 

1. I'd make row_x and nixie_y both arrays. 

The first step what I would do is make your current code work with arrays which comes with some minor changes.
Let's start with the definition:

Replace this:

const int nixie_0 = 2;
const int nixie_1 = 3;
const int nixie_2 = 4;
const int nixie_3 = 5; 
const int nixie_4 = 6;
const int nixie_5 = 7;
const int nixie_6 = 8;
const int nixie_7 = 9;
const int nixie_8 = 10;
const int nixie_9 = 11;

with this:

int nixies[] = {2,3,4,5,6,7,8,10,11};

NOTE: Instead of calling "nixie_0" in your code, you'd call it with "nixies[0]".
So you'd have to replace all "nixie_x" with "nixies[x]".

Same for rows, replace this:

const int row_1 = 0;  // caution: constants start counting at 1, where arrays start counting at zero!
const int row_2 = 1;
const int row_3 = 14;
const int row_4 = 15;
const int row_5 = 16;
const int row_6 = 17;

with

int rows[] = {0,1,14,15,16,17};

And for rows again you'd have to replace each occurance of "row_x" with "rows[x-1]".
Note: the rows are numbered different: arrays start counting with zero, and your rows start with "1".
So the index used should be decrease by one to match the correct index (hence the "x-1").

Not required, but I'd most certainly take a look at this:
I noticed that you've hardcoded all of the numbers, instead of using the defined constants (nixie_x and row_y).
It is good practice to actually use the defined constants.
This way, if you ever have to change one of the numbers (for example because you want to use a different pin), you'd have to change it in only one place: where the constants (or array) have been defined.

For example this line (there are more) can cause problems in the long run, when you change a pin - you'd have to hunt down every "17" and replace it with the new pin number:

on_number(17,j+2);

It should probably say something like this:

on_number(row_6,j+2);

When using arrays this would be:

on_number(rows[6-1],nixies[j+2]);

This goes for pretty much all "on_number()" and "digitalWrite()" calls in your code.
(remember that your previous rows start counting at "1", whereas arrays start with "0")

After a full cleanup and a working code, you can proceed to step 2.

 

2. I'd make a function to handle the suggested no-poisoning cycle:

void NoPoison() {
for(int r=0; r<6; r++) {
  for(int n=0; n<=9; n++) {
      on_number(r, n);
delay(100); // not sure if and how long of a delay you'd want here
    digitalWrite(r, LOW);
  }
}
}

You see that the code now has become significantly shorter and more efficient.

It occured to me though that since these are individual tubes, we can do all 6 digits in parallel, which would go faster than every individual number/tube combination.
Something like this, where we set a number for each nixie, wait a short time, and turn that number off again for each nixie.
It will go through all numbers for each nixie this way.

void NoPoison() {
int n=0; // we reuse these variables so we define them first
  int r=0;

// for every individual number:
for(n=0; n<=9; n++) {

// turn number "n" for every tube ON
  for(r=0; r<6; r++) {
      on_number(r, n);
    }

// again an arbitrary delay - up to you if you like this value
  delay(100);

// turn number "n" for every tube OFF
for(r=0; r<6; r++) {
      digitalWrite(r, LOW);
    }

}
}

 

 

3. Modify the loop()

No we can modify the loop to initiate the no-poison function when we hit either minute 0 or minute 30, where seconds=0.

void loop() {
if( ( (minute==0) || (minute==30) ) && (second==0) ) {
  NoPoison();
  }

 ... // the original code goes here

}

 

 

I realize that this may take some work, especially step 1, and I can imagine it to be a little much to comprehend or get used to.
Mind you: I do not have experience with Nixies (it is on my "todo" list haha) and I've typed all this without testing. There may be typos in it. 


   
pejman1998 reacted
ReplyQuote
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

@hans amazing job , thanks for taking the time for suggesting i will test it and i will inform you.


   
ReplyQuote
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

@hans hello ! after all this time i managed to run the code , unfortunately there is a problem with both no poison voids, the problem is at the moment that the no poison starts not all tubes are lit and in the tubes which start to run through the numbers all numbers stay lit and they dont turn off as the next number starts to glow ,i believe parallel code is better since all tubes run through same digits simultaneously , but as i said before this is due to POV actually they get lit one by one in a high refresh rate so i think there should be a way to imply the pov feature when it starts to run the code and the other thing is each digit should turn off after they get lit for a fraction of time but they stay ON , so what do you think?
regards


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

Hi Pejman1998,

It's been a while that we worked on this, so I have to dive in again to get familiar with the details 😋 

I have zero experience with Nixies,... so bear with me 😊 

This NoPoison does not work as expected?
Did I understand this right: this function doesn't work? The nixies stay on?

I'm not sure if I understand the issue haha. (sorry)

As I understood on_number(r,n) switches nixie "r" on and sets the number to "n",
And the same for digitalWrite(r,LOW) turns it off.

One thing I am wondering about now is this, the ON function sets 2 pins to high (row and nixie):

void on_number(int row, int nixie){
  digitalWrite(row, HIGH);
  digitalWrite(nixie, HIGH);
}

 

Maybe we should create an off function which reverses this, eg:

void off_number(int row, int nixie){
  digitalWrite(row, LOW);
  digitalWrite(nixie, LOW);
}

 

And modify this NoPoison to:

void NoPoison() {
  int n=0; // we reuse these variables so we define them first
  int r=0;

  // for every individual number: 
  for(n=0; n<=9; n++) {

    // turn number "n" for every tube ON
    for(r=0; r<6; r++) { 
      on_number(r, n);
    }

    // again an arbitrary delay - up to you if you like this value
    delay(100); 

    // turn number "n" for every tube OFF
    for(r=0; r<6; r++) { 
      off_number(r, n);
    }

  }
}

 

 

 


   
ReplyQuote
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

@hans yes you are right its been a while lol
i meant that even though it starts to work at the time of 30 or 00 minutes (which turns on only 2 tubes ) it starts to glow the digits sequently while the earlier digits glow new ones starts to glow i've uploaded the video for you to see this is my video with our code

you see that when it starts to change the time to new hour it kinda works but what we intened to make is something like this in   this video made by some you-tuber so i will test your new suggestion and i will tell you if it worked or not 
thanks a lot 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

By what I'm seeing in that other YouTube video, the digits are turned on/off very fast and several times?

So first thing, I think some of the code is a little confusing, in my own code as well.
I understand you have 6 tubes (nixies) and each can have a the value 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9.

This doesn't quite add up with the wording and the idea of using arrays to talk to the tubes, and I did see a mistake in my own code as well.

I'd change your "nixie_X" variabel name to something like "Digit_X" or in an array:

int Digits[] = {2,3,4,5,6,7,8,9,10,11};

 

I'd change your "row_X" variable to "NixieTube_X" and if not to confusing, in an array as well:

int NixieTubes[] = {0,1,14,15,16,17};

 

Next thing I did was rewrite some of the original code.
Keep in mind that I do not have Nixie tubes available, so this is all untested ...

#include <Wire.h>
#include "DS3231.h"

RTClib RTC;
DS3231 Clock;

int hour;
int minute;
int second;

// arrays with the pins for the rubes and the digits
int Digits[] = {2,3,4,5,6,7,8,9,10,11};
int NixieTubes[] = {0,1,14,15,16,17};

const int button_up = 12;
const int button_dn = 13;

int button_up_value;
int button_dn_value;

boolean hour_blink, min_blink, sec_blink;
int blink_latch = 0;
int mode_step = 0;
int mode_counter = 0;
int change_counter = 0;

const int time_on = 2;  //time display each number of nixie tube

void setup() {
  for(int Counter=0; Counter<=9; Counter++) {
    pinMode(NixieTubes[Counter], OUTPUT);
  }
  
  for(int Counter=0; Counter<6; Counter++) {
    pinMode(Digits[Counter], OUTPUT);
  }

  pinMode(button_up, INPUT_PULLUP);
  pinMode(button_dn, INPUT_PULLUP);

  Wire.begin();

  hour_blink = false;
  min_blink = false;
  sec_blink = false;
}

void loop() {
    //-------------------get clock value---------------------------
    DateTime now = RTC.now();
    hour = now.hour();
    minute = now.minute();
    second = now.second();

    // --- Trigger NoPoison every half hour
    if( ( (minute==0) || (minute==30) ) && (second==0) ) {
      NoPoison();
    }
      
    //-------------------show clock number ----------------------
    int j; //second number from right
    int k; //first number from right

    //-----------------------------------------------------------------------second number show
    j = second/10;
    k = second%10;

    if(sec_blink==false)
    {
      //-----------show first number of second
      AllOff();
      NumberON(0,k+2);
      delay(time_on);

      //-----------show second number of second
      AllOff();
      NumberON(1,j+2);
      delay(time_on);
    }
    else 
    {
      if(blink_latch < 8){  //blink_latch: time for blinking
        AllOff();
        delay(time_on);
        blink_latch++;
      }
      else 
      {
        //-----------show first number of second/ blink display
        AllOff();
        NumberON(0,k+2);
        delay(time_on);

        //-----------show second number of second/ blink display
        AllOff();
        NumberON(1,j+2);
        delay(time_on);
        if (blink_latch < 16) blink_latch++;
        else blink_latch = 0;
      }
    }

    //-------------------------------------------------------------minute number show
    j = minute/10;
    k = minute%10;

    if(min_blink==false)
    {
      //-----------show first number of minute
      AllOff();
      NumberON(14,k+2);
      delay(time_on);
      //-----------show second number of minute
      AllOff();
      NumberON(15,j+2);
      delay(time_on);
    }
    else
    {
      if(blink_latch < 8){  //blink_latch: time for blinking
        AllOff();
        delay(time_on);
        blink_latch++;
      }
      else
      {
        //-----------show first number of minute/ blink display
        AllOff();
        NumberON(14,k+2);
        delay(time_on);

        //-----------show second number of minute/ blink display
        AllOff();
        NumberON(15,j+2);
        delay(time_on);
        if (blink_latch < 16) blink_latch++;
        else blink_latch = 0;
      }
     }

    //-----------------------------------------------------------------hour number show
    j = hour/10;
    k = hour%10;
    if(hour_blink==false)
    {
      //-----------show first number of hour
      AllOff();
      NumberON(16,k+2);
      delay(time_on);

      //-----------show second number of hour
      AllOff();
      NumberON(17,j+2);
      delay(time_on);
    }
    else
    {
      if(blink_latch < 8) {  //blink_latch: time for blinking
        AllOff();
        delay(time_on);
        blink_latch++;
      }
      else
      {
        //-----------show first number of hour/ blink display
        AllOff();
        NumberON(16,k+2);
        delay(time_on);

        //-----------show second number of hour/ blink display
        AllOff();
        NumberON(17,j+2);
        delay(time_on);
        if (blink_latch < 16) blink_latch++;
        else blink_latch = 0;
      }
    }

  //---------------------------------------mode choosen: push two button same time
  button_up_value = digitalRead(button_up); //normal ON (1)
  button_dn_value = digitalRead(button_dn); //normal ON (1)

  if((button_up_value==0)&(button_dn_value==0)&(mode_step==0)){
    mode_step = 1;
  }

  //---------------------------allow to change second
  if(mode_step==1){
    if (mode_counter < 200){
      mode_counter++; // waiting time for changing value
    }
    else
    {
      mode_counter=0;
      mode_step=2;
      change_counter = 0;
    }
    sec_blink = true; // allow to change second
    min_blink = false;
    hour_blink = false;
  }

  //-------------------------allow to change minute
  if(mode_step==2){
    if (mode_counter < 200){
      mode_counter++; // waiting time for changing value
    }
    else
    {
      mode_counter=0;
      mode_step=3;
      change_counter = 0;
    }

    sec_blink = false;
    min_blink = true; // allow to change minute
    hour_blink = false;
  }

  //-------------------------allow to change hour
  if(mode_step==3){
    if (mode_counter < 200){
      mode_counter++; // waiting time for changing value
    }
    else 
    {
      mode_counter=0;
      mode_step=4;
      change_counter = 0;
    }

    sec_blink = false;
    min_blink = false;
    hour_blink = true;  // allow to change hour
  }

  //--------------------------escape changing time
  if(mode_step==4){
    mode_step=0;  // escape changing time
    sec_blink = false;
    min_blink = false;
    hour_blink = false;
    change_counter = 0;
  }

  //----------------------------------------------------------------------change-second +/-
  if ((button_up_value==0)&(sec_blink==true)){
    second++;
    if (second>59) second = 0;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setSecond(second);
      change_counter=0;
    }
  }

  if ((button_dn_value==0)&(sec_blink==true)){
    second--;
    if (second<0) second = 59;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setSecond(second);
      change_counter=0;
    }
  }

  //----------------------------------------------------------------------change-minute +/-

  if ((button_up_value==0)&(min_blink==true)){
    minute++;
    if (minute>59) minute = 0;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setMinute(minute);
      change_counter=0;
    }
  }

  if ((button_dn_value==0)&(min_blink==true)){
    minute--;
    if (minute<0) minute = 59;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setMinute(minute);
      change_counter=0;
    }
  }

  //----------------------------------------------------------------------change-hour +/-
  if ((button_up_value==0)&(hour_blink==true)){
    hour++;
    if (hour>23) hour = 0;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setHour(hour);
      change_counter=0;
    }
  }

  if ((button_dn_value==0)&(hour_blink==true)){
    hour--;
    if (hour<0) hour = 23;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setHour(hour);
      change_counter=0;
    }
  }
}

// --- Replacement for the on_number function
void NumberON(int Tube, int Digit){
  digitalWrite(NixieTubes[Tube], HIGH);
  digitalWrite(Digits[Digit], HIGH);
}

// --- Sets all tubes and digits to LOW
void AllOff() {
  SetAll(LOW); // LOW = OFF
}

// --- Sets all tubes and digits to HIGH
void AllOn() {
  SetAll(HIGH); // HIGH = ON
}

// --- Sets all tubes and digits to either LOW or HIGH (used by AllOn and AllOff)
void SetAll(int NewState){
  // All tubes ON or OFF
  for(int Counter; Counter<6; Counter++) {
    digitalWrite(NixieTubes[Counter], NewState);
  }
  // All Digits ON or OFF
  for(int Counter; Counter<=9; Counter++) {
    digitalWrite(Digits[Counter], NewState);
  }
  
  delayMicroseconds(400);  //to prevent "ghost" effect to other tube
}  
    
// --- Toggle all Tubes and Numbers ON and OFF 10 times
// --- You can change "10" to a different number if that works better 
void NoPoison() {
 for(int Counter=0; Counter<10; Counter++) {
   AllOn();
   AllOff();
  }
}

 

At the end you'll see that I've removed and replaced the old on_number and off_all functions.
I've added also AllOn and SetAll.

For ON and OFF switching for all tubes and digits we'd  need the same loops, just a different value.
This is where SetAll comes in play, as you can pass it the value (LOW or HIGH) we'd like to use.
This function is used by AllOn and AllOff.

You now see that we can write the NoPoison function a lot shorter as well.

Note: I've also added the 30 minute check (at the beginning of the void loop).

In the NoPoison function, up to you to determine if 10 is a good value 😊 

 

I hope this helps (and works hahah - it does compile, I just cannot test it by lack of hardware)!


   
pejman1998 reacted
ReplyQuote
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

@hans ok i just tested your new code and unfortunately the same thing happened with an exception that i could see that even though only 2 of tubes were glowing one of them was cycling the numbers over and over opposite of the prior code that after doing cycling it just returns to a normal clock mode until the next half hour , but  i thing you should have the hardware to tweak it yourself  then it would be fair to ask you for the code edition , i added the video of this times glitchy no poison cycle , thanks for your generosity to give your time to me
the 2nd video


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

Hmm, that is not good ... I wonder why this is.
Possibly my lack of knowledge on the Nixies ...?

Have you ever seen your Nixies all light up with all numbers on?
Just wondering if your power-supply is maybe not pulling it off?

If that is the case, then maybe this will work?
Instead of turning ALL digits on ALL tubes, at the same time, maybe mimic the Vegas protocol (= slot machines, where the wheels spin, all showing the same number).

I've changed the "delayMicroseconds" from the SetAll function, from 400 microseconds to 1 millisecond, and changed the NoPoison function to do this:


Repeat 10 times:

  All Tubes OFF.

  Repeat for each number (0-9):
    Set all tubes to a number, and leave it on that number for 5 milliseconds, and turn all tubes off again.

  When done with all 9 numbers, set all tubes OFF again.


 

Note that 1 millisecond = 1,000 microseconds, and 1 second = 1,000 milliseconds.
So I changed the delay from 400 microseconds to 1 millisecond (little more than double the time).

void SetAll(int NewState){
  // All tubes ON or OFF
  for(int Counter; Counter<6; Counter++) {
    digitalWrite(NixieTubes[Counter], NewState);
  }
  // All Digits ON or OFF
  for(int Counter; Counter<=9; Counter++) {
    digitalWrite(Digits[Counter], NewState);
  }
  
  delay(1);
}  

void NoPoison() {
 for(int Counter=0; Counter<10; Counter++) {
   AllOff();

   // set all tubes to the same Number
   // wait half a second
   // switch all tubes off 
   // repeat for the next Number
   
   for(int Digit=0; Digit<=9; Digit++) {
     for(int Tube=0; Tube<6; Tube++) {
       NumberON(Tube, Digit);
     }
     delay(5); // keep them on for 5 milliseconds
     AllOff();   // reset
   } 
  }
  
  delay(1);
}

 

 


   
ReplyQuote
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

@hans actually my clock works fine and all 6 of nixie tubes show the numbers at same time but the thing is its what my bare eyes (my brain) wants to believe , actually they turn on one by one from right to left with a high frequency and because of POV to human eye it appears steady but with a camera it flickers  and the reason for multiplexing them is because the nixie driver ICs are rare and expensive so instead of having six ICs one for each tube i used one IC for all six of them ,this way my PSU shouldn't be very powerful since they turn off and on sequently , so what do you think were you aware of this before?should we change anything in your prior codes to make it work?


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

What I meant was this: have each Nixie, glow all the numbers at the same time (eg. 0,1,2,...,9 are for that one nixie ALL on at the same time).

I see what you mean though, the driver controls only one nixie at a time, and only one segment in the nixie at a time.
In that case we'd have to modify the NoPoison again, I think ... just a quick thought:

1) The SetAll and AllOn function are not useful in this case, so remove those.

2) When trying to light up all nixies, we can probably use this?

I assume we can seat each Nixie to "0" by calling NumberOn for each tube.
Then turn them all OFF again, and repeat for "1", "2" etc.

Does this work?

void AllOff(){
  // All Digits OFF
  for(int Counter; Counter<=9; Counter++) {
    digitalWrite(Digits[Counter], LOW);
  }

  // All tubes OFF
  for(int Counter; Counter<6; Counter++) {
    digitalWrite(NixieTubes[Counter], LOW);
  }
  
  delay(1);
}  

void NoPoison() {
 for(int Counter=0; Counter<10; Counter++) {
   AllOff();

   // set all tubes to the same Number
   // wait half a second
   // switch all tubes off 
   // repeat for the next Number
   
   for(int Digit=0; Digit<=9; Digit++) {
     for(int Tube=0; Tube<6; Tube++) {
       NumberON(Tube, Digit); 
     }
     delay(5); // keep them on for 5 milliseconds
     AllOff();   // reset
   } 
  }
  
  delay(1);
}

   
ReplyQuote
(@pejman1998)
Active Member
Joined: 4 years ago
Posts: 9
Topic starter  

@hans hi hans im a bit confused about your last 3 recommendations , can you please gather them all in one code that you presume is the closer shot ? unfortunately im not as experienced as you think i am and i have trouble for figuring it out by myself to where to add the codes you give me so if its possible either tell me where to add pieces of code you give me or give a solid text so i can compile without overthinking it to see if it works or not.
thanks


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

No problem!

I've merged all of it in one sketch (I hope I didn't miss anything).
I tried compiling it and it did not give me any error messages, so it all looks good.

Give it a try ...

I've also attached it as a downloadable INO file:

 

#include <Wire.h>
#include "DS3231.h"

RTClib RTC;
DS3231 Clock;

int hour;
int minute;
int second;

// arrays with the pins for the rubes and the digits
int Digits[] = {2,3,4,5,6,7,8,9,10,11};
int NixieTubes[] = {0,1,14,15,16,17};

const int button_up = 12;
const int button_dn = 13;

int button_up_value;
int button_dn_value;

boolean hour_blink, min_blink, sec_blink;
int blink_latch = 0;
int mode_step = 0;
int mode_counter = 0;
int change_counter = 0;

const int time_on = 2;  //time display each number of nixie tube

void setup() {
  for(int Counter=0; Counter<=9; Counter++) {
    pinMode(NixieTubes[Counter], OUTPUT);
  }
  
  for(int Counter=0; Counter<6; Counter++) {
    pinMode(Digits[Counter], OUTPUT);
  }

  pinMode(button_up, INPUT_PULLUP);
  pinMode(button_dn, INPUT_PULLUP);

  Wire.begin();

  hour_blink = false;
  min_blink = false;
  sec_blink = false;
}

void loop() {
    //-------------------get clock value---------------------------
    DateTime now = RTC.now();
    hour = now.hour();
    minute = now.minute();
    second = now.second();

    // --- Trigger NoPoison every half hour
    if( ( (minute==0) || (minute==30) ) && (second==0) ) {
      NoPoison();
    }
      
    //-------------------show clock number ----------------------
    int j; //second number from right
    int k; //first number from right

    //-----------------------------------------------------------------------second number show
    j = second/10;
    k = second%10;

    if(sec_blink==false)
    {
      //-----------show first number of second
      AllOff();
      NumberON(0,k+2);
      delay(time_on);

      //-----------show second number of second
      AllOff();
      NumberON(1,j+2);
      delay(time_on);
    }
    else 
    {
      if(blink_latch < 8){  //blink_latch: time for blinking
        AllOff();
        delay(time_on);
        blink_latch++;
      }
      else 
      {
        //-----------show first number of second/ blink display
        AllOff();
        NumberON(0,k+2);
        delay(time_on);

        //-----------show second number of second/ blink display
        AllOff();
        NumberON(1,j+2);
        delay(time_on);
        if (blink_latch < 16) blink_latch++;
        else blink_latch = 0;
      }
    }

    //-------------------------------------------------------------minute number show
    j = minute/10;
    k = minute%10;

    if(min_blink==false)
    {
      //-----------show first number of minute
      AllOff();
      NumberON(14,k+2);
      delay(time_on);
      //-----------show second number of minute
      AllOff();
      NumberON(15,j+2);
      delay(time_on);
    }
    else
    {
      if(blink_latch < 8){  //blink_latch: time for blinking
        AllOff();
        delay(time_on);
        blink_latch++;
      }
      else
      {
        //-----------show first number of minute/ blink display
        AllOff();
        NumberON(14,k+2);
        delay(time_on);

        //-----------show second number of minute/ blink display
        AllOff();
        NumberON(15,j+2);
        delay(time_on);
        if (blink_latch < 16) blink_latch++;
        else blink_latch = 0;
      }
     }

    //-----------------------------------------------------------------hour number show
    j = hour/10;
    k = hour%10;
    if(hour_blink==false)
    {
      //-----------show first number of hour
      AllOff();
      NumberON(16,k+2);
      delay(time_on);

      //-----------show second number of hour
      AllOff();
      NumberON(17,j+2);
      delay(time_on);
    }
    else
    {
      if(blink_latch < 8) {  //blink_latch: time for blinking
        AllOff();
        delay(time_on);
        blink_latch++;
      }
      else
      {
        //-----------show first number of hour/ blink display
        AllOff();
        NumberON(16,k+2);
        delay(time_on);

        //-----------show second number of hour/ blink display
        AllOff();
        NumberON(17,j+2);
        delay(time_on);
        if (blink_latch < 16) blink_latch++;
        else blink_latch = 0;
      }
    }

  //---------------------------------------mode choosen: push two button same time
  button_up_value = digitalRead(button_up); //normal ON (1)
  button_dn_value = digitalRead(button_dn); //normal ON (1)

  if((button_up_value==0)&(button_dn_value==0)&(mode_step==0)){
    mode_step = 1;
  }

  //---------------------------allow to change second
  if(mode_step==1){
    if (mode_counter < 200){
      mode_counter++; // waiting time for changing value
    }
    else
    {
      mode_counter=0;
      mode_step=2;
      change_counter = 0;
    }
    sec_blink = true; // allow to change second
    min_blink = false;
    hour_blink = false;
  }

  //-------------------------allow to change minute
  if(mode_step==2){
    if (mode_counter < 200){
      mode_counter++; // waiting time for changing value
    }
    else
    {
      mode_counter=0;
      mode_step=3;
      change_counter = 0;
    }

    sec_blink = false;
    min_blink = true; // allow to change minute
    hour_blink = false;
  }

  //-------------------------allow to change hour
  if(mode_step==3){
    if (mode_counter < 200){
      mode_counter++; // waiting time for changing value
    }
    else 
    {
      mode_counter=0;
      mode_step=4;
      change_counter = 0;
    }

    sec_blink = false;
    min_blink = false;
    hour_blink = true;  // allow to change hour
  }

  //--------------------------escape changing time
  if(mode_step==4){
    mode_step=0;  // escape changing time
    sec_blink = false;
    min_blink = false;
    hour_blink = false;
    change_counter = 0;
  }

  //----------------------------------------------------------------------change-second +/-
  if ((button_up_value==0)&(sec_blink==true)){
    second++;
    if (second>59) second = 0;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setSecond(second);
      change_counter=0;
    }
  }

  if ((button_dn_value==0)&(sec_blink==true)){
    second--;
    if (second<0) second = 59;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setSecond(second);
      change_counter=0;
    }
  }

  //----------------------------------------------------------------------change-minute +/-

  if ((button_up_value==0)&(min_blink==true)){
    minute++;
    if (minute>59) minute = 0;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setMinute(minute);
      change_counter=0;
    }
  }

  if ((button_dn_value==0)&(min_blink==true)){
    minute--;
    if (minute<0) minute = 59;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setMinute(minute);
      change_counter=0;
    }
  }

  //----------------------------------------------------------------------change-hour +/-
  if ((button_up_value==0)&(hour_blink==true)){
    hour++;
    if (hour>23) hour = 0;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setHour(hour);
      change_counter=0;
    }
  }

  if ((button_dn_value==0)&(hour_blink==true)){
    hour--;
    if (hour<0) hour = 23;
    change_counter++; //prevent value change too fast
    mode_counter = 0; //hold mode
    if(change_counter>5){
      Clock.setHour(hour);
      change_counter=0;
    }
  }
}

// --- Replacement for the on_number function
void NumberON(int Tube, int Digit){
  digitalWrite(NixieTubes[Tube], HIGH);
  digitalWrite(Digits[Digit], HIGH);
}

void AllOff(){
  // All Digits OFF
  for(int Counter; Counter<=9; Counter++) {
    digitalWrite(Digits[Counter], LOW);
  }

  // All tubes OFF
  for(int Counter; Counter<6; Counter++) {
    digitalWrite(NixieTubes[Counter], LOW);
  }
  
  delay(1);
}  

void NoPoison() {
 for(int Counter=0; Counter<10; Counter++) {
   AllOff();

   // set all tubes to the same Number
   // wait half a second
   // switch all tubes off 
   // repeat for the next Number
   
   for(int Digit=0; Digit<=9; Digit++) {
     for(int Tube=0; Tube<6; Tube++) {
       NumberON(Tube, Digit); 
     }
     delay(5); // keep them on for 5 milliseconds
     AllOff();   // reset
   } 
  }
  
  delay(1);
}

   
pejman1998 reacted
ReplyQuote
Page 1 / 2
Share: