Need help with 7 segment displays. (also, is this the right section for this?)

So, I'm really new to both programming and microcontrollers, although I have a (very) small bit of experience in C++. While reading this, keep in mind my inexperience! After doing some of the beginner projects, I thought it would be cool to make a 4 digit counter. I planned out the multiplexing with transistors and pins on the arduino, and made (incomplete and probably atrociously disorganized and working around, I know there's probably a better way to do this) code. I got to here in the loop function before I realized something:

void loop() {
        settoDisp(4, timeCount1);
        if (timeCount1 == 0) {
              settoDisp(3, timeCount2);
              timeCount2++;
              if (timeCount2 == 0) {
                  settoDisp(2, timeCount3);
                  timeCount3++;
                  if (timeCount3 == 0) {
                      settoDisp(1, timeCount4);
                      timeCount3++
                      if
                  }
              }
        }
        timeCount1++;
        delay(1000);
}

I realized that if it delays for a second, it can't rapidly switch between the displays. I did some research on the internet, and found some stuff about shift registers that I didn't really get, and then I came here. I'd like to know how this would be possible, and also if there's something that would rapidly switch between the transistors so that I can write to the digits without stopping anything.

What you can do is use millis() or micros() & watch time go by, performing 2 functions at once.

The first will watch for 1 second to go by then, the update stuff as above. The other will watch for say 500uS to go by, and (assuming you have common cathode parts) will: turn off any cathodes (transistors) turn on the anodes for a digit turn on the cathode for that digit. When 500uS go by, do the same for next digit.

Conceptually:

void loop(){
if (1 second elapsed){
update the time elements
}
if (500uS elapsed){
update the display with the current time elements
update counter to update the next digit on the next pass thru
}
} // end void loop

This is the basis of Blink without Delay

Hmm, thanks, I'll see what I can do with that.

Am I doing it right?

long counter1 = 1000;
long counter2 = 480;
long oldTime;
long oldTime2;
void loop() {
    unsigned long currentTime = millis();
    unsigned long currentTime2 = micros();
if (currentTime - oldTime > counter1) {
update the times for that point
}
if (currentTime2 - oldTime2 > counter2){
setdisp1(updatedDigit1);
delayMicroseconds(5);
setdisp2(updatedDigit2);
delayMicroseconds(5);
setdisp3(updatedDigit3);
delayMicroseconds(5);
setdisp4(updatedDigit4);
delayMicroseconds(5);
}
}

//setdisp1-4() takes the number passed in and writes the cathodes and anodes

In the if statement you should update the oldTimer variable so it will run again after the correct time. You need to post all your code.

You would be better off not having a delay and only updating one digit in your time out routine. Use a variable to keep track of wat digit to update with each time out.

Why would I be better off, isn't the delay so short that the human eye can' t see the difference?

You would better off because you are not waisting the time of your processor. It has nothing to do with the refresh rate which will remain the same.

So something more like this?

if (currentTime2 - oldTime2 > counter2){
setdisp(keepTrack, updatedDigit);
    keepTrack++;
    if (keepTrack > 5)
    {
        keepTrack = 1
    }
}

Also I really need to sleep (3:00 AM). I'll finish the code ASAP and post it.

Yes that is the idea :)

So I finished the code. I know it’s not streamlined in the slightest bit, but when I started, I wanted to try figuring it out on my own so I could learn more. Would it work for my purpose?

clock.ino (4.14 KB)

Change the time variables to type: unsigned long for these:

long counter1 = 1000; long counter2 = 480; long oldTime; long oldTime2;

Change these to switch:case, no need to go thru 10 if:else sets of checks:

void setNum(int theNumber) { if (theNumber == 1) { digitalWrite(3, HIGH); digitalWrite(6, HIGH); }

switch(the Number){ case 1: digitalWrite(3, HIGH); digitalWrite(6, HIGH); break;

What will turn the other segments off?

Ah - I found the turn off here:

void settoDisp(int dispNum, int numtoSet) { clearAll();

This doesn't really need a change. Segments are usually defined like this:

aaaa f b f b f b gggg e c e c e c dddd dp

Yeah, I got the hardware working, and can power up all 4 digits, but when I use this loop, it just displays 0 on the thousands digit. halp?

int pinSet = 1;
unsigned long counter1 = 1000;
unsigned long counter2 = 480;
int keepTrack = 1;
unsigned long oldTime;
unsigned long oldTime2;
int delayTime = 1000;
int keepTrack2 = 1;
int units = 0;
int tens = 0;
int hundreds = 0;
int thousands = 0;
void setup() {
      pinMode(2, OUTPUT);
      pinMode(3, OUTPUT);
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      pinMode(7, OUTPUT);
      pinMode(8, OUTPUT);
      pinMode(9, OUTPUT);
      pinMode(10, OUTPUT);
      pinMode(11, OUTPUT);
      pinMode(12, OUTPUT);
      digitalWrite(8, HIGH);
      }


void loop() {
    unsigned long currentTime = millis();
    unsigned long currentTime2 = micros();
if (currentTime - oldTime > counter1) {
units++;
if (units == 9) {
  tens++;
  if (tens == 9);
  {
    hundreds++;
    if (hundreds == 9) {
      if (thousands == 9 && hundreds == 9 && tens == 9 && units == 9) {
        units = 0;
        tens = 0;
        hundreds = 0;
        thousands = 0;
      }
      thousands++;
      hundreds = 0;
    }
    tens = 0;
  }
  units = 0;
}
currentTime = oldTime;
currentTime2 = oldTime2;
}
if (currentTime2 - oldTime2 > counter2){
        if (keepTrack = 1) {
          keepTrack2 = thousands;
        }
        else if (keepTrack = 2) {
          keepTrack2 = hundreds;
        } 
        else if (keepTrack = 3) {
          keepTrack2 = tens;
        }
        else if (keepTrack = 4) {
          keepTrack2 = units;
        } 
        else {
          keepTrack2 = 1;
        }
        settoDisp(keepTrack, keepTrack2);
        keepTrack++;
}
        
}

Bump? I'm really confused.

I've done this part a little differently to handle the rollovers:

if (currentTime - oldTime > counter1) 
{
units++;
if (units == 10)
 {
  units = 0;
  tens++;
  if (tens == 10);
  {
    tens = 0
    hundreds++;
    if (hundreds == 10) 
       {
        hundreds = 0
        thousands++ = 0;
        if (thousands == 10)
        {
        thousands = 0;
        } // end thousands
      } // end hundreds
     }// end tens
    } // end ones
  } // end time increase check

I'm really confused.

Yes so am I.

When you post code you have to post all of it so we can compile it and test it. The code you posted will not compile because you have the line:-

 settoDisp(keepTrack, keepTrack2);

And no where do you define the function. It is this function that probably has the error in it.

Here, sorry.

pnpclock.ino (4.36 KB)

 if (keepTrack = 1)

Missing an equals sign here?

Sorry, now it just displays 8's.

Edit: I changed it so it actually displays the unit. They all turn on with 0 and then the units led turns on with zero and doesn't change.