TPIC6B595 shift register, 5-segment common anode LED, PWM

Hi all, I’ve been working on my project that was originally to drive five 7-segment 4" 10V LEDs with a Max 7219/7221 chip. I finally gave up on that even after breadboarding the Maxim Application Note 1196 solution for draining high voltages while retaining the multiplexing of the 7221, using 1 NPN and 1 MOSFET per segment and 1 NPN per digit. I scrapped these chips (burned one of them up with a “solution” I read on the web) and the common cathode 4" LEDs I originally bought and have got the first of five smaller 7-segment LEDs up and running with the TI-595.

(If anyone wants 10 yellow CC 4" LEDs, let me know :slight_smile: )

I’m posting this question/solution because (1) getting simple code to make all this work took a lot of research, so I’m sure there are people out there looking for a copy and paste solution, and (2) I’m confident that my coding skills are sub-par so perhaps someone can take a look at this and tell me how to do it “better”. Because RAM isn’t an issue with my particular project, I don’t know what “better” really means, but I’m always eager to learn from someone who knows more than me.

This code runs a single 7-segment common anode 5V LED using an Arduino Uno R3 and TI-595 and a few wires. The “schematic” is: 595 pin 2 = 5V, pin 3 = Arduino 11, pin 4-7 is Seg a-d, pin 8 is SRCLR, pin 9 = Arduino 9, Pin 10 & 11 = ground, pin 12 = RCK, pin 13 = SRCK, pin 14-17 = Seg e-DP, pin 18 = SER OUT (not connected…yet), pin 19 = Ground. Like I said, the circuit functions perfectly, so this is information purposes, not for diagnostics.

BTW, “perfect” means that using PWM, not much happens until the duty cycle drops to perhaps 10%. Then the display starts to dim in a meaningful way. In other words, expecting 50% brightness using “analogWrite(pwmPin, 127);” won’t do the trick. To my eye (I didn’t measure it, but I suppose I could) 50% is more like 200, not 127.

Here’s the code. I’m a mechanical engineer, goddammit, not a computer scientist. So I know there’s room for improvement. Flame suit “on”.

#include <SPI.h>

int latchPin = 12;   //TPIC 6B595 pin 12 RCK
int dataPin = 11;   //TPIC 6B595 pin 3 SER IN
int clockPin = 10;  //TPIC 6B595 pin 13 SRCK
int pwmPin = 9;    //TPIC 6B595 pin 9 G bar; holding G bar HIGH turns drain outputs OFF

int getBin();          // this is a subroutine for turning Arabic 0-9 into binary; see below

int d = 0;             //scratch variable for "d0", "d1", etc. (I have 5 digits to display)
int b = 0;             //scratch variable for binary value equivalent to d
void setup() {

  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(pwmPin, OUTPUT);

Serial.begin(9600);                 // so I can see whether the sketch is counting properly

void loop() {

Serial.println(d);                    // ditto

// take the latchPin low so 
// the LEDs don't change while you're sending in bits:

digitalWrite(latchPin, LOW);

// shift out the bits:

getBin (d);                                 // call subroutine

Serial.println(b);                         // print subroutine output

shiftOut(dataPin, clockPin, MSBFIRST, b);

//take the latch pin high so the LEDs will light up:

digitalWrite(latchPin, HIGH);
// pause before next value:


d ++;

analogWrite(pwmPin, 235);

if (d == 10){
  d = 0;

int getBin(int d) {                                                         // begin getBin subroutine
  const int x[ ] = {63, 262, 347, 335, 358, 365, 381, 263, 383, 359};
  b = x[d];
  return b;  

Thanks in advance for your wisdom.