Arduino_Genuino
Published

Arduino IoT Based Energy Meter

Monitor your energy consumption through the Arduino IoT Cloud using a MKR WiFi 1010, a MKR 485 Shield and a Modbus compatible energy meter.

IntermediateFull instructions provided8,959
Arduino IoT Based Energy Meter

Things used in this project

Hardware components

Arduino MKR WiFi 1010
Arduino MKR WiFi 1010
×1
Arduino MKR 485 Shield
Arduino MKR 485 Shield
×1
Finder TYPE 7M.24
×1
DIN rail panel mount power supply
×1
3D printed Enclosure
×1

Story

Read more

Custom parts and enclosures

MKR DIN Case

Schematics

Setup

Code

Energy Meter

Arduino
#include "thingProperties.h"
#include "ArduinoRS485.h"
#include "ArduinoModbus.h"

#undef ON
#undef OFF

float current;
float power;
float energy;

unsigned long rate = 10000; // Default refresh rate in ms
unsigned long lastMillis = 0;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
 */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
  
    // Start Modbus RTU client
  if (!ModbusRTUClient.begin(19200)) {
    Serial.println("- Failed to start Modbus RTU Client!");
    while (1);
  }
  
}

void loop() {
  ArduinoCloud.update();
// Update energy meter data and show it via the Serial Monitor
  if (millis() - lastMillis > rate) {
    lastMillis = millis();

    current = readCurrent();
    delay(1200);
    power = readPower();
    delay(1200);
    energy = readEnergy();
  
    Serial.println(String(current) + "A " + String(power) + "watt " + String(energy) + "kWh ");
    delay(100);
    
  }   
  
  currentDisplay = current;
  powerDisplay = power;
  energyDisplay = energy;
  
}

/* Functions to read Finder energy meter holding registers
 * For more information: https://gfinder.findernet.com/public/attachments/7E/EN/PRT_Modbus_7E_64_68_78_86EN.pdf
 */


float readCurrent() {
  float current = 0.;
  // Send reading request over RS485 
  if (!ModbusRTUClient.requestFrom(0x21, INPUT_REGISTERS, 0x7E, 2)) {
    // Error handling
    Serial.print("- Failed to read the current! ");
    Serial.println(ModbusRTUClient.lastError()); 
  } else {
    // Response handler 
    uint16_t word1 = ModbusRTUClient.read();  // Read word1 from buffer
    uint16_t word2 = ModbusRTUClient.read();  // Read word2 from buffer
    //uint32_t millivolt = 1word2 << 16 | word1; // Join word1 and word2 to retrieve voltage value in millivolts
    current = word2/1000.0;                  // Convert to volts
    //Serial.println(word1);
    //Serial.println(word2 / 10);
  }

  return current;
}

float readPower() {
  float power = 0.;
  // Send reading request over RS485 
  if (!ModbusRTUClient.requestFrom(0x21, INPUT_REGISTERS, 0x8C, 2)) {
    // Error handling
    Serial.print("- Failed to read the power! ");
    Serial.println(ModbusRTUClient.lastError()); 
  } else {
    // Response handler 
    int16_t word1 = ModbusRTUClient.read();  // Read word1 from buffer
    int16_t word2 = ModbusRTUClient.read();  // Read word2 from buffer
    //uint32_t millivolt = 1word2 << 16 | word1; // Join word1 and word2 to retrieve voltage value in millivolts
    power = word2/10.0;                  // Convert to volts
    //Serial.println(word1);
    //Serial.println(word2 / 10);
  }

  return power;
}

float readEnergy() {
  float energy = 0.;
  // Send reading request over RS485 
  if (!ModbusRTUClient.requestFrom(0x21, INPUT_REGISTERS, 0xAC0, 2)) {
    // Error handling
    Serial.print("- Failed to read the energy! ");
    Serial.println(ModbusRTUClient.lastError()); 
  } else {
    // Response handler 
    //short word1 = ModbusRTUClient.read();  // Read word1 from buffer
    float word2 = ModbusRTUClient.read();  // Read word2 from buffer
    //uint32_t millivolt = 1word2 << 16 | word1; // Join word1 and word2 to retrieve voltage value in millivolts
    energy = word2/10.0;                  // Convert to volts
    //Serial.println(word1);
    //Serial.println(word2 / 10);
  }

  return energy / 10000;
}

Credits

Arduino_Genuino

Arduino_Genuino

91 projects • 11336 followers

Comments