Smart Energy Meter with AWS cloud

Vertical: Industry 4.0

Stage 1 : Testing ModDus Communication (RS485) using modpoll

Step 1: Connect the A & B of energy meter to A & B pin in RuggedBoard RS485 port respectively.

For demonstration purpose I have used Elmeasure LG+ 1119 meter. If you are having any other meter then you have to read the datasheet of the meter vendor and provide proper parameters.

Step 2: Download the modpoll ARM execulatble binary and save it into your work directory. To download the file click below.

Step 3: Save the following code in .sh format on your working directory and name is as mbpoll.sh

./modpoll.bin -m rtu -a 1 -t 4:float -r 159 -b 9600 -s 1 -P none /dev/ttyS2

The above script has the following components:

  • m : communication mode

  • a : Slave address

  • t : data types of the slave holding register

  • r : Start Reference

  • b : Baudrate

  • s : Stopbits

  • p : Parity Bit

  • SERIALPORT : Serial port node of the RS485

Step 4: Run the above code to test ModBus communication

sh mbpoll.sh

If everything is correct your code will run without any error. and you can proceed to next stage.

Stage 2: Reading the Energy meter values using Python 3 Script.

Step 1: Connect the energy meter and the board as shown in the Stage 1.

Step 2: write the following code and save it as read_energymeter.py

#Python code to read data from Energy Meter:
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.constants import Endian
import time
client = ModbusClient(method='rtu', port='/dev/ttyS2', stopbits=1, bytesize=8, baudrate=9600, parity='N')
connection = client.connect()
counter = 1
while True:
print("==========================================================")
print("Iteration {}" .format(counter))
print("----------------------------------------------------------")
WattHour = client.read_holding_registers(0x009E, 2, unit=1)
decoder = BinaryPayloadDecoder.fromRegisters(WattHour.registers, Endian.Big, wordorder=Endian.Little)
print("Watt Hour Reading:", float(decoder.decode_32bit_float()))
counter += 1
print("==========================================================")
time.sleep(2)

Step 3: Run the above code to read data from Energy Meter

python read_energymeter.py

If everything is correct your code will run without any error and you can proceed to next stage to send the data to a AWS cloud and view it on a dashboard.

Stage 3: Reading the Energy meter values using Python 3 Script

I this stage you will be able to send command from cloud server (AWS) and start replying to the request from cloud. In this example we will send a command from cloud to start sending Energy Meter data and stop sending when the timer is out.

Step 1: Connect the energy meter and the board as shown in the Stage 1.

Step 2: Write the following code and save it as lg1119.py

#-------------------AWS MQTT init----------------------
import paho.mqtt.client as paho
import ssl, random
from time import sleep
import os
import json
import threading
#-----------------MODBUS init---------------------------
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.constants import Endian
#----------------Modbus client connection-------------------
modclient = ModbusClient(method='rtu', port='/dev/ttymxc5', stopbits=1, bytesize=8, baudrate=9600, parity='N')
connection = modclient.connect()
#----------------Global Variables----------------------------
Message = ''
TIMER = 0
Wflag = 0
mqtt_url = "a3hf64x6hul7tx-ats.iot.us-west-2.amazonaws.com"
root_ca = '/home/root/certs/Amazon_Root_CA_1.pem'
public_crt = '/home/root/certs/c17983007e-certificate.pem.crt'
private_key = '/home/root/certs/c17983007e-private.pem.key'
#----------------Functions-----------------------------------
def ledOn():
os.system("echo 29 > /sys/class/gpio/export")
os.system("echo out > /sys/class/gpio/PA29/direction")
os.system("echo 1 > /sys/class/gpio/PA29/value")
os.system("echo 29 > /sys/class/gpio/unexport")
def ledOff():
os.system("echo 29 > /sys/class/gpio/export")
os.system("echo out > /sys/class/gpio/PA29/direction")
os.system("echo 0 > /sys/class/gpio/PA29/value")
os.system("echo 29 > /sys/class/gpio/unexport")
def publishOn():
client.publish("Aws_regor", '{"voltage":' + str(Volt_val) + ', "frequency":' + str(Freq_val) + ', "status": "ON", "kwh":' + str(kWh_val) + ', "cost":' + str(cost) + '}', qos = 1)
def publishOff():
client.publish('Aws_regor', '{"voltage":' + str(Volt_val) + ', "frequency":' + str(Freq_val) + ', "status": "OFF", "kwh":' + str(kWh_val) + ', "cost":' + str(cost) + '}', qos = 1)
def timerCb():
global Message
global TIMER
global Wflag
print("Timer elapsed\n\nTurning off")
#ledOff()
publishOff()
#client.publish('Aws_regor', '{"voltage":' +str(Volt_val)', "frequency":' +str(Freq_val)', "message": "OFF"}', qos = 1)
Message = ''
TIMER = 0
Wflag = 0
def on_connect(client, userdata, flags, rc):
print("Connected with result code " + str(rc))
client.subscribe("ExampleTopic")
print("Subscribed")
def on_message(client, userdata, msg):
global Message
global TIMER
global timer
global Wflag
print ("Message Received")
print (msg.payload.decode("utf-8"))
msg.payload=msg.payload.decode("utf-8")
recvMesg = msg.payload
jsonMesg = json.loads(recvMesg)
Message = jsonMesg['message']
if (Message == 'ON'):
TIMER = jsonMesg['timer']
timer = threading.Timer(TIMER * 60, timerCb)
#ledOn()
timer.start()
Wflag = 1
print("Turning on LED")
#client.publish("sdk/test/cpp", 'ON', qos=1)
elif (Message == 'OFF'):
#ledOff()
print ("Turning off LED")
timer.cancel()
publishOff()
Wflag = 0
#client.publish("sdk/test/cpp", 'OFF', qos=1)
client = paho.Client()
client.tls_set(root_ca,
certfile = public_crt,
keyfile = private_key,
cert_reqs = ssl.CERT_REQUIRED,
tls_version = ssl.PROTOCOL_TLSv1_2,
ciphers = None)
client.on_connect = on_connect
client.on_message = on_message
client.connect(mqtt_url, port = 8883, keepalive=60)
client.loop_start()
# Publish to the same topic in a loop forever
loopCount = 0
while True:
if (Message == 'ON'):
'''
LineToNeutral = modclient.read_holding_registers(0x0F46, 2, unit=1)
decoder = BinaryPayloadDecoder.fromRegisters(LineToNeutral.registers, Endian.Big, wordorder=Endian.Little)
Volt_val = float(decoder.decode_32bit_float())
print("Line To Neutral Voltage:", Volt_val)
Frequency = modclient.read_holding_registers(0x0F4A, 2, unit=1)
decoder = BinaryPayloadDecoder.fromRegisters(Frequency.registers, Endian.Big, wordorder=Endian.Little)
Freq_val = float(decoder.decode_32bit_float())
print("Frequency:", Freq_val)
'''
Freq_val = 49.906
Volt_val = 230.507
Watthour = modclient.read_holding_registers(0x009E, 2, unit=1)
decoder = BinaryPayloadDecoder.fromRegisters(Watthour.registers, Endian.Big, wordorder=Endian.Little)
Wh_val = float(decoder.decode_32bit_float())
kWh_val = Wh_val / 1000.0
print("kWh: ", kWh_val)
if Wflag == 1:
WhIn = Wh_val
Wflag = 0
print(WhIn, Wh_val, (Wh_val - WhIn))
cost = (Wh_val - WhIn) * 0.2
print("==========================================================")
#volt_val = str(LineToNeutral.registers)
#freq_val = str(Frequency.registers)
publishOn()
sleep(5)
elif (Message == 'OFF'):
Wflag = 0
sleep(250/10000000.0)

Step 3: Run the above code to read data from Energy Meter

python lg1119.py

Step 4: Visit the following website and check the live energy meter data

https://ruggedboard.com/ev_demo/mqttSample/index.html

If everything is correct your code will run without any error and you can see live the data to a AWS cloud and view it on a dashboard.