MPLAB X & XC8 – #3: Libreria Float2String per LCD – Parte 3

Libreria per conversione da floating point a stringa…

 

 

 

 

INTRODUZIONE
In questo articolo viene presentata una semplice libreria che effettua la conversione da un numero float ad una stringa di testo, così da poterlo stampare su un display LCD. Questa libreria è pensata per poter lavorare con quella relativa agli LCD presentata in XC8 – #3 – Parte 1. La libreria è stata realizzata avendo come obiettivo principale il contenimento dell’occupazione di memoria, così da poter essere usata all’interno di altri codici senza incidere eccessivamente sulle risorse, caratteristica però che ne riduce la versatilità e i campi di utilizzo.

 

NUMERI FLOATING POINT
In diversi casi può essere utile o necessario lavorare con numeri reali rappresentati tramite i floating point. 
Un floating point è composto da due parti, la mantissa e l’esponente, in maniera da avere:

\(Floating Point = Mantissa * Base^{Esponente}\)

La base è 2 e permette la conversione in bit così da poter memorizzare il numero in un sistema digitale. All’aumentare del numero di bit della mantissa aumenta la precisione con cui si rappresenta il valore, mentre all’aumentare del numero di bit della mantissa aumenta il range di valori che possono essere rappresentati.
Come riportato nella sezione 5.4.3 di “XC8 C Compiler User’s Guide” della Microchip, il compilatore XC8 dispone di 3 tipi per poter rappresentare un floating point e sono float, double e long double.
Un numero floating point è solitamente rappresentato con 32 bit, di cui 24 per la mantissa e 8 per l’esponente. Nel compilatore XC8  di default i tipi float e double hanno 24 bit, 16 per la mantissa e 8 per l’esponente, ma è possibile portarli a 32 bit (24+8) selezionando nel riquadro del progetto “Properties >> Conf >> XC8 Global Options >> XC8 Linker”, selezionare nel menu a tendina “option categories” la voce “Memory Model” e scegliere il numero di bit (24 o 32) con cui rappresentare i tipi float e double (in XC8 long double ha stessa dimensione del double).

 

STAMPA NUMERI FLOATING POINT SU LCD
Utilizzando la libreria per LCD presentata in XC8 – #3 – Parte 1 si riesce a stampare un carattere o un testo. Se però si vuole stampare un numero è necessario passare dal valore numerico ad un valore interpretabile dal codice. 
Se il numero da stampare è rappresentato da una singola cifra è possibile sfruttare la relazione tra valore numerico e carattere ASCII. Le cifre da 0 a 9 rientrano nel set di caratteri ASCII e hanno valori che vanno da 48 per la cifra 0 fino a 57 per la cifra 9. Sfruttando questa relazione è possibile convertire una cifra in carattere semplicemente sommando 48 al valore del numero che si intende rappresentare. Quindi, passando alle funzioni Lcd_Char o Lcd_CharCP la somma tra il numero da stampare e 48 è possibile rappresentare il numero sul display LCD. Il comando diventa:

Lcd_CharCP(Cifra + 48);

Questo approccio può essere utilizzato anche per stampare numeri composti da più cifre, a patto di scomporre le une dalle altre.
Con questo approccio è però impossibile rappresentare numeri negativi in quanto non sarebbe più rispettata la relazione tra valore numerico e carattere. Per aggirare il problema sarebbe necessario determinare e stampare prima il segno del numero e successivamente i vari caratteri che lo compongono.

Un metodo più veloce per poter stampare un numero intero, sia positivo che negativo, è quello di usare la funzione itoa (per numeri positivi si può usare anche utoa) che converte un numero intero in una stringa. Tale funzione è presente nella libreria stdlib e può essere inclusa nel progetto tramite il comando:

#include <stdlib.h>

Per effettuare la conversione da numero intero a stringa è necessario passare alla funzione la variabile di tipo stringa in cui salvare il risultato della conversione, il valore da convertire e la base usata per rappresentare il numero. Stesso discorso vale per la utoa. Volendo convertire il numero 12345, espresso in base 10, nella stringa str e poi stampare il risultato, si avrebbe un codice del tipo:

itoa(str,12345,10);
Lcd_TextCP(str);

Quando si determina la dimensione della stringa si deve considerare che oltre al numero di caratteri desiderati si deve considerare anche quello relativo al terminatore /0, quindi la dimensione va estesa di 1.

Per convertire un numero da float a string esistono diverse librerie che includono anche delle funzioni speciali per adattare al meglio la conversione. Per esempio la funzione sprintf permette di ricevere in ingresso diversi parametri aggiuntivi che agiscono sul formato e sulla rappresentazione del numero convertito. Il problema di queste funzioni sono l’occupazione di memoria richiesta. In alcuni casi, con microcontrollori aventi poca memoria o con codici particolarmente pesanti, l’occupazione è tale da sforare i limiti.

 

LIBRERIA Float2String
Viene presentata una semplice libreria che permette di convertire un numero reale, rappresentato tramite una variabile float, in una stringa di testo, senza opzioni aggiuntive e avendo come obiettivo principale una bassa occupazione di memoria.
La libreria è composta da un file Float2String.c che contiene le istruzioni per eseguire la conversione e un file Float2String.h per l’header.

Float2String.h
Le prime due righe del file Float2String.h controllano che la libreria non sia già stata chiamata all’interno del progetto, evitando di includerla più volte.

