[PYTHON] Affichage graphique de la consommation électrique des ménages avec 3GPI et Raspeye

Fixez le capteur au tableau de distribution à la maison et faites un graphique comme celui-ci.

メイン.gif

Également la quantité d'énergie consommée par chaque circuit.

回路ごと.gif

introduction

Je voulais connaître la quantité d'énergie consommée à la maison. S'il y a une alimentation de veille inutile, je voudrais la réduire, et s'il y a un appareil qui gaspille de l'électricité, je voudrais le remplacer par un produit à faible consommation d'énergie. Si vous utilisez un compteur intelligent, vous pouvez voir la transition de la consommation électrique totale, mais vous ne pouvez pas connaître la consommation de chaque circuit dérivé du tableau de distribution. Je voudrais afficher un graphique de la consommation électrique de chaque circuit.

Le prix unitaire de l'électricité a été décidé à 25 yens / kWh sur la base des résultats de ma maison en 2015.

spec

Comment calculer la consommation d'énergie

Consommation d'énergie = tension x courant x temps Déterminé à la tension = 100 V Courant = [racine carrée moyenne carrée] de la valeur mesurée (https://ja.wikipedia.org/wiki/%E4%BA%8C%E4%B9%97%E5%B9%B3%E5%9D%87%E5% Utilisez B9% B3% E6% 96% B9% E6% A0% B9) Time = Accumuler les valeurs mesurées à chaque fois

Méthode de mesure actuelle

La méthode de mesure consistait à connecter la sortie du capteur de courant au convertisseur AD sans passer par un circuit de lissage ou un circuit de redressement. Je m'attends à pouvoir lire la forme d'onde si la vitesse d'échantillonnage est suffisante.

Je pensais que la vitesse d'échantillonnage devrait être d'environ 5 échantillons par demi-cycle. Afin de prendre en charge la fréquence d'alimentation de 50 Hz et 60 Hz, je voudrais avoir environ 600 échantillons par seconde.

conception

Vue d'ensemble du système (image de développement précoce)

構成図.png

Conception matérielle

Acheter de l'équipement Il était de 57 390 yens au total. Pour l'alimentation, le câble USB, la carte universelle, l'en-tête à broches, la prise à broches et les câbles, j'ai utilisé le surplus à la maison.

Les choses nécessaires Ce que j'ai acheté boutique Somme d'argent
Module de communication 3G 3GPI Changer de science 29,800 yens
Module de gestion de l'alimentation slee-Pi Changer de science 11,800 yens
Tarte Razz Raspberry Pi 2 Model B Changer de science 5,940 yens
Dongle WiFi GW-USNANO2A Changer de science 1,350 yens
4 capteurs de courant SR-3702-150N/14Z Électronique Akizuki 3,920 yens
1 convertisseur AD Module ADC1015 Électronique Akizuki 1,280 yens
4 résistances à film métallique 100Ω 100 pièces Électronique Akizuki 300 yens
SIM pour la communication So-net 0 sim Sonnet 3,000 yens

Puisqu'il s'agit d'une combinaison de pièces de module, il n'est pas nécessaire de concevoir ou d'ajuster un circuit difficile. La carte de conversion courant-tension est constituée d'une carte universelle.

Logiciel

Comme il existe de nombreuses bibliothèques, nous utiliserons Python autant que possible. J'ai hâte d'utiliser Python pour la première fois.

Le serveur de gestion et d'affichage des données utilise Sakura Rental Server Standard. Pour la bibliothèque de gestion de données, essayez d'utiliser RRDtool, qui a une fonction de sortie graphique. Sur le serveur que j'ai loué, il a été installé sous le nom rrdtool-fix.

Je ferai de plus en plus

  1. Capteur de courant
  2. Connecteur de câble
  3. Convertisseur AD
  4. Tarte Razz
  5. 3GPI
  6. Programme d'émission / réception de valeurs mesurées
  7. Programme d'affichage graphique

Capteur de courant

Soudez-le au câble LAN et installez-le sur le tableau de distribution.

2016_07_17_00845.JPG Installé dans le circuit principal

Le tableau de distribution est alimenté sur trois lignes: rouge, noire et blanche. J'ai installé quatre capteurs comme suit.

--Capteur 0: ligne noire principale --Capteur 1: ligne rouge principale --Capteur 2: Éclairage d'habitation, prise de vie (noir) --Sensor 3: Réfrigérateur, boulangerie maison (rouge)

Selon la Fiche technique (URD) d'un capteur similaire qui est un produit d'une autre société, conversion de tension avec une résistance de 10Ω Ensuite, 60A est converti en 0,2V. La fonction de conversion est "courant = tension * 300". Cela ne mesure pas les faibles courants, mais il semble que 1 à 60 A puisse être mesuré sans distorsion. La conversion de tension avec une résistance de 100Ω convertit 60A en 2,0V. La fonction de conversion est "courant = tension * 30". Il semble qu'il puisse être mesuré à partir d'environ 0,1 A.

Je suis perdu, mais le pic peut être légèrement déformé, alors je l'ai réglé sur 100Ω, ce qui peut lire un courant faible.

Bien que ce soit une pièce qui est effectivement utilisée, j'ai acheté une résistance avec une erreur de ± 1%. J'ai mesuré la valeur de résistance avec un testeur et utilisé quatre de la même valeur de résistance proche de 100 Ω.

Convertisseur AD

Concevez et construisez le circuit.

