Breaking a Serial Monitor Decimal Number down into components?

I'm working on an Arduino project where I trying to send a number (0 - 9999) from the serial monitor to a 4 digit 7 segment display utilizing a shift register. OK...I've got the circuit wired correctly and the display illuminated. I'm able to send all zeroes to the display at the start of the sequence.

I need to split up the 4 digit input from the serial monitor to get the 4 separate digits for the display. I'm getting hung up on trying to take a 4 digit number that I input into the serial monitor and use the output from the serial monitor to 'convert' to some number I can use to reference an array of binary numbers (0 - 9 in binary for the display).

If I type 1234 into the serial monitor I get an output like:

49
50
51
52

I know these are the decimal equivalents of 1234. What I'm unsure of is how to break down the number down into something useful to get the binary number from the array.

I have created variables for the 4 digits and when printing to the serial monitor I get an output like:

Input:
1

4 digit Output:
0
0
4
9

Currently, when I attempt to implement the code with the input of '1' I see a '9' in one of the digits and nothing in the other three. I'm sure this has to do with the conversion from decimal. Thank you in advance for the assistance!

You are sending text. ‘0’ equals 0x30 or 48d.

When you receive the character, you can subtract ‘0’ to get to an integer.

char ch = Serial.read();
if (ch>='0' && ch <= '9')
{
  int value = ch - '0';

  // send to display
  ...
  ...
}

Thank you!

OK, now I am able to get the exact integer value from what I input into the serial monitor! However, I’m still having trouble breaking a multiple digit integer number like 123 into its components 1, 2, and 3 to display properly on the multi-segment display.

It seems as though a multiple digit number is considered as 3 separate integer values. For instance, when I have a space inserted to view the value of displayValue2 I’ll get multiple values seperated with a space:

if (displayValue >= '0' && displayValue <= '9')
              {
           displayValue2 = displayValue - '0';
           Serial.print(" ");
           Serial.print(displayValue2); //  Display displayValue after conversion (debugging purposes)
              }

If I input 1234, I’ll get:

1 2 3 4

To me, it seems how these are printed they are considered separate numbers?

I need to take each of these numbers and be able to define each as a digit on the 4 digit display.

Currently, if I input a single digit I can get the appropriate single digit to display. If I input a multi-digit number only the last number (1’s place) is displayed where it should be.

The multidigit nmber is being stored as 4 separate numbers the way you're reading it because you're reading it in one digit at a time and storing those in separate variables. If you want to put it back together into one real number then imagine doing that with steps of adding and multiplying by 10.

Delta_G:
The multidigit nmber is being stored as 4 separate numbers the way you're reading it because you're reading it in one digit at a time and storing those in separate variables. If you want to put it back together into one real number then imagine doing that with steps of adding and multiplying by 10.

If it's being stored as four separate numbers in different variables can I access those to define as my digit variables?

I understand that I can recreate the number by multiplying each component by the appropriate power of 10 and then add them.

Please excuse the stupid questions I'm extremely new to Arduino and coding in general.

COMediSun:
If it's being stored as four separate numbers in different variables can I access those to define as my digit variables?

Sorry, I assumed you were storing them as four separate variables. You only posted a small snippet of the code so I can't really speak to what you really need to do. I was just giving general advice. If you want advice that related to your particular code then how do you expect that when I can't see your particular code?

Things come from serial one character at a time. You certainly have the option to store them in separate variables. An array sounds handy here.

You know I thought about an array too! But got an error like:

int[ ] does not match int

So I backed off…and posted here. I think some of my problems may rest in how I’m defining all the variables?

Here is the complete code I’m trying to implement…please excuse my working mess.

// shift register pins
const int latchPin = 5;  //74HC595  pin 9 ST_CP
const int clockPin = 6;  //74HC595  pin 10 SH_CP
const int dataPin  = 4;  //74HC595  pin 8 DS

// multi-segment digit select pins
const int digit1Pin = 9;    // segment pin 12
const int digit2Pin = 10;   // segment pin 10
const int digit3Pin = 11;   // segment pin 8
const int digit4Pin = 12;   // segment pin 6 

// digitTable stores the binary patterns for displaying values to display

