Arduino MKR1000 WIFI - dtostrf

Hola. Estoy probando el Arduino MKR1000 WIFI.

Tengo alguna función que no me compila. Una es la “dtostrf”. También una librería que ha veces utilizo para provocar “resets”, la “avr/wdt.h”.
Si el mismo programa lo compilo para Arduino Uno, Mega, Ethernet,... la “dtostrf” y “avr/wdt.h”, funcionan correctamente.

¿Cómo puedo solucionar este tema? Hay alguna alternativa para “dtostrf” y para “avr/wdt.h”

Gracias.

Hola @aprentik lee las normas del foro y mira como se postean los códigos en otros hilos y hazlo con el tuyo asi podemos entender mejor tu problema.

Los programas funcionan pero no todos los Arduinos son AVR. Los MKR tienen otra tecnología y requieres otras consideraciones.
dtostrf es genérica a cualquier tipo de arduino pero "avr/wdt.h" no. Hay que ver puntualmente que estas haciendo o usando para provocar los problemas que mencionas pero que no puedo imaginar al no ver el código.

Gracias @Surbyte.
No puedo poner el código porque está impresentable y no tiene sentido nada de lo que hace, es un código de pruebas donde he probado algunas cosillas que me interesa hacer funcionar. Este Arduino es muy interesante, es muy potente.
Ordenaré este código y lo publicaré, identificando estos problemas que he mencionado.
Gracias.

Aquí el codigo. En el codigo que paso está documentado lo que hace referencia a la libreria avr/wdt.h También la funcion dtostrf.
Tal como está, si se compila.
Es un programa que no hace nada, solo conectarse a la wifi. La funció "RegistreMySQL" se tiene que implementar.

//Arduino MKR1000 WIFI
//Problemas al compilar avr/wdt.h
//Problemas con la funcion dtostrf

#include <WiFi101.h>
#include <SPI.h>
//#include <avr/wdt.h>   // Control de prenjades.

WiFiClient client;
char server[] = "www.google.com";
int status = WL_IDLE_STATUS;
 
char ssid[] = "APTest";           //  your network SSID (name)
char pass[] = "Test2020";         // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)

bool val = true;



int idSonda  = 1011; 
int CO2 = 0 ;
 
void setup() 
  {
  Serial.begin(9600);      // initialize serial communication
  Serial.println(" ");
  Serial.print("Start Serial ");

  // Check for the presence of the shield
  Serial.print("WiFi101 shield: ");
  if (WiFi.status() == WL_NO_SHIELD) 
    {
    Serial.println("NOT PRESENT");
    return; // don't continue
    }
  Serial.println("DETECTED");
  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) 
    {
    
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    // wait 10 seconds for connection:
    delay(10000);
    }
  printWifiStatus();                        // you're connected now, so print out the status
  }

  
void loop() 
  {
  if(!client.available())
    {
      Serial.println("Client no disponible...");
    }
    while (client.available()) 
    {
      char c = client.read();
      Serial.write(c);
      Serial.println(c);
    }
    // if the server's disconnected, stop the client:
    if (!client.connected()) 
    {
      Serial.println();
      Serial.println("disconnecting from server.");
      client.stop();
    }    
    
    RegistreMySQL(idSonda, "CO2", CO2);
    delay(6000);
  }
  

void RegistreMySQL(int idSondaSQL, char IdTipusSondaSQL[], float ValorSQL)
  {
  String response; 
  char idSondaInsertat[4];
  char ValorInsertar[3];  

  //wdt_enable(WDTO_8S);  //8segons es el màxim !!!
  //wdt_reset();
  //wdt_disable();
  
  //dtostrf( idSondaSQL, 1, 0, idSondaInsertat);      // zero decimals
  //dtostrf( ValorSQL, 1, 2, ValorInsertar);       // dos decimals

  
  char INSERT_POST[] = "/ausacontrolapi/api/config";                                                       // <-- *** Línea modificada ***
  char INSERT_BODY[] = "nomUsuari=User&passwordUsuari=Pword&idSonda=%s&idTipusSonda=%s&valor=%s";   // <-- *** Línea afegida ***
  char query[128];
  Serial.println("Fi RegistreMySQL");

 
  }