電力量モニター回路図.png

vient de le faire. VDD a été réglé sur 3,3 V.

ボード.JPG

Le module convertisseur AD a une tension d'alimentation de 2 à 5 V et des vitesses I2C de 10 kHz à 400 kHz ainsi que 3,4 MHz. L'adresse I2C peut être modifiée de 0x48 à 0x4B à la destination de la broche ADDR. Il a un amplificateur intégré, peut mesurer le potentiel négatif et peut contrôler le gain avec un micro-ordinateur. Les 6 gammes suivantes.

En utilisant la plage ± 2,048 V (x2) avec PGA, le courant lu par le capteur de courant est de ± 61,44 A. Je vais l'essayer dans la gamme ± 2.048V. Une entrée négative est possible, ce qui est trop pratique. La résolution minimale est de 1 mV, ce qui se traduit par 30 mA en termes de courant. La consommation électrique est de 100 V x 30 mA = 3 W.

Tarte Razz

Aucune interface graphique n'est requise à des fins de mesure. Je suis accro à la console, je vais donc l'installer sur le réseau. J'ai hâte de toucher Razpai pour la première fois.

Installation

J'ai brûlé Raspbian Jessie Lite (2016-05-27) sur la carte SD restante (16 Go microSDHC Class4). Connectez simplement la carte de convertisseur AD que vous avez créée et le câble LAN, devinez l'adresse DHCP et SSH. C'était trop facile à battre. Voici la méthode d'installation.

#Désactiver la gestion de l'alimentation du LAN sans fil
sudo sh -c "echo options 8192cu rtw_power_mgnt=0 rtw_enusbss=1 rtw_ips_mode=1 > /etc/modprobe.d/8192cu.conf"

#Prolonger le délai d'expiration SSH
sudo sh -c "echo ClientAliveInterval 60 >> /etc/ssh/sshd_config"
sudo sh -c "echo ClientAliveCountMax 3 >> /etc/ssh/sshd_config"

#Mise à jour du package
sudo apt-get update
sudo apt-get upgrade

# i2c-installer des outils
sudo apt-get install i2c-tools

#Augmenter la fréquence d'horloge i2c
sudo sh -c "echo dtparam=i2c_baudrate=300000 >> /boot/config.txt"

#vérification i2c(Si 0x48 répond, ADS1015 répond)
i2cdetect -y 1 

#Installer la bibliothèque ADS1015
sudo apt-get install git build-essential python-dev
git clone https://github.com/adafruit/Adafruit_Python_ADS1x15.git
cd Adafruit_Python_ADS1x15
sudo python setup.py install
sudo shutdown -h now

Installation 3GPI

Débranchez l'alimentation lorsque le Raspberry Pi s'arrête. Connectez le 3GPI au Raspberry Pi et connectez l'alimentation fournie avec le 3GPI.

Plus d'informations sur 3GPI peuvent être trouvées ici [http://mechatrax.github.io/) et GitHub. 3gpi2.jpg

Installation 3GPI


sudo bash -c 'echo "deb http://mechatrax.github.io/3gpi ./" > /etc/apt/sources.list.d/3gpi.list'
sudo apt-get update
sudo apt-get install 3gpi-archive-keyring
sudo apt-get install 3gpi-utils 3gpi-network-manager
sudo reboot

Réglez l'APN. SIM a utilisé so-net 0sim. Il semble préférable de supprimer les informations APN inutilisées.

Paramètre APN


sudo nmcli con add type gsm ifname "*" con-name so-net apn so-net.jp user nuro password nuro
sudo nmcli c delete gsm-3gpi-iij
sudo nmcli c delete gsm-3gpi-soracom
sudo reboot

Avec juste cela, j'ai pu établir une connexion 3G. C'est une chose émouvante. Un ping lent est également la preuve d'une connexion 3G. Je suis heureux!

Via la ligne 3G


$ ping google.com -c 4
PING google.com (172.217.25.238) 56(84) bytes of data.
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=1 ttl=50 time=377 ms
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=2 ttl=50 time=386 ms
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=3 ttl=50 time=366 ms
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=4 ttl=50 time=404 ms

--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 366.570/383.838/404.300/13.866 ms

Via ligne optique


$ ping google.com
PING google.com (172.217.25.238) 56(84) bytes of data.
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=1 ttl=53 time=8.01 ms
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=2 ttl=53 time=9.52 ms
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=3 ttl=53 time=9.50 ms
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=4 ttl=53 time=9.66 ms
64 bytes from nrt12s14-in-f14.1e100.net (172.217.25.238): icmp_seq=5 ttl=53 time=9.47 ms
^C
--- google.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
rtt min/avg/max/mdev = 8.017/9.238/9.668/0.614 ms

Programme de mesure et de transmission

Calculez une ligne directrice pour le trafic. Ce programme envoie la consommation d'énergie toutes les minutes. Un message exprime l'horodatage et la consommation d'énergie de 4 canaux en texte ASCII, et la taille du message est d'environ 50 octets. Après avoir accumulé 5 minutes d'informations, bz2 compressé et envoyé. Puisqu'il peut être compressé en deux, la quantité réellement transmise est d'environ 120 octets, donc elle est d'environ 3,2 bps.

Compte tenu des frais généraux de TCP / IP, HTTP et SSL, il est difficile de le dire sans communiquer réellement.

0sim de so-net est exempt de frais de communication jusqu'à 500 Mo par mois. Converti à 1493 bps par seconde.

