从字符串中提取信息
Extracting info from a string
我一直在尝试用游戏中的汽车速度来驱动 Arduino 伺服系统 "Assetto Corsa"。我已经设法使用共享内存从游戏中提取实时数据,并试图通过串行端口将其发送到 Arduino。
我还没有设法在伺服上代表汽车的实际速度,我想知道为什么。我很确定问题出在 Arduino 代码上,我可以提取汽车的速度,但我不确定如何正确使用它。也许你能帮忙?
这是 Arduino 代码摘录:
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);
}
}
这是我用来从游戏中提取信息并将其发送到 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:
这是来自
的回声截图
Serial.write(NewAngle);
我用黄色勾勒出了汽车的速度。我的问题是:如何从接收到的数据中提取这个速度以与 Arduino Servo 一起使用?
非常感谢!
------------更新----------
有效!非常感谢,这是我改变的:
snprintf(Data, sizeof(Data)-1, "%3.3f", (int)(pf->speedKmh)*1.0);
将速度转换为 int 并乘以 1.0。这似乎已经成功了!这是 "Don't know why it doesn't work, change something, don't know why it works!"
的另一种情况
主要问题是这些短 "messages"(只是一个数字)没有任何框架。延迟或睡眠不算作帧,因为两个系统的时间不同步。
我建议在数字之间加一个换行符,这样您就可以知道一个数字在哪里结束,下一个数字从哪里开始。并注意两个系统上 '\n' 的差异...您可以显式发送 (char)10
或 (char)13
并在接收器中观察相同的字节。如果字符丢失,框架将允许您重新同步到消息边界。这也可以让您消除 Arduino 端的 delay
,这是一件非常好的事情。
这里有一个潜在的问题:
if (index < MaxChars&& isDigit(ch))
{
inData[index++] = ch;
}
else
{
inData[index] = 0;
测试应该是 index < MaxChars-1
因为你为 NUL 终止添加了一个字符。
当在 xbox 上打印接收到的字节时,您应该在数组元素之间放置一个分隔符:printf("%i,",inData[i])
您正在查看的数字可能是 2 和 3,或 23,或 238 .
我建议进行微小的更改:您正在发送一个浮点值,但随后您将接收到的字符串(在非数字处停止后)转换为具有 atoi
的整数。下一次循环时,你会得到你还没有读过的任何字符。您也可以将值作为整数发送:(int)(speed*100.0)
。这也避免了另外两个问题:当速度 < 100.0 时,%f3.3 将用空格填充(Arduino 不寻找这些);和速度的小数部分被截断。
我一直在尝试用游戏中的汽车速度来驱动 Arduino 伺服系统 "Assetto Corsa"。我已经设法使用共享内存从游戏中提取实时数据,并试图通过串行端口将其发送到 Arduino。
我还没有设法在伺服上代表汽车的实际速度,我想知道为什么。我很确定问题出在 Arduino 代码上,我可以提取汽车的速度,但我不确定如何正确使用它。也许你能帮忙?
这是 Arduino 代码摘录:
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);
}
}
这是我用来从游戏中提取信息并将其发送到 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:
这是来自
的回声截图Serial.write(NewAngle);
我用黄色勾勒出了汽车的速度。我的问题是:如何从接收到的数据中提取这个速度以与 Arduino Servo 一起使用?
非常感谢!
------------更新----------
有效!非常感谢,这是我改变的:
snprintf(Data, sizeof(Data)-1, "%3.3f", (int)(pf->speedKmh)*1.0);
将速度转换为 int 并乘以 1.0。这似乎已经成功了!这是 "Don't know why it doesn't work, change something, don't know why it works!"
的另一种情况主要问题是这些短 "messages"(只是一个数字)没有任何框架。延迟或睡眠不算作帧,因为两个系统的时间不同步。
我建议在数字之间加一个换行符,这样您就可以知道一个数字在哪里结束,下一个数字从哪里开始。并注意两个系统上 '\n' 的差异...您可以显式发送 (char)10
或 (char)13
并在接收器中观察相同的字节。如果字符丢失,框架将允许您重新同步到消息边界。这也可以让您消除 Arduino 端的 delay
,这是一件非常好的事情。
这里有一个潜在的问题:
if (index < MaxChars&& isDigit(ch))
{
inData[index++] = ch;
}
else
{
inData[index] = 0;
测试应该是 index < MaxChars-1
因为你为 NUL 终止添加了一个字符。
当在 xbox 上打印接收到的字节时,您应该在数组元素之间放置一个分隔符:printf("%i,",inData[i])
您正在查看的数字可能是 2 和 3,或 23,或 238 .
我建议进行微小的更改:您正在发送一个浮点值,但随后您将接收到的字符串(在非数字处停止后)转换为具有 atoi
的整数。下一次循环时,你会得到你还没有读过的任何字符。您也可以将值作为整数发送:(int)(speed*100.0)
。这也避免了另外两个问题:当速度 < 100.0 时,%f3.3 将用空格填充(Arduino 不寻找这些);和速度的小数部分被截断。