Is it possible to control the dp of sevseg displays seperately to a number using the sevseg library?

That's the simple version of my question... Here's the more detailed version:

I'm using a 4 digit sev seg display to display one of two possible values, stored in an array of integers. These values can be from 0-9950. Everything now works, but the problem I have is that the display I'm using has small marker arrows instead of decimal points, which I want to use as well, but because they are effectively the dp, one value will display as "0000" while the other displays as "0".


I've discovered from my searching so far that I can't simply add leading zeros to the second int, so I think the only way to make it display the same for both (either both as 0, or both as 0000, I don't mind but would like them to look the same) would be to convert them to char arrays somehow and use sevseg.setChars instead of setNumber. But how do I convert an int of "1234" to char of either "1.234" or "1234." depending on which value is being shown?

Here's the code:

#include <SevSeg.h>
#include <Bounce2.h>

// CONSTANTS
// Define number of buttons and pins attached to
const byte numModes = 2;
const byte modePins[numModes] = { 36, 39 };  // { SP(defrost), SN(steam) } !!!EXTERNAL PULLUP!!!
const byte plusPin = 34;                     // { plus, minus }!!!EXTERNAL PULLUP!!!
const byte minusPin = 35;                    // { plus, minus }!!!EXTERNAL PULLUP!!!
const byte startPin = 32;
const byte doorPin = 33;
// Define relay and buzzer pins
const byte relayPin = 13;
const byte buzzerPin = 23;
// Define LED display pins
const byte numDigits = 4;
const byte digitPins[] = { 12, 14, 27, 26 };
const byte segmentPins[] = { 15, 2, 0, 4, 16, 17, 5, 18 };  //Segments: A,B,C,D,E,F,G,Period
const byte dp[numModes] = { 3, 0 };
// Correct solutions
const int correctValues[numModes] = { 750, 3200 };
// Set the segments for "door" on the display
uint8_t displayDoor[4] = { 0x5E, 0x5C, 0x5C, 0x50 };
// Time in seconds to cook for
int cookTime = 11;
int holdTime = 800;


// GLOBAL VARIABLES
int currentValues[numModes] = { 0, 0 };
byte currentMode = 0;
unsigned long holding = 0;
unsigned long cooking = 0;


// CREATE INSTANCES
SevSeg sevseg;
Bounce2::Button modeButtons[numModes] = { Bounce2::Button(), Bounce2::Button() };
Bounce2::Button plusButton = Bounce2::Button();
Bounce2::Button minusButton = Bounce2::Button();
Bounce2::Button startButton = Bounce2::Button();
Bounce2::Button door = Bounce2::Button();


bool isSolved() {
  bool valuesSolved = true;
  for (int i = 0; i < numModes; i++) {
    if (currentValues[i] != correctValues[i]) {
      valuesSolved = false;
    }
  }
  return valuesSolved;
}


bool timePeriod(unsigned long& startPeriod, unsigned long time) {
  unsigned long currentTime = millis();
  if (currentTime - startPeriod >= time) {
    startPeriod = currentTime;
    return true;
  } else return false;
}


void setup() {
  // put your setup code here, to run once:

  // Setup sevseg
  sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins);
  sevseg.setBrightness(50);
  sevseg.blank();

  // Setup Buttons
  for (int i = 0; i < numModes; i++) {
    modeButtons[i].attach(modePins[i], INPUT);
    modeButtons[i].setPressedState(LOW);
  }
  plusButton.attach(plusPin, INPUT);
  plusButton.setPressedState(LOW);
  minusButton.attach(minusPin, INPUT);
  minusButton.setPressedState(LOW);
  startButton.attach(startPin, INPUT_PULLUP);
  startButton.setPressedState(LOW);
  door.attach(doorPin, INPUT_PULLUP);
  door.setPressedState(LOW);

  // Setup relay and buzzer pins
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH);
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(buzzerPin, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:
  
  // check for mode change
  for (int i = 0; i < numModes; i++) {
    modeButtons[i].update();
    if (modeButtons[i].pressed()) {
      currentMode = i;
    }
  }

// update plus button and act upon outcome
  plusButton.update();
  if (plusButton.pressed() && currentValues[currentMode] < 9950) {
    currentValues[currentMode] += 50;
    holding = millis();
    digitalWrite(buzzerPin, HIGH);
    digitalWrite(buzzerPin, LOW);
  }
  if (plusButton.isPressed() && currentValues[currentMode] < 9950) {
    if (millis() - holding > holdTime) {
      currentValues[currentMode] += 50;
      holding = millis();
      if (holdTime > 50) {
        holdTime /= 1.5;
      }
    }
  } else if (plusButton.released()) {
    holdTime = 800;
  }

// update minus button and act upon outcome
  minusButton.update();
  if (minusButton.pressed() && currentValues[currentMode] > 0) {
    currentValues[currentMode] -= 50;
    holding = millis();
  }
  if (minusButton.isPressed() && currentValues[currentMode] > 0) {
    if (millis() - holding > holdTime) {
      currentValues[currentMode] -= 50;
      holding = millis();
      if (holdTime > 50) {
        holdTime /= 1.5;
      }
    }
  } else if (minusButton.released()) {
    holdTime = 800;
  }

// set display to current mode and value
  sevseg.setNumber(currentValues[currentMode], dp[currentMode]);
  sevseg.refreshDisplay();

// update start button and check for correct solution
  startButton.update();
  if (startButton.pressed()) {
    if (isSolved()) {
      door.update();
      while (!door.isPressed()) {
        sevseg.setSegments(displayDoor);
        sevseg.refreshDisplay();
        door.update();
      }
      onSolve();
    } else {
      for (int i = 0; i < numModes; i++) {
        currentValues[i] = 0;
      }
      currentMode = 0;
    }
  }
}


