Dealing with 10 bits for a 74HC595 shift register (for driving Nixie tubes)

Hello.

This might be a long post. I already have some experience using 74HC595 SIPO shift register with stuff like 7 segment displays which is nice and easy since you only need to deal with 8 bits, which is the same # of outputs on the IC. I've also used them to drive Nixie tubes with the k155id1 nixie driver, which required 4 bits input and decodes a one of ten (0-9) decimal value on the Nixie.

So, I wanted to try driving nixies with only shift registers, instead using MPSA42 transistors to deal with the high voltage stuff. I would connect it like so:

0000000001 -> digit 0
0000000010 -> digit 1... etc (one of ten fashion)

Since the number of bits is greater than the # of outputs on the IC, I decided that I would divide it by 8's, sorta. Like this:

00000000 - 01000000 -- 0010XXXX (we don't care about the last 4 remainder bits for now)

so the first 10 bits are connected to the first tube, the next 10 are connected to the next, etc.

if we look every 10 bits (ignoring those 4 remainders) we get:
0000000001 --> 0000000010 which is the correct sequence of digits to display.

I realized that each register would kinda follow this pattern:

first register is just the first 8 bits of the first digit (from left to right), so I used a bit shift for this.

second register is the last 2 bits of the first digit followed by the first 6 digits of the second digit. (achieved this with a bit shift along with a bitwise OR)

the third is would be the last 4 bits of the second digit followed by the first 4 of the the next digit. (I didn't specify the third digit yet, so its just "0bXXXXXXXXXX" for now.)

I then continued this logic for the other registers, but I'm keeping it to 3 in this for brevity.

As for the code, it works completely as intended (unless there's some unique test case im missing but I doubt that) , but I'm just wondering if I overlooked a simpler way to do this:

const byte data = 5;
const byte latch = 4;
const byte clk = 3;
byte reg1;
byte reg2;
byte reg3;
byte reg4;
byte reg5;
byte reg6;
byte reg7;
byte reg8;
byte newbyte;
//int arr[] = {0b0000000001, 0b0000000010, 0b0000000100, 0b0000001000, 0b0000010000, 0b0000100000, 0b0001000000, 0b0010000000, 0b0100000000, 0b1000000000};
int arr[] = {1,2,4,8,16,32,64,128,256,512}; //displays: "0" , "1" , "2", "3" ... etc.
int h0 = arr[1]; // display #1, displaying a "1"
int h1 = arr[9]; // display #2, displaying a "9"
int m0 = arr[3]; // display #3, you get the point.
int m1 = arr[4];
int s0 = arr[5];
int s1 = arr[6];
byte n;
byte f;
void setup() {
  // put your setup code here, to run once:
  pinMode(data, OUTPUT);
  pinMode(latch, OUTPUT);
  pinMode(clk, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  reg1 = (h0 >> 2); //first 8 bits of digit 1
  reg2 = ((h0 << 6) | (h1 >> 4)); // last 2 bits of digit 1 followed by first 6 bits of digit 2
  reg3 = ((h1 << 4) | (m0 >> 6)); // last 4 bits of digit 2 followed by first 4 of digit 3
  reg4 = ((m0 << 2) | (m1 >> 8)); // and so on
  reg5 = (m1);
  reg6 = (s0 >> 2);
  reg7 = ((s0 << 6) | (s1 >> 4));
  reg8 = (s1 << 4);
  Serial.println("------- ");
  bitset(reg1);
  bitset(reg2);
  bitset(reg3);
  bitset(reg4);
  bitset(reg5);
  bitset(reg6);
  bitset(reg7);
  bitset(reg8);
  Serial.println("------- ");
  delay(1000);
}

byte bitset(byte f) {
  //example: 0b1000000000 ---> 512, however, we want the first 8 bits ---> 0b00000000 ---> 0. i'll just read up til the 8th one.
  for (byte i = 0; i < 8; i++) {
    n = (bitRead(f, i));
    bitWrite(newbyte, i, n);
  }
  Serial.println(newbyte); //replace with shiftOut(data,clk,LSBFIRST,newbyte); (im too lazy to set up the breadboard atm)
}

And here's a simplified version of the schematic:

So yeah, my method works and all, but I'm just wondering if I made it more complicated than it has to be?

Thanks.

I would say not. If you want to use shift registers this is how to do it.
I am assuming that you have the shift register clocks common, and you have but a ceramic decoupling capacitor (0.1uF) across power and ground of each shift register.

1 Like

Ah I figured. Thanks a lot for your input. yes, I do have the clocks common, as well as the decoupling caps.

1 Like

You could make it a little simpler to code by using two full shift registers (16 output pins) for each tube. Only you can decide if the savings in hardware (5 registers for 4 tubes instead of 8 registers for 4 tubes) is worth the additional complexity.

Another option is to put the 8 and 9 bits of each tube into a single 'extra' register:

76543210 76543210 76543210 76543210 98989898

I think that will be easier to code and involve fewer shifts.

  byte register[5];  // The data for the 5 shift registers
  register[4] = 0; // Clear the 8/9 bits
  for (d=0; d<4; d++)
  {
    if (digit[d] < 8)
      register[d] = 1 << digit[d];  // Values 0 through 7
    else
    {
      register[d] = 0;
      // For values of 8 or 9 we set bits in register[4]
      byte bit = 1 << (digit[d] - 8);  // 8 = 0b01, 9 = 0b10
      register[4] |= (bit << ((3-d)*2));
    }
  }
1 Like

I see. That's a good solution. I like the idea of having an extra register to hold the 2 most significant bits.

(5 registers for 4 tubes instead of 8 registers for 4 tubes)

Unless I misunderstood you, my code has 8 registers for 6 tubes though. Regardless, I get your point.

Thanks a lot for your help!

Did you think of the voltage on the nixie segments when 'off'.
The 74HC595 can't have more than VCC+0.5volt on it's outputs.
Maybe try TPIC6B595 chip, which have a 50volt rating.
Leo..

well that's why the mpsa42's are there

I suppose that you could make the code simpler if you use you own version of shiftOut() which pushes 10 bits out at a time to the shift register chain instead of 8. Then You'd do something like:
shiftOutNew( secondsLow) ;
shiftOutNew( secondsHigh) ;
shiftOutNew( minutesLow) ;
Etc.
At the end you'd have have to push through 4 bits to make up the full 64 bits.
You could use the remaining 4 bits to control the digit separator neons.

There are other option like pairing the tubes and have each pair driven by 3 shift registers. That would make the design more modular at the cost of an additional shift register.

You can use TPIC6B595 shift registers, as already suggested, because these have 50 volt clamp diodes allowing you to drive (sink) the tubes directly (say 170volt on, 120volt off). However, if you want to display a blank digit (say for scrolling) then you need to switch the anode off to achieve that. I have made such a Nixie clock using these chips.

I've seen other options say using 16 high voltage opto couplers for a 6 digit clock also a design using a single k155id1 chip. However, these designs involve multiplexing which reduces the effective brightness.

By using the fact that the high hours digit displays only a 0, 1, or 2, you could also reduce the hardware. However, it prevents that tube being fully incorporated in an anti cathode poisoning cycle.

1 Like

I suppose that you could make the code simpler if you use you own version of shiftOut() which pushes 10 bits out at a time to the shift register chain instead of 8.

ah, this didn't occur to me. I think I'll implement this. thanks!

By using the fact that the high hours digit displays only a 0, 1, or 2, you could also reduce the hardware. However, it prevents that tube being fully incorporated in an anti cathode poisoning cycle.

I considered this at first, but I wanted to have it display stuff other than the time, not to mention the cathode poisoning issue.

I suppose I'll implement my own shiftout and use the TPIC. I've also seen SPI use for this type of shift register purposes iirc. I'll check it out some more I guess. Thanks again.

SPI is just doing in hardware what shiftOut() is doing by bit banging.
For your purpose, speed in not an issue. The maximum refresh rate would be half a second if you are flashing digit separators or one second if not. Even if you use a multiplexing solution the refresh rate would be a few ms, nothing like the 10MHz or so that SPI can achieve.

There are several TPIC6B595 nixie projects floating on the net.
Try EEVblog#948 and it's following chapters on Youtube.
Leo..

... and that give me an opportunity to present my version of a 6 digit TPIC6B595 Nixie clock. I used a modular approach so the hours, minutes and seconds are handled in an identical manner to each other. If I was doing it again, I'd also use the spare shift register outputs to (somehow) control the anodes as well. That would allow blank digit suppression which you can't otherwise do with the TPIC6B595 approach. I'd also improve the decoupling between the two boost converters.
The schematic is here, spread over two projects and the end result was two boards which sandwiched together over an 8 way connection.

DisplayBoard_V0_01.pdf (222.0 KB)
ControlBoard_V0_01.pdf (118.8 KB)

There is a picture of it here:
https://europe1.discourse-cdn.com/arduino/original/4X/c/0/9/c09005f4e72f9d2858e94763070a8994df4d64df.jpeg (middle)

Well in the commercial world reduction in hardware is always preferable that an increase in software complexity. Basically on the grounds that you pay for software only once and you pay for hardware on every unit you make.

I understand that this is only a hobby but using the minimum number of parts makes you design more reliable, that is a lower mean time between failures. Also a lower component makes the best of the planet's resources.

Note that this chip only pulls down and not up.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.