How to turn segments on multiplexed display circuit

I was given a few 6-digit displays that receive data from RS232 to be displayed, although it only displays numbers and filters out any other characters; therefore, I wanted to create a circuit using two 74HC595 to drive the digits and the segments and show anything I want.

Before I start with that, I wanted to understand how the circuit works and possibly make a basic code using Arduino to turn on even one segment at a time to ensure I can communicate with the circuit.

The circuit in question uses an ancient AT89 mounted on a socket. Therefore, my idea is to take that off and tap into the circuit to connect the Arduino.

I have done some research, and from what I understand, the digits 7-segment displays are common anodes that use a PNP transistor to drive the digits (please correct me if I am wrong).

The circuit uses Darlington ICs, which I am unfamiliar with, so I am here asking for help.

My question at the moment is:

If I connect one digital pin of the Arduino to, say, Pin 12 (P1.0) and another to Pin 11 (P.3.7) where the AT89 was, and I pull both low, will one segment of one digit turn on? I am unsure if this is the correct approach; therefore, I am open to suggestions.

The final idea is to realise a proper circuit that plugs into where the AT89 is, but for now, I want to focus on getting some segments to light up.

Here is the schematic of the reverse engineering I did; I know it is not the prettiest, but I wanted to keep things as close as possible to the original board layout to make it easy to track things. I have triple-checked it, but I do not exclude that there are some mistakes.

EDIT:

This above circuit is not a circuit that I have designed or that I am planning to make, this circuit is an existing circuit part of a remote display that utilises RS232 protocol to receive data and display it.

First off, you do know you can't put RS232 signals directly into an AT89, or any other Arduino, or I would venture to say any other embedded processor.

An RS232 signals with +/- 12V and is inverted with regard to the normal TTL input processors take.

Also I can't see that circuit being correct as you have no way of turning off those transistors. To turn off a PNP transistor you have to take the base to within 0.7V of the voltage on the emitter. And there is no way your circuit can do that.

Yes there is also an MAX232 section of the circuit but as I metioned above i will scrap the AT89 chip and I won't need the serial anymore, I just want to drive the segments directly. I will double check the circuit again, what part do you reckon is incorrect?

How did you come up with the 25V supply needed for the dispalys?

I have edited the post to clarify this better, this is not a circuit that I have designed or that I am planning to make, theses are remote displays that already exist I have only reverse engineerd the circuit. All I know is that at the at the emitter are supplied 25V and the digits are 180mm so perhaps they require a substantial amount of voltage to keep the luminosity consistent?

I also do not have any part code nor a datasheet available to double check the 7 segment specs. :weary:

Before you connect your arduino, you bettor check your reverse engineering.
Your schematic shows pin 1 of RP2 connect to 5V. If that were true, the transistors would never turn off. Are you sure it isn't 25V?

