Driving a 14V common anode 7 segment Display

Hi
I have 3 common anode 7 segment leds (FJS50101BH) and using ULN2003 to drive them with Arduino. I want to make Up counter with a sensor connected to A0 pin
I'll attach my schematic diagram and the code I found it here actually.
I have problem simulating the circuit all 7 segments are flickering quickly, Will they be like that when I start wiring the circuit in real?
I have 5V supply connected to Arduino, and the common of the 7 segments are connected directly to the Arduino digital pins and 220 ohm resistors connected between ULN2003 outputs and the 7 segment pins.

Here's the code:

#define aPin 3  //        
#define bPin 5  //             
#define cPin 6  //            
#define dPin 9  //         
#define ePin 10  //          
#define fPin 11  //       
#define gPin 12  //          

#define c1Pin 2  // Common pin for digit 1
#define c2Pin 4 // Common pin for digit 2
#define c3Pin 7 // Common pin for digit 3

#define bt_up     A0
#define bt_reset  A1

long Counter=0;

int flag1=0, flag2=0, timer=0;

int Common = 1; //<Common=1; for Common anode> <Common=0; for Common cathode>
int On, Off, Off_C; 
int DTime = 4; // Display timer

void setup(){ // put your setup code here, to run once  
  
 pinMode(bt_up,    INPUT_PULLUP);
 pinMode(bt_reset, INPUT_PULLUP);

 pinMode(aPin, OUTPUT);
 pinMode(bPin, OUTPUT);
 pinMode(cPin, OUTPUT);
 pinMode(dPin, OUTPUT);
 pinMode(ePin, OUTPUT); 
 pinMode(fPin, OUTPUT);
 pinMode(gPin, OUTPUT);

 pinMode(c1Pin, OUTPUT);
 pinMode(c2Pin, OUTPUT);
 pinMode(c3Pin, OUTPUT);
 
 if(Common==1){On=0, Off=1, Off_C=0;} //for Common anode
          else{On=1, Off=0, Off_C=1;} //for Common cathode
}

void loop(){  

if(digitalRead (bt_up) == 0){ 
if(flag1==0){ flag1=1;
Counter = Counter+1;
if(Counter>999){Counter=0;} 
 }
}else{flag1=0;}

if(digitalRead (bt_reset) == 0){ 
Counter=0; 
}

showNumber(Counter%10);
digitalWrite(c1Pin, Common);
delay(DTime);
digitalWrite(c1Pin, Off_C);

showNumber((Counter/10)%10);
digitalWrite(c2Pin, Common);
delay(DTime);
digitalWrite(c2Pin, Off_C);

showNumber((Counter/100)%10);
digitalWrite(c3Pin, Common);
delay(DTime);
digitalWrite(c3Pin, Off_C);

}

void showNumber(int x){
  
   switch(x){
     case 1: one();   break;
     case 2: two();   break;
     case 3: three(); break;
     case 4: four();  break;
     case 5: five();  break;
     case 6: six();   break;
     case 7: seven(); break;
     case 8: eight(); break;
     case 9: nine();  break;
     default: zero(); break;
   }
}

void one(){
  digitalWrite( aPin, On); //      
  digitalWrite( bPin, Off);  //     
  digitalWrite( cPin, Off);  //      
  digitalWrite( dPin, On); //        
  digitalWrite( ePin, On); //       
  digitalWrite( fPin, On);
  digitalWrite( gPin, On);
}

void two(){
  digitalWrite( aPin, Off);  //    
  digitalWrite( bPin, Off);  //        
  digitalWrite( cPin, On); //    
  digitalWrite( dPin, Off); //  
  digitalWrite( ePin, Off);  //  
  digitalWrite( fPin, On);
  digitalWrite( gPin, Off);
}

void three(){
  digitalWrite( aPin, Off);  //   
  digitalWrite( bPin, Off);  //       
  digitalWrite( cPin, Off);  //    
  digitalWrite( dPin, Off);  //       
  digitalWrite( ePin, On); //      
  digitalWrite( fPin, On); 
  digitalWrite( gPin, Off);
}

void four(){
  digitalWrite( aPin, On); //  
  digitalWrite( bPin, Off);  //  
  digitalWrite( cPin, Off);  //   
  digitalWrite( dPin, On); //         
  digitalWrite( ePin, On); //         
  digitalWrite( fPin, Off);
  digitalWrite( gPin, Off);
}