const unsigned char digitTable[16]={
                             B11111100,   //  0 
                             B01100000,   //  1 
                             B11011010,   //  2
                             B11110010,   //  3
                             B01100110,   //  4
                             B10110110,   //  5
                             B10111110,   //  6   
                             B11100000,   //  7
                             B11111110,   //  8
                             B11100110,};   //  9
                             
                             
//  Declares a variable to store the integer.
   int displayValue;  //  This is the value that will be shown on the multi-digit display.

void setup() 
{
   //  Set pinMode for shift register pins:
  pinMode( latchPin , OUTPUT ); 
  pinMode( clockPin , OUTPUT ); 
  pinMode( dataPin  , OUTPUT ); 
   
  //  Set pinMode for seven segment pins:
  pinMode( digit1Pin , OUTPUT ); 
  pinMode( digit2Pin , OUTPUT );  
  pinMode( digit3Pin , OUTPUT );  
  pinMode( digit4Pin , OUTPUT ); 
      
  //  Setup serial port
  Serial.begin(9600); 
      
  //  Initialize displayValue to 0.
  displayValue = 0;    

  //  Display 0000 at Start
  digitalWrite( latchPin , LOW );
  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ displayValue ] );  
  digitalWrite( latchPin , HIGH );
}

//  Sends binary pattern for 4 digits to the shift register 

//Send Digit 1
void displayDigit1( unsigned char digit1 )
{
  digitalWrite( latchPin, LOW );
  shiftOut(dataPin , clockPin , LSBFIRST , digitTable[ digit1 ] );
  digitalWrite( latchPin, HIGH); 

  //  Sets digit 1 ON
  digitalWrite( digit1Pin , LOW  );
  digitalWrite( digit2Pin , HIGH );
  digitalWrite( digit3Pin , HIGH );
  digitalWrite( digit4Pin , HIGH ); 
}

//Send Digit 2
void displayDigit2( unsigned char digit2 )
{
  digitalWrite( latchPin , LOW );
  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ digit2 ] );
  digitalWrite( latchPin, HIGH ); 

  //  Sets digit 2 ON
  digitalWrite( digit1Pin , HIGH );
  digitalWrite( digit2Pin , LOW  );
  digitalWrite( digit3Pin , HIGH );
  digitalWrite( digit4Pin , HIGH );
}

//Send Digit 3
void displayDigit3( unsigned char digit3 )
{
  digitalWrite( latchPin, LOW );
  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ digit3 ] );
  digitalWrite( latchPin , HIGH ); 

  //  Sets digit 3 ON
  digitalWrite( digit1Pin , HIGH );
  digitalWrite( digit2Pin , HIGH );
  digitalWrite( digit3Pin , LOW  );
  digitalWrite( digit4Pin , HIGH );
}

//Send Digit 4
void displayDigit4( unsigned char digit4 )
{
  digitalWrite( latchPin , LOW );
  shiftOut(dataPin , clockPin , LSBFIRST , digitTable[ digit4 ] );
  digitalWrite( latchPin , HIGH ); 
  
  //  Sets digit 4 ON  
  digitalWrite( digit1Pin , HIGH );
  digitalWrite( digit2Pin , HIGH );
  digitalWrite( digit3Pin , HIGH );
  digitalWrite( digit4Pin , LOW  );
}

void splitDisplayvalue( int displayValue )
{

unsigned int digit1 , digit2 , digit3 , digit4 ; //  Declare 1 - 4 digit variables
  
unsigned int displayValue2;

if (displayValue >= '0' && displayValue <= '9')
  {
    displayValue2 = displayValue - '0';
    Serial.print(" ");
    Serial.print(displayValue2); //  Display displayValue2 after conversion (debugging purposes)
              }
    

// Not Sure if this needed or not this is something I found online...
digit1 = ( displayValue2 / 10U ) % 10; // digit 1 = displayValue  / 1000 % 10
Serial.print(" ");
Serial.print(digit1);
digit2 = ( displayValue2 / 100U ) % 10; // digit 2 = displayValue  / 100  % 10
Serial.print(" ");
Serial.print(digit2);
digit3 = ( displayValue2 / 1000U ) % 10; // digit 3 = displayValue  / 10   % 10
Serial.print(" ");
Serial.print(digit3);
digit4 = displayValue2 % 10; // digit 4 = displayValue         % 10
Serial.print(" ");
Serial.println(digit4);


//  Send 4 digit values to displayDigits
displayDigit1(digit1);
displayDigit2(digit2);
displayDigit3(digit3);
displayDigit4(digit4);

}

