Working with negative numbers from a serial read string

Hello all,
This is my first post on any forum, ever. Please excuse any ignorance on my part!

I've been programming Arduino boards for several years now, and am finally getting past the beginner "if blank, then digitalWrite HIGH stuff.

I'm building a scaled down model of a motion flight simulator platform to get it working before I start the big project of the full scale version. I'm going to be using Microsoft flight simulator FSX and sending data to my Arduino board using Link2fs (jimspage.co.nz). Using an MPU6050 gyro and accelerometer to measure the difference between the sim's angle, and FSX pitch and roll data.

My problem is this:
The aircraft pitch data is sent to my Arduino via serial, and sent in this format: <Q-002.6
the first two letters identify what kind of data (in this case, pitch (<Q)) followed by the neg or pos pitch angle in degrees. I've tried to change the incoming string to an int by using the toInt() function which works great! Only problem is that I can't get the expected values to print to the serial monitor screen.

For example, the aircraft is pitched down 2 degrees in FSX, Link2fs is sending my Arduino the string <Q+002.0 (Positive is down). I'm unable to get the Arduino to distinguish the positive or the negative angles I'm seeing on the serial monitor. (I'd like to invert them so positive is up). I'm ALWAYS getting positive numbers when the aircraft is pitched up or down. Here's the code I'm trying (an example I've changed that came with the Link2fs program to do what I want):

/* 
    This code is in the public domain
    For use with "Link2fs_Multi"
    Jimspage.co.nz
    My thanks to the Guys that gave me snippets of code. 
    
    This sets the complete Arduino card for "keys" input except pin 13.
    Attach a switch to any pin (except 13) and program that pin in "Multi"
    Pin 13 is used for the servo to indicate flaps.
    For this servo code to work you must tick "<G" (Flap position) in Multi.
    Everything to do with "Keys"  starts with a "K" in this code.

*/



int CodeIn;// used on all serial reads
int KpinNo; 
int Koutpin;
String flaps;
String pitch;
String pitchPosOrNeg = "";
String rollPosOrNeg = "";
bool pitchUp = false;
bool rollRight = false;

String KoldpinStateSTR, KpinStateSTR, Kstringnewstate,Kstringoldstate;

void setup() 
{
  Kstringoldstate = "111111111111111111111111111111111111111111111111111111111111111111111";
  
  for (int KoutPin = 2; KoutPin < 70; KoutPin++)// Get all the pins ready for "Keys"  
  {
    pinMode(KoutPin, INPUT);
    digitalWrite(KoutPin, HIGH);  
  }
 Serial.begin(115200); 
 pinMode(13, OUTPUT);// For the servo.
  
}

void loop() {
  {KEYS();} //Check the "keys" section
  if (Serial.available()) {
    CodeIn = getChar();
    if (CodeIn == '=') {EQUALS();} // The first identifier is "="
    if (CodeIn == '<') {LESSTHAN();}// The first identifier is "<"
    if (CodeIn == '?') {QUESTION();}// The first identifier is "?"
    if (CodeIn == '/') {SLASH();}// The first identifier is "/" (Annunciators)
  }

}

char getChar()// Get a character from the serial buffer
{
  while(Serial.available() == 0);// wait for data
  return((char)Serial.read());// Thanks Doug
}

void EQUALS(){      // The first identifier was "="
 CodeIn = getChar(); // Get another character
  switch(CodeIn) {// Now lets find what to do with it
    case 'A'://Found the second identifier
       //Do something
    break;
     
    case 'B':
       //Do something
    break;
     
    case 'C':
       //Do something
    break;
     }
}

void LESSTHAN(){    // The first identifier was "<"
CodeIn = getChar(); // Get another character
  switch(CodeIn) {// Now lets find what to do with it
    case 'Q'://Found the second identifier
       pitch = "";
       pitchPosOrNeg = "";
       pitchPosOrNeg += getChar();
       if(pitchPosOrNeg = "+"){
        pitchUp = false;
       }
       else{
        pitchUp = true;
       }
       pitch += getChar();
       pitch += getChar();
       pitch += getChar();
       getChar();
       getChar();
       int pitchDeg;
       pitchDeg = pitch.toInt();
       Serial.print("Pitch: ");
       if(pitchUp = false){
        pitchDeg *= -1;
        Serial.println(pitchDeg);
       }
       else{
       Serial.println(pitchDeg);
       }
    break;
     
    case 'B':
       //Do something
    break;
     
    case 'G'://Found the second identifier ("G" Flaps position)
      
    break;
     }
}

void QUESTION(){    // The first identifier was "?"
CodeIn = getChar(); // Get another character
  switch(CodeIn) {// Now lets find what to do with it
    case 'A'://Found the second identifier
       //Do something
    break;
     
    case 'B':
       //Do something
    break;
     
    case 'C':
       //Do something
    break;
     }
}
void SLASH(){    // The first identifier was "/" (Annunciator)
  //Do something
}
void KEYS() 
{
  Kstringnewstate = "";
  for (int KpinNo = 2; KpinNo < 70; KpinNo++){
    KpinStateSTR = String(digitalRead(KpinNo)); 
    KoldpinStateSTR = String(Kstringoldstate.charAt(KpinNo - 2));
    if (KpinStateSTR != KoldpinStateSTR)
    {
      if (KpinNo != 13){
      //Serial.print ("D"); 
      //if (KpinNo < 10) Serial.print ("0");
      //Serial.print (KpinNo);
      //Serial.println (KpinStateSTR);
      }
    }
    Kstringnewstate += KpinStateSTR;
  }
  Kstringoldstate = Kstringnewstate;
}

I've written the "Void lessthan, case Q" section.
Any help would be great! I tried setting a bool operator to determine if it's up or down, but I'm scratching my head.

Thanks in advance!

This maybe?

      if (pitchPosOrNeg = "+") {

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text. The parsing will easily deal with negative values.

...R

Or this if(pitchUp = false){

Robin2:
Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text. The parsing will easily deal with negative values.

...R

Robin2, you are awesome! I ate that article up, and solved my issue! I didn't know that there was a Serial.parseFloat(). That was exactly what I needed. A lot of the other information on that site is very cool. Here's my (Very shortened) fixed code snipit for anybody who is interested in the solution:

float pitch = 0.0; //I added this before void setup.

void LESSTHAN(){    // The first identifier was "<"
CodeIn = getChar(); // Get another character
 switch(CodeIn) {// Now lets find what to do with it
   case 'Q'://Found the second identifier
      pitch = 0.0;
      pitch += Serial.parseFloat();//returns the first valid floating point number from the Serial 
                                               //buffer. Characters that are not digits (or the minus sign) are 
                                               //skipped. parseFloat() is terminated by the first character that  
                                               //is not a floating point number. (taken from Arduino website)
      pitch *= -1; //Inverts the number so a pitch up is a positive number.
      Serial.print("Pitch: ");
      Serial.println(pitch);
    break;

You completely missed the point of Robin2's thread 8)

sterretje:
You completely missed the point of Robin2's thread 8)

But it's nice to be awesome even if it is for the wrong reason :slight_smile:

...R

sterretje:
You completely missed the point of Robin2's thread 8)

Please share! I got my code behaving exactly how I wanted because of the post. If somehow, something went over my head, I'm always willing to take some criticism. And learn something new. I understand that in the post, it says Serial.parseFloat() is a "serial blocking event", but that's not an issue in this case. I'm using 3 Arduino boards (long story), and the only function for this board is getting the serial output from Link2fs, and sending it to another board which takes care of all the calculations and motor controls. I also can't choose the data sent to the Arduino from Link2fs, so I have to work with what I've got (no end markers, or "constant" start markers).

It's not criticism.

The use if the String class in an Arduino is often a recipe for difficult to trace problems. Using character arrays is a far more solid approach.

Further parseFloat is a blocking function (something one usually tries to prevent) and any hick ups in communication might make it convert incorrectly.

Your code should basically first read a full message and next parse it. Robin2's second example might do for the reading. One of the examples uses atoi() to convert a number to an integer; to convert floats, you can use atof().

sterretje:
It's not criticism.

The use if the String class in an Arduino is often a recipe for difficult to trace problems. Using character arrays is a far more solid approach.

Further parseFloat is a blocking function (something one usually tries to prevent) and any hick ups in communication might make it convert incorrectly.

Your code should basically first read a full message and next parse it. Robin2's second example might do for the reading. One of the examples uses atoi() to convert a number to an integer; to convert floats, you can use atof().

I appreciate that! I'll give it a go instead of taking the easy way out with parseFloat. That post was my first introduction to atoi() atof() atol() etc. I've been nerding it up all afternoon reading about them. Thank you for helping me out.