grazie mille faccio un po' di prove così intanto prendo confidenza con la scrittura.
Mi sarebbe piaciuto fare una cosa che sposta il punto automaticamente a seconda del numero che introduco.
Questo per sfruttare i 14bit che ho a disposizione.
In questo caso misuro delle tensioni.
Ad esempio : 5555Volt 555.5Volt 55.55Volt 5.555Volt
Ci penserò appena comincio a capirci qualcosa.
Ancora Grazie
ms
... la stringa di formattazione la decidi tu e ... puoi crearla anche dinamicamente
Guglielmo
Ancora difficile per me comprenderne le potenzialità.
Oggi ho già imparato una cosa nuova.
Non vedo l'ora di lavorarci domani per fare qualche altro passo avanti.
Grazie ancora
ms
Io uso sempre la variante snprintf().
Il motivo è che sprintf()
, non fa alcun controllo sulla lunghezza della stringa formattata e se abbiamo dichiarato l'array di destinazione con una dimensione insufficiente, l'area di memoria adiacente all'array viene sovrascritta con "l'eccedenza", causando problemi come si può ben immaginare.
snprintf()
invece tronca la stringa formattata alla dimensione massima passata come secondo parametro e quindi è più "sicura" in caso di errori o sviste.
char buf[8];
snprintf(buf, sizeof(buf), "%6.2f", f);
... vero, sicuramente meglio, specie agli inizi
Guglielmo
Grazie mille
Ho aggiornato il codice con un solo voltmetro e grazie ai vostri suggerimenti comincia a funzionare
#include <Arduino.h>
#include <LedControl.h> // Libreria per MAX7219
// Pin del MAX7219
#define DIN 12
#define CS 10
#define CLK 11
// Inizializzazione del display
LedControl lc = LedControl(DIN, CLK, CS, 1);
// Buffer per la stringa
char buffer[10];
// Pin analogici per voltmetro e amperometro
#define VOLT_PIN A0
#define AMP_PIN A1
// Variabili per calcolo tensione e corrente
float voltage = 0.0;
float current = 0.0;
const float VOLT_DIVIDER = 1000.0; // Fattore divisore per il partitore di tensione
const float AMP_CALIBRATION = 0.1; // Calibrazione sensore corrente
// Numero intero
int numero;
void setup() {
Serial.begin(9600); //Per monitorare debugg
analogReadResolution(14); // Imposta la risoluzione ADC a 14 bit
lc.shutdown(0, false); // Accende il display
lc.setIntensity(0, 5); // Imposta la luminosità
lc.clearDisplay(0); // Pulisce il display
// Usa snprintf per formattare
snprintf(buffer, sizeof(buffer), "% 5d", numero);
// Stampa sul monitor seriale
Serial.println(buffer); // Output: Valore: 1234
}
void loop() {
// Nulla da fare qui
// Leggi tensione e corrente
voltage = analogRead(VOLT_PIN) * (5.0 / 16383.0) * VOLT_DIVIDER;
current = analogRead(AMP_PIN) * (5.0 / 16383.0) / AMP_CALIBRATION;
delay(200);
numero = voltage;
// Usa snprintf per formattare
snprintf(buffer, sizeof(buffer), "% 5d", numero);
// Stampa ogni elemento dell'array
for (int i = 0; i < sizeof(buffer); i++) {
/* Serial.println(numero);
Serial.println(voltage);*/
Serial.println(buffer);
Serial.println(buffer[4]);
Serial.println(buffer[3]);
Serial.println(buffer[2]);
Serial.println(buffer[1]);
Serial.println(buffer[0]);
lc.setChar(0, 0, buffer[4], false); // quarto digit
lc.setChar(0, 1, buffer[3], false); // terzo digit
lc.setChar(0, 2, buffer[2], false); // Secondo digit
lc.setChar(0, 3, buffer[1], false); // Primo digit
}
}
Non hai letto con attenzione la documentazione su sprintf()
Con la stringa di formattazione che stai usando, il risultato sarà un numero intero di lunghezza fissa di 4 caratteri con "zero padding" ovvero il carattere 0 al posto delle decine/centinaia/migliaia anche quando il numero non lo prevede.
Per fare quello che penso tu stia cercando di fare, devi fare la stessa cosa, ma usando lo spazio come carattere per il padding.
snprintf(buffer, sizeof(buffer), "% 4d", numero);
Grazie Mille questa cosa è magica
Se ben ricordo, se si omette è pari a spazio, se invece si vogliono gli zeri davanti si deve specificare ... almeno per la sprintf(), per la snprintf() è diverso???
Guglielmo
Si in effetti è cosi, specificando solo la lunghezza di default viene usato lo spazio per allineare a destra il numero.
Ci sono tante altre opzioni come ad esempio l'allineamento a sinistra, la forzatura del segno etc etc.
Si, infatti, anche io, già dal post #6, avevo detto di studiarsi quanto era indicato per printf() dando lo stesso link
Guglielmo
Buonasera
Dopo aver studiato un po' sono arrivato a questo codice che sembra funzionare.
Si tratta di un Voltmetro 4digit ed un Amperometro 4digit con Max7219.
Per ora sia il voltmetro che l'amperometro sono tarati per 5000Volt e 5000Amper.
Ho fatto in modo che la misura sposti il punto automaticamente.
Esempio: 5000Volt,500.0Volt,50.00Volt,5.000Volt.
Anche le cifre si spostano a sinistra man mano che i valori misurati diminuiscono
Volevo il vostro parere per poter imparare.
Grazie a voi sono arrivato fino a qui
ms
/*Voltmetro e Amperometro con spostamento automatico dei punti e dei numeri a sinistra*/
/*Atduino Uno R4 minima*/
/*Max 7219*/
#include <Arduino.h>
#include <LedControl.h> // Libreria per MAX7219
// Pin del MAX7219
#define DIN 12
#define CS 10
#define CLK 11
//punto automatico
char punto7, punto6, punto5, punto3, punto2, punto1 = 0;
// Inizializzazione del display
LedControl lc = LedControl(DIN, CLK, CS, 1);
// Pin analogici per voltmetro e amperometro
#define VOLT_PIN A0
#define AMP_PIN A1
float voltage;
float current;
// Buffer per il risultato volt
char risultatovolt[20];
// Buffer per il risultato volt
char risultatoAmper[20];
void setup() {
Serial.begin(9600); //Per monitorare debugg
analogReadResolution(14); // Imposta la risoluzione ADC a 14 bit
lc.shutdown(0, false); // Accende il display
lc.setIntensity(0, 5); // Imposta la luminosità
lc.clearDisplay(0); // Pulisce il display
}
void loop() {
// Leggi tensione e corrente
voltage = analogRead(VOLT_PIN) * (5.0 / 16383.0) * 1000;
current = analogRead(AMP_PIN) * (5.0 / 16383.0) * 1000;
// Chiamata alla funzione per scalare le cifre
scalaCifreVolt(voltage, risultatovolt);
stampaVolt(); /*funzione che mette i volt nel display*/
scalaCifreAmp(current, risultatoAmper);
stampaAmper(); /*funzione che mette gli amper nel display*/
delay(200);
puntoautomatico(); /*Funzione automatica punto Volt*/
// Stampa il risultato Volt
Serial.print("risultatovolt: ");
Serial.println(voltage); // Output
// Stampa il risultato Amp
Serial.print("risultatoAmp: ");
Serial.println(current); // Output
}
// Funzione per scalare le cifre di una singola misura verso sinistra
void scalaCifreVolt(float voltage, char* risultatovolt) {
// Converti il valore in una stringa
char buffer[20];
dtostrf(voltage, 10, 4, buffer); // Converti con 4 cifre decimali
// Rimuovi gli spazi iniziali
trimSpaces(buffer);
// Trova la posizione del punto decimale
char* puntoDecimale = strchr(buffer, '.');
if (puntoDecimale != nullptr) {
// Rimuovi il punto decimale
memmove(puntoDecimale, puntoDecimale + 1, strlen(puntoDecimale));
}
// Copia il risultato nel buffer di output
strcpy(risultatovolt, buffer);
}
// Funzione per scalare le cifre di una singola misura verso sinistra
void scalaCifreAmp(float current, char* risultatoAmper) {
// Converti il valore in una stringa
char buffer[20];
dtostrf(current, 10, 4, buffer); // Converti con 4 cifre decimali
// Rimuovi gli spazi iniziali
trimSpaces(buffer);
// Trova la posizione del punto decimale
char* puntoDecimale = strchr(buffer, '.');
if (puntoDecimale != nullptr) {
// Rimuovi il punto decimale
memmove(puntoDecimale, puntoDecimale + 1, strlen(puntoDecimale));
}
// Copia il risultato nel buffer di output
strcpy(risultatoAmper, buffer);
}
// Funzione per rimuovere gli spazi iniziali da una stringa
void trimSpaces(char* str) {
int i = 0;
while (str[i] == ' ') {
i++;
}
memmove(str, str + i, strlen(str) - i + 1);
}
// Funzione che Stampa ogni elemento dell'array buffervolt
void stampaVolt() {
lc.setChar(0, 4, risultatovolt[3], 0); // quarto digit
lc.setChar(0, 5, risultatovolt[2], punto5); // quinto digit
lc.setChar(0, 6, risultatovolt[1], punto6); // sesto digit
lc.setChar(0, 7, risultatovolt[0], punto7); // settimo digit
}
/*Funzione automatica per spostare il punto Volt*/
void puntoautomatico() {
int numeroV = atoi(risultatovolt);
int numeroA = atoi(risultatoAmper);
if (voltage < 999 && voltage > 99) {
punto5 = 1;
} else {
punto5 = 0;
}
if (voltage < 99 && voltage > 9) {
punto6 = 1;
} else {
punto6 = 0;
}
if (voltage < 9) {
punto7 = 1;
} else {
punto7 = 0;
}
if (current < 999 && current > 99) {
punto1 = 1;
} else {
punto1 = 0;
}
if (current < 99 && current > 9) {
punto2 = 1;
} else {
punto2 = 0;
}
if (current < 9) {
punto3 = 1;
} else {
punto3 = 0;
}
}
// Funzione che Stampa ogni elemento dell'array buffera,amper
void stampaAmper() {
lc.setChar(0, 0, risultatoAmper[3], 0); // primo digit
lc.setChar(0, 1, risultatoAmper[2], punto1); // secondo digit
lc.setChar(0, 2, risultatoAmper[1], punto2); // terzo digit
lc.setChar(0, 3, risultatoAmper[0], punto3); // quarto digit
}