S'il y a beaucoup de trafic, prolongez l'intervalle de transmission pour le gérer.

Pointez sur la carte de conversion 3GPI et AD sur la tarte à la râpe et écrivez le programme.

sudo mkdir -p /opt/whmonitor/bin/
sudo vi /opt/whmonitor/bin/whmonitor.py
sudo chmod +x /opt/whmonitor/bin/whmonitor.py

/opt/whmonitor/bin/whmonitor.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import time
import math
from collections import deque
import copy
import sys
import datetime
import urllib
import urllib2
import bz2
import Adafruit_ADS1x15
import RPi.GPIO as GPIO


#Constantes associées pour la mesure de puissance
MEASURE_INTERVAL = 60
CHANNEL_CHANGE_INTERVAL = 10
CONVERSION_CONSTANT = 30 # 100 ohm
VOLTAGE = 100
TO_KILOWATT = 0.001

#Constantes liées au rythme cardiaque( slee-Pour Pi)
FLIP_INTERVAL = 500
HEARTBEAT_GPIO = 5

#Constantes associées à ADC1015
I2C_BUSNUM = 1
ADS1015_I2C_BASE_ADDRESS = 0x48
SENSORS = 4
PGA_GAIN = 2
SAMPLING_RATE = 3300

#Constantes liées à la transmission de données
MINIMUM_UPLOAD_QUEUE_LENGTH = 5
UPLOAD_URL = "https://[Nom d'hôte du serveur de réception des données]/whupdate.cgi"
BASICAUTH_ID = "[ID d'authentification de base]"
BASICAUTH_PASS = "[Mot de passe d'authentification de base]"
COMPRESSION_LEVEL = 9



class Recorder:
    """Cette classe télécharge des données sur un serveur Web.
Il a une file d'attente à l'intérieur et enregistre()Contient la liste reçue par la méthode.
Lorsque la file d'attente est suffisamment longue, elle envoie les données au serveur Web.
Si la transmission échoue, la transmission sera tentée au moment de l'enregistrement suivant.
    """

    def __init__(self, url, ba_id, ba_pass, minimum_upload_queue_length = 1):
        self.data_queue = deque()

        self.url = url
        self.ba_id = ba_id
        self.ba_pass = ba_pass
        self.compression_level = COMPRESSION_LEVEL
        self.minimum_upload_queue_length = minimum_upload_queue_length


    def record(self, data):
        self.data_queue.append(self.__build_message(data))
        tmp_queue=copy.deepcopy(self.data_queue)

        try:
            if self.minimum_upload_queue_length <= len(tmp_queue) :
                self.__send_queue(tmp_queue)
                for dummy in tmp_queue:
                    self.data_queue.popleft()
        except:
            print("===Les données n'ont pas pu être envoyées.===")
            d=datetime.datetime.today()
            print d.strftime("%Y-%m-%d %H:%M:%S"),'\n'


    def __send_queue(self, queue):
        send_string = ""
        for data in queue:
            send_string += " " + data
        response=self.__send_string(send_string)


    def __send_string(self, message):

        pswd_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
        pswd_mgr.add_password(None, self.url, self.ba_id, self.ba_pass)
        opener = urllib2.build_opener(urllib2.HTTPSHandler(),
            urllib2.HTTPBasicAuthHandler(pswd_mgr))
        urllib2.install_opener(opener)

        request = urllib2.Request(self.url)
        request.add_data(bz2.compress(message,self.compression_level))

        response = urllib2.urlopen(request)
        return response.read()


    def __build_message(self, data):
        message = str(int(time.time()))
        for value in data:
            message += ":" + str(value)
        return message


class Knocker:
    """Cette classe modifie la tension de sortie du GPIO.
    flip()Inversez la sortie de la broche GPIO spécifiée chaque fois que la méthode est appelée.
    """

    def __init__(self, port):
        self.port = port
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(port,GPIO.OUT)


    def flip(self):
        GPIO.output(self.port,(GPIO.input(self.port)+1)%2)



class IntervalTimer(object):
    """Cette classe est occupée à pleine vitesse()Exécutez la méthode.
En outre, longloop toutes les secondes spécifiées dans le constructeur()Exécutez la méthode
    """

    def __init__(self, interval = 1):
        self.interval = interval

    def busyloop(self):
        pass

    def longloop(self):
        print time.time()-self.start

    def loop(self):
        self.start=int(time.time())
        prev=self.start
        while True:
            while time.time()-prev < self.interval:
                self.busyloop()
            prev = int(time.time())
            self.longloop()


class Sampler(IntervalTimer):

    """Cette classe est la classe principale.
Gère les convertisseurs AD, les transmissions de données et les pulsations.
    """

    def __init__(self,interval):
        super(Sampler, self).__init__(interval)
        self.knocker = Knocker(HEARTBEAT_GPIO)
        self.recorder = Recorder(UPLOAD_URL, BASICAUTH_ID, BASICAUTH_PASS, \
            MINIMUM_UPLOAD_QUEUE_LENGTH)
        self.adc = Adafruit_ADS1x15.ADS1015(\
            address=ADS1015_I2C_BASE_ADDRESS,busnum=I2C_BUSNUM)
        self.reset_valiables()


    def reset_valiables(self):
        self.sensor = 0
        self.samples = 0
        self.sample_buffer = [0]*SENSORS
        self.sample_length = [0]*SENSORS
        self.watt = [0]*SENSORS


    def busyloop(self):
        if self.samples%CHANNEL_CHANGE_INTERVAL == 0 :
            self.sensor=(self.samples/CHANNEL_CHANGE_INTERVAL)%SENSORS
            self.adc.start_adc(self.sensor, gain=PGA_GAIN, \
                data_rate=SAMPLING_RATE)
            time.sleep(2.0/SAMPLING_RATE)

        current=self.adc.get_last_result()*CONVERSION_CONSTANT

        self.sample_buffer[self.sensor] += current * current
        self.sample_length[self.sensor] += 1
        if self.samples%FLIP_INTERVAL == 0:
            self.knocker.flip()
        self.samples += 1



    def longloop(self):
        for self.sensor in range(SENSORS):
            if self.sample_length[self.sensor] == 0:
                self.watt[self.sensor]=0
            else:
                self.watt[self.sensor]=\
                    math.sqrt(self.sample_buffer[self.sensor]\
                    /self.sample_length[self.sensor])*VOLTAGE*TO_KILOWATT

        self.recorder.record(self.watt)
        self.reset_valiables()



sampler = Sampler(MEASURE_INTERVAL)
sampler.loop()

Inscription au service

Créez des informations d'enregistrement de service.

sudo vi /etc/systemd/system/whmonitor.service

Le contenu est comme ça. Même si le programme s'arrête, il redémarrera automatiquement.

/etc/systemd/system/whmonitor.service


[Unit]
Description = watt hour monitor

[Service]
ExecStart = /opt/whmonitor/bin/whmonitor.py
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

Activez et exécutez le service.

sudo systemctl enable whmonitor
sudo systemctl start whmonitor

configuration slee-Pi

slee-Pi surveille la vitalité du système d'exploitation en installant sleepi-firmware. Avec le firmware standard, le système d'exploitation semble envoyer HEARTBEAT vers GPIO5 et slee-Pi le surveille. Si HEARTBEAT ne peut pas être confirmé pendant un certain temps, le Raspberry Pi sera arrêté ou redémarré.

Je veux surveiller la vie et la mort de l'application, donc j'annule le firmware standard. En activant / désactivant la broche GPIO5 dans la boucle de l'application, sleep-Pi est surveillé à vie ou à mort.

sudo bash -c 'echo "deb http://mechatrax.github.io/sleepi ./" > /etc/apt/sources.list.d/sleepi.list'
sudo apt-get update
sudo apt-get install sleepi-archive-keyring
sudo apt-get update
sudo apt-get install sleepi-firmware
sudo shutdown -h now
  1. Débranchez le Raspberry Pi (3GPI)
  2. Connectez la carte de convertisseur slee-Pi, 3GPI, AD
  3. Connectez l'alimentation à slee-Pi
  4. Appuyez sur le bouton de démarrage sur slee-Pi
#Arrêtez le programme de surveillance
sudo systemctl stop whmonitor.service
#Diminuer l'horloge i2c
sudo rmmod i2c_bcm2708 
sudo modprobe i2c_bcm2708 baudrate=100000
#Vérifiez le délai d'attente en secondes entre la fin du battement de cœur et l'arrêt
printf "%d\n" `i2cget -y 1 0x69 6 b`
#Définir le délai d'expiration à 120 secondes
i2cset -y 1 0x69 6 120 
#Réglez le mode de fonctionnement sur "Redémarrer activé, rallumer en l'absence de réponse"
i2cset -y 1 0x69 5 1
#Augmentez l'horloge i2c
sudo rmmod i2c_bcm2708
sudo modprobe i2c_bcm2708 baudrate=300000
#Démarrage du programme de surveillance de la consommation d'énergie
sudo systemctl start whmonitor.service
# sleepi-Désinstaller le firmware
sudo apt-get remove sleepi-firmware
# reboot
sudo reboot

Base de données et récepteur

Recevez chez Sakura le serveur de location Internet "Standard".

Création de base de données

create.sh


#!/bin/sh

/usr/local/bin/rrdtool-fix create  \
        /Répertoire de stockage de la base de données/watt.rrd --step 60 \
        DS:sensor0:GAUGE:120:0:1000000 \
        DS:sensor1:GAUGE:120:0:1000000 \
        DS:sensor2:GAUGE:120:0:1000000 \
        DS:sensor3:GAUGE:120:0:1000000 \
        RRA:AVERAGE:0.5:1:1054080 \
        RRA:MAX:0.5:1:1054080 \
        RRA:MIN:0.5:1:1054080 \
        RRA:LAST:0.5:1:1054080

Programme de réception

whupdate.cgi


#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import cgi
import cgitb
import os
import sys
import subprocess
import shlex
import bz2
import re

cgitb.enable()

if os.environ['REQUEST_METHOD'] != "POST":
    print 'invalid access'
    sys.exit()

rrd="/Répertoire de stockage de la base de données/watt.rrd"
lines = bz2.decompress(sys.stdin.read())
if re.match("^[0-9 :\.]+$",lines):
    cmd='/usr/local/bin/rrdtool-fix update {rrd} {param}'.format(rrd=rrd,param=lines)
    ret=subprocess.check_output(shlex.split(cmd))

print ('Content-type: text/html; charset=UTF-8')
print ("\r\n\r\n")
print

affichage graphique

Téléchargez Police IPA. IPA Gothic (et non P Gothic) est recommandé. Puisque la police a la même largeur, les lignes verticales sont difficiles à réduire. Enregistrez ipag.ttf dans le même répertoire que le programme d'affichage graphique.

graph_total.cgi


#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import subprocess
import os
import shlex
import cgi
import config
import sys
import re

os.environ["RRD_DEFAULT_FONT"]="/Répertoire de stockage des polices/ipag.ttf"
os.environ['LANG'] = 'ja_JP.UTF-8'

title=""
end="now"
start="now-12hour"
width=800
height=200


form=cgi.FieldStorage()
strnum=re.compile("^[0-9a-zA-Z\-]+$")

if form.has_key("title") and strnum.match(form["title"].value):
        title=" "+form["title"].value
if form.has_key("end") and strnum.match(form["end"].value):
    end=form["end"].value
if form.has_key("start") and strnum.match(form["start"].value):
        start=form["start"].value
if form.has_key("width") and form["width"].value.isdigit():
        width=form["width"].value
if form.has_key("height") and form["height"].value.isdigit():
        height=form["height"].value
if form.has_key("graph_id") and form["graph_id"].value.isdigit():
        graph_id=int(form["graph_id"].value)

cmd_src='/usr/local/bin/rrdtool-fix graph - \
            --start {start} --end {end} \
            --width {width} --height {height} \
            --title "charges d'électricité{title}" \
            --font "DEFAULT:9:" \
            --font "TITLE:12:" \
            --font "LEGEND:12:" \
            --lower-limit 0 --step 60 --slope-mode \
            --vertical-label "Watt" \
            DEF:s0_avg={rrd}:sensor0:AVERAGE \
            DEF:s1_avg={rrd}:sensor1:AVERAGE \
            DEF:s0_max={rrd}:sensor0:MAX \
            DEF:s1_max={rrd}:sensor1:MAX \
            DEF:s0_min={rrd}:sensor0:MIN \
            DEF:s1_min={rrd}:sensor1:MIN \
            CDEF:main_avg=s0_avg,s1_avg,+ \
            CDEF:main_max=s0_max,s1_max,+ \
            CDEF:main_min=s0_min,s1_min,+ \
            CDEF:main_yps=main_avg,3600,1000,*,/,25,* \
            VDEF:main_yen=main_yps,TOTAL \
            LINE1:main_avg#00ff00ff:"" \
            AREA:main_avg#00ff0033:"" \
            COMMENT:" \\n" \
            GPRINT:main_yen:"charges d'électricité%7.1lf yen" '

rrd="/Répertoire de stockage de la base de données/watt.rrd"
cmd=cmd_src\
    .format(rrd=rrd,width=width,height=height,start=start,end=end,title=title)
output=subprocess.check_output(shlex.split(cmd))

print ('Content-type: image/gif')
print
print output

graph_para.cgi


#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import subprocess
import os
import shlex
import cgi
import config
import sys
import re

os.environ["RRD_DEFAULT_FONT"]="/Répertoire dans lequel les polices sont enregistrées/ipag.ttf"
os.environ['LANG'] = 'ja_JP.UTF-8'

title=""
end="now"
start="now-12hour"
width=800
height=200
graph_id=0


form=cgi.FieldStorage()
strnum=re.compile("^[0-9a-zA-Z\-]+$")

if form.has_key("title") and strnum.match(form["title"].value):
        title=" "+form["title"].value
if form.has_key("end") and strnum.match(form["end"].value):
    end=form["end"].value
if form.has_key("start") and strnum.match(form["start"].value):
        start=form["start"].value
if form.has_key("width") and form["width"].value.isdigit():
        width=form["width"].value
if form.has_key("height") and form["height"].value.isdigit():
        height=form["height"].value
if form.has_key("graph_id") and form["graph_id"].value.isdigit():
        graph_id=int(form["graph_id"].value)

cmd_src='/usr/local/bin/rrdtool-fix graph - \
            --start {start} --end {end} \
            --width {width} --height {height} \
            --title "Consommation électrique par circuit{title}" \
            --font "DEFAULT:9:" \
            --font "TITLE:12:" \
            --font "LEGEND:10:" \
            --lower-limit 0 --step 60 --slope-mode \
            --vertical-label "Watt" \
            DEF:s0_avg={rrd}:sensor0:AVERAGE \
            DEF:s1_avg={rrd}:sensor1:AVERAGE \
            DEF:s2_avg={rrd}:sensor2:AVERAGE \
            DEF:s3_avg={rrd}:sensor3:AVERAGE \
            DEF:s0_max={rrd}:sensor0:MAX \
            DEF:s1_max={rrd}:sensor1:MAX \
            DEF:s2_max={rrd}:sensor2:MAX \
            DEF:s3_max={rrd}:sensor3:MAX \
            DEF:s0_min={rrd}:sensor0:MIN \
            DEF:s1_min={rrd}:sensor1:MIN \
            DEF:s2_min={rrd}:sensor2:MIN \
            DEF:s3_min={rrd}:sensor3:MIN \
            CDEF:total_avg=s0_avg,s1_avg,+ \
            CDEF:total_max=s0_max,s1_max,+ \
            CDEF:total_min=s0_min,s1_min,+ \
            CDEF:total_yps=total_avg,3600,1000,*,/,25,* \
            VDEF:total_yen=total_yps,TOTAL \
            CDEF:others_avg=s0_avg,s1_avg,+,s2_avg,s3_avg,+,- \
            CDEF:others_min=s0_min,s1_min,+,s2_min,s3_min,+,- \
            CDEF:others_max=s0_max,s1_max,+,s2_max,s3_max,+,- \
            CDEF:s2_yps=s2_avg,3600,1000,*,/,25,* \
            VDEF:s2_yen=s2_yps,TOTAL \
            CDEF:s3_yps=s3_avg,3600,1000,*,/,25,* \
            VDEF:s3_yen=s3_yps,TOTAL \
            CDEF:others_yps=others_avg,3600,1000,*,/,25,* \
            VDEF:others_yen=others_yps,TOTAL \
            COMMENT:"__________\t_cost___ _cur_ _min_ _max_ _ave_"\
            COMMENT:"\\n" \
            LINE1:total_avg#00ff0077:"total\t\g" \
            GPRINT:total_yen:"%7.1lf\g"  \
            GPRINT:total_avg:LAST:" %5.0lf\g"  \
            GPRINT:total_min:MIN:" %5.0lf\g"  \
            GPRINT:total_max:MAX:" %5.0lf\g"  \
            GPRINT:total_avg:AVERAGE:" %5.0lf\g"  \
            COMMENT:"\\n" \
            LINE1:s2_avg#00aa88:"vivant\t\g" \
            GPRINT:s2_yen:"%7.1lf\g"  \
            GPRINT:s2_avg:LAST:" %5.0lf\g"  \
            GPRINT:s2_min:MIN:" %5.0lf\g"  \
            GPRINT:s2_max:MAX:" %5.0lf\g"  \
            GPRINT:s2_avg:AVERAGE:" %5.0lf\g"  \
            COMMENT:"\\n" \
            LINE1:s3_avg#8800aa:"cuisine\t\g" \
            GPRINT:s3_yen:"%7.1lf\g"  \
            GPRINT:s3_avg:LAST:" %5.0lf\g" \
            GPRINT:s3_min:MIN:" %5.0lf\g" \
            GPRINT:s3_max:MAX:" %5.0lf\g" \
            GPRINT:s3_avg:AVERAGE:" %5.0lf\g" \
            COMMENT:"\\n" \
            LINE1:others_avg#aa8800:"Autre\t\g" \
            GPRINT:others_yen:"%7.1lf\g"  \
            GPRINT:others_avg:LAST:" %5.0lf\g"  \
            GPRINT:others_min:MIN:" %5.0lf\g"  \
            GPRINT:others_max:MAX:" %5.0lf\g"  \
            GPRINT:others_avg:AVERAGE:" %5.0lf"  \
            '

rrd="/Répertoire de stockage de la base de données/watt.rrd"
cmd=cmd_src\
    .format(rrd=rrd,width=width,height=height,start=start,end=end,title=title)
output=subprocess.check_output(shlex.split(cmd))


print ('Content-type: image/gif')
print
print output

Naviguer

Après environ 5 minutes, accédez à l'URL suivante pour vérifier le graphique.

http://[公開サーバー]/[ディレクトリ]/graph_total.cgi http://[公開サーバー]/[ディレクトリ]/graph_para.cgi

Achevée

J'ai pu afficher le graphique dans le navigateur. Avec cela, vous pouvez exposer l'alimentation de secours et les gros appareils ménagers.

graph_total.gif

graph_para.gif

Résumé

Je vais revoir la composition générale.

Flux de données

Le flux de données est divisé en deux systèmes. Ici, il est décrit comme un système de collecte de données et un système d'affichage de données.

Système de collecte de données

  1. Convertissez le courant en tension avec le capteur de courant et la résistance
  2. Amplifié et échantillonné avec ADS1015
  3. Obtenez des données d'échantillonnage avec Raspeye (en utilisant le bus I2C et la bibliothèque ADS1x15)
  4. Calcul 5.3 Envoi vers CGI sur un serveur de gestion de données via 3GPI
  5. Reçu par CGI et enregistré dans la base de données round robin de RRDtool

Système d'affichage des données

  1. Le navigateur demande à CGI d'afficher le graphique
  2. CGI oblige RRDtool à générer un graphique et à l'envoyer au navigateur
  3. Afficher dans le navigateur

Programmes et paramètres

Collectez le programme développé, le fichier de configuration et les fichiers externes nécessaires.

Côté tarte Razz

--Programme de mesure whmonitor.py --Fichier de configuration du service /etc/systemd/system/whmonitor.service

Du côté serveur

Impressions

Vous pouvez désormais mesurer la consommation d'énergie en toute sécurité. La communication 3G était possible, la surveillance du fonctionnement de l'application était possible, la consommation d'énergie était mesurée et un graphique pouvait être affiché. La mesure de la consommation électrique est un travail électronique recommandé car il est pratique et facile à préparer du matériel. Cependant, veuillez faire attention aux travaux sur le tableau de distribution et à l'isolation autour du capteur.

Il existe un risque de mort, tel qu'un choc électrique pendant le travail, une fuite électrique due à l'équipement installé ou un incendie dû à un court-circuit. Je ne peux pas juger si l'installation du capteur de courant sur le tableau de distribution correspond à des travaux électriques nécessitant une licence. J'ai étudié en tant qu'électricien de deuxième classe, mais selon l'interprétation, cela peut être lu comme nécessaire ou inutile. Dans tous les cas, il est préférable de comprendre les risques, il est donc sûr d'avoir les connaissances équivalentes à un électricien de deuxième classe. Le site Web SHARP fournit un exemple d '«installation sûre du client». → Puis-je installer le capteur CT à circuit unique moi-même?

À propos des résultats de mesure

Lorsque j'ai commencé à collecter des données, je m'intéressais aux appareils à forte puissance de crête. Calculez la charge d'électricité par heure. Le prix unitaire de l'électricité est fixé à 25 yens par kWh sur la base des résultats réels en 2015.

Matériel usagé Consommation électrique moyenne[w] Durée d'utilisation moyenne[h] Consommation d'énergie[kWh] charges d'électricité[Cercle]
four micro onde 1500 0.033 0.050 1.3
Sèche-linge de salle de bain 800 4.0 3.2 80
Sèche-couette 600 2.0 1.2 30
Diverses puissances de veille 80 24 1.2 30

Deux semaines après la mesure, je pouvais voir le prix approximatif par jour.

Article Consommation électrique moyenne[w] Durée d'utilisation moyenne[h] Consommation d'énergie[kWh] charges d'électricité[Cercle]
total 250 24 6.0 150
Alimentation de secours 50 18 0.9 23

Selon cela, 15% était une alimentation en veille. Les appareils comptés comme puissance de veille sont les fours à micro-ondes, les cuiseurs à riz, les yaourts, les boulangeries à domicile, les téléviseurs, les routeurs WiFi, les répéteurs WiFi, les haut-parleurs de PC, les disques durs externes, les ordinateurs portables (hors tension), les ordinateurs de bureau (hors tension), les PC. Moniteur et imprimante. Il y en a pas mal à énumérer, mais j'ai laissé les prises branchées, y compris celles que je n'utilise qu'occasionnellement. Le débranchement complet lorsqu'il n'est pas utilisé réduira votre facture d'électricité de 15%. La facture annuelle d'électricité en 2015 était de 60 000 yens, elle a donc pu être réduite à 51 000 yens.

J'ai estimé que les mesures de puissance de secours seraient efficaces pour réduire les frais d'électricité.

À propos des données de consommation d'énergie

En regardant le modèle d'augmentation / diminution de puissance, je peux comprendre à peu près l'heure et ce que j'ai fait. Utilisation du climatiseur. Utilisation d'un four à micro-ondes. La charge sur le réfrigérateur en raison de la température. Utilisation d'un cuiseur à riz. Éclairage allumé. Heure du réveil, heure du coucher. Par exemple, utiliser les toilettes la nuit. Avec la diffusion des compteurs intelligents, les entreprises d'électricité seront en mesure d'acquérir des changements dans la consommation d'énergie. En analysant l'état de consommation électrique de chaque foyer, vous pouvez comprendre ce qui se passe à la maison. En particulier, le modèle du micro-ondes est caractéristique. Vous pouvez obtenir des informations sur quand et combien de fois vous l'avez utilisé, et combien de fois par jour vous l'avez utilisé. Il peut s'agir de données convoitées pour les fabricants d'appareils électroménagers.

Il semble que la tarte aux râpes en cours d'exécution puisse échantillonner environ 1600 fois par seconde. Même si la fréquence d'alimentation est de 60 Hz, vous pouvez échantillonner 26 fois par cycle. Je pense qu'il est possible d'analyser la forme d'onde d'une manière ou d'une autre, il peut donc être possible d'analyser si l'équipement consommé est une charge telle qu'un moteur, un onduleur, un chauffage, etc.

À propos du développement

J'ai utilisé Razzpie pour la première fois et cela fonctionne assez bien. Je suis également reconnaissant pour la grande quantité d'informations. Je remercie mes ancêtres. Je n'avais pas à me soucier de l'exécuter en continu. Python était aussi beaucoup d'informations et facile à apprendre. Il existe de nombreuses bibliothèques et j'ai compris pourquoi elles étaient si populaires. Je suis un peu gêné car je ne pense pas avoir pu programmer selon les manières de Python.

Le temps de développement total est d'environ 40 à 50 heures. Le développement du matériel a pris environ 5 heures pour la sélection, la conception et la fabrication des pièces. Grâce à l'ADS1015, il est impressionnant que le temps de développement matériel ait été très court. Étant donné que l'échelle du circuit était petite, je l'ai soudé depuis le début, mais je pense qu'il peut être développé en un temps plus court s'il est assemblé avec une planche à pain.

J'ai l'impression qu'il a fallu du temps pour développer le logiciel. J'étais particulièrement accro à l'utilisation de RRDtool. Essayer de faire quelque chose de élaboré nécessitait peu d'informations et d'essais et d'erreurs. En particulier, j'ai l'impression qu'il a fallu beaucoup de temps pour savoir comment utiliser la syntaxe VDEF. 3GPI est très pratique car il fonctionne sans réfléchir. Je pensais que si je savais comment utiliser NetworkManager, je pourrais l'utiliser de manière plus avancée, comme la configuration d'une ligne de sauvegarde. Le slee-Pi est à l'origine un appareil qui surveille le fonctionnement de l'OS, mais je voulais surveiller le fonctionnement de l'application, donc je n'ai pas utilisé le pilote du fabricant. Puisqu'il génère un battement de cœur dans la boucle de l'application, il redémarrera automatiquement la tarte aux râpes lorsque l'application s'arrête. Vous pouvez également utiliser la fonction de surveillance de Raspeye, mais il est prudent de forcer un redémarrage de l'extérieur.

Remarques

La fixation d'un capteur sur le tableau de distribution présente un risque de mort tel qu'un choc électrique pendant le travail, une fuite électrique due à l'équipement installé et un incendie dû à un court-circuit. Soyez prudent lorsque vous prenez une décision, y compris si elle peut être mise en œuvre ou non.

Recommended Posts

Affichage graphique de la consommation électrique des ménages avec 3GPI et Raspeye
Production de système de contrôle de température avec tarte aux framboises et ESP32 (1)
Mesurez et comparez les températures avec Raspberry Pi et générez automatiquement des graphiques
Faire une boussole d'affichage kanji avec Raspberry Pi et Sense Hat
Surveillance des animaux avec Rekognition et Raspberry pi
Exécuter le servomoteur SG-90 avec Raspberry Pi
Production d'un système de contrôle de température avec tarte aux framboises et ESP32 (2) Production d'un appareil de transmission
MQTT Radicon Car avec Arduino et Raspberry
Allumez / éteignez votre PC avec Raspberry Pi
Sortie CSV des données d'impulsion avec Raspberry Pi (sortie CSV)
Obtenez des informations sur le processeur de Raspberry Pi avec Python
Obtenez la température et l'humidité avec DHT11 et Raspberry Pi
Mesurer la température du processeur de Raspeye avec Python
Construction VPN simple de la passerelle IPsec avec Ubuntu 20.04 et Raspberry Pi ―― 1. StrongSwan introduit
Connectez-vous à la console Raspberry PI et affichez les informations IP et SD locales
J'ai tweeté l'éclairement de la pièce avec Raspberry Pi, Arduino et un capteur optique
Enregistrez la température et l'humidité avec systemd sur Raspberry Pi
Apprentissage automatique avec Raspberry Pi 4 et Coral USB Accelerator
Afficher des images intégrées de mp3 et flac avec mutagène
IoT facile pour démarrer avec Raspeye et MESH
GPGPU avec Raspberry Pi
Construction VPN simple de la passerelle IPsec avec CentOS 8 et openSUSE (Raspberry Pi) --1 Introduction de StrongSwan
Détecter l'état de port du masque avec OpenCV et Raspberry Pi
Prenez la valeur du thermo-hygromètre SwitchBot avec Raspberry Pi
Mesurez la température et l'humidité avec Raspberry Pi3 et visualisez avec Ambient
Changer les valeurs du thermo-hygromètre Bot avec Raspberry Pi
Ubuntu 20.04 sur raspberry pi 4 avec OpenCV et utilisation avec python
Contrôler la mise sous / hors tension du port USB du Raspberry Pi
DigitalSignage avec Raspberry Pi
Installation de Docker sur Raspberry Pi et L Chika
Construction VPN simple de la passerelle IPsec avec Ubuntu 20.04 et Raspberry Pi --2 Confirmation de connexion VPN StrongSwan
Résoudre les problèmes liés à l'installation d'OpenCV sur Raspberry Pi et à la capture
Afficher l'image de la caméra USB avec OpenCV de Python avec Raspeye
Exploitons GPIO de Raspeye avec Python CGI
Créez facilement un TweetBot qui vous informe de la température et de l'humidité avec Raspberry Pi + DHT11.
Contrôlez librement l'affichage du tableau d'affichage RGB LED Matirix Lightning avec Raspberry Pi 3B +
Introduction facile au piratage domestique avec Raspberry Pi et discord.py
Créez une caméra de surveillance WEB avec Raspberry Pi et OpenCV
J'ai essayé d'exécuter Movidius NCS avec python de Raspberry Pi3
Créez des jeux LCD (16x2) avec Raspberry Pi et Python
Découvrez la puissance de l'accélération avec NumPy / SciPy
J'ai essayé de connecter Raspeye et conect + avec l'API Web
Plantes Mutter avec Raspberry Pi
Reconnaissance d'image des déchets avec Edge (Raspberry Pi) à partir de zéro connaissance en utilisant AutoML Vsion et TPU
Mesurez la température, l'humidité, etc. avec SensorTag et envoyez-le à Ambient via Raspberry Pi 3 pour le représenter graphiquement Partie 2
J'ai essayé d'automatiser l'arrosage du pot avec Raspberry Pi
Classique de Noël (?) Éclairage d'un arbre de Noël avec Raspberry Pi et Philips Hue
Notifier LINE de la température corporelle du thermomètre BLE avec la tarte à la râpe # 1
Avertir LINE de la température corporelle du thermomètre BLE avec la tarte à la râpe n ° 2
Créez un thermomètre avec Raspberry Pi et rendez-le visible sur le navigateur Partie 4
Instrument de pesage utilisant Raspberry Pi et Hx711 (affichage GUI dans Tkinter)
Consigner périodiquement les valeurs des capteurs d'environnement Omron avec Raspberry Pi
Comment mettre OpenCV dans Raspberry Pi et collecter facilement des images des résultats de détection de visage avec Python
J'ai fait un package npm pour obtenir l'ID de la carte IC avec Raspberry Pi et PaSoRi
Lisez les données du lecteur NFC connecté à Raspberry Pi 3 avec Python et envoyez-les à openFrameworks avec OSC
[Raspberry Pi] Contrôle du moteur pas à pas avec Raspberry Pi
Utilisez vl53l0x avec RaspberryPi (python)
MQTT sur Raspberry Pi et Mac
Communication série avec Raspberry Pi + PySerial