SevSeg and strings

I'm writing a program for a clock on a CC 7 segment display. I'm using the SevSeg library which allows a string to be displayed using the sevseg.setChar() function. From the GitHub page, they say

Setting a character string:

sevseg.setChars("abcd");

Character arrays can be displayed - as accurately as possible on a seven segment display. See SevSeg.cpp digitCodeMap to notes on each character. Only alphanumeric characters, plus ' ', '-' and '.' are supported. The character array should be NULL terminated.

I want to display "12hr" to specify 12 or 24hr time. If I put the string "12hr" in quotes inside the function, it works. Cool.

Next, I want to make a pushbutton interrupt change the contents of the string. I have the interrupt change a global string I defined as String settings = "12hr" at the top of my code. However, when I change the values between the parentheses to sevseg.setChar(settings), it gives me the error:

no matching function for call to 'SevSeg::setChars(String&)'

Why is this? (I have to head out but can post my whole code in a bit)

Please post your code. Your post shows setChar (singular) but the error message references setChars (plural). These are NOT the same. What actually happened?

Try it using a string, not a String

Character arrays can be displayed - as accurately as possible on a seven segment display. See SevSeg.cpp digitCodeMap to notes on each character. Only alphanumeric characters, plus ' ', '-' and '.' are supported. The character array should be NULL terminated.

char settings[] = "12hr";


sevseg.setChars(settings);

Alright, so I switched String() to char. It seemed to do the trick. And no, it wasn’t a syntax thing. I meant to write setChars but I had a typo.

Here’s the code so far:

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

int intPin = 2; //Interrupt pin 2
int presses = 0; //Button has been pressed 0 times
char settings [] = "test"; //Display "test" on the 7seg

void setup() {
  byte numDigits = 4; //4 digits on the display
  byte digitPins[] = {13, 12, 11, 10}; 
  byte segmentPins[] = {9, 3, 4, 5, 6, 7, 8};
  bool resistorsOnSegments = true; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_CATHODE; // See README.md for options
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool leadingZeros = true; // Use 'true' if you'd like to keep the leading zeros
  bool disableDecPoint = true; // 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(50);

  pinMode(intPin, INPUT); //Button is an input
  attachInterrupt(digitalPinToInterrupt(intPin), pin_ISR, RISING); //Trigger on the rising edge of a button press

  Serial.begin(9600);
}

void loop() 
{
  sevseg.setChars(settings); //Display whatever "settings" is equal to
 
  sevseg.refreshDisplay(); // Must run repeatedly (for multiplexing)
}

void pin_ISR() //If interrupt is detected
{
    presses = presses + 1; //Increment presses
    menu(presses); //Run this function
    Serial.println(presses); 
}

void menu(int value)
{
  switch(value)
  {
    case 1: //If presses = 1
      char settings[] = "12hr"; //Make the display say "12hr"
      Serial.println("got here");
      break;

    case 2:
      char settings[] = "brt";
      break;

    case 3:
      char settings[] = "1200";
      break;
  }
}

This should redefine what “settings” is, no? And apparently it doesn’t like to redefine settings without putting char in front of it. When I try this for more than 1 case, it gives me an error about the redeclaration of it.

How do I redefine what “settings” is in my interrupt function? I can’t put it in a loop otherwise the multiplexing wouldn’t work.

char array is a little bit tricky to use, but it's all worth it. In order to change the content of your "settings", you must declare it with the biggest storage you will ever gonna need. Then use strcpy() to copy different content into your "settings". Example code:

char settings[50] = "test";

void setup()
{
   strcpy(settings, "12hr"); //settings now is "12hr"
   strcpy(settings, "brt"); //settings now is "brt"
}

Cosmonaut:

void menu(int value)

{
 switch(value)
 {
   case 1: //If presses = 1
     char settings = "12hr"; //Make the display say "12hr"
     Serial.println("got here");
     break;




This should redefine what "settings" is, no? And apparently it doesn't like to redefine settings without putting char in front of it. When I try this for more than 1 case, it gives me an error about the redeclaration of it.

You are not redefining the contents of settings, you are creating a new character array named settings that is local to where it is declared. It would be inaccessible outside of the bracketed area of the switch statement in which it is declared.

To change the contents of settings, use the strcpy() command, such as:

void menu(int value)
{
  switch(value)
  {
    case 1: //If presses = 1
      strcpy(settings,"12hr"); //Make the display say "12hr"
      Serial.println("got here");
      break;

Just make sure that when settings is initially declared, that the number of elements in the character array is at least 1 more than the longest text that it will need to hold, so that there is room for the terminating null character.

Something else that will get you in trouble, Serial.print should not be used in an interrupt service routine. Serial requires interrupts, and interrupts are disabled inside an ISR. An ISR should also be as short as possible, calling the menu function from within an ISR is not a good idea, better to set a flag to indicate an interrupt has occurred, then check the flag in the main loop to see if you need to execute the menu() function. Additionally, variables used within an ISR should be declared as volatile.

void pin_ISR() //If interrupt is detected
{
    presses = presses + 1; //Increment presses
    menu(presses); //Run this function
    Serial.println(presses);
}