Sunday, May 15, 2016

Internet Connected Energy Meter

This is the final post in a series of post that explains how I installed an electrical energy meter in my house and connected  it to the internet.

Here are the steps involved:

  1. Installing a 3 phase energy meter in your home [Blog post here]
    (I used Selec MFM383C Modbus capable energy meter, connected it to my router using USB<>RS485 interface based on FT232RL and MAX485)
    Modbus capable energy meter
  2. Installing OpenWrt 15.05 Chaos Calmer on TP-LINK TL-MR3020 [Blog post here]
    (required adding a USB hub to it, a USB flash drive to hold the rootfs, an FT232RL widget  for getting console access to the router over serial and another FT232RL based USB<>RS485 UART for interfacing to the energy meter using modbus. Instead of TL-MR3020, you can use TL-MR3040 as well which has its own battery pack in it.)

    TL-MR3040 (White color) with a USB hub sporting an 8GB Flash drive and USB<>RS485
    convertor.

    A TL-MR3020 with a USB hub (Flash drive in one of the ports) and
    an FT232RL used to gain console access.
  3. Compiling the binaries for libmodbus and mfm383c [Blog post here]
      
  4. Install drivers for FT232RL based RS485 bridge, curl and some other important stuff on your router:
    # opkg update#  opkg install kmod-usb-serial-ftdi kmod-usb-acm kmod-usb-serial curl coreutils-stty usbutils libmodbus bash nano grep getopt ip-full syslog-ng
      
  5. Installing CA Certificates on your TL-MR3020 running OpenWrt
    We need HTTPS support to upload datapoints to initialstate.com, so to avoid the "(51) Cert verify failed: BADCERT_NOT_TRUSTED" error thrown by cURL, we need to install the certificates, do this by issuing the commands to your router:

    # opkg update
    # opkg install ca-certificates


  6. Sign up for an Initial State account.
      
  7. Write script to execute mfm383c.out, read all the registers from the energy meter over modbus and use cURL
    Script is appended below, place it in /root of your router. Make sure to use your own access key and bucket key from your initial state account and add them to the script accordingly.
      
  8. Finally add it to the crontab - use the web GUI and set the script to execute once every minute.
Configuring the router to run the script every minute

This is what my initial state tiles view looks like.
It not only has data coming in from my energy meter but also from my weather station.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/bin/bash

export SSL_CERT_DIR=/etc/ssl/certs


# InitialState Configuration:
INITIALSTATE_ACCESS_KEY="YOUR ACCESS KEY"
INITIALSTATE_BUCKET_KEY="YOUR BUCKET KEY"

register_names=( "KWH" "V1N" "V2N" "V3N" "I1" "I2" "I3" "FREQ" "KW_TOTAL" "KVA_TOTAL" )
array_len=${#register_names[@]}

logger 'Reading Registers from Selec MFM383C over RS485/Modbus'
echo 'Reading Registers from Selec MFM383C over RS485/Modbus'
echo 'Baud 9600 | Data bits 8 | Parity bits N | Stop bits 1 | Port /dev/ttyUSB0'
echo 'Slave ID 1 | Response timeone 1 second | Byte timeout 1 second'
echo '--------------------------------------------------------------------------'
echo ''


# ------ Initial State -------------------------------------------------------------

# Prepare cURL HTTP PUT data
DATA_JSON="["

for (( i=0; i<${array_len}; i++ ));
do
 # Send two Ping request packets and 4 seconds timeout
 register_value=$(/root/mfm383c.out -b 9600 -r ${register_names[$i]})
 return_value=$?
 case $return_value in
  0)  #Register read successfully
   logger "Selec MFM383C register read successfully ${register_names[$i]} = $register_value"
   DATA_JSON="$DATA_JSON"$'\n'"     { \"key\" : \"Electricity_${register_names[$i]}\","
   DATA_JSON="$DATA_JSON"$'\n'"      \"value\" : \"$register_value\""
   if [ $((i)) = $((array_len-1)) ]; then
    DATA_JSON="$DATA_JSON"$'\n'"    }"
   else
    DATA_JSON="$DATA_JSON"$'\n'"    },"
   fi
   ;;
  1)  #Reading register failed: Incorrect command line parameters
   logger "Selec MFM383C register read error: Incorrect command line parameters"
   ;;
  2)  #Reading register failed: Modbus library error
   logger "Selec MFM383C register read error: Modbus library error"
   ;;
  3)  #Reading register failed: Modbus serial error
   logger "Selec MFM383C register read error: Modbus serial error"
   ;;
  *)  #Reading register failed
   logger "Selec MFM383C register read error"
   ;;
 esac
done
DATA_JSON="$DATA_JSON"$'\n'"  ]"

echo $DATA_JSON

# execute cURL
curl --max-time 5 \
--include \
--request POST \
--header "Content-Type: application/json" \
--header "X-IS-AccessKey: $INITIALSTATE_ACCESS_KEY" \
--header "X-IS-BucketKey: $INITIALSTATE_BUCKET_KEY" \
 --header "Accept-Version: 0.0.4" \
 --data-binary "$DATA_JSON"  \
'https://groker.initialstate.com/api/events'

1 comments:

Unknown said...

Hello Anurag, I would like to make contact with you about an expansion to this great system and possible commercial application. My email is tomikeshaw@hotmail.com Thks Mike

Post a Comment