Arduino 使用 sscanf 读取浮点数
Posted
技术标签:
【中文标题】Arduino 使用 sscanf 读取浮点数【英文标题】:Arduino Reading floating point numbers with sscanf 【发布时间】:2019-11-21 13:12:45 【问题描述】:我正在尝试使用 sscanf() 读取数字,但我使用双变量没有成功,但可以读取 int
双重示例
//double var reading not working
const char KBuffer[80] = "0x3:2.1:2.1:2.1";
int rt;
double p,i,d;
int n = sscanf(KBuffer, "%x:%lf:%lf:%lf", &rt, &p, &i, &d);
Serial.println();
Serial.print("rt "); Serial.print(rt);
Serial.print(" P ");Serial.print(p);
Serial.print(" i ");Serial.print(i);
Serial.print(" d ");Serial.print(d);
// 输出 rt 3 P 0.00 i ovf d 0.00
整数示例
// int reading working ok
const char KBuffer[80] = "0x3:2:2:2";
int rt;
int p,i,d;
int n = sscanf(KBuffer, "%x:%d:%d:%d", &rt, &p, &i, &d);
Serial.println();
Serial.print("rt "); Serial.print(rt);
Serial.print(" P ");Serial.print(p);
Serial.print(" i ");Serial.print(i);
Serial.print(" d ");Serial.print(d);
// output
rt 3 P 2 i 2 i 2
所以知道做错了什么
当我在 c++ 在线编译器上运行时相同的代码,例如:https://onlinegdb.com/ryS8zfE3r
我得到了正确的结果
【问题讨论】:
"%d:%lf:%lf:%lf"
-> "%x:%lf:%lf:%lf"
@Jabberwocky 恐怕还不够
@Jabberwocky 我更新了它,有点错误但问题是一样的
@SamVarshavchik Arduino 语言是具有 C++ 语法和非标准库的 C++ 编译器。
@AnttiHaapala 它是没有 90% 的 C++ 的 C++ 变体 - 对标准 C++ 库的支持非常有限
【参考方案1】:
即使第一次转换顺利,arduino scanf 也不会读取浮点数,printf 也不会打印它们。 scanf 和 printf 系列函数默认不支持浮点数。
第一个问题很容易排序:int n = sscanf(KBuffer, "0x%x:%d:%d:%d", &rt, &p, &i, &d);
第二个需要通过添加-Wl,-u,vfscanf -lscanf_flt -lm
来更改编译器(或链接器)选项,但 irt 会增加大约 15kb 的图像大小。
在安装板库的目录中的hardware/tools/avr/doc/avr-libc/group__avr__stdio.html
中阅读更多信息
【讨论】:
【参考方案2】:花了一段时间后,我得出结论,sscanf 无法处理浮点/双精度值,因此为了解决通过串行通信输入浮点数的问题,我采用了另一种方法,分享它可能会对某人有所帮助
void setup()
Serial.begin(9600);
void loop()
char KBuffer[80] = "c:0x3;p:2.12;i:2.15;d:2.17";
bool top_pid_input = false;
// Read each command pair
char* command = strtok(KBuffer, ";");
while (command != NULL)
// Serial.print(command);
// Split the command in two values
char* separator = strchr(command, ':');
if (separator != 0)
// Actually split the string in 2: replace ':' with 0
*separator = 0;
// string
if(strcmp(command, "c") == 0 )
top_pid_input = true;
Serial.println();Serial.print(" command: ");Serial.print(command);
++separator;
Serial.print(separator);
else if(top_pid_input && strcmp(command, "p") == 0 )
Serial.println();Serial.print(" p: ");Serial.print(command);
++separator;
Serial.print(separator);
else if(top_pid_input && strcmp(command, "i") == 0 )
Serial.println();Serial.print(" i: ");Serial.print(command);
++separator;
Serial.print(separator);
else if(top_pid_input && strcmp(command, "d") == 0 )
Serial.println();Serial.print(" d: ");Serial.print(command);
++separator;
Serial.print(separator);
// convert char to float
top_kd = atof(separator);
// Find the next command in input string
command = strtok(0, ";");
delay(300000);
【讨论】:
【参考方案3】:编辑:问题已被编辑,因此此答案不再相关。
根据man pages对scanf()
家庭功能:
返回值 这些函数返回输入项的数量 成功匹配和分配,可以少于提供的 在早期匹配失败的情况下,甚至为零。
您应该检查代码中的返回值n
,以查看转换是否失败。
这里,第一次转换失败:%d
无法读取十六进制数字。再次从手册页:
d
匹配一个可选的有符号十进制整数;下一个指针必须是 一个指向 int 的指针。
您必须改用%x
:
x
匹配一个无符号的十六进制整数;下一个指针必须是 指向无符号整数的指针。
因为第一次转换失败,所以其他的转换都没有执行。
【讨论】:
@P__J__ 你能解释一下吗? @Jabberwocky 看看我的回答 你看过这个问题的原始版本吗?格式使用%d
而不是%x
所以rt
为0,因为第一次转换失败。你描述的不是不符合的行为。嵌入式系统中的浮点数通常需要额外的链接标志。但是添加这些标志不会使原始代码成为 IMO。以上是关于Arduino 使用 sscanf 读取浮点数的主要内容,如果未能解决你的问题,请参考以下文章
ValueError:无法将字符串转换为浮点数:使用 matplotlib、arduino 和 pyqt5 时
Arduino对串口接收到的数据处理以及对整数或者浮点数数据进行提取