void five(){
  digitalWrite( aPin, Off);  //  
  digitalWrite( bPin, On); //  
  digitalWrite( cPin, Off);  // 
  digitalWrite( dPin, Off);  //     
  digitalWrite( ePin, On); //    
  digitalWrite( fPin, Off);   
  digitalWrite( gPin, Off);
}

void six(){
  digitalWrite( aPin, Off);  //  
  digitalWrite( bPin, On); //  
  digitalWrite( cPin, Off);  // 
  digitalWrite( dPin, Off);  // 
  digitalWrite( ePin, Off);  // 
  digitalWrite( fPin, Off);
  digitalWrite( gPin, Off);
}

void seven(){
  digitalWrite( aPin, Off);  //  
  digitalWrite( bPin, Off);  //   
  digitalWrite( cPin, Off);  //     
  digitalWrite( dPin, On); //        
  digitalWrite( ePin, On); //       
  digitalWrite( fPin, On);
  digitalWrite( gPin, On);
}

void eight(){
  digitalWrite( aPin, Off); //  
  digitalWrite( bPin, Off); // 
  digitalWrite( cPin, Off); // 
  digitalWrite( dPin, Off); // 
  digitalWrite( ePin, Off); // 
  digitalWrite( fPin, Off); 
  digitalWrite( gPin, Off); 
}

void nine(){
  digitalWrite( aPin, Off);  //  
  digitalWrite( bPin, Off);  // 
  digitalWrite( cPin, Off);  //
  digitalWrite( dPin, Off);  //     
  digitalWrite( ePin, On); //    
  digitalWrite( fPin, Off); 
  digitalWrite( gPin, Off);
}

void zero(){                 
  digitalWrite( aPin, Off); //  
  digitalWrite( bPin, Off); //
  digitalWrite( cPin, Off); // 
  digitalWrite( dPin, Off); // 
  digitalWrite( ePin, Off); //
  digitalWrite( fPin, Off); 
  digitalWrite( gPin, On);   

Your circuit diagram is not readable and where is the 14V connected to the common anodes? No Arduino pin can drive a common 7segment pin.

@DrDiettrich
I forget to mention this circuit is for a 5V 7 segment so the common is connected directly to the Arduino pins, I want to use ULN2003 to drive a 3 (14V) 7 segment , it draws less than 100mA.
here's the link I took the code from

https://create.arduino.cc/projecthub/embeddedlab786/how-to-make-4-digit-counter-using-7segment-display-519d1a

so you are using ULN drivers for the cathodes, but source the anodes with Arduino pins.
Do you really believe that this is a good idea?

If you sink all 8 segments + the decimal point, how much current will be sourced from the poor Arduino pin driving the anode?

Yes I figured it out, I'm not familiar with ULN2003 yet.
So, What to use with ULN2003 to make it right?

Well you could wire up the ground of the ULN2003 chips to the ground of the Arduino, that at least would make them work.

However a ULN2003 chip only pulls down, that is connects the outputs to ground. It will not source a voltage, that is it will not produce a voltage. So to make it right you have to remove the ULN2003 pins from anything that is expecting a positave voltage like all the anodes of your display.

Despite what you think about that idea it will burn out your Arduino because it will draw too much current from the pins.

You also have no current limiting resistors in the cathode pins, a 220R in each should do it.
As the the anode pins you need a top switch circuit in them to be able to supply the power.
This is a typical top switch for 5V.

Note the transistor is a PNP one and the collector is connected to each of your anode. You need one of these circuits for each anode.

A common cathode display.

I probably would drop the ULN2003 and use something with a current sink for LEDs.

24-Channel, Constant-Current LED Driver With Global Brightness Control And LED Open-Short Detection seems not too far off...

I would think it is very far off, as it needs constant clocking. Consider the MAX7219, that is made for the job and once set up will do all the multiplexing for you. So no constant CPU processing cycles consumed.

What am I missing here?

I opened the datasheet for Max7219, Its a driver for common cathode , the ones I have are common anodes.

Im using 74HC595 with ULN2803, But Im a little bit having problem with the code, Can u give any idea how to make it right?

I want to count up from 0 to 999 with a push button

It can drive an 8x8 LED matrix. Updating the "wrong" 7-seg display will be a pain but fixable in software... I'm not sure about the 14V requirement of your display.

Do you have an updated schematic? (Assuming you are using 3 shift register)

You need to

  • Calculate the value of each digit
  • Use a lokuptable to convert the value to "segment-data"
  • Shift the segment data out into the shift register

//  AA
// F  B
// F  B
//  GG
// E  C
// E  C
//  DD
//
//  AFEDBGCx
static const uint8_t lookup[10] = {
  0b11111010, // 0
  0b00001010, // 1
  0b10111100, // 2
  0b10011110, // 3
  0b01001110, // 4
  0b11010110, // 5
  0b11110110, // 6
  0b10001010, // 7
  0b11111110, // 8
  0b11011110, // 9
};


void doit(){
int value = 123;

int a = value % 10;
int b = (value / 10) % 10;
int c = (value / 100) % 10;

uint8_t as = lookup[a];
uint8_t bs = lookup[b];
uint8_t cs = lookup[c];

shiftOut(dataPin, clockPin, bitOrder, as);
shiftOut(dataPin, clockPin, bitOrder, bs);
shiftOut(dataPin, clockPin, bitOrder, cs);

// and here pulse the latchPin
 
}

It can be wired to accept common Anode displays. There are plenty of people who have done this in the past. Just search the forum for it.

The only drawback is you can't use the internal binary to seven segment conversion you have to do in in software. This is a small price to pay, which you will have to do anyway once you get your current arrangement working.

Here's the final wiring of the circuit.

Is power and ground connected to the shift register and the ULNs?

They are hidden in proteus but I think they are internally connected

595

Try the following setup using SevSeg.h Library.

1. Build the following multiplexed display unit as per Fig-1. In a multiplexed display unit, the identical segments pins are shorted together and the CA-pin are kept isolated. Adjust R1 = R2 = R3 for acceptable brightness of the CA-type display units. Note that the use of inverting type buffer ULN2003 has made the CA-type display unit to have been seen by UNO as CC-type display unit.


Figure-1:

2. Upload the following Sketch. do not forget to include the SevSeg.h Library in your IDE.

#include <SevSeg.h>
SevSeg sevSeg; 

void setup()
{
  Serial.begin(9600);
  byte ccDPins[] = {9, 10, 11}; //9 = cc0-pin/CA0-pin, 10 = cc1/CA1-pin, ...
  byte segDPins[] = {2, 3, 4, 5, 6, 7, 8}; //2 = seg-a, 3 = seg-b ...
  sevSeg.begin(COMMON_CATHODE, 3, ccDPins, segDPins, false, false, false, false);
  analogReference(INTERNAL); //1.1V Vref for ADC
}

void loop()
{
  unsigned long prMillis = millis();
  while (millis() - prMillis < 2000) //temperature sampling interval is 2-sec
  {
    sevSeg.refreshDisplay();  //keep refreshing display until 2-sec has elapsed
  }
  float rawTemp = 100 * ( 1.1 / 1023) * analogRead(A4);// 31.25xxxx...
  rawTemp = rawTemp*100.00; //myTemp = 3125.xxxx.......
  unsigned int myTemp = (unsigned int)rawTemp; //myTemp = 3125(.(xxxx...) takes onlyinteger part
  sevSeg.setNumber(myTemp, 1, LOW); //arg2=digit after point, arg3=base-10
}

3. To know about SevSeg.h Library, you may read the post of this link.

@PaulRB
Hi Paul,
I just saw your replies on that forum and I wish u could help me.

I have the same circuit counting 0 to 999 but no flex sensor in the Input, I have a limit switch sensor ( just like a push button pressed or not pressed )
I have a 6 14V common Anode 7-segments each 2 display the same number
I'm using 74HC595 with ULN2803 Driver and each ULN2803 drive will be connected with separate resistors to 2 7 segments

Here's my schematic

I need ur help with the code to make its sequence right as I'm confused trying to make it work.
Thank you.

Your diagram shows only 3, not 6. Are the other 3 wired with a further 3 74hc595+uln2803? Or in some other way?

Please explain what you mean by this, it is confusing.

Your circuit counts up to 999 on 3 digits and the other 3 digits show the same count?

What is "right"? On the topic you linked, the code was said to be working.

You do not need to connect the COM pins of the uln2803, it is not important with LEDs.

You could replace each 74hc595+uln2803 with one chip tpic6b595 to simplify your circuit. The resistors would still be required.

Whether you use 74hc595 or tpic6b595, you must have a 0.1uF ceramic bypass cap connected between the Vcc and GND pins of each chip.

Yes they show the same count, here they are
7 seg
the other two are like this

const int buttonThreshold = 500;
int lastButton = 1023;

I dont understand what these values are, and will it work in my case using a push button not a flex sensor?
I didnt connect it as hardware yet, I'm trying to make the simulation work 1st
Or the simulation in proteus maybe have some bugs thats why not working on it?