void onSolve() {
  digitalWrite(relayPin, LOW);

  if (timePeriod(cooking, 1000)) {
    cookTime--;
  }
  sevseg.setNumber(cookTime);
  sevseg.refreshDisplay();

  if (cookTime > 0) {
    onSolve();
  } else if (cookTime == 0) {
    digitalWrite(relayPin, HIGH);
    sevseg.blank();
    for (int b = 0; b < 3; b++) {
      digitalWrite(buzzerPin, HIGH);
      delay(500);
      digitalWrite(buzzerPin, LOW);
      delay(500);
    }
    for (int i = 0; i < numModes; i++) {
      currentValues[i] = 0;
    }
    currentMode = 0;
    cookTime = 11;
  }
}

void zeroPad() {
  float num = (random(1000) / 10);
  if (num < 1000) Serial.print("0");
  if (num < 100) Serial.print("0");
  if (num < 10) Serial.print("0");
  Serial.print(num);
}

Thanks. That would be useful if I wanted to print the number via serial, but I want to display it on an led display using the sevseg library, hence why what I actually said was "I can't add leading zeros to an integer"

have you tried using

  void setNumberF(float numToShow, int8_t decPlaces=-1, bool hex=0);

see SevSeg

Sure you can. See the library's 'setSegments()' and 'setSegmentsDigit()' functions.

This has the same problem. Because of the position of the decimal point, it still displays one as 0.000 and the other as 0.

I knew there had to be a simple solution!
I didn't even try this at first because I thought setting the number after setting the blank spaces to a 0 would just remove the zeros again, which having now tried it, it does. But never thought about doing it the other way around - setting the number first, then setting the blank digits to zeros. This has done it and put an end to my misery! Shame about the countless hours I'm not going to get back though :joy:

The order of putting digits and zeros is not important. With 'setSegmentsDigit()' function you have a random and independent access to any digit position of the display.

What I meant was that the following still only displays "0" (when the value is still 0), because setting the number turns the leading zeros back off again:

if (currentMode == 1) {
    if (currentValues[currentMode] < 1000) {
      sevseg.setSegmentsDigit(0, 0b00111111);
    }
    if (currentValues[currentMode] < 100) {
      sevseg.setSegmentsDigit(1, 0b00111111);
    }
    if (currentValues[currentMode] < 10) {
      sevseg.setSegmentsDigit(2, 0b00111111);
    }
  }
  sevseg.setNumber(currentValues[currentMode], dp[currentMode]);
  sevseg.refreshDisplay();

Whereas the following displays "0000":

sevseg.setNumber(currentValues[currentMode], dp[currentMode]);
  if (currentMode == 1) {
    if (currentValues[currentMode] < 1000) {
      sevseg.setSegmentsDigit(0, 0b00111111);
    }
    if (currentValues[currentMode] < 100) {
      sevseg.setSegmentsDigit(1, 0b00111111);
    }
    if (currentValues[currentMode] < 10) {
      sevseg.setSegmentsDigit(2, 0b00111111);
    }
  }
  sevseg.refreshDisplay();

Do not mix using of setNumber and setSegmentsDigit together.
If you need a full control to screen - output every digits by setSegmentsDigit only.

For example, if you need to display "0025"

 sevseg.setSegmentsDigit(0, digitCodeMap[0]);   // 0
 sevseg.setSegmentsDigit(1, digitCodeMap[0]);   // 0
 sevseg.setSegmentsDigit(2, digitCodeMap[2]);   // 2
 sevseg.setSegmentsDigit(3, digitCodeMap[5]);   // 5

Any reason not to do it as above? It seems to work.
If I was to do each digit like you suggest, then I also need to convert the int somehow into separate digits. I don't need to display a certain fixed number, it needs to display a variable. Also, how would I show the decimal point on the last digit, as well as specifying the digit itself? Presumably I would then have to set the segments individually instead of just setting a digit?

This way, I'm just setting the int value as it is and then adding in any leading zeros that are needed to fill the display.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.