Serial.print is printing random results

Hello everyone,

I am trying to make a command parser with my arduino. I decided to use the Reverse Polish Notation for input of the commands/values. Therefore I have the following syntax:
I put in a byte. The last digit of the byte says if the inputbyte is a command (1) or a value (0). If the last digit is a 0, the inputbyte is a value and the other 7 digits stand for the value itself.
If the last digit is a 1 we got a command. The first three digits represent the index of the command. The other four digits are not relevant for the problem.

example for the value 114: 1110010 0
example for the command with the index 3: 011 0000 1

I got the four most important commands add, subtract, multiply and divide. They got the following indeces:

command: index: binary:
add 0 000
subtract 1 001
multiply 2 010
divide 3 011

an example how the task 3 + 2 would look like:
reverse polish notation: 3 2 +
my code:
00000110
00000100
00000001

6
4
1

This is my code (only the relevant code):

#include <StackArray.h>

struct solution_type {
  long res;
  String sol;
};

void setup() {
  Serial.begin(9600);
  byte lines[5] = {18, 6, 6, 1, 33};
  solution_type s = runThrough(lines, 5);
  Serial.println(s.res);
  Serial.println(s.sol);
}

void loop() {}

bool isCommand(byte line) {
  if (line % 2 == 0) {
    return false;
  } else {
    return true;
  }
}

solution_type runThrough(byte lines[], int lnnum) {
  solution_type _solution;

  StackArray <long> values;
  StackArray <String> solution;

  for (int i = 0; i < lnnum; i++) {
    delay(1000);
    if (!isCommand(lines[i])) {
      byte value = lines[i] >> 1;
      String strValue = String(value);
      values.push(value);
      solution.push(strValue);
      //Serial.println("pushing value");

    } else if (isCommand(lines[i])) {
      //Serial.println("executing command");
      byte command = lines[i] >> 5;
      long val2 = values.pop();
      long val1 = values.pop();
      
      long interRes = execute(command, val1, val2);
      values.push(interRes);

      String strVal2 = solution.pop();
      String strVal1 = solution.pop();
      bool isCalc1 = false;
      bool isCalc2 = false;

      for (byte j = 0; j < 2; j++) {
        if(strVal1.indexOf(getOperator(j)) != -1)
          isCalc1 = true;
      }
      for (byte j = 0; j < 2; j++) {
        if(strVal2.indexOf(getOperator(j)) != -1)
          isCalc2 = true;
      }

      if (command < 2 || (command < 4 && !isCalc1 && !isCalc2)) {
        solution.push(strVal1 + getOperator(command) + strVal2);
        
      } else if (command > 1 && command < 4 && (isCalc1 || isCalc2)) {
        if(isCalc1) {
          solution.push("(" + strVal1 + ")" + getOperator(command) + strVal2);
        } else {
          solution.push(strVal1 + getOperator(command) + "(" + strVal2 + ")");
        }
        
      } else if (command == 4) {
        solution.push(String(interRes));
        
      } else if (command == 5) {
        //...
      }
    }
  }

  _solution.res = values.pop();
  _solution.sol = solution.pop();
  return _solution;
}

long execute(byte command, long val1, long val2) {
  if (command == 0) {
    return add(val1, val2);

  } else if (command == 1) {
    return subtract(val1, val2);

  } else if (command == 2) {
    return multiply(val1, val2);

  } else if (command == 3) {
    return divide(val1, val2);

  } else if (command == 4) {
    return expandln(val1, val2);

  } else if (command == 5) {
    //return text(val1, val2);

  } else if (command == 6) {
    //?
  }
}

String getOperator(byte command) {
  if (command == 0) {
    return "+";

  } else if (command == 1) {
    return "-";

  } else if (command == 2) {
    return "*";

  } else if (command == 3) {
    return "/";
  }
}


//Befehle

long add(long val1, long val2) {
  long sum = val1 + val2;
  return sum;
}

long subtract(long val1, long val2) {
  long diff = val1 - val2;
  return diff;
}

long multiply(long val1, long val2) {
  long prod = val1 * val2;
  return prod;
}

long divide(long val1, long val2) {
  float fquot = val1 / val2;
  long quot = round(fquot);
  return quot;
}

