voltmetro e barra lcd

buongiorno a tutto il forum.
cercando qua e la sono riuscito a mettere insieme un voltmetro per una batteria al litio da3,7volt
con una barra progressiva, funziona,pero' chiedo la vostra supervisione per valutare se e'necessaria qualche modifica.
vi ringrazio in anticipo

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
double percent = 100.0;
float somma = 0.0;
float media = 0.0;
int i = 0;
#define led_pin 13
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int LCD_NB_ROWS = 1;
const int LCD_NB_COLUMNS = 6;
byte START_DIV_0_OF_1[8] = {
  B11111,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B11111
};
byte START_DIV_1_OF_1[8] = {
  B11111,
  B10000,
  B10011,
  B10011,
  B10011,
  B10011,
  B10000,
  B11111
};
byte DIV_0_OF_2[8] = {
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111
};
byte DIV_1_OF_2[8] = {
  B11111,
  B00000,
  B11000,
  B11000,
  B11000,
  B11000,
  B00000,
  B11111
};
byte DIV_2_OF_2[8] = {
  B11111,
  B00000,
  B11011,
  B11011,
  B11011,
  B11011,
  B00000,
  B11111
};
byte END_DIV_0_OF_1[8] = {
  B11100,
  B00100,
  B00111,
  B00001,
  B00001,
  B00111,
  B00100,
  B11100
};
byte END_DIV_1_OF_1[8] = {
  B11100,
  B00100,
  B11111,
  B11111,
  B11111,
  B11111,
  B00100,
  B11100
};
float voltage;
void setup() {
  pinMode(A0, INPUT);
  pinMode(led_pin, OUTPUT);
  lcd.init();
  lcd.backlight();
  setup_progressbar();
  lcd.clear();
}
void loop() {
  {

    for (i = 0; i < 100; i++)
    {
      voltage = analogRead(A0) * (4.87 / 1023.00) ;
      somma = (somma + voltage);
      delay(20); //ritardo tra due campionature successive
    }
    media = (somma / 100); //calcolo del valore medio di 8 rilievi
    percent = media / 4.5 * 100.0; //calcola la percentuale
    somma = 0; // riazzeramento della variabile somma
    if (media < 3.00) //set the voltage considered low battery here
    {
      digitalWrite(led_pin, HIGH);
    }
    else {
      digitalWrite(led_pin, LOW);
    }

    draw_progressbar(percent);
  }
}
void setup_progressbar() {
  lcd.createChar(0, START_DIV_0_OF_1);
  lcd.createChar(1, START_DIV_1_OF_1);
  lcd.createChar(2, DIV_0_OF_2);
  lcd.createChar(3, DIV_1_OF_2);
  lcd.createChar(4, DIV_2_OF_2);
  lcd.createChar(5, END_DIV_0_OF_1);
  lcd.createChar(6, END_DIV_1_OF_1);
}
void draw_progressbar(byte percent)
{
  lcd.setCursor(0, 0);
  lcd.print(media);
  lcd.print(F(" V "));
  lcd.setCursor(11, 0);
  lcd.print(percent);
  lcd.setCursor(0, 1);
  byte nb_columns = map(percent, 0, 100, 0, LCD_NB_COLUMNS * 2 - 2);
  for (byte i = 0; i < LCD_NB_COLUMNS; ++i) {
    if (i == 0) {
      if (nb_columns > 0) {
        lcd.write(1);
        nb_columns -= 1;
      } else {
        lcd.write((byte) 0);
      }
    } else if (i == LCD_NB_COLUMNS - 1) {
      if (nb_columns > 0) {
        lcd.write(6);
      } else {
        lcd.write(5);
      }
    } else {
      if (nb_columns >= 2) {
        lcd.write(4);
        nb_columns -= 2;

      } else if (nb_columns == 1) {
        lcd.write(3);
        nb_columns -= 1;

      } else {
        lcd.write(2);
      }
    }
  }
}

Così a primo colpo d'occhio non vedo grandi cose da fare, più ch altro cavolate tipo i dati di tipo int (come la variabile i) che non superano i 25 puoi definirli byte e risparmi un byte.
L'altra cosa che puoi fare è evitare di scrivere sull'lcd ad ogni giro di loop, ma solo quando il valore di percent è differente rispetto all'ultima volta che hai scritto, ti basta una variabile appoggio per memorizzare l'ultimo valore scritto su lcd, se diverso dalla percentuale attuale allora scrivi, altrimenti no.
Nel setup questa variabile appoggio la valorizzi con una valore superiore a 100 in modo che sei sicuro che al primo giro scrivi per forza sull'lcd essendo che la percentuale attuale sarà per forza di cose diversa rispetto alla precedente.

ok, grazie, vedo di sistemare questi errori.una cosa, nel momento in cui levo l'alimentazione dal arduino uno, il led della alimentazione resta leggermente acceso.
cosa che indica che la tensione rientra dal pin A0, ce qualche modo per evitare cio' o devo mettere un rele' che isola un polo della batteria?

Io l'ho fatto e l'ho usato più di una volta. Funziona benissimo, ma non è così complesso. Se fosse stato così complesso, avrei avuto problemi per metterci tutto il resto! :slight_smile:
La tensione della batteria puoi leggerla tra una volta al secondo e una volta ogni trenta secondi (tanto in 30 secondi rimane praticamente costante) con una cosa tipo:

int Vcc;

void loop()
{
if(millis()-t3>29999) // Una volta ogni 30 secondi:
  {
  analogRead(A0); // Prelettura
  Vcc=analogRead(A0);
  t3+=30000;
  ...

Se, come normalmente accade, fa parte di un progetto più grande, devo limitarmi a un'icona grande un carattere, perciò disegno le icone della batteria da completamente scarica a completamente carica. Se mi servono altri caratteri speciali, poiché la memoria del display ne può contenere solo otto, tramite uno switch/case carico di volta in volta solo l'icona che rappresenta lo stato attuale della batteria:

// Batteria: metterà quello scelto in carattere 0:
byte Batt_0[8]=
{10,17, 0,17, 0,17, 0,21};
byte Batt_1[8]=
{14,17,17,17,17,17,17,31};
byte Batt_2[8]=
{14,17,17,17,17,17,31,31};
byte Batt_3[8]=
{14,17,17,17,17,31,31,31};
byte Batt_4[8]=
{14,17,17,17,31,31,31,31};
byte Batt_5[8]=
{14,17,17,31,31,31,31,31};
byte Batt_6[8]=
{14,17,31,31,31,31,31,31};
byte Batt_7[8]=
{14,31,31,31,31,31,31,31};

daniele999:
Nel momento in cui levo l'alimentazione da arduino uno, il led della alimentazione resta leggermente acceso, cosa che indica che la tensione rientra dal pin A0: c'è qualche modo per evitare ciò?

Succede perché la batteria rimane collegata quando togli l'alimentazione alla scheda. Concettualmente è sbagliato: quando spegni, devi spegnere tutto. Il fatto è che tutti i pin dell'atmega328p hanno dei diodi di protezione, che tosano la tensione di ingresso, impedendo che vada al di sotto di -0,6V o al di sopra di Vcc+0,6V: se l'alimentazione è assente, alimentando un ingresso il diodo di protezione verso il positivo va in conduzione e alimenta tutto il circuito! Quanto meno devi mettere in serie all'ingresso una resistenza abbastanza elevata (4,7~10kOhm), mantenendo però bassa l'impedenza dinamica con una condensatore da circa 100nF tra l'ingresso analogico e massa.

grazie delle risposte quindi cancello i caratteri che ho memorizzato e li metto cosi?

if (nb_columns > 0) {
        lcd.write(1);//cancello questo e metto  {10,17, 0,17, 0,17, 0,21};
        nb_columns -= 1;
      } else {
        lcd.write((byte) 0);
      }

scusami ma sto iniziano ora e non e' che ci azzecco alla prima....

Che cosa vuoi ottenere, esattamente?

una barra che al massimo occupa 6 "spazi " sul lcd che in base alla carica della batteria riempie lo spazio interno una cosa tipo cosi , come ho fatto generando i caratteri con l'ultimo carattere sagomato tipo pila

barra.gif