简体   繁体   中英

Extracting info from a string

I have been trying to actuate an Arduino Servo with the speed of the car from the game "Assetto Corsa". I have managed to extract the live data from the game using Shared Memory and am trying to send it to the Arduino over the Serial port.

I have not yet managed to represent the actual speed of the car on the Servo, and I am wondering why. I'm pretty sure the problem comes from the Arduino Code, I can extract the speed of the car but I'm unsure how to use it properly. Maybe you could help?

This is the Arduino code extract :

char inData[8];    
char inChar; // Where to store the character read
byte index = 0; // Index into array; where to store the character
int angle = 0;
int newAngle = 0;
int MaxChars = sizeof(inData);
char ch;


      while (Serial.available())
      {
        char ch = Serial.read();
        Serial.write(ch);
        if (index < MaxChars && isDigit(ch))
        {
          inData[index++] = ch;
        }
        else
        {
          inData[index] = 0;
          newAngle = atoi(inData);
          Serial.write(newAngle);
          if (newAngle > 0 && newAngle < 180)
          {
            if (newAngle < angle)
              for (; angle > newAngle; angle -= 1)
              {
                myServo.write(angle);
              }
            else
              for (; angle < newAngle; angle += 1)
              {
                myServo.write(angle);
              }
          }
          index = 0;
          angle = newAngle;
          delay(1000);
        }
      }

And this is the code I am using to extract info from the game and send it to the Arduino :

while (true)
{

    snprintf(Data, sizeof(Data)-1, "%3.3f", pf->speedKmh);

    SP->WriteData(Data, sizeof(Data));              

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    int readResult = SP->ReadData(inData, sizeof(inData));

       printf("\t Bytes read:  %i\n",readResult);

       for (int i = 0; i < sizeof(inData); i++)
       {
           printf("%i", inData[i]);
           inData[i] = 0;
       }
}

Output screenshot : 1个

This is a screenshot of the echo coming from

Serial.write(NewAngle);

I have outlined in yellow the speed of the car. My question is : How do I extract this speed from the data I receive to use it with the Arduino Servo?

Thank you very much!

----------UPDATE----------

It works! Thank you very much, this is what I changed :

snprintf(Data, sizeof(Data)-1, "%3.3f", (int)(pf->speedKmh)*1.0);

Casted the speed to an int and multiplied by 1.0. That seems to have done the trick! It's another case of "Don't know why it doesn't work, change something, don't know why it works!"

The main problem is that these short "messages" (just a number) don't have any framing. A delay or sleep doesn't count as framing, because the two system's times are not synchronized.

I would suggest putting a newline between numbers so you can tell where one number ends and the next begins. And watch out for differences in '\\n' on the two systems... you could explicitly send a (char)10 or (char)13 and watch for the same byte in the receiver. If a character gets dropped, the framing will allow you to resync to the message boundaries. This also lets you eliminate the delay on the Arduino side, a very good thing.

A potential problem is here:

if (index < MaxChars&& isDigit(ch))
{
  inData[index++] = ch;
}
else
{
  inData[index] = 0;

The test should be index < MaxChars-1 because you add one more char for NUL termination.

When printing the received bytes on the xbox, you should put a delimiter between array elements: printf("%i,",inData[i]) The numbers you're looking at could be a 2 and a 3, or a 23, or a 238.

I minor change I would suggest: You are sending a floating-point value, but then you are converting the received string (after stopping at non-digits) to an integer with atoi . The next time through the loop, you will get whatever characters you didn't read yet. You might as well send the value as an integer: (int)(speed*100.0) . This also avoids two other problems: %f3.3 will pad with spaces when speed < 100.0 (the Arduino doesn't look for these); and fractional parts of the speed get truncated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM