Servo Motor causes sevseg display to flicker/turn off

Hello,

I'm trying to build a clock that shows the hours on a seven segment display and the minutes via a mechanical indicator. I'm controlling the mechanical aspect via a stepper motor.

Everything seems to be working as desired, except that each time the stepper motor turns on, the hour display turns off or gets stuck with only a single segment lit up for as long as it takes the stepper to complete its required number of steps.

In the code below, the "hour" changes every 3 seconds. The stepper motor takes 50 steps every 1 second after completing its previous 50th step.

I know you cannot use the delay() function with a seven segment display. The stepper motor is effectively introducing the delay.

Is there a work around for this problem?

Thank you for your assistance.

Michael

//THis is a copy
#include "SevSeg.h"
#include <Stepper.h>
SevSeg sevseg; //Instantiate a seven segment controller object

int Hr = 1; // Current Hour
unsigned long currentMillis = 0;
int HrUpPin = 41;
int HrDnPin = 43;
int HrUpState = 0;
int HrDnState = 0;
int lastHrUpState = 0;
int lastHrDnState = 0;
int MinUpPin = 45;
int MinDnPin = 47;
int MinUpState = 0;
int MinDnState = 0;
int lastMinUpState = 0;
int lastMinDnState = 0;
static unsigned long hrtimer = millis(); // timer is how long between number change
static unsigned long mintimer = millis();
unsigned long previousMinMillis = 0; //will store last minutes was updated
#define STEPS 2038 // the number of steps in one revolution of your motor (28BYJ-48)
Stepper stepper(STEPS, 12, 44, 13, 46);

void setup() {
  byte numDigits = 2;
  byte digitPins[] = {10, 11};
  byte segmentPins[] = {3, 9, 8, 6, 7, 4, 1, 2};
  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_ANODE; // 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(90);

}

void loop() {
  HrAdj();
  HrDisp();
  MinDisp();
}

void HrDisp() { //Displays the hour

  sevseg.setNumber(Hr);
  if (millis() - hrtimer >= 3000) // number of seconds between number change
  {
    hrtimer += 3000; //sets timer to equal millis()
    Hr++;
    if (Hr == 13) { // Reset to 0 after counting for 10 seconds.
      Hr = 1;
    }
  }

  sevseg.refreshDisplay(); // Must run repeatedly

}
void HrAdj() { // Adjusts the Hour
  //Getting the reads from the buttons
  HrUpState = digitalRead(HrUpPin);
  HrDnState = digitalRead(HrDnPin);

  //Detecting button press and getting the button status
  //Do this for the button up

  if (HrUpState != lastHrUpState)
  {
    lastHrUpState = HrUpState;
    if (HrUpState == HIGH)
    {
      ++Hr;
      hrtimer = millis(); //sets timer to equal millis() after changing Hr
      if (Hr >= 13) {
        Hr = 1;
      }

    }
  }

  //Do this for the button down

  if (HrDnState != lastHrDnState)
  {
    lastHrDnState = HrDnState;
    if (HrDnState == HIGH)
    {
      --Hr;
      hrtimer = millis(); //sets timer to equal millis() after changing Hr
      if (Hr <= 0) {
        Hr = 12;
      }

    }
  }
}

void MinDisp() { //Advances servo to track minutes
  if (millis() - mintimer >= 1000) // number of seconds between number change
  {
    stepper.setSpeed(1); // 1 rpm
    stepper.step(50); // do 2038 steps -- corresponds to one revolution in one minute
    sevseg.refreshDisplay(); // Must run repeatedly
    mintimer = millis();
  }

  previousMinMillis = currentMillis;

  MinUpState = digitalRead(MinUpPin);
  MinDnState = digitalRead(MinDnPin);
  if (MinUpState != lastMinUpState)
  {
    lastMinUpState = MinUpState;
    if (MinUpState == HIGH)
    {
      stepper.setSpeed(1); // 1 rpm
      stepper.step(50); // do 2038 steps -- corresponds to one revolution in one minute
      previousMinMillis = currentMillis;
    }
  }
  if (MinDnState != lastMinDnState)
  {
    lastMinDnState = MinDnState;
    if (MinDnState == HIGH)
    {
      stepper.setSpeed(1); // 1 rpm
      stepper.step(-50); // do 2038 steps -- corresponds to one revolution in one minute
      previousMinMillis = currentMillis;
    }

  }
}
/// END ///

I noticed your Post in Bar Sport. I had previously seen this Thread but I confess I did not think I would have anything to contribute when I saw it was about 7-segment displays. Also your Title mentions a servo rather than a stepper motor.

The standard Stepper library blocks while it moves. There are two ways round that. Either move the motor one step at a time and use your own non-blocking step timing or use the non-blocking capabilities of the AccelStepper library

...R

Hello Michael,
Like Robin I saw this in bar sport. I have nothing to add to Robin's answer but I strongly suggest you remove your email address from the post. Never put your email address on any web site because spam bots will find it and start sending you spam.

    stepper.step(50); // do 2038 steps -- corresponds to one revolution in one minute
    sevseg.refreshDisplay(); // Must run repeatedly

What part of "must run repeatedly" did you not get?
While it is stepping it is not running.

Also how is 50 = 2038 steps? I would have though 50 = 50 steps?

Assuming the step function parameter is the required number of steps, you could try...

for (int step = 0; step < 50; step++)
{
    stepper.step(1);
    sevseg.refreshDisplay();
}

All depends how long a step takes.

Robin2, I just realized that I failed to thank you for your reply. Please forgive my unintended rudeness. I will look into the AccelStepper library
and/or try the "one step at a time" as you and pcbbc are suggesting.

Thank you for your suggestion, PerryBebbington. I obviously did not think of that and have removed my email address.