Progetto: Mini display LCD collegato a Metern

Discussioni relative al software di monitoraggio energetico METERN
Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 30/01/2017, 16:25

Per i motivi che già ho spiegato qui mi sono imbarcato nel progetto di collegare un mini display LCD a metern, in modo da poter visualizzare in continuo i consumi, la produzione, i prelievi e qualche sensore senza dover consultare lo smartphone o il pc.
Sono a buon punto con il progetto: ho pronto il programmino in python, ho eseguito le prime prove con il display, realizzato il primo video dimostrativo. Mi manca giusto qualche componente hardware, la base di supporto e tutto il lavoro di rifinitura del progetto.
Vorrei utilizzare questo 3d per raccogliere suggerimenti e impressioni e per lasciare tutto quel che serve a chi fosse interessato con un certo ordine.

Comincio a mettere video dimostrativo tanto per introdurre l'argomento.


Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 30/01/2017, 16:28

SCRIPT IN PYTHON


Questo è il file in python per la gestione del display: FILE

Codice: Seleziona tutto

#!/usr/bin/python
 
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
 
# Software di controllo di un display LCD
# per la visualizzazione dei consumi eletrici istantanei
# monitorati con il software metern/123solar di (www.metern.org) Credit: Jean-Marc Louviaux
 
####################################################################################
#### Autore: Alessandro Botta - amorospo@yahoo.it               ####
#### Grazie per le info e l'aiuto ricevuto alla comunita' dei forum:        ####
#### http://www.energeticambiente.it/index.php                  ####
#### http://www.flanesi.it/forum/                       ####
####################################################################################
 
# importo le librarie necessarie
import RPi.GPIO as gpio
import linecache
import Adafruit_CharLCD as LCD
import time
import sys
 
# Definisco i pin dei led
gpio.setmode(gpio.BCM)                  # Imposto la numerazione BCM per i pin gpio
gpio.setwarnings(False)                 # Disattiva messaggi d'avviso
pin_v = 25              # Numero BCM del pin gpio del led verde
pin_r = 21              # Numero BCM del pin gpio del led rosso
pin_g = 12              # Numero BCM del pin gpio del led giallo
pin_b = 20              # Numero BCM del pin gpio del led blu
pin_buz = 16                # Numero BCM del pin gpio del buzzer di allarme
gpio.setup(pin_v, gpio.OUT, initial=1)  # Inizializzo e accendo il led verde
gpio.setup(pin_r, gpio.OUT, initial=1)  # Inizializzo e accendo il led rosso
gpio.setup(pin_g, gpio.OUT, initial=1)  # Inizializzo e accendo il led giallo
gpio.setup(pin_b, gpio.OUT, initial=1)  # Inizializzo e accendo il led blu
gpio.setup(pin_buz, gpio.OUT, initial=0)# Inizializzo e spengo il buzzer di allarme
time.sleep(0.1)
 
# Numero GPIO connessione LCD al Raspberry PI
lcd_rs      = 26
lcd_en      = 19
lcd_d4      = 13
lcd_d5      = 6
lcd_d6      = 5
lcd_d7      = 11
lcd_backlight   = 17
 
# Definisco il numero di colonne e righe del display lcd
lcd_columns = 20
lcd_rows    = 4
 
# Inizializzo il display LCD
time.sleep(0.1)
lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7,
                lcd_columns, lcd_rows, lcd_backlight)
 
# Definisco i file da cui prendere i dati
cons = "/home/pi/Filediprova/test.txt"      #file metern lettura contatore SDM
met_cons = "2"                  #numero del metern dei consumi
prod = "/home/pi/Filediprova/metern2p.txt"  #per crearlo editare il file /comapps/pool123s.php aggiungendo verso la fine la riga
                        #   file_put_contents("/run/shm/prodpower$METERID.txt", "$METERID($GP*W\n");
                        #tra la riga
                        #   if ($argv[1] == 'power') {
                        #e la riga
                        #   echo "$METERID($GP*W)\n";
                        #file metern lettura produzione da creare con aurora o 123solar o altro contatore SDM
met_prod = "2"                  #numero del metern di produzione
DHT = "/home/pi/Filediprova/metern6.txt"    #file metern lettura sensore DHT
met_DHT = "6"                   #numero del metern di lettura del sensore DHT
 
# Creo il carattere speciale dei gradi centigradi (https://www.quinapalus.com/hd44780udg.html)
lcd.create_char(1, [6, 9, 9, 6, 0, 0, 0, 0])
 
# Pausa di riflessione per evitare errori di inizializzazione
time.sleep(0.3)
 
# Comincio un ciclo infinito di letture
while True:
    try:
        #pulisco il display
        lcd.clear()
        #leggo file consumi
        file_cons = linecache.getline(cons,1)
        if file_cons.startswith(met_cons) is True:
            mtc = "("
            mtc0 = "".join([met_cons,mtc])
            txt_cons_div = file_cons.replace(mtc0," ").replace("*W)"," ").strip()
            lcd.set_cursor(0,0)
            lcd.message("Consumo:")
            toMoveC = lcd_columns - len(txt_cons_div)
            lcd.set_cursor(toMoveC,0)
            lcd.message(txt_cons_div)
        else:
            lcd.set_cursor(0,0)
                        lcd.message("Err. lettura Consumi")
 
        #leggo file produzione
        file_prod = linecache.getline(prod,1)
        if file_prod.startswith(met_prod) is True:
            mtp = "("
            mtp0 = "".join([met_prod,mtp])
            txt_prod_div = file_prod.replace(mtp0," ").replace("*W)"," ").strip()
            lcd.set_cursor(0,1)
                        lcd.message("Produzione:")
                        toMoveP = lcd_columns - len(txt_prod_div)
                        lcd.set_cursor(toMoveP,1)
                        lcd.message(txt_prod_div)
        else:
            lcd.set_cursor(0,1)
                        lcd.message("Err. lettura Produz.")
 
        #leggo file sensore DHT
        #lettura temperatura
        file_tmp = linecache.getline(DHT,1)
        if file_tmp.startswith(met_DHT) is True:
            mtt = "_1("
            mtt0 = "".join([met_DHT,mtt])
            txt_tmp_div = file_tmp.replace(mtt0," ").replace("0*C)","\x01").strip()
            lcd.set_cursor(0,3)
                        lcd.message("Tmp:")
            lcd.set_cursor(4,3)
                        lcd.message(txt_tmp_div)
        else:
            lcd.set_cursor(0,3)
                        lcd.message("Err. Temp.")
 
        #lettura umidita'
        file_hum = linecache.getline(DHT,2)
        if file_hum.startswith(met_DHT) is True:
            mtu = "_2("
            mtu0 = "".join([met_DHT,mtu])
            txt_hum_div = file_hum.replace(mtu0," ").replace("0*%)","%").strip()
                        toMoveU = lcd_columns - len(txt_hum_div) - 5
            lcd.set_cursor(toMoveU,3)
            lcd.message("Umdt:")
                        lcd.message(txt_hum_div)
        else:
            lcd.set_cursor(10,3)
                        lcd.message("Err. Umid.'")
         
        #creo valore di immissione/prelievo
        if file_prod.startswith(met_prod) is True and file_cons.startswith(met_cons) is True:
            prod_num = float(txt_prod_div)
            cons_num = float(txt_cons_div)
            delt = prod_num - cons_num
            delt1 = abs(delt)
            delta = str(delt1)
            #prova led
            #se produco piu' o uguale di quanto consumo
            if prod_num >= cons_num:
                if delt1 > 2500:
                    #decido quale led accendere o spegnere quando produco piu' di 2.5kW piu' di quello che consumo
                                    gpio.output(pin_v, 1)
                                    gpio.output(pin_r, 0)
                                    gpio.output(pin_g, 0)
                                    gpio.output(pin_b, 0)
                                    gpio.output(pin_buz, 0)
                elif delt1 > 1500 and delt1 <= 2500:
                    #decido quale led accendere o spegnere quando produco tra 1500 e 2500W piu' di quello che consumo
                                        gpio.output(pin_v, 1)
                                        gpio.output(pin_r, 0)
                                        gpio.output(pin_g, 0)
                                        gpio.output(pin_b, 1)
                                        gpio.output(pin_buz, 0)
                elif delt1 > 500 and delt1 <= 1500:
                                        #decido quale led accendere o spegnere quando produco tra 500 e 1500W piu' di quello che consumo
                                        gpio.output(pin_v, 0)
                                        gpio.output(pin_r, 0)
                                        gpio.output(pin_g, 0)
                                        gpio.output(pin_b, 1)
                                        gpio.output(pin_buz, 0)
                else:
                    #decido quale led accendere o spegnere quando produco meno di 500W piu' di quello che consumo
                    gpio.output(pin_v, 0)
                    gpio.output(pin_r, 0)
                    gpio.output(pin_g, 1)
                    gpio.output(pin_b, 1)
                    gpio.output(pin_buz, 0)
            else:           
                #se produco meno di quanto consumo
                maxPW = 4950            #inserire la potenza max di stacco del contatore in Watt
                                #oppure la potenza a cui far partire gli allarmi
                #se supero la soglia impostata
                if delt1 > maxPW:
                    #faccio suonare l'allarme
                    gpio.output(pin_buz, 1)
                    #decido quali led far lampeggiare quando supero la soglia massima
                    gpio.output(pin_v, 0)
                    gpio.output(pin_r, 0)
                    gpio.output(pin_g, 0)
                    gpio.output(pin_b, 0)
                    time.sleep(0.5)
                    gpio.output(pin_v, 1)
                    gpio.output(pin_r, 1)
                    gpio.output(pin_g, 1)
                    gpio.output(pin_b, 1)
                    time.sleep(0.5)
                    gpio.output(pin_v, 0)
                    gpio.output(pin_r, 0)
                    gpio.output(pin_g, 0)
                    gpio.output(pin_b, 0)
                    time.sleep(0.5)
                    gpio.output(pin_v, 1)
                    gpio.output(pin_r, 1)
                    gpio.output(pin_g, 1)
                    gpio.output(pin_b, 1)
                #se NON supero la soglia impostata
                else:
                    if delt1 > 3500:
                                            #decido quale led accendere o spegnere quando consumo piu' di 3.5kW piu' di quello che produco
                                            gpio.output(pin_v, 0)
                                            gpio.output(pin_r, 1)
                                            gpio.output(pin_g, 0)
                                            gpio.output(pin_b, 0)
                                            gpio.output(pin_buz, 0)
                                    elif delt1 > 2000 and delt1 <= 3500:
                                            #decido quale led accendere o spegnere quando consumo tra 2000 e 3500W piu' di quello che produco
                                            gpio.output(pin_v, 0)
                                            gpio.output(pin_r, 1)
                                            gpio.output(pin_g, 1)
                                            gpio.output(pin_b, 0)
                                            gpio.output(pin_buz, 0)
                                    elif delt1 > 500 and delt1 <= 2000:
                                            #decido quale led accendere o spegnere quando consumo tra 500 e 2000W piu' di quello che produco
                                            gpio.output(pin_v, 0)
                                    gpio.output(pin_r, 0)
                                            gpio.output(pin_g, 1)
                                            gpio.output(pin_b, 0)
                                            gpio.output(pin_buz, 0)
                                    else:
                                            #decido quale led accendere o spegnere quando consumo meno di 500W piu' di quello che produco
                                            gpio.output(pin_v, 0)
                                            gpio.output(pin_r, 0)
                                            gpio.output(pin_g, 1)
                                            gpio.output(pin_b, 1)
                                            gpio.output(pin_buz, 0)
                #fine stato led
 
            if prod_num > cons_num:
                lcd.set_cursor(0,2)
                            lcd.message("Immissione:")
                toMoveI = lcd_columns - len(delta)
                lcd.set_cursor(toMoveI,2)
                lcd.message(delta)
            else:
                if prod_num == cons_num:
                                    lcd.set_cursor(0,2)
                                    lcd.message("Punto  di  pareggio")
                else:
                    lcd.set_cursor(0,2)
                                    lcd.message("Prelievo:")
                    toMoveP1 = lcd_columns - len(delta)
                                    lcd.set_cursor(toMoveP1,2)
                                    lcd.message(delta)
 
        else:
            lcd.set_cursor(0,2)
                        lcd.message("Err.calcolo prelievo")
 
        #aggiorno la cache per la rilettura dei dati con intervallo di x secondi
        linecache.checkcache()
        time.sleep(2)
         
    except KeyboardInterrupt:
        #spengo il display all'uscita da tastiera con ctrl+c
        linecache.clearcache()
        lcd.clear()
        lcd.set_backlight(0)
        gpio.cleanup()     
        sys.exit()
Ultima modifica di amorospo il 31/01/2017, 10:20, modificato 1 volta in totale.

Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 30/01/2017, 16:48

I display LCD più comuni in commercio (esempi) vanno dalle 16 alle 20 colonne e dalle 2 alle 4 righe. Ci sono sia rgb che monocromatici. La retroilluminazione più comune è blu o verde. L'unico aspetto fondamentale per quanto ci riguarda è che sia basato sul controller HD44780 (praticamente tutti lo sono).
Il collegamento del display al raspberry può avvenire a 4 bit, a 8 bit o tramite bus I2C. La differenza sta nel numero di collegamenti da effettuare e quindi nel numero delle gpio da impegnare oltre che nell'efficienza del refresh dei dati.
Per ora ho sviluppato il progetto sulla base del collegamento a 4 bit (la via di mezzo per quanto riguarda le gpio impegnate), ma ho intenzione di approfondire il discorso I2C più avanti. Il display scelto da me è un monocromatico 20x4, ma il tutto è facilmente trasportabile su display con specifiche diverse.
Per chi ha difficoltà con le saldature o non ci si vuole mettere esistono in commercio anche display con morsettiere presaldate. Costano un po' di più ma sono indubbiamente più comodi. Tanto si parla di prezzi di max 10 euro.
Esempi:

Display 20x4 come il mio con connettori da saldare:
Immagine

Display 20x4 I2C:
Immagine

Display con morsettiera presaldata
Immagine

Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 30/01/2017, 18:21

INSTALLARE LIBRERIA ADAFRUIT LCD

Introdotto l'hardware display lcd, veniamo a come poterlo pilotare. Partendo dall'immagine solarjessie 2.6 l'unica libreria aggiuntiva di cui avremo bisogno è la relativa libreria Adafruit, installabile velocemente digitando da terminale uno alla volta i seguenti comandi:

sudo -s
cd /home/pi
git clone https://github.com/adafruit/Adafruit_Python_CharLCD.git
cd Adafruit_Python_CharLCD
python setup.py install

Fatto! Niente di difficoltoso.
Tutto il resto che serve è già presente nell'immagine solarjessie 2.6. Ora siamo pronti per far funzionare il nostro display LCD. Non ci resta che collegarlo.
La libreria Adafruit LCD utilizza la numerazione BCM delle porte GPIO, quindi bisogna fare riferimento a questa codifica quando si inizializza l'lcd nello script python.

File pdf porte GPIO
Ultima modifica di amorospo il 31/01/2017, 10:21, modificato 1 volta in totale.

Avatar utente
Flane
Messaggi: 2460
Iscritto il: 16/01/2016, 15:02

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda Flane » 30/01/2017, 22:07

Ottimo lavoro amorospo :D

Unica nota, proprio non capisco perchè crei degli ulteriori file per le letture dei consumi e della produzione quando si può semplicemente estrarre il valore dai file meterX.txt nella cartella /dev/shm,
oppure semplicemente far eseguire allo script gli stessi comandi che usa metern per leggere rispettivament
produzione: pool123s power
consumi: poolerconsumi 2 power

Creare ulteriori file mi sembra un passaggio inutile...... :?

Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 30/01/2017, 22:44

Flane ha scritto:Ottimo lavoro amorospo :D

Unica nota, proprio non capisco perchè crei degli ulteriori file per le letture dei consumi e della produzione quando si può semplicemente estrarre il valore dai file meterX.txt nella cartella /dev/shm,
oppure semplicemente far eseguire allo script gli stessi comandi che usa metern per leggere rispettivament
produzione: pool123s power
consumi: poolerconsumi 2 power

Creare ulteriori file mi sembra un passaggio inutile...... :?


Non creo ulteriori file nè vado ad eseguire ulteriori comandi; leggo proprio quei file temporanei nella directory shm.
Lo script di prova sta girando su un muletto che non è collegato al contatore sdm, quindi ho inventato dei file ad hoc solo per provare il display.


Inviato dal mio iPhone utilizzando Tapatalk

Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 30/01/2017, 23:26

Ho cominciato a costruirmi il case e devo dire che per ora mi sta proprio dando soddisfazione.
Manca ancora il buzzer di allarme ed i potenziometri per luminosità e contrasto che non mi sono ancora arrivati, però il risultato finale comincia a intravedersi.
Ho caricato un nuovo video fatto in fretta e furia dove ripeto la simulazione di un consumo crescente costante (+200W al secondo), fino al superamento della soglia di allarme e poi ripristino la situazione simulando un aumento improvviso della produzione. A parte il led verde un po' moscetto (avrò cannato la misura della resistenza...) per ora son soddisfatto.
Video nuova simulazione

Avatar utente
Flane
Messaggi: 2460
Iscritto il: 16/01/2016, 15:02

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda Flane » 30/01/2017, 23:31

AK ok, avevo guardato velocemente lo script. :oops:

Ora ho visto che crei solo un file per la produzione, che effettivamente non c'è se si legge direttamente dall'inverter.
Passaggio che non serve nel caso si usi un contatore anche per la produzione.

Il tuo sistema è veramente valido e devo dire che ci avevo pensato anch'io tempo fà(ho anch'io una moglie che il massimo che comprende sono due led verde e rosso .... :lol: :mrgreen: )
Però avevo accantonato la cosa in quanto ho poi pensato di lavorare solo di software invece che di hardware, realizzando una paginetta aggiuntiva per Metern molto semplice ma intuitiva in cui visualizzare e dati essenziali e gli eventuali allarmi in modo molto evidente ed a cui aggiungere eventuali notifiche push sul cell o via email. (un tablet a parete lo visualizzerebbe in modo altrettanto efficace quanto il tuo hardware).

Il progetto è però fermo con le quattro frecce .... :(

PS: per semplificare anche i cablaggi secondo me si potrebbe utilizzare un ESP8266 (o sonoff) da collegare al display LCD, e questo si legge i dati dal raspi via wifi. In questo modo lo potresti mettere dove vuoi, e non si è vincolati a stare nei paraggi del raspberry, basta solo dargli l'alimentazione.

Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 31/01/2017, 9:01

Flane ha scritto:PS: per semplificare anche i cablaggi secondo me si potrebbe utilizzare un ESP8266 (o sonoff) da collegare al display LCD, e questo si legge i dati dal raspi via wifi. In questo modo lo potresti mettere dove vuoi, e non si è vincolati a stare nei paraggi del raspberry, basta solo dargli l'alimentazione.


E' in programma anche questo sviluppo, tempo permettendo. Per ora la situazione cablaggio (che poi spiegherò dettagliatamente) è questa:
- con il collegamento a 4 bit l'lcd ha bisogno di 8 fili diversi (+1 se lo volessi accendere/spegnere da remoto) impegnando 6(+1) pin gpio diversi oltre a GND e +5V; quindi facendogli arrivare un cavo di rete (da smembrare in 8 fili) potrebbe bastare. Poi, per ogni led o buzzer bisogna aggiungere un nuovo filo ed un nuovo pin gpio impegnato sul raspi. In pratica per fare tutto devo far arrivare al display 2 cavi di rete;
- tutto è più semplice se il display ha l'interfaccia I2C; in quel caso basterebbero solo 3 fili (GND, +5V, 1 GPIO) + i 4+1 per led e buzzer. In pratica un singolo cavo di rete smembrato da 8 fili. Per ora però non ho tempo di approfondire l'argomento I2C.

Alla fine anche con un ESP8266 bisogna far arrivare al display almeno l'alimentazione, quindi portare questa o uno o due cavi lan potrebbe non essere molto differente.

Avatar utente
amorospo
Messaggi: 61
Iscritto il: 20/01/2016, 15:44

Re: Progetto: Mini display LCD collegato a Metern

Messaggioda amorospo » 31/01/2017, 9:23

Piccola gallery fotografica per la costruzione del case:
Immagine Immagine Immagine Immagine

Immagine Immagine Immagine Immagine

Immagine Immagine Immagine Immagine

Immagine Immagine Immagine Immagine

Immagine Immagine Immagine Immagine

Immagine Immagine Immagine


Scatoletta e placchetta acquistate a Bricoman a poco più di 2 euro.


Torna a “MeterN”

Chi c’è in linea

Visitano il forum: Nessuno e 12 ospiti