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.

Last updated