Meine Funktion ftoa (float to array) für Arduino und Attiny

Für eine Anwendung für Attiny benötigte ich eine Funktion, die mir Float-Zahlen in ein Character-Arrays (string) umwandeln. Nun, die Funktion gibt es ja mit dtostrf() (= dezimal to string float) in der Standard-IDE, jedoch der dafür benötigte Flash-Speicherplatz veranlasste mich, dafür eine eigene Funktion zu schreiben. Da es aber nicht sinnvoll ist, für eine Funktion eine Library zu schreiben, stelle ich meine Funktion "ftoa" hier zum Kopieren und zum Einfügen in das eigene Programm bereit.


Speicherplatzvergleich:

Vergleich des benötigten Speicherplatzes bei Verwendung der dtostrf()-Funktion zu meiner ftoa()-Funktion für Attiny85:


Verwendung von dtostrf():

char str[10];
float zahl = 23.2345;

void setup() {
  dtostrf(zahl, 1, 3, str);

}

void loop() {
}

Der Sketch verwendet 1.784 Bytes (21%) des Programmspeicherplatzes. Das Maximum sind 8.192 Bytes. Globale Variablen verwenden 19 Bytes (3%) des dynamischen Speichers, 493 Bytes für lokale Variablen verbleiben.


Verwendung von ftoa():

void ftoa(float, char*, byte);

char str[10];
float zahl = 23.2345;

void setup() {
  ftoa(zahl, str, 3);

}

void loop() {
}

//Funktion ftoa (ftoa.txt in den Sketch reinkopieren)

void ftoa(float floatVal, char* floatStr, byte dec)

{

  ..............

}

Der Sketch verwendet 604 Bytes (7%) des Programmspeicherplatzes. Das Maximum sind 8.192 Bytes. Globale Variablen verwenden 31 Bytes (6%) des dynamischen Speichers, 481 Bytes für lokale Variablen verbleiben.


Wie man sieht, benötigt meine Funktion bei der Übersetzung für Attiny85 zwar geringfügig (12 Byte) mehr SRAM-Speicher, jedoch ca. nur ein Drittel des Flash-Speichers (604 Bytes zu 1784 Bytes). Auch bei Verwendung eines Arduino Uno oder Nano zeigt sich ein ähnliches Bild beim Flash-Speicher (788 Bytes zu 2006 Bytes).


Funktion:

void ftoa(float zahl, char* str, byte dec)

Funktion: Umwandlung einer Float-Zahl in ein Character-Array, mit Angabe der Anzahl der Kommastellen und Rundung

Parameter: zahl: Float-Zahl, die in ein Character-Array umgewandelt werden soll

                 str: Character-Array, in dem das Ergebnis der Umwandlung stehen soll

                 dec: Anzahl der auszugebenen Kommastellen (max. 6 Kommastellen)

Rückgabe: keine

Beispiel: Siehe oben unter Speicherplatzvergleich

Bemerkung:

  • Im aufrufenden Programm muss das Character-Array mit so einer Größe definiert werden, dass eine Float-Zahl einschließlich Vorzeichen, Kommapunkt und abschließendem NULL-Zeichen Platz hat. So wäre z.B. für einen gewünschten Zahlenbereich von -99.9999 bis 99.9999 ein Array mit 9 Stellen (char str[9]) erforderlich. Ist der mögliche Zahlenbereich im Vorhinein nicht bekannt, sollte man sicherheitshalber 14-15 Stellen reservieren. Aber man sollte dabei immer die nachfolgende Einschränkung berücksichtigen.
  • Float-Zahlen haben nur eine Genauigkeit von 6-7 Digits. Das bedeutet die Gesamtanzahl der Digits, nicht die Anzahl der Digits auf der rechten Seite des Dezimalpunktes! (Siehe dazu: www.arduino.cc/en/Reference/Float , wo es heißt: Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point.)


Hier meine Funktion ftoa():

Version 1.0

ftoa.txt

Zur Verwendung die Funktion herunterladen und den Text in den eigenen Sketch hineinkopieren.


Testprogramm für die Funktion ftoa():

Das Testprogramm wandelt die Float-Zahl Pi nacheinander in Character Arrays mit 0 bis 6 Kommastellen um und gibt diese am Seriellen Monitor aus.

//Testprogramm für die Funktion ftoa()
//Code fuer Arduino und Attiny
//Author Retian
//Version 1.0


//Prototyp:
void ftoa(float, char*, byte);


char str[12];
float pi = 3.14159265;


void setup() {
  Serial.begin(115200);
}


void loop() {
  for (byte i = 0; i < 7; i++)
  {
    ftoa(pi, str, i);
    Serial.println(str);
    delay(1000);
  }
  Serial.println();
}


//***** Hier beginnt die eingefuegte Funktion ftoa() *****


//Funktion ftoa (float to array)
//Code fuer Arduino und Attiny
//Author Retian
//Version 1.0
void ftoa(float floatVal, char* floatStr, byte dec)
{
  long vk = 0;
  long nk = 0;
  float nkf;
  char vkStr[10] = "\0";
  char nkStr[7] = "\0";
  float f;
  float add;

  //Additionswert und Faktor fuer Rundung festlegen
  //dec = 0: add = 0.5         f = 1
  //dec = 1: add = 0.05        f = 10
  //dec = 2: add = 0.005       f = 100
  //dec = 3: add = 0.0005      f = 1000
  //dec = 4: add = 0.00005     f = 10000
  //dec = 5: add = 0.000005    f = 100000
  //dec = 6: add = 0.0000005   f = 1000000
  f = 1;
  if (dec > 0)
  {
    for (byte i = 0; i < dec; i++) f *= 10;
  }
  add = 0.5 / f;

  if (floatVal >= 0) floatVal += add;
  else floatVal -= add;

  //Vorkommastellen in String wandeln
  vk = (long)floatVal;
  ltoa(vk, vkStr, 10);

  //Nachkommastellen ermitteln
  nkf = abs(floatVal - vk);

  //Anzahl der "Vornullen" der Nachkommastellen ermitteln
  byte z = 0; //Zaehler fuer Anzahl der "Vornullen"
  while (nkf < 0.1)
  {
    nkf *= 10;
    f /= 10;
    if (z < dec) z++;
    else break;
  }

  //Nachkommastellen (ohne Vornullen) in String umwandeln
  nk = (long)(nkf * f);
  if (nk > 0) ltoa(nk, nkStr, 10);

  //Ergebnis-String zusammenstellen
  //
  //Vorkommastellen in Ergebnis-String kopieren
  strcpy(floatStr, vkStr);
  //Dezimalpunkt und Nachkommastellen an Ergebnis-String anhaengen
  if (dec > 0)
  {
    //Dezimalpunkt an Ergebnis-String anhaengen
    strcat(floatStr, ".");
    //Vornullen an Ergebnis-String anhaengen
    if (z > 0)
    {
      for (byte i = 0; i < z; i++) strcat(floatStr, "0");
    }
    //Nachkommastellen (ohne Vornullen) an Ergebnis-String anhaengen
    strcat(floatStr, nkStr);
  }
  //Begrenzer an Ergebnis-String anhaengen
  strcat(floatStr, "\0");
}


//************* Hier endet die Funktion ftoa() *************

Ergebnis:


Bild 1: Ausgabe des Testprogramms am Seriellen Monitor