Search code examples
carduinoesp8266nodemcuarduino-esp8266

How to generate string from variable in a function and show it by serial port (ESP8266)


I use to program different microcontrollers, but at low level. I mean, I program them to control power converters and so.

However, I am interested in working with the nodemcu (ESP8266) due to the fact that messages can be send via MQTT protocol.

I did a very easy program generating the messages by concatenating strings. Now I am trying to do the same thing but in a more elegant way i.e. with functions. Due to my poor skills, I sweating like a pig trying to figure out what I am doing wrong. Hope you can help me! :D

Here is the code. As you can see, I have a float variable that increases with a counter, just to change its value, you know. Then, I call a function to generate the message and send it to the serial port (later it would be 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);
}

This should generate something like:

Message: 3926.496

Message: 4015.709

Message: 4105.925

But what I read in the serial port is:

Message:
3926.496Message:

4015.709Message:

4105.925

Could you help me a little? I thought Serial.println automatically changed the line.

Thank you so much, community.

Once we have this solved, I have more questions :D


Solution

  • The line:

      //I need to do this. Otherwise, dtostrf doesn't work
      destino ="";
    

    Is quite definitely incorrect, since it makes destino point to a zero length string constant, then dtostrf then writes to that location, which is both constant and too short. The consequent behaviour is undefined. You do need to change the code to make it work, but that is not the correct solution.

    Instead Vbat_en_string should point to a buffer of sufficient length before generamensaje() is called. It also need not be global - you should avoid globals where possible and it is possible in all cases - unfortunately most Arduino sketch examples are poor in this respect and as a "teaching" platform set a bad example:

    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);
    }