#c #arduino #esp8266 #nodemcu #arduino-esp8266
#c #arduino #esp8266 #nodemcu #arduino-esp8266
Вопрос:
Я использую для программирования разные микроконтроллеры, но на низком уровне. Я имею в виду, я программирую их для управления преобразователями питания и так далее.
Тем не менее, я заинтересован в работе с nodemcu (ESP8266) из-за того, что сообщения могут отправляться по протоколу MQTT.
Я создал очень простую программу, генерирующую сообщения путем объединения строк. Теперь я пытаюсь сделать то же самое, но более элегантным способом, то есть с помощью функций. Из-за моих плохих навыков я потею, как свинья, пытаясь понять, что я делаю не так. Надеюсь, вы сможете мне помочь! : D
Вот код. Как вы можете видеть, у меня есть переменная с плавающей запятой, которая увеличивается со счетчиком, просто чтобы изменить ее значение, вы знаете. Затем я вызываю функцию для генерации сообщения и отправки его на последовательный порт (позже это будет MQTT).
#include <string.h> // Libreria para trabajar con caracteres
int contador=1;
float Vbat=2.1; // tension de la bateria
char *Vbat_en_string;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
// This function generates the message. Turns float into string.
void generamensaje(float valor, char* destino)
{
//I need to do this. Otherwise, dtostrf doesn't work
destino ="";
//Saving float "valor" in string "destino"
dtostrf(valor,6,3,destino);
}
void loop() {
generamensaje(Vbat,Vbat_en_string);
Serial.print("Message:");
Serial.println(Vbat_en_string);
contador ;
Vbat = Vbat contador*1.0024;
delay(2000);
}
Это должно генерировать что-то вроде:
Message: 3926.496
Message: 4015.709
Message: 4105.925
Но то, что я прочитал в последовательном порту, это:
Message:
3926.496Message:
4015.709Message:
4105.925
Не могли бы вы мне немного помочь? Я думал, что Serial.println автоматически изменил строку.
Большое вам спасибо, сообщество.
Как только мы решим эту проблему, у меня возникнет больше вопросов: D
Ответ №1:
Строка:
//I need to do this. Otherwise, dtostrf doesn't work
destino ="";
Совершенно определенно неверно, поскольку оно destino
указывает на строковую константу нулевой длины, dtostrf
а затем записывает в это местоположение, которое является постоянным и слишком коротким. Последующее поведение не определено. Вам нужно изменить код, чтобы он работал, но это неправильное решение.
Вместо Vbat_en_string
этого следует указывать на буфер достаточной длины перед generamensaje()
вызовом. Это также не обязательно должно быть глобальным — вам следует избегать глобальных значений, где это возможно, и это возможно во всех случаях — к сожалению, большинство примеров Arduino sketch в этом отношении плохи и в качестве «обучающей» платформы подают плохой пример:
include <string.h> // Libreria para trabajar con caracteres
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
}
// This function generates the message. Turns float into string.
void generamensaje(float valor, char* destino)
{
//Saving float "valor" in string "destino"
dtostrf(valor,6,3,destino);
}
void loop()
{
static int contador=1;
static float Vbat=2.1; // tension de la bateria
char Vbat_en_string[32] ;
generamensaje(Vbat,Vbat_en_string);
Serial.print("Message:");
Serial.println(Vbat_en_string);
contador ;
Vbat = Vbat contador*1.0024;
delay(2000);
}
Комментарии:
1. Я попробую то, что вы говорите. Спасибо Клиффорду 🙂
2. Дорогой Клиффорд, спасибо, что показал мне, я понятия не имею… Ваш код работает отлично. Надеюсь, вы будете рядом, когда я подготовлю свой следующий пост в stack overflow . Приветствую и желаю хорошего дня.
3. Обратите внимание, что единственное изменение, необходимое для работы вашего кода, — это удалить присвоение
Vbat_en_string
ingeneramensaje
и изменить его тип с указателя на массив. Устранение глобальных значений — это просто совет , и потому, что я не мог заставить себя публиковать код с ненужными глобальными значениями, как вопрос профессиональной честности 😉 Стоит прочитать: embedded.com/a-pox-on-globals