Entering Numbers into Serial Monitor

Hi,

I'm trying to calculate volume. I’ve started by prompting the user to enter each of the 3 sides of the rectangle. I have odd findings, namely that vars side_1 and side_3 get retained throughout the code, but side_2 does not. However, side_ 2 DOES work initially to get area (side 1 * side 2). Thus, when I try to calculate volume, I get 0

The program appears to loose the stored value of var ‘side_2’ when the code enters input for side_3

The program should really sit and hand until all 3 sides have been entered, but that’s perhaps for later as another problem (and others, etc.)

I don’t know why side_2 is being lost when transitioning to side_3, but I’m thinking either of these may be an issue (although I don’t know):

  1. clear the array, char myData, so that I can use it again (but then why does side_3 work?)
  2. clear the buffer (don’t know how, if needed)

*Note: I've attached my code as it exceed the character limit.

Any ideas what I'm missing?

math_formulas_user_entry_3.ino (10.5 KB)

Which of the many different side_2 variables in your sketch is causing the problem ?

Multiple variables with the same name and different scopes is not a good idea

Scope.

as usual, it's the user interface that become complicated

consider

char s [100];
int  idx = 0;

void
loop ()
{
    if (! Serial.available ())
        return;

    char c = Serial.read ();
    if ('\n' == c)  {
        s [idx] = 0;

        int  a, b, c;
        if (3 == sscanf (s, "%d,%d,%d", &a, &b, &c))  {
            sprintf (s, " %6d = %6d x %6d x %6d", a*b*c, a, b, c);
            Serial.println (s);
        }
        else {
            sprintf (s, "requires 3 values");
            Serial.println (s);
        }
        idx = 0;
    }
    s [idx++] = c;
}

void
setup (void)
{
    Serial.begin (115200);
}

when i first say that '/n'==c i wondered how on earth a 2 byte expression can be one byte, but i guess the '' explains that and the compiler resolves /n to a one byte value.

am i right?

That is right. '\n' is line feed. Its ASCII code is decimal 10 (hex 0x0A).

some single byte non-printable characters are represented with a '' and a character (see wiki)

Except, it is '\n' not '/n'.

thanks

Great comment:

UKHeliBob:
Which of the many different side_2 variables in your sketch is causing the problem ?

Multiple variables with the same name and different scopes is not a good idea

And with that, I've made much progress and my code works (see code attachment). However, I'm a bit unsure why, regarding two issues:

  1. In the first while loop, I have to use a for loop to limit the printing prompt of entering side 1. However, on all subsequent while loops - I can exclude a for loop as it only prints once in those. Why?

  2. In the first while loop, the line

if (Serial.available() > 0)

is used to check for if any data has been entered into the serial monitor. However, on all subsequent while loops, I can exclude it. I figured I’d need to check the buffer each time, but apparently not. Why?

math_formulas_user_entry_7.ino (7.15 KB)

project_science:
However, on all subsequent while loops, I can exclude it. I figured I’d need to check the buffer each time, but apparently not. Why?

I didn't look at your code. But based on similar questions, I would guess that it is because your code runs slower than the rate of characters coming in, so that there "happens" to be a character available when you get one. But it is timing dependent, so in fact, you should first check for available(), always!

you should first check for available(), always!

That was a great clue. It appears I was "doubling up" on checking Serial.available(). Once in side 1, but it was also contained within the function, ReadLine(myData), which I was calling for upon the prompt for each side entry.

Only problem remains is why I don't have to limit printing of text for each side entry. In fact, I was able to remove the for loop prompt all together. (I even tried switching the baud from 9600 to 115200, but result was unchanged.)

So it appears that after I ask user to enter a side, program will hang forever, until a side is entered. It's exactly what I want to do, but I'm not sure why it's working. Thoughts?

/*  Goal: Feed dimensions of Rectangle into serial monitor, and have cpu do calculations on it 
 *  
 *  a)  enter sides of a Rectangle to find volume, hitting return after each entry
 *  
 *  b)  combine data into 1D array format and only hit enter once [length, width, height], optional

    
    Serial Monitor Notes (helpful): https://forum.arduino.cc/index.php?topic=396450
 */


/***** GLOBAL VARIABLES *****/

// these will be populated when user enteres data.  Initialize to 0.
int side_1 = 0;  // length
int side_2 = 0;  // width
int side_3 = 0;  // height

int area;
int volume;

int i = 0;  // for loop uses it for printing

char myData[20]; // create an array size of 20 elements, 
                                           /*  If Arduino rec. only use the data type char for storing characters, then it follows
                                            *     to only use a data type char for an array if holding the characters
                                            */
int bufferCount;  // used for passing parameter, char array 'myData', into the arguements of function ReadLine()


/***** FUNCTION PROTOTYPES *****/

// get data from serial monitor
int ReadLine(char);

// area of Rectangle
int areaRectangle(int, int); 

// volume of Cube
int volumeCube(int, int, int);


/***** SETUP *****/
void setup() 
{
  Serial.begin(9600);
}


/***** VOID LOOP *****/
void loop() 
{

 /***** SIDE 1 *****/     
while(true)
{
  
 if (side_1 == 0) // no data has been entered
     {
         Serial.print("enter side 1: ");
         bufferCount = ReadLine(myData);   //Passes parameter, char array 'myData', into the arguements of function ReadLine() for the following:
         side_1 = atoi(myData);  // converts contents of char array (which is a string) to int data type
         Serial.println(side_1);
     }

     else // data was entered
      {break;}
 } 
    

/***** SIDE 2 *****/
while(true)
{   
  if (side_2 == 0) // no data has been entered
     {
        Serial.print("enter side 2: ");
        bufferCount = ReadLine(myData);   //Passes parameter, char array 'myData', into the arguements of function ReadLine() for the following:
        side_2 = atoi(myData);  // converts contents of char array (which is a string) to int data type
        Serial.println(side_2);
     }

     else // data was entered
      {break;}
}

    
/***** SIDE 3 *****/
while(true)
  {
     if (side_3 == 0) // no data has been entered
     {
        Serial.print("enter side 3: ");
        bufferCount = ReadLine(myData);   //Passes parameter, char array 'myData', into the arguements of function ReadLine() for the following:
        side_3 = atoi(myData);  // converts contents of char array (which is a string) to int data type
        Serial.println(side_3);
     }

      else // data was entered
        {break;}
  }
  
/***** END Serial Monitor Input *****/


// print calculations  
   for(i; i < 1; i++)
  {
    Serial.println();  // line skip
    area = areaRectangle(side_1, side_2);  
    volume = volumeCube(side_1, side_2, side_3);  
  }


}   
/***** END OF LOOP *****/



/***** FUNCTIONS *****/

// area of a Rectangle
int areaRectangle(int side_1, int side_2)   
  {
    area = side_1 * side_2;   
    Serial.print("area of rectangle = ");
    Serial.println(area);
    return area;  
  }

// volume of a Rectangle
int volumeCube(int side_1, int side_2, int side_3)   
  {
    volume = side_1 * side_2 * side_3;   
    Serial.print("volume of cube = ");
    Serial.println(volume);
    return volume;  
  }



// get data from serial monitor
/*****
 * Purpose:  Read data from serial port until newline characater is read ('\n')
 * 
 * 2 Parameters:
 *     Character Array, which will strore contents entered from serial monitor
 *         char myData[]  // the character array, 'myData', and will be treated it as a nul-terminating string
 *  
 *     Return value:
 *         int   // the number of characters read for the string, using int index
 *    
 *  CAUTION:  This method will sit here forever if no input is read from the serial monitor port and no newline character is entered. (if that a bad thing?)
 *  
 *****/ 

 int ReadLine(char myData[])  // passes parameter array, 'myData[]' into the arguement of the function, 'Readline()'
 {
    char new_character;    /* stores each character as entered into the serial monitor, which gets passed, one by one, into the buffer
                              It’s recommended to only use char for storing characters. source: https://www.arduino.cc/reference/en/language/variables/data-types/char/
                           */
  
    
    int index = 0;        /*  counter for storing incoming characters entered into array 'myData[]'
                              
                              Each new var 'c' entered will increase the position 
                              of the array which the new character is entered in. This will con't until a '\n' is read via the while loop,
                              as long as there is data in the buffer (hence the statement, Serial.available() > 0)
                          */
  
    while (true)
    {
      if (Serial.available() > 0)
        {
          new_character = Serial.read(); // all data entered into the serial monitor by default is a char
          
          if (new_character != '\n')    // \n is C programmning code for indicating that the Enter button was pressed
            {
              myData[index++] = new_character;  // place character into char array myData at +1 element position
            }
  
           else
             {
               myData[index] = '\0';  // add a null termination character to the string
                     
               break;              /* Used to break out of the while loop (even if nesting occurs), hence ending reading from the serial buffer
                                      That occurs is that the break returns a "false" paramtere to the while() function, which ends the loop
                                      The code will then con't to next line of code after the while loop, which here is "return index"
                                   */                                
           }
      }
  }

  return index;            // returns the counter value of var index to var bufferCount
 }