#ifndef Float2String_H
#define Float2String_H
...
#endif

Seguono le inclusioni delle librerie necessarie, che permettono di usare valori mnenmonici per indicare i tipi delle variabili (stdint.h), la funzione per convertire da intero a stringa (stdlib) e le funzioni necessarie per la gestione delle stringhe (string.h).

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

Segue infine il prototipo della funzione, che riceve in ingresso un valore float, il numero di cifre decimali con cui rappresentare il numero e la stringa nella quale inserire il risultato della conversione.

char* Float2String(float value, uint8_t decimal, char* str);

Float2String.c
Per prima cosa si include l’header file della libreria.

#include "Float2String.h"

All’interno della funzione, dopo aver dichiarato le variabili, vengono svolte le varie operazioni necessarie alla conversione, prima fra tutte il reset della stringa str passata alla funzione, impedendo così che la nuova conversione venga messa in coda alla precedente stringa.

char* Float2String(float value, uint8_t decimal, char* str){
const uint8_t base = 10;
uint8_t i;

uint8_t temp_str[21];
uint8_t digit;
uint16_t dt_int;
uint16_t dt_dec;
uint16_t power = 1;

strcpy(str, "");

...

return str;

}

Segue la conversione della parte intera in stringa. Per far ciò si associa il valore del numero reale ad una variabile uint16_t, così da associare la sola parte intera, mentre il segno viene determinato dalla variabile di tipo float, infatti se value è negativa viene concatenato alla stringa il segno “-“. La variabile contenente la parte intera viene convertita in stringa tramite la funzione utoa e concatenata alla stringa str che, essendo stata ripulita, contiene il solo valore intero del numero reale e l’eventuale segno. La funzione utoa ammette valori unsigned a 16 bit.

   // Conversione parte intera
if(value >= 0){
dt_int = (uint16_t)value;
}
else{
dt_int = -(uint16_t)value;
strcat(str,"-");
}
utoa(temp_str,dt_int,base);
strcat(str,temp_str);

Segue la conversione della parte decimale, che avviene esclusivamente se il numero di cifre decimali desiderate è superiore a 0, pertanto la prima istruzione è un if che controlla il valore della variabile decimal e, in caso positivo, viene concatenato il punto alla stringa.
Segue quindi un ciclo for che ha lo scopo di eseguire il calcolo della potenza necessario ad eseguire la convertire da valore decimale ad intero (parzialmente o totalmente a seconda del valore reale e del numero di cifre richieste). Per l’elevamento a potenza si sarebbe potuto utilizzare la funzione pow() ma da alcune prove effettuate la soluzione che richiede meno occupazione di memoria è risultata essere quella calcolata tramite ciclo for.
Segue il calcolo della parte decimale ottenuta tramite la differenza tra il valore reale moltiplicato per la potenza e il valore della parte intera moltiplicato per la potenza. La differenza tra i due valori tiene conto del segno della variabile di tipo float e del fatto che la parte intera viene memorizzata come valore senza segno. 
Segue quindi la conversione della parte decimale in stringa. Si utilizza la funzione utoa che converte un numero positivo in stringa.
Prima di concatenare la stringa temp_str con la stringa str, si esegue uno zero-padding, che consiste nel riempire di ‘0’ le posizioni delle cifre decimali non occupate da alcun valore. Questa operazione è ottenuta tramite la funzione strlen() che restituisce la lunghezza della stringa temp_str (che in quel punto di codice rappresenta la parte decimale del numero) che, confrontata con la variabile decimal, determina il numero di cifre da riempire con ‘0’. 
Come ultima operazione si concatena la stringa così ottenuta con la parte già determinata di str e se ne restituisce il valore.

   // Conversione parte decimale
if(decimal> 0){
strcat(str,".");

for(i=0; i<decimal; i++){
power *= 10;
}

if(value>= 0){
dt_dec = (uint16_t)( value*power - dt_int*power);
}
else{
dt_dec = (uint16_t)(-value*power - dt_int*power);
}

utoa(temp_str,dt_dec,base);
digit = decimal-strlen(temp_str);
if(digit){
for(i=0; i<digit; i++){
strcat(temp_str,"0");
}
}

strcat(str,temp_str);
strcat(str," ");
}

La funzione Float2String ha due limitazioni sulle conversioni da floating point a stringa. Sia la parte intera che decimale sono convertite tramite la funzione utoa che accetta valori rappresentati tramite uint16_t a cui è associato il range [0; 65535]. Ciò comporta che:

  1. La parte intera deve avere un valore che ricade nel range [0; 65535]. Questo influisce sul massimo numero convertibile in stringa (trascurando il contributo della parte decimale).
  2. La parte decimale deve avere un valore che ricade nel range [0; 65535]. Tale range determina il numero massimo di cifre decimali. Per avere la certezza che il dato sia corretto si può avere un massimo di 4 cifre decimali.

La libreria è pensata per funzionare in codici che sfruttano il modulo ADC o con sensori che richiedono numeri reali che normalmente ricadono in tali range.
Se il numero reale non dovesse ricadere in tale range è possibile utilizzare funzioni più precise per eseguire la conversione.

 

DOWNLOAD
Al seguente link è possibile scaricare i file Float2String.c e Float2String.h relativi alla libreria per la conversione da float a stringa: DOWNLOAD.

 

 

[Voti Totali: 0 Media Voti: 0]
Segui la Nostra Pagina Facebook:
Facebook

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *