Voltmetro Wifi con Wemos D1 Mini

Vedremo come utilizzare Wemos D1 Mini Lite ESP8266 come un Voltmetro Wifi, avremo la possibilità di poter misurare da remoto una tensione tra 0 e 12V. Questo è utile se ci occorre controllare lo stato di carica della batteria di un camper o dell’auto o se vogliamo acquisire un segnale di tensione proveniente da un sensore (esempio: temperatura, umidità, luminosità, ecc).
Il server privato di Blynk riceverà i dati acquisti dalla scheda e che poi verranno inviati all’applicazione installata sul nostro smartphone.
Qui sotto ho inserito uno schema di come sarà il nostro Voltmetro Wifi.

LutriTech.it - Voltmetro Wifi
Voltmetro Wifi – LutriTech

Per questo nuovo progetto saranno necessari:

In qualità di affiliato Amazon io ricevo un guadagno dagli acquisti idonei. A voi non costerà nulla di più e avrete modo di supportare così il mio lavoro. Grazie.
L’ESP8266 possiede al suo interno un Convertitore Analogico Digitale (ADC) a 10 bit che può convertire la tensione analogica da 0 a 1V in 1024 valori digitali compresi tra 0 e 1023.
Sul PCB del Wemos D1 Mini è già presente un partitore di tensione che ci permette di misurare tensioni fino a 3.3V, ma non è sufficiente per misurare tensioni maggiori come quelle di una batteria LiPo (3.7V) , di un battery Pack USB (5V) o di una batteria per auto/moto(12V). Qui sotto è rappresentato il pinout della scheda Wemos da dove si nota che il pin A0 è l’unico ingresso analogico.

Partitore di Tensione

Possiamo vedere lo schema elettrico della scheda sul sito ufficiale.
Vediamo che il partitore interno è composto da due resistenze: R1 = 220 KΩ  e R2 = 100 KΩ ,
questo permette che sul pin A0 ci sia una tensione di 3.3V e all’ingresso dell’ADC 1V.

LutriTech.it - Partitore Wemos

Ricordo la formula generica del partitore di tensione :

LutriTech.it - Partitore di Tensione
Formula Partitore di Tensione

Per misurare tensioni superiori bisogna modificare il partitore presente aggiungendo in serie a R1 un’ulteriore Resistenza esterna.
La tensione sull’ADC interno all’ESP8266 sarà uguale alla Vout calcolata qui sotto:

LutriTech.it - Formula Partitore

Ma come si calcola la Resterna??? Vi risparmio tutti i passaggi e vi indico la formula matematica finale:

LutriTech.it - Resistenza Esterna Calcolo

Ipotizzando una tensione massima misurabile Vin:

  • Vin=5V e Vout=1 ottengo una Resterna da 180KOhm.
  • Vin=12V e Vout=1 ottengo una Resterna da 880KOhm.
  • Vin=18V e Vout=1 ottengo una Resterna da 1480KOhm.
  • Vin=24V e Vout=1 ottengo una Resterna da 2080KOhm.
  • Vin=32V e Vout=1 ottengo una Resterna da 2880KOhm

Questi sono valori teorici matematici, poi la realtà è sempre diversa! Vediamo se una comune resistenza da 1MOhm può andare bene lo stesso per misurare 12V:

Vout Formula Completa - LutriTech.it
Vout - LutriTech.it
Vout Finale - LutriTech.it

Avremo che la tensione Vout presente all’ingresso dell’ADC sarà di circa 0,91Volt.
Quindi con una resistenza esterna da 1MΩ siamo sicuri di non causare problemi al microcontrollore perché lavoriamo nell’intervallo delle tensioni consentite, 0V<Vout<0,91V<1V
La vera tensione che ci interessa misurare Vin è calcolata in questo modo:

Vin - LutriTech.it

Quando la tensione sarà di 0,91V l’ADC attribuirà il valore di campionamento pari a 1023, quando la tensione sarà 0 il valore di campionamento sarà 0.

raw = analogRead(A0); // è il campione preso dall'ADC e può valere da 0 a 1023 compresi. se raw è 1023 la tensione è 0,91V , se raw è 0 la tensione è 0V
volt = raw /1023; 
volt = volt / 0.07575;  // divido per rapporto di conversione trovato dalla formula del partitore