//String text(String val1, String val2) {
//
//}

long expandln(long val1, long val2) {
  long res = (val1 << 7) + val2;
  return res;
}

When I try to print the result/solution the Serial monitor is starting to print randomly. Sometimes it prints nothing, sometimes it prints any random numbers or results and sometimes but rarest it prints what it should print. Can anyone help?

Give a numerical example on: what you want to enter from the InputBox of Serial Monitor and then what (in response) you want to see on the OutputBox of Serial Monitor.

An example for input (bold):

void setup() {
Serial.begin(9600);
byte lines[5] = {18, 6, 6, 1, 33};
** solution_type s = runThrough(lines, 5);**
Serial.println(s.res);
Serial.println(s.sol);
}

The task would be 9 3 3 + - in RPN.
The output of the Serial monitor should be first the result and the solution:

3
9-3+3

I know that there should be parentheses around 3+3 but I did not include this in the code yet.

That means:
You will enter this: 9 3 3 + - in the InputBox (Fig-1) of Serial Monitor.

In response, you will see the following on the OutputBox of Serial Monitor.
3
9-3+3


Figure-1:

I dont get what you are trying to explain to me. I am not using the Input box of the serial monitor.

badeyy:
I am trying to make a command parser with my arduino. I decided to use the Reverse Polish Notation for input of the commands/values. Therefore I have the following syntax:
I put in a byte. The last digit of the byte says if the inputbyte is a command (1) or a value (0). If the last digit is a 0, the inputbyte is a value and the other 7 digits stand for the value itself.
If the last digit is a 1 we got a command. The first three digits represent the index of the command. The other four digits are not relevant for the problem.[...]

You have used the phrase command parser and the word input; all those have made me to believe that the command comes from the InputBox of the Serial Monitor.

OK. I expressed myself unclearly. The input data comes from measuring data with the arduino. So I am not inputting the command per Serial monitor.

Does anyone have an answer?

Have you looked to fixing the compiler warnings?

Here is some code that does your RPN

#include <StackArray.h>

enum Operators { ADD, SUBTRACT, MULTIPLY, DIVIDE, EXPANDLN };

struct solution_type {
  long res;
  String sol;
};

StackArray <long> stack;


void setup() {
  Serial.begin(9600);
  byte lines[5] = {18, 6, 6, 1, 33};
  long s = runThrough(lines, 5);
  Serial.println(s);
}

void loop() {}

bool isCommand(byte line) {
  if (line & 1 == 0) {
    return false;
  } else {
    return true;
  }
}

long runThrough(byte lines[], int lnnum) {

  for (int i = 0; i < lnnum; i++) {
    delay(1000);
    if (!isCommand(lines[i])) {
      byte value = getValue(lines[i]);
      stack.push(value);
      //Serial.println("pushing value");

    } else if (isCommand(lines[i])) {
      //Serial.println("executing command");
      byte command = getOperator(lines[i]);
      long val2 = stack.pop();
      long val1 = stack.pop();

      long interRes = execute(command, val1, val2);
      stack.push(interRes);
    }
  }
  return stack.pop();
}

long execute(byte command, long val1, long val2) {
  long result = 0;
  switch (command) {
    case ADD:
      result = val1 + val2;
      break;

    case SUBTRACT:
      result = val1 - val2;
      break;

    case MULTIPLY:
      result = val1 * val2;
      break;

    case DIVIDE:
      result = round((float)val1 / val2);
      break;

    case EXPANDLN:
      result = (val1 << 7) + val2;  // This should be an 8 bit shift????
      break;
  }
  return result;
}

byte getValue(byte val) {
  return val >> 1;
}


byte getOperator(byte val) {
  byte command = val >> 5;
  byte op = 0;
  switch ( command ) {
    case ADD:
    case SUBTRACT:
    case MULTIPLY:
    case DIVIDE:
    case EXPANDLN:
      op = command;
      break;

    default:
      Serial.print( "Bad operator " );
      Serial.println( command );
      while (1); // loop forever
  }
  return op;
}


long expandln(long val1, long val2) {
  long res = (val1 << 7) + val2;
  return res;
}

I removed all the String stuff since you do not want to be using the String class, especially on a dynamic stack. You will totally fragment your limited memory and crash the arduino.