void loop() {
  //char inputNumber = 0;  //  Initialize inputNumber = 0
  
  // Show displayValue on the multi-segment display (will need to break it into 4 digits)
//  displayDigit1(); //  Commented out not sure if needed
//  displayDigit2();
//  displayDigit3();
//  displayDigit4();

  //When Serial data is available
  if(Serial.available())                 // Reads available serial input...when available
    {
      char inputNumber = Serial.read();                // Read the integer value
                    
             
      if( inputNumber > 0 && inputNumber < 9999 ) //  Input Number is between 0 and 9999
        {
          displayValue = inputNumber;               //  Input Value is equal to displayValue

        }

   splitDisplayvalue(displayValue);            //  Send displayValue to splitDisplayvalue()
            
    }  
}

This works as is to display the 1’s place of a multi-digit number, but will not display the other three digits. I believe everything should work if I can define each input digit as a seperate variable. Thank you.

You only asked for display :wink: Not for storing.

Store the received characters in an array; see Serial Input Basics for ideas. It also contains an example to convert text to an integer using atoi(). After that, you can use the divide / modulo operators to split it.

int[ ] does not match int

This is not C# :wink:

sterretje:
Store the received characters in an array; see Serial Input Basics for ideas. It also contains an example to convert text to an integer using atoi().

Thank you! From the link provided, I believe I got the serial input split into 4 separate variables using atoi() and I'm able to display each digit on the display separately! Progress!

OK, now I'm having a problem with multiplexing the code/circuit to allow all 4 of the digits to remain illuminated at the same time. Currently, each digit is displayed VERY rapidly and ends with illuminating the final digit.

Any suggestions for multiplexing? My lack of experience makes me unsure exactly how I would apply it to my situation.

I've looked online and found examples where people use a delay to change the pin mode from high to low, or something more complicated like adding a timer function to the loop.

Currently I'm using this for each digit:

 //  Sets digit 1 ON
  digitalWrite( digit1Pin , LOW  );
  digitalWrite( digit2Pin , HIGH );
  digitalWrite( digit3Pin , HIGH );
  digitalWrite( digit4Pin , HIGH ); 
  delay(100);

which just cycles each digit on for 1 second then off. Thank you for the assistance!

which just cycles each digit on for 1 second then off.

Are you SURE about that?

PaulS:
Are you SURE about that?

Cycles on for 0.1 second then off…been messing with the numbers and things are getting fuzzy

Got it! Now for some formatting!

COMediSun:
OK, now I'm having a problem with multiplexing the code/circuit to allow all 4 of the digits to remain illuminated at the same time. Currently, each digit is displayed VERY rapidly and ends with illuminating the final digit.

Any suggestions for multiplexing? My lack of experience makes me unsure exactly how I would apply it to my situation.
Currently I'm using this for each digit:

 //  Sets digit 1 ON

digitalWrite( digit1Pin , LOW  );
 digitalWrite( digit2Pin , HIGH );
 digitalWrite( digit3Pin , HIGH );
 digitalWrite( digit4Pin , HIGH );
 delay(100);

It would help if we could see your whole code, so that we could understand exactly what it is you are now trying. (It's hard to fix what you can't see.)

"Each digit is displayed very rapidly" is pretty much the definition of multiplexing. If you do it rapidly enough, it tricks your eyes into seeing all the digits at once. (Google "persistence of vision".)

It seems that you are missing two things.
The first thing is that, in order to fool the eye, you must display each digit for only a very, very short time. Even 100 milliseconds is much too long. Better would be maybe 3 milliseconds, or even shorter.
The second thing is that, once you are done with the last digit, you must start again with the first digit. Try going through all the digits 5 or 10 times in a row. Then, the next time through loop(), do it again, and so forth.