Risparmio Energetico

Per questa tipologia di progetti dove la nostra scheda è alimentata da una batteria esterna e che le operazioni compiute terminano dopo solo una decina di secondi, si possono minimizzare i consumi elettrici facendo “addormentare” la scheda. Così facendo si allunga l’autonomia della batteria di alimentazione.
Nello specifico il Voltmetro Wifi controllerà la tensione in alcuni momenti della giornata questo per evitare di scaricare velocemente il battery pack usb che lo alimenta.
Per arrivare a questo obiettivo bisogna attivare la modalità DeepSleep del Wemos D1 Mini, questa garantisce consumi più bassi rispetto le altre due modalità, come indicato dal manuale del produttore:

LutriTech.it - Sleep Modes Esp8266

In questa modalità, il chip disattiverà la connettività Wi-Fi e la connessione dati, rimane solo funzionante il modulo RTC, cioè “l’orologio interno” che sarà il responsabile
della sveglia. Per abilitare la modalità DeepSleep serve la seguente riga di codice nel nostro sketch:

ESP.deepSleep(durataTemporale);

la funzione necessita di una durata temporarel per cui l’ESP8266 si risveglierà dalla modalità di sonno profondo. 
Il tempo massimo nel sonno profondo è 4.294.967.295 µs, ovvero circa 71 minuti. Se volete un tempo ancora più grande potete usare questo comando:

ESP.deepSleep(ESP.deepSleepMax());

Così facendo si ottiene una durata (sempre diversa) che si aggira su 14270595065μs –> 14270s–> circa 4 ore!
Dopo questo tempo, l’ESP8266 verrà riattivato da un impulso di ripristino dal pin D0 (GPIO16), che è definito appunto come linea di riattivazione. 
Serve connettere fisicamente D0 con RST.

LutriTech.it - Connessione RST con D0 del Wemos D1 Mini
Collegamento necessario per la riattivazione della scheda

Configurazione dell’applicazione su Blynk del Voltmetro Wifi

Dopo esservi loggati sulla vostra applicazione di Blynk potete cliccare in alto a destra come mostrato nell’immagine qui sotto per importare un clone del progetto.

LutriTech.it - Import app da Blynk

Basta inquadrare il codice QR mostrato qui sotto per avere già tutto pronto:

LutriTech.it - Codice QR per import app Blynk

Se tutto è andato per il meglio l’interfaccia grafica si presenterà in questo modo:

LutriTech.it - Voltmetro Wifi applicazione

Ho inserito la data e l’ora dell’ultima acquisizione fatta in modo da capire se la scheda sta effettivamente inviando dati al server di Blynk.

Codice dello sketch del Voltmetro Wifi

Qui potete copiare il programma e adattarlo alla vostre esigenze.

// Collega RST al pin D0 del Wemos!

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

#include <TimeLib.h>
#include <time.h>
#include <Timezone.h>    // https://github.com/JChristensen/Timezone

char auth[] = "VostroToken"; //token progetto server Blynk
char ssid[] = "VostraReteWifi";
char pass[] = "VostraPasswordWifi";


unsigned int raw = 0;
float volt = 0.0;
String voltString = "";
String currentDate = "";

const int sleepTimeS = 60; // Time to sleep (in seconds):

WiFiUDP ntpUDP;
int GTMOffset = 0; // SET TO UTC TIME
NTPClient timeClient(ntpUDP, "it.pool.ntp.org", GTMOffset * 60 * 60, 60 * 60 * 1000);

// Central European Time (Frankfurt, Paris)
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     // Central European Summer Time
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       // Central European Standard Time
Timezone CE(CEST, CET);

static tm getDateTimeByParams(long time) {
  struct tm *newtime;
  const time_t tim = time;
  newtime = localtime(&tim);
  return *newtime;
}

/**
   Input tm time format and return String with format pattern
*/
static String getDateTimeStringByParams(tm *newtime, char* pattern = (char *)" %H:%M:%S %d/%m/%Y") {
  char buffer[30];
  strftime(buffer, 30, pattern, newtime);
  return buffer;
}

/**
   Input time in epoch format format and return String with format pattern
*/
static String getEpochStringByParams(long time, char* pattern = (char *)" %H:%M:%S %d/%m/%Y") {
  tm newtime;
  newtime = getDateTimeByParams(time);
  return getDateTimeStringByParams(&newtime, pattern);
}

void setup() {
  Serial.begin(115200);
  pinMode(A0, INPUT);
  Serial.println("Mi sono svegliato");

  leggiTensione();
  Serial.println("tensione letta al setup"); //per debug
  Serial.println(voltString); //per debug


  Blynk.begin(auth, ssid, pass, IPAddress(x, y, z, w), 8080); //al posto di x, y, z, w mettere il vostro ip del server Blynk
  orologio();
}

void loop() {
  Blynk.run();
  //
  Serial.println("tensione inviata dal loop"); //per debug
  Serial.println(voltString); //per debug
  Blynk.virtualWrite(V2, voltString);

  Serial.println("data inviata nel loop"); //per debug
  //Serial.println(currentDate);  //per debug
  Blynk.virtualWrite(V3, currentDate );

  delay(250); //per connessione a blynk

  Serial.println("mi addormento");
  //ESP.deepSleep(sleepTimeS * 1000000); // nel caso volessi impostare una durata in secondi per il DeepSleep
  Serial.println("max deep sleep: " + uint64ToString(ESP.deepSleepMax())); //per debug
  ESP.deepSleep(ESP.deepSleepMax());//serve per avere la massima durata di sospensione
}


String leggiTensione() {
  unsigned int x;
  for (int i = 0; i < 100; i++) {
    raw = analogRead(A0) - 5 ; //5 è un offset trovato collegando A0 a GND
    volt = (raw + i * raw ) / (i + 1);  //calcola il valore medio per 100 acquisizioni
   yield(); //per evitare riavvi per causa del watchdog(WDT)
  }
  volt = raw /1023; 
  volt = volt / 0.07575;  // divido per rapporto di conversione trovato dalla formula del partitore

  voltString = String(volt);
  return voltString;
}


String orologio() {   // scarica l'ora del server ntp secondo il formato definito all'inizio
  timeClient.begin();
  delay ( 1000 );
  if (timeClient.update()) {
    unsigned long epoch = timeClient.getEpochTime();
    setTime(epoch);
  } else {
    Serial.print ( "aggiornamento ora fallito" );
  }
  currentDate = String (getEpochStringByParams(CE.toLocal(now())));
  Serial.println ( currentDate);
  return currentDate;
}

String uint64ToString(uint64_t input) { //permette di stampare sul monitor seriale un uint64
  String result = "";
  uint8_t base = 10;

  do {
    char c = input % base;
    input /= base;

    if (c < 10)
      c +='0';
    else
      c += 'A' - 10;
    result = c + result;
  } while (input);
  return result;
}

Il codice è commentato in modo che sia di facile comprensione. Riepilogando velocemente:

Alla prima accensione, a wifi spento, viene invocata leggiTensione() che acquisisce 100 campioni di tensione e ne fa la media, calcolando poi la tensione reale.
Successivamente viene attivato il wifi, quindi la connessione al Blynk Server, viene scaricata l’ora corrente dall’ntp server. successivamente vengono inviati i valori della tensione e dell’ora.
Dopo la scheda si iberna. Dopo sleepTimeS secondi la scheda si sveglia e viene rieseguito il codice contenuto nel setup() e poi nel loop().

Concludendo: abbiamo costruito un voltmetro wifi che ci permette di controllare da remoto una tensione come quella di una batteria per auto/camper/moto. Abbiamo imparato anche come ibernare la scheda far risparmiare più energia possibile.

Condivi sui Social

Lascia un commento

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

20 commenti su “Voltmetro Wifi con Wemos D1 Mini”

  1. Buongiorno
    Ho trovato questo progetto molto interessante, ho installato blynk iot l’unica app che ho trovato nel play store, ma ho un problema leggendo il qrcode mi restituisce questo errore “blynk iot qr body is too long. max length is 200 symbols” cosa sto sbagliando? non è che serve una versione precedente di Blynk.
    Cordialmente
    Mauro

    1. Ciao Mauro,
      È necessaria la vecchia app e il server privato di blynk.nell’articolo ci sono i link con le guide relative.
      Se non vuoi usare blynk Legacy avevo scritto il codice anche per il bot di telegram.
      Un caro saluto.
      Giuseppe

      1. Ciao Giuseppe
        ho creato, seguendo le tue dettagliate istruzioni, un server su google cloud ho ricontrollato tutto e l’istanza vw pare essere corretta ma connettendomi all’indirizzo https://—————:9443/admin mi restituisce l’errore Impossibile raggiungere il sito Connessione negata, è possibile che il sito Blynk non sia più disponibile.
        Cordialmente
        Mauro

        1. Ciao Mauro,
          scusa per la risposta tardiva ma non sono stato bene in questi giorni.
          Ti consiglio di fare queste 3 verifiche:
          1) collegati sulla vm e verifica che la porta 9443 sia aperta.
          2) se è aperta dal tuo pc prova con il comando telnet a vedere se la porta è raggiungibile
          3) pinga dal tuo pc l’ip pubblico della vm.

          Sulla console di google bisogna aprire le porte come la 9433 affinché siano raggiungibili dall’esterno.
          Il sito del cloud di Blynk non è più accessibile ma con la procedura della vm su google ne usiamo una tutta nostra!
          Quindi siamo svincolati.
          Facci sapere.
          Un saluto.

  2. ciao Giuseppe.
    Ho provato a replicare questo progetto, ma non trovo la libreria BlynkSimpleEsp8266.h; potresti indicarmi un link o il nome corretto della libreria da installare?
    Grazie

      1. Grazie Giuseppe. Adesso le librerie sono a posto e funziona quasi tutto; trova l’orario, ma non mi legge la tensione; o legge 0,00 oppure un valore strano 55424476,00 in genere quando ho il cavo positivo scollegato dalla batteria (da 5 volt; ho inserito R esterna da 220K senza cambiare i parametri dell’esempio) e lo tocco con la mano.
        Per fare le prove ho ridotto lo “sleep” ad 1 minuto.
        Con il monitor seriale mi appaiono una serie di caratteri strani poi mi appaiono tutte le voci iniziando da “tensione letta al setup” (il secondo Serial.println all’interno del void setup), fino al “mi addormento” finale. Ho provato ad inserire un delay di 1 secondo dopo il serial.begin, ma non è cambiato nulla: il “Mi sono svegliato” non lo vedo dal monitor e forse anche “leggi.tensione” non mi funziona”.
        Qualche idea? Come sempre, grazie!

        1. Ciao Carlo,
          per 5 Volt va bene la resistenza da 220K..
          ma devi modificare il codice che ho indicato dell’articolo.
          Facendo i conti si ha
          Vout=5*0.185=0.925 quindi si è sotto il volt massimo consentito.
          quindi nel codice devi sostituire la riga
          volt = volt / 0.07575;
          con
          volt = volt / 0.185;

          Varrebbe la pena mettere sulla pagina un form che faccia i calcoli per gli utenti 🙂
          Per fare le prove metti la resistenza da 220K tra il pin dei +5V della scheda e A0 così non usi la batteria esterna.
          fammi sapere

          1. Ciao Giuseppe
            Non avevo corretto quel numero perchè secondo me non è quello il problema…. comunque ora l’ho fatto e il risultato è cambiato così: fino a che il pin A0 è collegato ai 5 volt, la lettura rimane 0,00 e quando lo scollego, ogni tanto appare 22694076,00; ricollegandolo ai 5 volt torna 0,00.
            Quindi: 55424476/22694076=2.442 e anche 0,185/0,07575=2.442 allora secondo me non è cambiato nulla, è come se al posto di un ingresso analogico avessi un ingresso digitale 0/1 “quasi invertito”.
            L’ultima prova che posso fare è utilizzare un altro D1 e vedere se mi fa la stessa cosa; magari questo durante le prove ha avuto un problema con la porta analogica.

            In passato, ad un ESP8266-01 ho collegato un filo al pin analogico del chip, ma APPENA la tensione superava 1 volt, il chip si “fondeva” cioè assorbiva 300mA e non funzionava più (me ne sono accorto a mie spese…. dopo il secondo pezzo che mi si è fuso sono stato bene attento a non andare oltre 1 volt, anche perchè per stagnare un filo in quel pin microscopico mi ci voleva almeno mezz’ora di tempo). Ora sono passato al D1 che ha il pin analogico collegato e con già il partitore, ma vedo che i miei problemi continuano.
            Grazie dell’aiuto.

Torna in alto