发布 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。

您还声明它是一个全局变量,但似乎不需要它是全局变量。最好通过仅在需要的地方提供它来限制其范围。在这种情况下,您似乎可以将distanceduration 都移动到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.2fsnprintf() 格式字符串中 - 这告诉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 开发

MQTT For ESP8266的调试

ESP8266 AT指令开发(基于STC89C52单片机): 测试下诱人的程序(51单片机,8266,MQTT远程通信控制)

阿里云物联网平台配置ESP8266真实设备AT串口连接,支持MQTT协议通信