// Funció temps d'espera entre captura de dades, en minuts-------------------
void Esperem (int minuts)
  {
  Serial.print(" -> Esperant (minuts) :");
  Serial.print( minuts);
  Serial.print(" ");
  for (int a=0; a<minuts; a++)
    {      
    delay(60000);  //60000 es un minut
    Serial.print(".");
    }
  Serial.println (" ");  
  }
// Fi funció temps d'espera--------------------------------------------------

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
 
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
 
  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  // print where to go in a browser:
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
  Serial.println("-----------------------------------------------------------");

Entiendo que estás haciendo pruebas pero atento que el buffer de salida de dtostrf() (tomo el caso de ValorInsertar) se queda "corto".

dtostrf(ValorSQL, 1, 2, ValorInsertar);

Tienes (al menos) 1 caracter para el entero, 2 caracteres para los decimales, un caracter '.' (punto decimal) más un caracter '\0' como finalización de la cadena. Entonces como mínimo tienes 5 caracteres y tu defines el buffer con una longitud de 3

char ValorInsertar[3];

Eso si no provoca un error en tiempo de compilación lo va a provocar en tiempo de ejecución con resultados imprevisibles.

Te aconsejo que definas el buffer como mínimo con 8 caracteres (lo que da lugar suficiente para 6 dígitos mas el '.' y '\0'), o sea

char ValorInsertar[8];

Saludos

Gracias @gatul.
Si tienes razon, Char ValorInsertat[8] mejor. El problema principal es que "dtostrf" no se compila para la Arduino MKRWIFI 1000.

//Arduino MKR1000 WIFI
//Problemas al compilar avr/wdt.h
//Problemas con la funcion dtostrf

#include <WiFi101.h>
#include <SPI.h>
//#include <avr/wdt.h>   // Control de prenjades.

WiFiClient client;
char server[] = "www.google.com";
int status = WL_IDLE_STATUS;
 
char ssid[] = "APTest";           //  your network SSID (name)
char pass[] = "Test2020";         // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)

bool val = true;



int idSonda  = 1011; 
int CO2 = 0 ;
 
void setup() 
  {
  Serial.begin(9600);      // initialize serial communication
  Serial.println(" ");
  Serial.print("Start Serial ");

  // Check for the presence of the shield
  Serial.print("WiFi101 shield: ");
  if (WiFi.status() == WL_NO_SHIELD) 
    {
    Serial.println("NOT PRESENT");
    return; // don't continue
    }
  Serial.println("DETECTED");
  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) 
    {
    
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    // wait 10 seconds for connection:
    delay(10000);
    }
  printWifiStatus();                        // you're connected now, so print out the status
  }

  
void loop() 
  {
  if(!client.available())
    {
      Serial.println("Client no disponible...");
    }
    while (client.available()) 
    {
      char c = client.read();
      Serial.write(c);
      Serial.println(c);
    }
    // if the server's disconnected, stop the client:
    if (!client.connected()) 
    {
      Serial.println();
      Serial.println("disconnecting from server.");
      client.stop();
    }    
    
    RegistreMySQL(idSonda, "CO2", CO2);
    delay(6000);
  }
  

void RegistreMySQL(int idSondaSQL, char IdTipusSondaSQL[], float ValorSQL)
  {
  String response; 
  char idSondaInsertat[4];
  char ValorInsertar[3];  

  //wdt_enable(WDTO_8S);  //8segons es el màxim !!!
  //wdt_reset();
  //wdt_disable();
  
  //dtostrf( idSonda, 1, 0, idSondaInsertat);      // zero decimals
  //dtostrf( ValorSQL, 1, 2, ValorInsertar);       // dos decimals

  
  char INSERT_POST[] = "/ausacontrolapi/api/config";                                                       // <-- *** Línea modificada ***
  char INSERT_BODY[] = "nomUsuari=user&passwordUsuari=pwww&idSonda=%s&idTipusSonda=%s&valor=%s";   // <-- *** Línea afegida ***
  char query[128];
  Serial.println("Fi RegistreMySQL");

 
  }

