Multiplexing LED - Only displays 8's? Won't turn on?

Don't have a picture of my actual breadboard at the moment but I recreated this tinkercad I made onto an actual breadboard and it won't even turn on. In the tinkercad, it also doesn't work because when I turn it on it won't light up at all or sometimes it will light up but only show the number 8? Information: The two seven segment displays are common anode and the goal of this project is for it to count up from 0 and display it on the 7 segment displays.

Any advice for how to make this work on the tinkercad (I can just apply the same logic to making it on a breadboard if I fix the tinkercad)!

Heres my code for reference:

// blinking lights at different rates using the timer module

// -------------------------------------------------------------------------------------------
// hook into timer0 that's already setup for the millis function to give 1ms timer interrupts
// on real hardware you could use the Timer1 library but it's not avaibale in Tinkercad.

class TimerZero
{
  public:
  
  void initialize()
  {
    // compare interrupt somewhere in the middle of the count
    OCR0A = 0xAF;
  }
  
  //  Interrupt Function
  void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
    isrCallback = isr;
    TIMSK0 |= _BV(OCIE0A);
  }

  static void (*isrCallback)();
  
};

TimerZero Timer0;              // preinstatiate
void (*TimerZero::isrCallback)() = NULL;

ISR(TIMER0_COMPA_vect)
{
  Timer0.isrCallback();
}
// -------------------------------------------------------------------------------------------



// pin definitions
#define SEGMENT_A_PIN 9
#define SEGMENT_B_PIN 10
#define SEGMENT_C_PIN 4
#define SEGMENT_D_PIN 5
#define SEGMENT_E_PIN 6
#define SEGMENT_F_PIN 8
#define SEGMENT_G_PIN 7

#define DIGIT_1_PIN 2
#define DIGIT_2_PIN 3


#define NUM_SEGMENTS 7
#define NUM_DIGITS 2
#define NUM_SYMBOLS 10

// counter definitions, in milliseconds
const uint16_t MUTIPLEX_COUNT = 10;   // 20ms multiplex rate
const uint16_t SLOW_COUNT     = 400;  // 5 updates a second 
const uint8_t digits[NUM_DIGITS] = {DIGIT_1_PIN, DIGIT_2_PIN};
const uint8_t segments[NUM_SEGMENTS] = {SEGMENT_A_PIN, SEGMENT_B_PIN, SEGMENT_C_PIN, SEGMENT_D_PIN, SEGMENT_E_PIN, SEGMENT_F_PIN, SEGMENT_G_PIN };
const uint8_t symbols[NUM_SYMBOLS][NUM_SEGMENTS] = {
  {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW}, 	// 0
  {LOW, HIGH, HIGH, LOW, LOW, LOW, LOW}, 		// 1
  {HIGH, HIGH, LOW, HIGH, HIGH, LOW, HIGH}, 	// 2
  {HIGH, HIGH, HIGH, HIGH, LOW, LOW, HIGH}, 	// 3
  {LOW, HIGH, HIGH, LOW, LOW, HIGH, HIGH}, 		// 4
  {HIGH, LOW, HIGH, HIGH, LOW, HIGH, HIGH}, 	// 5
  {HIGH, LOW, HIGH, HIGH, HIGH, HIGH, HIGH}, 	// 6
  {HIGH, HIGH, HIGH, LOW, LOW, LOW, LOW}, 		// 7
  {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH}, 	// 8
  {HIGH, HIGH, HIGH, HIGH, LOW, HIGH, HIGH} 	// 9
};

// initialise variables
uint16_t mutiplexCounter = MUTIPLEX_COUNT;
uint16_t slowCounter = SLOW_COUNT;
uint8_t currentDigit = 1;
uint8_t digitNum[NUM_DIGITS] = {0,0};


// timer callback function
void timerCallback(void)
{
  // handle the 1 second heartbeat counter
  if (!--mutiplexCounter)
  {
    // switch off current digit
    digitalWrite(digits[currentDigit], LOW);

    // 
    if(++currentDigit > NUM_DIGITS-1)
    	currentDigit = 0;
    
	for (uint8_t segment=0; segment < NUM_SEGMENTS; segment++)
    {
      	digitalWrite(segments[segment], symbols[digitNum[currentDigit]][segment]);
    }
    
    // switch on new digit
    digitalWrite(digits[currentDigit], HIGH);
    
    // reload heartbeat counter
    mutiplexCounter = MUTIPLEX_COUNT;
  }
  
  if (!--slowCounter)
  {
    	digitNum[0]++;
    	if (digitNum[0] > NUM_SYMBOLS-1)
        {
          	digitNum[0] = 0;
          	digitNum[1]++;
          	if (digitNum[1] > NUM_SYMBOLS-1)
            	digitNum[1]=0;
        }
        // reload the slow counter
		slowCounter = SLOW_COUNT;
  }
}
  
