LoRa Energy Meter using Arduino, LoRa Power Meter, electricity meter
Table of Contents
LoRa Energy meter using Arduino:
LoRa Energy Meter using Arduino, LoRa Power Meter, electricity meter- Are you tired of the traditional energy meters that only give you basic readings? Well, I got something that’s going to revolutionize the way you monitor your power consumption. With my designed LoRa Energy Meter, you’ll have access to real-time data, accurate measurements, and the ability to track your energy usage like never before.
Imagine having the power to monitor your electricity consumption from anywhere, anytime, all through a simple and user-friendly interface. Thanks to LoRaWAN, a low-power, wide-area network protocol, and the flexibility of Arduino, I have combined the best of both worlds to create this game-changing device.
This LoRa-based electricity meter shows off some impressive features. It wirelessly transmits data using the LoRa technology, ensuring long-range connectivity within a range of up to 5 kilometers while maintaining minimal power consumption. This means you can easily monitor and analyze your energy usage, without any complicated wiring or limitations.
But that’s not all! My LoRa Energy Meter goes above and beyond to provide you with comprehensive information about your power consumption. It allows you to monitor key parameters such as voltage, current, power, and units consumed.
By monitoring voltage, current, power, and units consumed, you can make informed decisions about your energy usage. But there’s another incredible feature that sets this meter apart. When the power is cut off or the voltage falls below 150Vac, the onboard buzzer is activated.
This feature serves as a valuable safety measure, enabling you to promptly respond to power disruptions. By hearing the buzzer, you can take immediate action, such as turning off sensitive loads or investigating the cause of the power outage. It’s an added layer of protection and convenience for your electrical system.
The voltage and current values are quite accurate because I have calibrated the ZMPT101B voltage sensor and the CT Clamp Current Sensor. I have explained it in my previous article “Arduino Home Energy Monitor”.
I am sure by now, you might have got an idea of how does this system work. So, without any further delay let’s get started!!!
Amazon Links:
Arduino Nano USB-C Type (Recommended)
*Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.
About the Current Sensor and Voltage Sensor:
You can see the CT Clamp Current Sensor and the ZMPT101B AC Voltage Sensor. If you want to know about their technical specifications and how to use these sensors individually, then you can read my getting started articles on the CT Clamp Current Sensor and ZMPT101B AC Voltage Sensor.
Gravity: Analog AC Current Sensor (20A)
When you want to measure the AC current, are you still having trouble cutting the wires, wiring, or soldering. Gravity: Analog AC Current Sensor comes to the rescue, eliminating the need to cut wires or reconnect circuits. Simply clamp the AC transformer probe on the AC line, and then plug the 3.5mm headphone jack into the signal conversion module to read the current AC current value. The analog output is designed to be compatible with 3V3/5V micro-controller. It can be conveniently used for AC current measurement to monitor AC motors, lighting equipment, air compressors, etc.
Pin Description:
LABEL | NAME | Function Description |
1 | – | GND |
2 | + | Power Input (3.3V-5.5V) |
3 | A | Signal Output (0.2-2.8VDC) |
4 | Φ3.5mm 3P plug | AC Transformer Input Signal |
FEATURES
- Non-contact measurement, high safety
- Multiple ranges for various measurement scenarios
- Compatible with 3V3/5V micro-controller
APPLICATIONS
- AC motor automatic monitoring
- Lighting and electrical equipment measurement
SPECIFICATION
AC Current Signal Conversion Module
- Input Voltage (VCC): 3.3V-5.5V
- Interface: Gravity Analog (PH2.0-3P,analog voltage output 0.2-2.8V DC)
- AC Voltage Input Range: 0-1V (AC RMS)
- Relative Error: ±4%
- Dimension: 32×27 mm /1.26×1.06 in
- Weight: 5g
Open Type AC Transformer Probe
- AC Current Range: 0-20A
- Signal Output (standard Φ3.5mm 3P plug): 0-1V AC voltage, linear corresponding range 0-20A
- Accuracy: ±1%
- Non-linearity: ≤±0.2%
- Frequency Range: 50Hz~1kHz
- Cable Length: 1m
- Working Temperature: -25 ℃~+70 ℃
- Opening Size: 13×13 mm / 0.51×0.51 in
- Weight: 50g
ZMPT101B 230 volts AC Mains Voltage Sensor:
This module is based on a high precision ZMPT101B voltage Transformer. This module makes it easy to monitor AC mains voltage up to 250 volts. This module comes with Multi-turn trim pot which can be used for adjusting the Analog output.Using ZMPT101B AC Voltage Sensor you can easily measure main voltage using Arduino or even Raspberry Pi (external ADC required).
Features of ZMPT101B AC voltage sensor Module
- Voltage upto 250 volts can be measured
- Light weight with on-board micro-precision voltage transformer
- High precision on-board op-amp circuit
- Operating temperature: 40ºC ~ + 70ºC
- Supply voltage 5 volts to 30 volts
Advantages of ZMPT101B AC voltage sensor
- Analog output corresponding quantity can be adjusted.
- Pcb board size: 49.5 (mm) x19.4 (mm)
- Good consistency, for voltage and power measurement
- Very efficient and accuracy
LoRa Energy Meter Circuit Diagrams:
As usual, I am using my designed Arduino LoRa development boards on both the side. But, you can also do the same exact connections on a bread board. And let me also tell you, for now forget about these relays, because in this project no relays are used. It doesn’t matter if you are a beginner, as I am going to explain every single connection. So, Let’s go ahead and first start with the Transmitter side.
LoRa Energy Meter Transmitter Side:
Connect the VCC and GND pins of the ZMPT AC voltage sensor to the Arduino 5V and GND. In my case I have connected the VCC wire to the Arduino Vin pin which is connected to the regulated 5v and 3A power supply. Connect the Out pin of the ZMPT voltage sensor to the Arduino Analog pin A0.
Connect the VCC and GND wires of the AC Current Sensor to the Arduino 5V and GND. But, in my case I have connected it to the external 5V and 3A power supply. Connect the output signal wire A to the Arduino Analog pin A1.
The LoRa Ra-02 433Mhz transceiver module NSS, SCK, MOSI, and MISO pins are connected to the Arduino pins 10, 13, 11, and 12. The reset pin of the LoRa module is connected to the Arduino pin 9. And its 3.3V and GND pins are connected to the Arduino 3.3V and GND pins. And don’t forget to add these 22uF and 0.1uF decoupling capacitors.
This is a 5V and 3A power supply based on the MP1584EN-LF-Z. I have already explained this in my previous video. In that video, I have also explained how to get different voltages at the output. Now, let’s go ahead and take a look at the receiver side.
LoRa Energy Meter Receiver Side:
The LoRa and power supply connections on the receiver side remains exactly the same.
Connect the Vin and Gnd to the external 5V and 3A power supply. I have already shared the 5V and 3A power supply circuit diagram above. Or you can also use a ready 5V regulated power supply. Or you can use your laptop/PC to power up the Receiver side. It depends on you how you power up your Arduino board.
The GND and VCC pins of the SSD1306 Oled display module are connected to the Arduino GND and 3.3V, whereas the SCL and SDA pins of the Oled display module are connected to the Arduino A5 and A4 pins. A5 is the SCL and A4 is the SDA.
A 5V buzzer is connected to the Arduino Pin D8 and I am using 2n2222 NPN transistor for controlling this buzzer. Connect the positive pin of the Buzzer to the 5V which is VIN and connect the GND pin of the Buzzer to the collector of 2N2222 NPN transistor. Connect emitter to the GND and connect the Base to the digital pin D8 through this 10K resistor.
Now, let’s go ahead and take a look at the programming.
Altium Designer + Altium 365 + Octopart:
Altium 365 lets you hold the fastest design reviews ever. Share your designs from anywhere and with anyone with a single click. it’s easy, leave a comment tagging your teammate and they’ll instantly receive an email with a link to the design. Anyone you invite can open the design using a web browser. Using the browser interface, you’re able to comment, markup, cross probe, inspect, and more. Comments are attached directly to the project, making them viewable within Altium designer as well as through the browser interface. Design, share, and manufacture, all in the same space with nothing extra to install or configure. Connect to the platform directly from Altium Designer without changing how you already design electronics. Altium 365 requires no additional licenses and comes included with your subscription plan.
Get real-time component insights as you design with Octopart built into Altium 365. Octopart is the fastest search engine for electronic parts and gives you the most up-to-date part data like specs, datasheets, cad models, and how much the part costs at different amounts etc. Right in the design environment so you can focus on your designs. Start with Altium Designer and Activate Altium 365. Search for electronic parts on Octopart.
LoRa Energy Meter Arduino Programming:
Required Libraries:
You will also need to download the ZMPT101B library. Go to the Sketch menu > then to Include Library > and click on the Manage Libraries. Search for the ZMPT101B library and install it.
LoRa Energy Meter Tx Arduino Programming:
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
/* Transmitter, nano */ #include <SPI.h> // include libraries #include <Wire.h> #include <LoRa.h> #include <ZMPT101B.h> #define SENSITIVITY 500.0f // ZMPT101B sensor output connected to analog pin A0 // and the voltage source frequency is 50 Hz. ZMPT101B voltageSensor(A0, 50.0); float correctionfactor=6.5; float Current_Value = 0; const int ACPin = A1; //set arduino signal read pin #define ACTectionRange 20; //set Non-invasive AC Current Sensor tection range (5A,10A,20A) #define VREF 5 char watt[5]; unsigned long last_time =0; unsigned long current_time =0; float Wh =0 ; String outgoing; // outgoing message byte msgCount = 0; // count of outgoing messages byte localAddress = 0xBB; // address of this device byte destination = 0xFF; // destination to send to long lastSendTime = 0; // last send time int interval = 50; // interval between sends String Mymessage = ""; void setup() { Serial.begin(9600); // initialize serial Wire.begin(); voltageSensor.setSensitivity(SENSITIVITY); if (!LoRa.begin(433E6)) { // initialize ratio at 915 MHz Serial.println("LoRa init failed. Check your connections."); while (true); // if failed, do nothing } Serial.println("LoRa init succeeded."); } void loop() { if (millis() - lastSendTime > interval) { float accurrent=0; float current_value = readACCurrentValue(); accurrent=current_value; Serial.print(accurrent); Serial.println(" A"); if(accurrent<0.3) { accurrent=0; } //current += current_value; // delay(1000); // //Serial.print(current); // Serial.println("Current: "); float acvoltage = voltageSensor.getRmsVoltage(); Serial.print(acvoltage); Serial.println("V"); if(acvoltage<5) { acvoltage=0; } float P = acvoltage * accurrent; last_time = current_time; current_time = millis(); long milisec = current_time -last_time; long sec=milisec/1000; // convert milliseconds to seconds Wh = Wh+ P *(( sec) /3600000.0) ; //dtostrf(Wh, 4, 2, watt); //Serial.write(Wh); Mymessage = Mymessage + acvoltage +"," + accurrent + "," +P+ ","+Wh; sendMessage(Mymessage); delay(100); Mymessage = ""; //Serial.println("Sending " + message); lastSendTime = millis(); // timestamp the message interval = random(50) + 100; } } void sendMessage(String outgoing) { LoRa.beginPacket(); // start packet LoRa.write(destination); // add destination address LoRa.write(localAddress); // add sender address LoRa.write(msgCount); // add message ID LoRa.write(outgoing.length()); // add payload length LoRa.print(outgoing); // add payload LoRa.endPacket(); // finish packet and send it msgCount++; // increment message ID } float readACCurrentValue() { float ACCurrtntValue = 0; float peakVoltage = 0; float voltageVirtualValue = 0; //Vrms for (int i = 0; i < 5; i++) { peakVoltage += analogRead(ACPin); //read peak voltage peakVoltage = peakVoltage + correctionfactor; delay(1); } peakVoltage = peakVoltage / 5; voltageVirtualValue = peakVoltage * 0.707; //change the peak voltage to the Virtual Value of voltage /*The circuit is amplified by 2 times, so it is divided by 2.*/ voltageVirtualValue = (voltageVirtualValue / 1024 * VREF ) / 2; ACCurrtntValue = voltageVirtualValue * ACTectionRange; return ACCurrtntValue; } |
90% of this code is from my Arduino Home Energy Monitor project. This time round I added code for the LoRa, you can see I have added the localAddress and the destination address. You can add multiple address if you want to monitor multiple energy meters using a LoRawan. In the upcoming version, I will also add a Gateway.
Anyway, what I am doing is, I added all the parameters in a message and then I send it to the remote side LoRa module.
1 2 3 |
Mymessage = Mymessage + acvoltage +"," + accurrent + "," +P+ ","+Wh; sendMessage(Mymessage); |
You can clearly see, I have separated the values using comma as the delimiter; this will help me in splitting the entire message on the receiver side. And then I can store these values in their corresponding variables for the further processing. And everything else remain exactly the same. Now, let’s go ahead and take a look the receiver side programming.
LoRa Energy Meter Rx Arduino Programming:
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
/* Receiver, Nano */ #include <SPI.h> // include libraries #include <LoRa.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> int buzzer=8; float acvoltage; float accurrent; float acpower; float units; String outgoing; // outgoing message byte msgCount = 0; // count of outgoing messages byte localAddress = 0xFF; // address of this device byte destination = 0xBB; // destination to send to long lastSendTime = 0; // last send time int interval = 50; // interval between sends #define SCREEN_WIDTH 128 // ORelay display width, in pixels #define SCREEN_HEIGHT 64 // ORelay display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define ORelay_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, ORelay_RESET); void setup() { Serial.begin(9600); // initialize serial; pinMode(buzzer,OUTPUT); if (!LoRa.begin(433E6)) { // initialize ratio at 915 MHz Serial.println("LoRa init failed. Check your connections."); while (true); // if failed, do nothing } Serial.println("LoRa init succeeded."); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); delay(2000); display.clearDisplay(); display.setTextColor(WHITE); } void loop() { // parse for a packet, and call onReceive with the result: onReceive(LoRa.parsePacket()); } void onReceive(int packetSize) { if (packetSize == 0) return; // if there's no packet, return // read packet header bytes: int recipient = LoRa.read(); // recipient address byte sender = LoRa.read(); // sender address byte incomingMsgId = LoRa.read(); // incoming msg ID byte incomingLength = LoRa.read(); // incoming msg length String incoming = ""; while (LoRa.available()) { incoming += (char)LoRa.read(); } if (incomingLength != incoming.length()) { // check length for error // Serial.println("error: message length does not match length"); ; return; // skip rest of function } // if the recipient isn't this device or broadcast, if (recipient != localAddress && recipient != 0xFF) { //Serial.println("This message is not for me."); ; return; // skip rest of function } // if message is for this device, or broadcast, print details: // Serial.println("Received from: 0x" + String(sender, HEX)); // Serial.println("Sent to: 0x" + String(recipient, HEX)); //Serial.println("Message ID: " + String(incomingMsgId)); // Serial.println("Message length: " + String(incomingLength)); //Serial.println("Message: " + incoming); //Serial.println("RSSI: " + String(LoRa.packetRssi())); //Serial.println("Snr: " + String(LoRa.packetSnr())); //Serial.println(); String v = getValue(incoming, ',', 0); String i = getValue(incoming, ',', 1); String p = getValue(incoming, ',', 2); String u= getValue(incoming, ',', 3); acvoltage = v.toFloat(); accurrent = i.toFloat(); acpower = p.toFloat(); units = u.toFloat(); if(acvoltage<150) { digitalWrite(buzzer,HIGH); delay(1000); digitalWrite(buzzer,LOW); } display.clearDisplay(); display.setCursor(0,0); display.setTextSize(2); display.setTextColor(WHITE); display.print("V:"+String(acvoltage)); display.setCursor(0,20); display.setTextSize(2); display.setTextColor(WHITE); display.print("I:"+String(accurrent)); display.setCursor(0,45); display.setTextSize(1); display.print("P:"+String(acpower)+" U:"+String(units)); display.display(); delay(1000); incoming = ""; } String getValue(String data, char separator, int index) { int found = 0; int strIndex[] = { 0, -1 }; int maxIndex = data.length() - 1; for (int i = 0; i <= maxIndex && found <= index; i++) { if (data.charAt(i) == separator || i == maxIndex) { found++; strIndex[0] = strIndex[1] + 1; strIndex[1] = (i == maxIndex) ? i+1 : i; } } return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; } |
Buzzer is connected to the digital pin 8. I also defined these 4 variables of the type float for storing the Voltage, current, power, and Units.
The localAddress is set to 0xFF and the destination address is set to 0xBB. If it doesn’t make any sense to you then you need to read my article on Multiple loRa transmitters with single LoRa Receiver. Anyway, let’s go to the loop() function.
We simply read the packet. And then split the entire string and store the retrieved values in the variables. And then we convert those into float types and store them in variables acvoltage, accurrent, acpower, and units.
I have also added a condition, if incase the ac voltage falls below 150Vac the buzzer will turn ON. It will also turn ON if there is a power failure.
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 |
display.clearDisplay(); display.setCursor(0,0); display.setTextSize(2); display.setTextColor(WHITE); display.print("V:"+String(acvoltage)); display.setCursor(0,20); display.setTextSize(2); display.setTextColor(WHITE); display.print("I:"+String(accurrent)); display.setCursor(0,45); display.setTextSize(1); display.print("P:"+String(acpower)+" U:"+String(units)); display.display(); delay(1000); |
All these instructions are used to print these values on the Oled display module.
The getValue function is a user-defined function and its job is to split a string message using any character as the delimiter. So, that’s all about the programming, and now let’s go ahead and start the practical demonstration.
LoRa Energy Meter Practical Demonstration:
I have powered up the Transmitter and Receiver side. And you can clearly see there is no physical connection between the transmitter and receiver side.
I have powered up the receiver side using my created 4S lithium Ion Battery and now its completely portable. I can move around with this circuit and monitor the Energy Meter within 5 kilometers. I have tested the range of these loRa modules using different types of antenna. I have added a link in the description.
Anyway, you can already see the voltage, current, power, and units on the display. These are the measured values and I checked against the actual values measured using a multimeter and Ampere meter. The values were pretty close.
Anyway, the Buzzer is OFF because the voltage is above 150Vac. I am going to cut off the power and let’s see if the buzzer is going to turn ON.
This is pretty awesome. The buzzer also turned ON and the same time the Voltage and Current values also changed to 0.
Now, my designed LoRa energy meter is going to alert me if the voltage falls below 150Vac or if there is any power failure. So, that’s all about the LoRa Energy Meter.
dear Shahzada Fahad
thank you for explaining project “LoRa Energy Meter using Arduino, LoRa Power Meter, electricity meter”
i have some problems with AC invasive current clamp(stc013-20A) and “current ac sensor v01 board” when i connect clamp to board the measured current is not correct even applied “correctionfactor=9” the output voltage of the board was 51mv with no load ,when i connect a load such as filament lamp (100w )measured current on serial port was “0.31 A”,”correctionfactor=9″ what do you think about this problem
regard s.n.mozaffari