// Funció temps d'espera entre captura de dades, en minuts-------------------
void Esperem (int minuts)
  {
  Serial.print(" -> Esperant (minuts) :");
  Serial.print( minuts);
  Serial.print(" ");
  for (int a=0; a<minuts; a++)
    {      
    delay(60000);  //60000 es un minut
    Serial.print(".");
    }
  Serial.println (" ");  
  }
// Fi funció temps d'espera--------------------------------------------------

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
 
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
 
  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  // print where to go in a browser:
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
  Serial.println("-----------------------------------------------------------");

Para un Arduino Uno, Mega,... si se compila.
Sino tiene solución tengo que buscar alguna función equivalente.
Gracias

Si no compila es porque MKR tiene soporte para float asi que prueba usar esto

char buffer[20];
float variable_float = 23.45f;
sprinf(buffer,"%f", variable_float);
Serial.println(buffer);

Gracias @Surbyte.

void RegistreMySQL(int idSondaSQL, char IdTipusSondaSQL[], float ValorSQL)
  {
  String response; 
  char idSondaInsertat[6];
  char ValorInsertar[6];  

  //wdt_enable(WDTO_8S);  //8segons es el màxim !!!
  //wdt_reset();
  //wdt_disable();
  
  //dtostrf( idSondaSQL, 1, 0, idSondaInsertat);      // zero decimals
  //dtostrf( ValorSQL, 1, 2, ValorInsertar);       // dos decimals

  sprinf(idSondaSQL,"%f", idSondaInsertat);
  sprinf(ValorInsertar,"%f", ValorSQL);
  
  char INSERT_POST[] = "/ausacontrolapi/api/config";                                                       // <-- *** Línea modificada ***
  char INSERT_BODY[] = "nomUsuari=User&passwordUsuari=Pword&idSonda=%s&idTipusSonda=%s&valor=%s";   // <-- *** Línea afegida ***
  char query[128];

  sprintf(query, INSERT_BODY, idSondaInsertat, IdTipusSondaSQL, ValorInsertar); 
  //sprintf(query, INSERT_BODY, "1017", "CO2", "433"); 
  Serial.print(" Query ->"); Serial.println(query);

  Serial.println("Fi RegistreMySQL");
  }

Tampoco le gusta "sprintf" , el complidor da el error: 'sprint' was not decalred in this scope.
No deveria pasar, ¿no estaré comentiendo algun error?

Creo que he encontrado la soulucion en:

https://forum.arduino.cc/t/dtostrf-function-available-for-mkr-gsm-1400/545654

@pert:
Add this line to your sketch:

#include <avr/dtostrf.h>

Ya se compila el "dtostrf"

1 Like

no es sprinf es sprintf, si lo he escrito mal disculpas.

Si, lo escribí mal. Lleva una t que omití.

gràcias !!!

La libreria “avr/wdt.h” se puede substituir por la "#include <Adafruit_SleepyDog.h>".

He echo unas pruevas i creo que se puede controlar los resets port software, paso el codigo del ejemplo, que seguro es mejorable:

#include <Adafruit_SleepyDog.h>

int countdownMS;

void setup() 
  {
  Serial.begin(9600);
  while (!Serial) 
    delay(10);  
  Serial.println("Adafruit Watchdog Library - test");
  Serial.println();
  
  }

