Visualizzare tensione batteria alimentazione

Salve a tutti, sono nuovo e ho pochissime competenze e questo è il mio primo post.

Ho assemblato tramite diverse librerie una radio FM con un Nano clone ed un modulo SI4703 e display TFT 7735.
Funziona tutto.
Per alimentarlo correttamente devo usare 5V sul Vin ottenuti da un modulino booster che provvede anche alla carica della batteria lipo 18650.

Ho utilizzato un listato che mi consente di visualizzare la tensione di alimentazione tramite questo listato:

volts = readVcc();

long readVcc() {
//unsigned int readVcc(void) {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  ADMUX = (1<<REFS0) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= (1<<ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
  unsigned int result = ADC;
  //custom scale factor, processor specific
  result = 1119000UL / (unsigned long)result; // Calculate Vcc (in mV); 1125300 = 1.1*1024*1000
  return result; // Vcc in millivolts

Il problema è che mi visualizza correttamente sul display sempre una tensione fissa di alimentazione di 5,08V fornita dal modulino booster, ma io vorrei leggere la vera tensione ai capi della batteria Lipo 18650 che avrà un' escursione da 4,2 a 3,5 V .

Sapete suggerirmi come fare ?

Grazie

Buongiorno e benvenuto nella sezione Italiana del forum,

:warning: prima di tutto ti segnalo che, nella sezione in lingua Inglese, si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post; questa volta esso è stato spostato, da un moderatore della sezione di lingua Inglese, nella sezione di lingua Italiana ... la prossima volta potrebbe venire direttamente eliminato, dopo di che ...

... cortesemente, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15) e poi, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

P.P.S.: Evitate di utilizzare la traduzione automatica fatta dal browser ... vi impedisce di capire la lingua della sezione dove andate a scrivere ...

Grazie Guglielmo per i suggerimenti.
Per la presentazione, da perfetto niubbo credevo di averla già fatta, mentre per la sezione in Italiano, ho scoperto, sempre grazie alla tua risposta, la sua presenza.
Grazie :slightly_smiling_face:

Michele

Ciao, benvenuto! :slight_smile:

Devi collegare il positivo dell'elemento al litio direttamente a un ingresso A0.. A7 (è un Nano) e leggere con analogRead(). Come è risaputo, è bene che tu faccia due letture di seguito:

analogRead(A0); float Vcc=analogRead(A0)/1024*5.0;
1 Like

Eccomi, tutto chiaro, provo subito ad applicare allo sketch la tua riga con l'istruzione.