Thanks for pointing this out I have checked the circuit again and RP1 common is connected to pin 20 of the AT89 so 5V (it's missing the label as well) while RP2 common I have it connected to 5V but its actually connected to 25V.

I have also noticed that C12 is connected to R8 but it's in fact decoupling the 25V.

I will go through everything again and update the schematic.

Thank you again for pointing out some mistakes.

If your circuit diagram is accurate, the displays are common cathode.

The 8x pnp transistors drive the segment anodes. The pnp bases are driven by a uln2803.

The cathodes are driven by uln2003. The MCU drives both the ULN chips with 8+6 output pins.

Why are you concerned? You are not planning to replace these, I think? Arduino outputs can drive these chips just the same as the at89 did before.

No, I don't think so. Maybe if you set both outputs to HIGH.

But there is a danger. The display is designed to be multiplexed. If you do not multiplex with the Arduino, the higher average current may damage the led segments.

Let's make sure you don't connect 25V to your arduino.

Yes absolutely, I had planned only to share a common ground and power the Arduino externally while testing.

To test, I'd just work up a scan routine for the right number of DO for driving the digits, similar for the segments, and hook the outputs to the AT outputs. Don't forget to connect the ground, as well, and do NOT use your Arduino's 5V to power any of this.(edit - ignore that).
However, first step would be to remove the AT, power the board, and measure signal voltages on all pins you intend to connect to. There's always that chance that 25V appears because of a desoldering short circuit, for example, and you don't want to buy another Arduino just because.
And yes, a high to the segment drive turns them on, as does a high to the digit driver, so you'll want to code such that a walking one runs across both output sets.

Ok, thanks for explaining this.

I was planning to use something like this for testing:

const int digitPins[] = {2, 3, 4, 5, 6, 7};       // Pins for controlling digits
const int segmentPins[] = {8, 9, 10, 11, 12, 13, A0, A1};  // Pins for controlling segments including dp

const byte digitSegments[][8] = {
  {1, 1, 1, 1, 1, 1, 0, 0}, // Digit 0
  {0, 1, 1, 0, 0, 0, 0, 0}, // Digit 1
  {1, 1, 0, 1, 1, 0, 1, 0}, // Digit 2
  {1, 1, 1, 1, 0, 0, 1, 0}, // Digit 3
  {0, 1, 1, 0, 0, 1, 1, 0}, // Digit 4
  {1, 0, 1, 1, 0, 1, 1, 0}, // Digit 5
  {1, 0, 1, 1, 1, 1, 1, 0}, // Digit 6
  {1, 1, 1, 0, 0, 0, 0, 0}, // Digit 7
  {1, 1, 1, 1, 1, 1, 1, 0}, // Digit 8
  {1, 1, 1, 1, 0, 1, 1, 0}  // Digit 9
};

void setup() {
  for (int i = 0; i < 6; i++) {
    pinMode(digitPins[i], OUTPUT);
  }

  for (int i = 0; i < 8; i++) {
    pinMode(segmentPins[i], OUTPUT);
  }
}

void loop() {
  for (int digit = 0; digit < 6; digit++) {
    // Turn off all digits
    for (int i = 0; i < 6; i++) {
      digitalWrite(digitPins[i], HIGH);
    }

    // Turn on the selected digit
    digitalWrite(digitPins[digit], LOW);

    // Display a number on the segment
    displayNumber(digit);

    delay(5);
  }
}

void displayNumber(int digit) {
  for (int segment = 0; segment < 8; segment++) {
    digitalWrite(segmentPins[segment], digitSegments[digit][segment]);
  }
}

Could this work on this setup, give that the schematic I have provided is correct?

Thanks for the input, I will double check tomorrow and run some tests.

Also the AT89 is mounted on a socket so no desoldering required.

Your could install the SevSeg Arduino library and use an example sketch from the library. Always best to start with known working code before trying new code.

yep, displays are CC

Thanks for all the inputs from everyone so far, I have plugged in the 6 digits, 7 segments and DP pins, by using SevSeg and I was able to get a correct output the only issue is that all the DP are always on and I have a feeling that there is something wrong with my connection/pin declaration. I haven't had time to go through the circuit again, I will take some time in the next few days and I will also show the code I am using at the moment.

Here a quick snapshot of the display:

This is a unit that had some faulty digits for testing so one digit is missing.

Cool!

I have by manged to solve the DP issue by re-checking all the connections. The code works very well, with no flickering, high brightness and no ghosting.

The code I have used is as follows:

#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment controller object

void setup() {
  byte numDigits = 5;
  byte digitPins[] = {10,11,12,13,A0};
  byte segmentPins[] = {9, 8, 7, 6, 5, 4, 3, 2};
  bool resistorsOnSegments = true; // 'false' means resistors are on digit pins
  byte hardwareConfig = N_TRANSISTORS; // See README.md for options
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
  bool disableDecPoint = false; // Use 'true' if your decimal point doesn't exist or isn't connected
  
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
  updateWithDelays, leadingZeros
  , disableDecPoint);
  sevseg.setBrightness(0);
  Serial.begin(9600);
}

void loop() {
  sevseg.setChars("Hello");
  sevseg.refreshDisplay();
}

I am now trying to attempt to drive the display using two 74HC595 and the SevSegShift library, a fork of SevSeg that adds support for shift registers, although I did not have great luck so far.

I have also tried the hybrid configuration as listed on library's git but with the same results.

I am able to light up each digit although I am not able to control each individual segment, all I am getting are the 8 segments always light up, I have tried to add a delay in the loop to see if there was some segments sequence but all I'm getting is all the segments on or off altogether.

I have tried all the HardwareConfig settings:

COMMON_CATHODE
COMMON_ANODE
N_TRANSISTORS
P_TRANSISTORS
NP_COMMMON_CATHODE
NP_COMMMON_ANODE

Although I do not see any difference beside all the segments being full brightness or slightly dimmed.

My question is could it be something to do with the darlington arrays interfering with the logic?

This is the code I have at the moment (I am using the hybrid configuration):

#include "SevSegShift.h"

#define SHIFT_PIN_DS   13 /* Data input PIN */
#define SHIFT_PIN_STCP 12 /* Shift Register Storage PIN */
#define SHIFT_PIN_SHCP 11 /* Shift Register Shift PIN */

//Instantiate a seven segment controller object (with Shift Register functionality)
SevSegShift sevsegshift(
                  SHIFT_PIN_DS, 
                  SHIFT_PIN_SHCP, 
                  SHIFT_PIN_STCP, 
                  1, /* number of shift registers there is only 1 Shiftregister 
                        used for all Segments (digits are on Controller)
                        default value = 2 (see SevSegShift example)
                        */
                  true /* Digits are connected to Arduino directly 
                          default value = false (see SevSegShift example)
                        */
                );

void setup() {
  byte numDigits = 5;
  byte digitPins[] = {2,3,4,5,6};
  byte segmentPins[] = {0, 1, 2, 3, 4, 5, 6, 7};
  bool resistorsOnSegments = true; // 'false' means resistors are on digit pins
  byte hardwareConfig = N_TRANSISTORS; // See README.md for options
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
  bool disableDecPoint = false; // Use 'true' if your decimal point doesn't exist or isn't connected

  sevsegshift.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
  updateWithDelays, leadingZeros, disableDecPoint);
  sevsegshift.setBrightness(0);
}

void loop() {
  sevsegshift.setChars("Hello");
  sevsegshift.refreshDisplay();
}