void loop() 
  {

  Serial.println("Enabled the watchdog with max countdown of 4s");  
  countdownMS = Watchdog.enable(4000);


  for (int a=0; a<5; a++)
    {
    delay(1000);
    Serial.print("No reset (s):"); Serial.println(a);
    //Serial.print(countdownMS, DEC); Serial.println(" milliseconds!");
    Watchdog.reset();
    }
  Serial.println("Desactiva watchdog");
  #ifndef NRF52_SERIES // cannot disable nRF's WDT
    // Disable the watchdog entirely by calling Watchdog.disable();
    Watchdog.disable();
  #endif

  Serial.println("Esperem 10s");
  for (int a=0; a<5; a++)
    {
    Serial.print("Segons (s):"); Serial.println(a);  
    delay(1000);
    }

  Serial.println("Enabled the watchdog with max countdown of 4s");
  countdownMS = Watchdog.enable(4000);  
  for (int a=0; a<5; a++)
    {
    delay(1000);
    Serial.print("Si reset si a>3 (s):"); Serial.println(a);
    //Serial.print(countdownMS, DEC); Serial.println(" milliseconds!");
    }    
  Serial.println("Desactiva watchdog");    
  Watchdog.disable();
  
  }

He probado esto y funciona


float var = 13.45f;
void setup() {
  Serial.begin(9600);
  char buffer[20];
  sprintf(buffer, "%f", var);
  Serial.println(buffer);
}

void loop() {
  // put your main code here, to run repeatedly:
}

No tengo MKR solo compilé.

EDITO: ahora amplié la idea usando tu rutina con datos genéricos y tmb compila.

void RegistreMySQL(int idSondaSQL, char IdTipusSondaSQL[], double ValorSQL) {
  String response;
  char idSondaInsertat[6];
  char ValorInsertar[6];

  sprintf(idSondaInsertat, "%d", idSondaSQL);
  sprintf(ValorInsertar,   "%f", ValorSQL);

  char INSERT_POST[] =
      "/ausacontrolapi/api/config"; // <-- *** Línea modificada ***
  char INSERT_BODY[] = "nomUsuari=User&passwordUsuari=Pword&idSonda=%s&"
                       "idTipusSonda=%s&valor=%s"; // <-- *** Línea afegida ***
  char query[128];

  sprintf(query, INSERT_BODY, idSondaInsertat, IdTipusSondaSQL, ValorInsertar);
  // sprintf(query, INSERT_BODY, "1017", "CO2", "433");
  Serial.print(" Query ->");
  Serial.println(query);

  Serial.println("Fi RegistreMySQL");
}

void setup() {
  Serial.begin(9600);
  // void RegistreMySQL(int idSondaSQL, char IdTipusSondaSQL[], float ValorSQL)
  RegistreMySQL(23, "1234", 1.234);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Mil grácias @Surbyte y @gatul.

Hola.
La libreria <avr/dtostrf.h> me ha dejado de funcionar !!!
Da el error: avr/dtostrf.h: No such file or directory.
Ayer funcionava y hoy no !!!!
Mas información. Ayer pare el PC y hoy lo he encendido, no hay mas diferencia que esta !!!
Voy a substituir la funcion dtostrf por la propuesta de @Surbyte y ja no utilizaré esta libreria.

void RegistreMySQL(int idSondaSQL, char IdTipusSondaSQL[], double ValorSQL)
  {
  String response; 
  char idSondaInsertat[6];
  char ValorInsertar[6];  
  
  sprintf(idSondaInsertat, "%d", idSondaSQL);
  sprintf(ValorInsertar,   "%f", ValorSQL);

  char INSERT_POST[] = "/ausacontrolapi/api/config";                                                       // <-- *** Línea modificada ***
  char INSERT_BODY[] = "nomUsuari=user&passwordUsuari=pw&idSonda=%s&idTipusSonda=%s&valor=%s";  // <-- *** Línea afegida ***
  char query[128];

  sprintf(query, INSERT_BODY, idSondaInsertat, IdTipusSondaSQL, ValorInsertar); 
  
  Serial.print(" Query ->"); Serial.println(query);

  //POST
  // ....
  //Fi POST  
  }

Solucionado

Los AVR tienen poca flash y pero estos MKR no, entonces el soporte de punto flotante esta disponible y puedes trabajar directamente con sprintf y todas la potencia que ésta función tiene.