Il fatto delle due letture mi è sconosciuto (fosse l'unica cosa... :wink: ), ma adesso provo a capire come funziona.
Grazie mille

Michele

Eccomi, aggiustando un po' il tuo codice, usandolo come base, dopo mille difficoltà per me, data la mia incompetenza, adesso visualizzo la tensione della batteria nel display SPI TFT ST7735 1.8".

Lo sketch che sto usando (SI470X/si470x_02_TFT_display.ino at master · pu2clr/SI470X · GitHub)
è lungo e complesso, a forza di metterci le mani sopra sono riuscito ad aggiungere la visualizzazione del valore del Volume, e adesso anche la tensione della batteria.

int v = analogRead(A1);     // ********** TENSIONE BATTERIA ***************
int Vbatt = map(v,0,1023,0,5070);   // 5070 anzichè 5000 per correggere il valore visualizzato
delay(200);
sprintf(Vbatt, "V.%i", Vbatt);
 tft.setFont(&Serif_plain_10);
  tft.setTextSize(1);
 printValue(110, 75, oldVbatt, Vbatt, 8, COLOR_RED);

La visualizzazione sul dispaly appare così "V. 3970"

nella riga sprintf(Vbatt, "V.%i", Vbatt); la formattazione ho visto che deriva dal "%i" .

Come fare per visualizzare "V. 3.970" oppure anche "V. 3,97" ?

Grazie

Michele

Sicuro che ci sia Vbatt sia all'inizio che alla fine? Il primo argomento dovrebbe essere una stringa... Se non mi sono perso qualcosa...
Comunque per formattare il numero puoi usare qualcosa tipo

sprintf(Vbatt, "V. %d,%02d", Vbatt/100, Vbatt%100);

Per info sui parametri della printf puoi guardare qui

No, guarda, non ne sono sicuro, sono uno smanettone che copia, cerca di capire, e se riesco provo ad adattare per ottenere un risultato.
Comunque anche in questo caso grazie, sono riuscito a visualizzare la tensione della batteria nel formato desiderato.
Ho solo cambiato il "Vbatt/100, Vbatt%100" con "Vbatt/1000, Vbatt%1000" per ottenere la visualizzazione corretta, ovvero V. 3,897.

Ho provato a ridurre le cifre dopo la virgola da 3 a 2, per ottenere V. 3,89 ma naturalmente, non ci sono riuscito.

Grazie a tutti

Michele

In teoria quello che ho scritto io dovrebbe visualizzare 2 cifre decimali.


int v = analogRead(A1); // // ********** TENSIONE BATTERIA ***************
int Vbatt = map(v,0,1023,0,5100);
sprintf(Vbatt, "V.%d,%02d", Vbatt/1000, Vbatt%1000);  // riga suggerita da fratt
 tft.setFont(&Serif_plain_10);
  tft.setTextSize(1);
 printValue(100, 55, oldVbatt, Vbatt, 8, COLOR_RED);
delay(100);

Questa è la sezione dello sketch che mi visualizza "V. 3,xxx"

C'è qualche valore sbagliato che fa visualizzare le 3 cifre dopo la virgola ?

Grazie

Vuoi due cifre o ne vuoi tre???...
Comunque V. xxx mi sembra tanto versione... :slight_smile:

Mi spiego meglio:

Prima della tua riga, visualizzavo per esempio "V. 3967" tremilanovecentoerotti Volt :wink:

Dopo applicando la tua stringa (aggiungendo uno zero in più), come ho scritto sopra, visualizzo finalmente "V. 3,967" che è corretto.

Poi per strafare, se fosse possibile, vorrei visualizzare "V. 3,96" per una questione "estetica" poichè 3 cifre dopo la virgola su un display di una radio mi sembra eccessivo.

Ma altrimenti va bene anche così

Grazie per gli aiuti

Come ha suggerito @fratt al #7 non funziona?
Togli uno zero:

sprintf(Vbatt, "V.%d,%02d", Vbatt/1000, Vbatt%100); 

Se no, c'è sempre la tanto discussa ma semplice "scaletta" di if...
Mi piacerebbe fare un confronto di occupazione di memoria e di velocità di esecuzione...

Ho fatto una prova veloce usando la riga come indicata:

sprintf(Vbatt, "V.%d,%02d", Vbatt/1000, Vbatt%100); 

e succede una cosa strana:
Sul display è correttamente visualizzata con 2 cifre dopo la virgola, però se alimento Arduino Nano con USB va bene, quando poi stacco il cavo USB e alimento con il modulino che fornisce 5V e gestisce la batteria 18650, il display cambia luminosità ed è come se perdesse il sincronismo.

Se invece l'istruzione è con il "Vbatt%1000" visualizzo le 3 cifre ma sia con USB che con i 5V (applicati al 5V del Nano) il display si vede correttamente.

Stasera proverò ancora a capire questa stranezza.

C'è qualcosa che non torna con il codice.
sprintf vuole come primo argomento un buffer che sarebbe qualcosa come:

char buffer[10]; // globale
char buffer[10] = { 0 }; // se è locale, cioè dentro una funzione

Posta anche il resto del codice.
Comunque la riga di codice corretta è:

char rowBuff[10] = {0};  // buffer locale
sprintf(rowBuff, "V. %u,%2u", (uint16_t)Vbatt/1000, (uint16_t)(Vbatt / 10) % 100);

Altra cosa strana nel tuo codice è che non mostri la riga che stampa sul display
dove appunto dovresti stampare rowBuf.

Ciao.

Hai provato a vedere questo video?

Saluti
Enrico

Non conosco le funzioni per scrivere su quel display; comunque:

analogRead(A0); 
delay(10); // Serve un delay di almeno 7ms.
uint16_t centoVcc = analogRead(A0)/1024.0*500+.5; // +.5 è per l'approssimazione.
uint8_t parte_intera = centoVcc/100;
uint8_t centesimi = centoVcc%100;
// Su un LCD 1602 verrebbe:
lcd.print(parte_intera); lcd.print('.');
if(centesimi<10) lcd.print('0');
lcd.print(centesimi); lcd.print('V');

Tutto lo sketch ?
Perchè la sezione che riguarda la lettura della tensione della batteria, con il suggerimento del post #7 è nel post # 10.

int v = analogRead(A1); // // ********** TENSIONE BATTERIA ***************
int Vbatt = map(v,0,1023,0,5100);
sprintf(Vbatt, "V.%d,%02d", Vbatt/1000, Vbatt%1000);  // riga suggerita da fratt
 tft.setFont(&Serif_plain_10);
  tft.setTextSize(1);
 printValue(100, 55, oldVbatt, Vbatt, 8, COLOR_RED);
delay(100);

Se non comporta problemi, perchè è abbastanza lungo, lo posto tutto.

Si, l'avevo già visto, ed avevo anche applicato quanto spiegava nel video, ma il problema è che io uso un modulino che fa da boot alla tensione della batteria a 5V e provvede alla carica e scarica della 18650.

Quindi io alimento il nano a 5V e devo leggere una tensione che non è quella di alimentazione ma di una batteria.

Comunque grazie del suggerimento

Si ho visto il codice. @fratt qui ti ha fatto una domanda?

La domanda è lecita e la tua risposta potrebbe essere: SI, NO, non sono sicuro.
Il problema principale (ce ne sono altri) è che non ha capito come funziona sprintf e da quel codice la stai usando male anzi malissimo,

sprintf(Vbatt, "V.%i", Vbatt);
          ^

Il primo argomento evidenziato dalla freccina non può essere Vbatt ma deve per forza essere un buffer. Questo buffer viene riempito con la conversione di Vbatt da numero a rappresentazione ASCII. Alla funzione che stampa sul display dovrai passare come argomento il buffer.

Ora se mi mostri come visualizzi sul display posso aggiustare la funzione in modo che ti visualizza ciò che hai richiesto.

Dal tuo codice vedo che usi una funzione di nome printValue puoi mostrare cosa contiene.

Ciao.