Lisa
Lisa

Reputation: 41

Sending multiple values through serial port

I am using an Arduino UNO for a project, however I don't know how to go about achieving what I want. I'm also a beginner therefore I sometimes don't know how to use some functions to do what I want.

I basically want to send 3 values through the serial monitor all at once.

The first value is a string that points to an operator (A, S, M, D, P), and then I want to take 2 more values. For example, if I input 'A012556 it should add 12 and 556 which will give me 568.

Currently I am doing exactly this, but it's asking for each input separately. For example, it will ask for the operator (I can only input ints because I cannot get it to take string/chars) first, where I will input 1 (should be A for addition), and then it asks for the first number, and then the second number, and then adds them both together and outputs the result. This works fine, but it's not what I'm trying to achieve.

  Serial.println ("Enter your chosen operator");
  Serial.println ("A for Addition, S for Subtraction, M for Multiplication,");
  Serial.println ("D for Division, and P for Potentiometer: ");

  // Takes an input from the user
  int theOperator = dataInput();

  if (theOperator == 1) {
    // If input is equal to 1, carry out function 'addition()'
    addition();
  } else if ..............

Above is in the loop function currently, and it points to the function below. This is the same for subtract/multiply/divide/etc.

  void addition() {

  Serial.println ("A");
  Serial.println ("Please enter first number in format nnn: ");
  firstNumber = dataInput(); // Asks the user to input the first set of numbers

  /* Message must be in format cnnnnnn
     therefore first number must be greater than or equal to -99 and less than or equal to 999*/
  if (firstNumber >= -99 && firstNumber <= 999) {
    Serial.println (firstNumber); // Prints the first set of numbers for the user to view
  }
  else {
    /* If the data input does not match the format cnnnnnn then this error message will display
       if the input is invalid the red LED will also turn on */
    digitalWrite(LED_RED, HIGH);
    Serial.println ("--------------- ERROR ---------------");
  }

  Serial.println ("Please enter second number in format nnn: ");
  secondNumber = dataInput(); // Asks the user to input the second set of numbers

  /* Message must be in format cnnnnnn
     therefore second number must be greater than or equal to -99 and less than or equal to 999*/
  if (secondNumber >= -99 && secondNumber <= 999) {
    // The LED will turn off if it was previously on because this is a valid input
    digitalWrite(LED_RED, LOW);
    Serial.println (secondNumber); // Prints the second set of numbers for the user to view
  }
  else {
    digitalWrite(LED_RED, HIGH);
    Serial.println ("--------------- ERROR ---------------");
  }

  /* Give time for the red error LED to stay on
     for the user to notice he/she has made an invalid input */
  delay(500);
  digitalWrite(LED_RED, LOW);

  // As this case is for addition, it will add the first and second numbers
  value = (firstNumber + secondNumber);

  Serial.print("Value: ");
  // Prints the value of the two sets of numbers so that the user can see the value of their message
  Serial.println(value);
}

Therefore is there any way of doing this? Do I need something like a substring?

Thank you in advance, any advice would be appreciated.

Upvotes: 3

Views: 3496

Answers (2)

Ihdina
Ihdina

Reputation: 1760

#include <string.h>
#include <SoftwareSerial.h>

#define RX_TIMEOUT = 5000; // wait until 5 second

void initSerial() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect
  }
}

int hex2int(char *hexStr) {
    int v = 0;
    while (*hexStr) {
        char c = *hexStr++; 

        if (c >= '0' && c <= '9') c = c - '0';
        else if (c >= 'a' && c <='f') c = c - 'a' + 10;
        else if (c >= 'A' && c <='F') c = c - 'A' + 10;    

        v = (v << 4) | (c & 0xF);
    }
    return v;
}

int main(){
    char data[128];

    initSerial();

    while (1) {
          // operator A
          // value1 ranges = 0x0000 - 0xFFFF (hex 2 bytes);
          // value2 ranges = 0x0000 - 0xFFFF (hex 2 bytes);
          // 
          // value1 = 10 (decimal) = 00 0A (hex 2 bytes)
          // value2 = 20 (decimal) = 00 14 (hex 2 bytes)
          // A  00 0A  00 14 
          Serial.println ("Enter A000A0014");

          unsigned long startTime = millis();
          int i = 0;
          do {
            int length = Serial.available();
            if(length > 0) {
                if(i >= 128) {
                    break;
                }
                data[i++] = Serial.read();
            }
          } while ( millis() - startTime < RX_TIMEOUT);              
          data[i] = '\0';

          if(data[0]== '\0') {
            Serial.println ("Time out.., try again!");
            continue;
          }

          char c1[2], c2[2];
          int v1, v2, v3;

          memcpy(c1, &data[1], 2); // data[1], data[2]
          v1 = hex2int(c1);

          memcpy(c2, &data[3], 2);  // data[3], data[4]
          v2 = hex2int(c2);

          switch(data[0]){
            case 'A':                   
                v3 = v1 + v2;
                Serial.write(v3);
                break;

            case 'S':                   
                v3 = v1 - v2;
                Serial.write(v3);
                break;

            case 'M':
                v3 = v1 * v2;
                Serial.write(v3);
                break;

            case 'D':
                v3 = v1 / v2;
                Serial.write(v3);
                break;

            case 'P':
                // todo
                break;

            default:
                // else
                break;
          }
    }
    return 0;
}

Upvotes: 1

Micha&#235;l Roy
Micha&#235;l Roy

Reputation: 6471

Yes, a substring is what you need.

Fortunately, String provides a substring function.

https://www.arduino.cc/en/Reference/StringSubstring

You code could look a bit like this:

// expecting operation in for "oxxxyyy" where o is the operator, xxx, yyy operands.

   bool ParseOperation(String& strInput, char& op, int& x, int& y)
   {
       if (strInput.length() != 7)
           return false;

       op = strInput[0];
       x = atoi(strInput.substring(1, 4).c_str());
       y = atoi(strInput.substring(4).c_str());
       return true;
   }

   // call as:

   void loop()
   {
       String str;
       char op;
       int r, x, y;

       // read user input into str...

       if (ParseOperation(str, op, x, y))
       {
           switch(op)
           {
           case 'A': case 'a': 
               op = '+'; 
               r = x + y; 
               break;

           // etc...

           default:
                // print some error message...
                break;
           }
           // print x op y = r
       }
       else
       {
            // print error message...
       }
   }

Upvotes: 1

Related Questions