14

我必须通过计算机管理伺服系统。

所以我必须将管理消息从计算机发送到 Arduino。我需要管理伺服和角的数量。我正在考虑发送类似这样的内容:“1;130”(第一个伺服和角 130,分隔符“;”)。

有没有更好的方法来实现这一点?

这是我的这段代码:

String foo = "";
void setup(){
   Serial.begin(9600);
}

void loop(){
   readSignalFromComp();
}

void readSignalFromComp() {
  if (Serial.available() > 0)
      foo = '';
  while (Serial.available() > 0){
     foo += Serial.read(); 
  }
  if (!foo.equals(""))
    Serial.print(foo);
}

这行不通。有什么问题?

4

7 回答 7

22
  • 您可以使用 Serial.readString() 和 Serial.readStringUntil() 在 arduino 上解析来自 Serial 的字符串
  • 您还可以使用 Serial.parseInt() 从串行读取整数值

代码示例

int x;
String str;

void loop() 
{
    if(Serial.available() > 0)
    {
        str = Serial.readStringUntil('\n');
        x = Serial.parseInt();
    }
}

通过串行发送的值是 "my string\n5",结果是 str = "my string" 和 x = 5

注意:Serial.available() 继承自 Stream 实用程序类。 https://www.arduino.cc/reference/en/language/functions/communication/serial/available/

于 2014-01-07T00:56:56.467 回答
5

这是我发现的一个很棒的潜艇。这非常有帮助,我希望它也对你有用。

这是调用子的方法。

String xval = getValue(myString, ':', 0);

这是子!

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {
    0, -1  };
  int maxIndex = data.length()-1;
  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
于 2013-08-25T05:35:44.760 回答
5

大多数其他答案要么非常冗长,要么非常笼统,所以我想我会举例说明如何使用 Arduino 库通过您的特定示例来完成它:

您可以使用方法Serial.readStringUntilSerial端口读取直到您的分隔符。

然后使用toInt将字符串转换为整数。

举一个完整的例子:

void loop() 
{
    if (Serial.available() > 0)
    {
        // First read the string until the ';' in your example
        // "1;130" this would read the "1" as a String
        String servo_str = Serial.readStringUntil(';');

        // But since we want it as an integer we parse it.
        int servo = servo_str.toInt();

        // We now have "130\n" left in the Serial buffer, so we read that.
        // The end of line character '\n' or '\r\n' is sent over the serial
        // terminal to signify the end of line, so we can read the
        // remaining buffer until we find that.
        String corner_str = Serial.readStringUntil('\n');

        // And again parse that as an int.
        int corner = corner_str.toInt();

        // Do something awesome!
    }
}

当然我们可以稍微简化一下:

void loop() 
{
    if (Serial.available() > 0)
    {
        int servo = Serial.readStringUntil(';').toInt();
        int corner = Serial.readStringUntil('\n').toInt();

        // Do something awesome!
    }
}
于 2015-12-29T19:14:31.627 回答
2

您需要构建一个读取缓冲区,并计算您的 2 个字段(伺服 # 和角)的开始和结束位置。然后您可以读入它们,并将字符转换为整数以在其余代码中使用。像这样的东西应该可以工作(未在 Arduino 上测试,但在标准 C 上测试):

void loop()
        {
            int pos = 0; // position in read buffer
            int servoNumber = 0; // your first field of message
            int corner = 0; // second field of message
            int cornerStartPos = 0; // starting offset of corner in string
            char buffer[32];

            // send data only when you receive data:
            while (Serial.available() > 0)
            {
                // read the incoming byte:
                char inByte = Serial.read();

                // add to our read buffer
                buffer[pos++] = inByte;

                // check for delimiter
                if (itoa(inByte) == ';')
                {
                    cornerStartPos = pos;
                    buffer[pos-1] = 0;
                    servoNumber = atoi(buffer);

                    printf("Servo num: %d", servoNumber);
                }
            }
            else 
            {
                buffer[pos++] = 0; // delimit
                corner = atoi((char*)(buffer+cornerStartPos));

                printf("Corner: %d", corner);
            }
        }
于 2012-06-25T20:59:10.687 回答
1

看起来你只需要更正

  foo = '';  >>to>>  foo = "";

  foo += Serial.read();  >>to>>  foo += char(Serial.read());

我也做了类似的东西..:

void loop(){
  while (myExp == "") {
    myExp = myReadSerialStr();
    delay(100);
  }
}    

String myReadSerialStr() {
  String str = "";
  while (Serial.available () > 0) {
    str += char(Serial.read ());
  }
  return str;
}
于 2015-11-22T23:00:50.653 回答
0

它是通用解析器

struct servo
{
    int iServoID;
    int iAngle;
};

std::vector<std::string> split(const std::string& str, const std::string& delim)
{
    std::vector<std::string> tokens;
    size_t prev = 0, pos = 0;
    do
    {
        pos = str.find(delim, prev);
        if (pos == std::string::npos) pos = str.length();
        std::string token = str.substr(prev, pos-prev);
        if (!token.empty()) tokens.push_back(token);
        prev = pos + delim.length();
    }
    while (pos < str.length() && prev < str.length());
    return tokens;
}

std::vector<servo> getServoValues(const std::string& message)
{
    std::vector<servo> servoList;
    servo servoValue;
    std::vector<std::string> servoString;
    std::vector<std::string> values = split(message, ",");
    for (const auto& v : values)
    {
        servoString.clear();
        servoString = split(v, ";");
        servoValue.iServoID = atoi(servoString[0].c_str()); //servoString[0].toInt();
        servoValue.iAngle = atoi(servoString[1].c_str());// servoString[1].toInt();
        servoList.emplace_back(servoValue);
    }
    return servoList;
}

打电话:

std::string str = "1;233,2;123";
std::vector<servo> servos = getServoValues(str);
for (const auto & a : servos)
    std::cout<<a.iServoID << " " << a.iAngle << std::endl;

结果

1 233
2 123
于 2020-06-25T13:50:37.523 回答
0

此代码读取字符串,直到看到'>'字符

void loop() {
  // put your main code here, to run repeatedly:
  String msg = getMessage();
}

String getMessage() {
  String msg = "";

  while (Serial.available()>0) {
    msg =  Serial.readStringUntil('>');
  }
  return msg;
}
于 2020-06-02T17:32:46.233 回答