void setup() 
{
    // configure pins
  	for (uint8_t segment=0; segment < NUM_SEGMENTS; segment++)
    {
      pinMode(segments[segment], OUTPUT);
    }
  	pinMode(DIGIT_1_PIN, OUTPUT);
  	pinMode(DIGIT_2_PIN, OUTPUT);
  
    

    // set up the timer
    Timer0.initialize(); // 1 millisecond timer rate
  	// each interrupt, call our function
    Timer0.attachInterrupt(timerCallback);
}

void loop() 
{
  // all the work is done on the timer callback
}

Project Image:

изображение

	digitalWrite(segments[segment], !symbols[digitNum[currentDigit]][segment]);

Are your displays common cathode?

Hi, @kolaha
Where are the current limit resistors for the display?

Tom.. :grinning: :+1: :coffee: :australia:

these are special 7seg displays, they contain any possible and impossible protection circuitry

Hi, @humayunpi

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Fritzy images do not tell all the story

Can you post some images of your project?
So we can see your component layout.

Have you written some simple code to test your hardware, before attempting multiplexing?

Thanks.. Tom.. :grinning: :+1: :coffee: :australia:

Code works.

I changed around the pin numbers for the segments to match the vintage calculator display that was handy but that's all I changed.

Are you using NPN transistors?

Do you have them wired correctly? If they're in the breadboard in real life as they are in that Fritzing diagram, the answer to that question is no. They might as well not be there - you're just feeding the digit output pins right to the display. the digit pins are permanently grounded.

What values are those base resistors? If they're 1K that's fine (I used 2.2K). If they're 10K, that could be too high.

I wired the NPN transistor similar to how I did in the online version- is that now how it is supposed to be connected? If so, how should I wire them instead? Also my base resistors are at 1K.

Thanks!

1K is fine.

And your transistors are definitely wired up wrong.


All the connections in each column of 5 (the red rectangles in the above image) are connected together. You transistors are shorted out (emitter connected to base connected to collector) and your digits pins are feeding right through to the display. and your digit pins are grounded.

Look at my circuit to see how they should be connected. Each pin should be in a different column. And for my transistors (2N2222A) the pins are (from the left to right) E, B, C.

My transistors are CBE, but I see what you mean, trying that out now

Okay so I fixed the resistors but not sure if I fixed the transistors. The base is connected to the 1000 ohm and then to the digital output pin. The emitter is connected to the ground and and collector is connected to the common.

Updated picture:

No. Your digit pins 2 & 3 are feeding right into the base of the transistor w/o going through the 1K resisitor. Look at my circuit photo again. The base resistors should go across the central gap and the digit pins should feed into the lower end of the resistor, on the bottom side of the gap.

Also, you've lost the ground connection back to the Arduino in this revision.

To be very honest I have no idea what you mean by that.. like this?

image

As it turns out, you knew exactly what I meant. :slight_smile: That's it.

Thank you! But...new problem: when I run it, they both turn on now but it is not displaying numbers? Its like random parts will light up..?

Screenshot 2023-12-11 9.40.33 PM
Screenshot 2023-12-11 9.40.30 PM

Heh; maybe not random but I can see why you'd think so. Imagine if on segments were off and off segments were on. The top one would read 30, and the bottom one 10. Could your simulator is using common anode displays? If so, it's not as smart as it should be; there's no way those displays would light up at all in real life with no ground connection to the breadboard. And common anode displays would need +5 on the anode, and they're not going to get that at all with this circuit.

Ohh that makes sense they are both common anode displays. So do I just connect the common pin to the positive side of the breadboard?

You'll have to use PNP transistors with their emitters hooked up to +5V rather than ground, invert all the HIGHs and LOWs in symbols[], and write a HIGH to turn off the current digit and a LOW to turn it on. i think.

Alright I tried that I'm pretty sure the code is right so I probably just have messed up something with the wires?


// blinking lights at different rates using the timer module

// -------------------------------------------------------------------------------------------
// hook into timer0 that's already set up for the millis function to give 1ms timer interrupts
// on real hardware, you could use the Timer1 library, but it's not available in Tinkercad.

class TimerZero
{
  public:
  
  void initialize()
  {
    // compare interrupt somewhere in the middle of the count
    OCR0A = 0xAF;
  }
  
  //  Interrupt Function
  void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
    isrCallback = isr;
    TIMSK0 |= _BV(OCIE0A);
  }

  static void (*isrCallback)();
  
};

TimerZero Timer0; // pre-instantiate
void (*TimerZero::isrCallback)() = NULL;

ISR(TIMER0_COMPA_vect)
{
  Timer0.isrCallback();
}
// -------------------------------------------------------------------------------------------

// pin definitions
#define SEGMENT_A_PIN 9
#define SEGMENT_B_PIN 10
#define SEGMENT_C_PIN 4
#define SEGMENT_D_PIN 5
#define SEGMENT_E_PIN 6
#define SEGMENT_F_PIN 8
#define SEGMENT_G_PIN 7

#define DIGIT_1_PIN 2
#define DIGIT_2_PIN 3

#define NUM_SEGMENTS 7
#define NUM_DIGITS 2
#define NUM_SYMBOLS 10

// counter definitions, in milliseconds
const uint16_t MUTIPLEX_COUNT = 10; // 20ms multiplex rate
const uint16_t SLOW_COUNT = 400;    // 5 updates a second 
const uint8_t digits[NUM_DIGITS] = {DIGIT_1_PIN, DIGIT_2_PIN};
const uint8_t segments[NUM_SEGMENTS] = {SEGMENT_A_PIN, SEGMENT_B_PIN, SEGMENT_C_PIN, SEGMENT_D_PIN, SEGMENT_E_PIN, SEGMENT_F_PIN, SEGMENT_G_PIN };
const uint8_t symbols[NUM_SYMBOLS][NUM_SEGMENTS] = {
  {LOW, LOW, LOW, LOW, LOW, LOW, HIGH},     // 0
  {HIGH, LOW, LOW, HIGH, HIGH, HIGH, HIGH}, // 1
  {LOW, LOW, HIGH, LOW, LOW, HIGH, LOW},     // 2
  {LOW, LOW, LOW, LOW, HIGH, HIGH, LOW},     // 3
  {HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW},    // 4
  {LOW, HIGH, LOW, LOW, HIGH, LOW, LOW},     // 5
  {LOW, HIGH, LOW, LOW, LOW, LOW, LOW},     // 6
  {LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH},  // 7
  {LOW, LOW, LOW, LOW, LOW, LOW, LOW},      // 8
  {LOW, LOW, LOW, LOW, HIGH, LOW, LOW}      // 9
};

// initialise variables
uint16_t mutiplexCounter = MUTIPLEX_COUNT;
uint16_t slowCounter = SLOW_COUNT;
uint8_t currentDigit = 1;
uint8_t digitNum[NUM_DIGITS] = {0,0};

// timer callback function
void timerCallback(void)
{
  // handle the 1 second heartbeat counter
  if (!--mutiplexCounter)
  {
    // switch on current digit (inverted logic)
    digitalWrite(digits[currentDigit], HIGH);

    // 
    if(++currentDigit > NUM_DIGITS-1)
        currentDigit = 0;
    
    for (uint8_t segment=0; segment < NUM_SEGMENTS; segment++)
    {
        digitalWrite(segments[segment], symbols[digitNum[currentDigit]][segment]);
    }
    
    // switch off new digit (inverted logic)
    digitalWrite(digits[currentDigit], LOW);
    
    // reload heartbeat counter
    mutiplexCounter = MUTIPLEX_COUNT;
  }
  
  if (!--slowCounter)
  {
      digitNum[0]++;
      if (digitNum[0] > NUM_SYMBOLS-1)
      {
          digitNum[0] = 0;
          digitNum[1]++;
          if (digitNum[1] > NUM_SYMBOLS-1)
            digitNum[1]=0;
      }
      // reload the slow counter
      slowCounter = SLOW_COUNT;
  }
}
  
void setup() 
{
    // configure pins
    for (uint8_t segment=0; segment < NUM_SEGMENTS; segment++)
    {
      pinMode(segments[segment], OUTPUT);
    }
    pinMode(DIGIT_1_PIN, OUTPUT);
    pinMode(DIGIT_2_PIN, OUTPUT);

    // set up the timer
    Timer0.initialize(); // 1 millisecond timer rate
    // each interrupt, call our function
    Timer0.attachInterrupt(timerCallback);
}

void loop() 
{
  // all the work is done on the timer callback
}

Now the displays do not turn on at all: