发布 HC-SE04 MQTT ESP8266 的值“从 'char' 到 'char*' [-fpermissive] 的无效转换”
Posted
技术标签:
【中文标题】发布 HC-SE04 MQTT ESP8266 的值“从 \'char\' 到 \'char*\' [-fpermissive] 的无效转换”【英文标题】:publish the values of the HC-SE04 MQTT ESP8266 "invalid conversion from 'char' to 'char*' [-fpermissive]"发布 HC-SE04 MQTT ESP8266 的值“从 'char' 到 'char*' [-fpermissive] 的无效转换” 【发布时间】:2022-01-22 06:06:57 【问题描述】:我正在编写代码来做监控,我无法将计算出的距离值转换为 const char* 以在 mqtt 中发布。我能做些什么来解决我的问题?我已经尝试过使用 sprintf 但没有结果。
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#define TOPICO_SUBSCRIBE "..."
#define TOPICO_PUBLISH "..."
#define ID_MQTT "..."
const char* ssid = "...";
char* password = "...";
char* BROKER_MQTT = "broker.hivemq.com";
int BROKER_PORT = 1883;
WiFiClient espClient;
PubSubClient MQTT(espClient);
const int trigPin = 2; //D4
const int echoPin = 0; //D3
long duration;
int distance;
void setup()
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
init_serial();
init_wifi();
init_mqtt();
这里开始我的问题(我削减了代码的 sn-ps 以便能够发布)
void loop()
verifica_conexoes_wifi_mqtt();
MQTT.publish(TOPICO_PUBLISH, "ESP32 se comunicando com MQTT");
MQTT.loop();
delay(1000);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
char msgDistance;
msgDistance = distance;
sprintf(msgDistance,"A distância lida é: ", distance);
MQTT.publish(TOPICO_PUBLISH, msgDistance);
【问题讨论】:
char msgDistance;
将msgDistance
变量定义为单个字符。像您尝试将 sprintf
放入其中一样,它如何适合完整的字符串?
您将 distance
声明为 int。然后你做distance = duration*0.034/2
,它把一个double分配给一个int。最后,您执行msgDistance = distance
,它将一个 int 分配给一个 char。
【参考方案1】:
此代码的问题在于它如何存储距离计算的结果以及如何使用sprintf
来格式化您要传输的消息。
首先,您将distance
定义为int
,这确实不适用于这一行:
distance= duration*0.034/2;
您正在做浮点数学运算。如果将结果存储在 int
中,您将丢失结果的任何小数值。如果结果小于 1,则最终为 0。
您还声明它是一个全局变量,但似乎不需要它是全局变量。最好通过仅在需要的地方提供它来限制其范围。在这种情况下,您似乎可以将distance
和duration
都移动到loop()
中,因此您可以在setup()
之前删除它们的定义并将它们写入loop()
中:
void loop()
long duration;
float distance;
您的sprintf()
代码目前如下所示:
char msgDistance;
msgDistance = distance;
sprintf(msgDistance,"A distância lida é: ", distance);
这有几个问题:
sprintf()
需要将字符数组指针作为其第一个参数。相反,您将其传递给单个字符变量。这没有任何意义,并且会生成您所看到的编译器错误。
sprintf()
需要一个格式字符串来告诉它要打印什么(写为%X
,其中X
是一个字符,表示正在打印的数据类型。您包含了一些文本但没有格式字符串。
sprintf()
可以很容易地溢出它正在打印到的char
数组;你应该改用snprintf()
为了解决第一个问题,我们需要 msgDistance
是一个字符数组:char []
。
您的代码需要看起来更像这样:
char msgDistance[32];
snprintf(msgDistance, sizeof(msgDistance), "A distância lida é: %0.2f", distance);
变化是:
msgDistance
现在是 snprintf()
可以使用的字符数组
删除了对msgDistance
的不必要分配,由于它是char
数组,因此会导致错误
snprintf()
是 sprintf()
的更安全形式 - 它以字符数组的长度作为参数,这样就不会意外溢出数组
sizeof()
是一个内置函数,它在编译时返回变量的大小;这是一种在这里使用数组大小的简单方法,但请注意,如果您不真正了解 C/C++ 数组、指针和字符串,它可能无法达到您的预期效果
%0.2f
在snprintf()
格式字符串中 - 这告诉snprintf()
打印一个float
变量(即f
),如果需要,带有前导零(即0
部分和两个小数位精度(这是2
部分 - 如果你想要一位小数,你可以写成%0.1f
)
您可以使用搜索引擎了解更多关于printf()
格式字符串的信息;网上有很多很好的教程和参考资料。
【讨论】:
以上是关于发布 HC-SE04 MQTT ESP8266 的值“从 'char' 到 'char*' [-fpermissive] 的无效转换”的主要内容,如果未能解决你的问题,请参考以下文章
开源app 控制ESP8266,通过mqtt,app inventor开发
我无法在 Lua 上为 ESP8266 订阅 MQTT 代理
巴法云开源安卓App控制ESP8266,通过MQTT协议,APP Inventor 开发
ESP8266 AT指令开发(基于STC89C52单片机): 测试下诱人的程序(51单片机,8266,MQTT远程通信控制)