A super simple IOT home electric meter / record keeper

Simple IOT project of the day, a super simple IOT home electric meter / record keeper, without a need to modify anything at home.

  • Before you Start – This is very simple hands on
  • What is it – It’s a home electric meter that counts in both directions
  • What is it for – Keeping track of power consumption
  • How it is done – A clamp meter and a microcontroller board
  • Show me before i begin – A photo gallery
  • Components – What you need
  • Steps – steps to making the device

Before you start, you only need the first few paragraphs to construct this device, the rest of the blog post is simply an explanation of why we did things this way, the whole tutorial should be very simple to follow step by step. Photos of everything you need are also provided 😉 If you know how to solder, you can get through this. if you don’t, find a tutorial on YouTube on how to solder.

What is it

It is a simple always on clamp meter that keeps track of power consumption on a small server (Online, or at home), added in the same cabinet as the utility meter installed by the power company.

What is it for

Since this device allows me to continuously keep track of power consumption, and graph it, I can track down things that are not functioning as they should and drawing much more electricity than they should.

The idea was inspired by the fact that my water cooler was drawing way too much power, and it turned out that it was heating the water it cooled and cooling the water it heated ! so it was basically “on” for far longer periods than it should, the fault turned out to be a loose plastic piece in the cooler’s water tank.

How is it done

A cheap current transformer (Clamp) is attached to a microcontroller that is WIFI enabled, the microcontroller sends the readings to a server in the basement (That server is used for 1001 other things too).

Show me before i dig in

Here is a small gallery of everything you might want to see before you even begin !

HERE GALLERY

Action

Components

NOTE: This tutorial will show you how to do this with an ESP32 board as well as my own setup which is a combination of ESP8266 and Arduino pro mini

The components I chose here are mostly because i already have them lying around, if you are going the ESP32 route, I will cover it too.

  • 2 current transformers to take readings for 2 electric meters, in this example, they are the sct013 100A / 50mA
  • 2 Microcontroller boards, an esp8266 (esp8266MOF-12E) and an Arduino pro mini 3.3V (8MHz) (ESP32 is also covered as a single board)
  • A lousy 5V phone charger that is not capable of providing enough current to charge a modern phone in a timely fashion, but should do for this as long as we have a voltage of above 4.1V.
  • An LD33CV voltage regulator combined with 2 capacitors (10V – 680uF) each.
  • 1 x 10uF capacitor
  • An 23.34ohm resistor (Either series resistors or step down) as a burden resistor if you are using 3.3V board such as ESP8266 or ESP32, or a 35.36 ohm resistor if you are using a 5V board. if the values can’t be made with resistors in series, you need to go DOWN with the value to the next resistance value
  • 2 SCT013 – 100A – 50mA current transformers
  • A pair of equal resistance resistors as a voltage divider, the values are anything between 10 kΩ and 400 kΩ (The smaller is more precise, the larger resistance consumes less battery)
  • A 5CM x 7CM Universal PCB Board

And obviously you need to use a soldering iron unless you wish to use a breadboard.

IMPORTANT: I recommend you use 1 ESP32 board instead of my setup, and use the analogue inputs on that, AND SKIP MUCH OF THIS BUSINESS, one thing to note though is that the ESP32 has one of it’s 2 ADC channels disabled when WiFi is enabled (A channel with X Analogue pins), I will cover this so don’t worry.

So why did i make it with an Arduino pro mini (3.3V) and an ESP8266 connected together in SPI (Against my own recommendation) ? that is because i got those current transformers and went to sleep, by the time i woke up, it was 12:43AM, I woke up and decided on the project, and those are the parts that were at hand that very minute, the Arduino has 8 usable analogue inputs (for sensing the current passing through the current transformer) , The ESP8266 on the other hand has 1 analogue pin and i wish to connect 2 clamp meters to this board

The Arduino pro mini (or any other using the ATmega328 micro controller) only has 6 ADC pins available instead of 8 if you use I2C as 2 are for I2C

Now, let us get to making it, this project takes a few hours to make, and you might want to change some things as i don’t think you need to have 2 microcontrollers connected together in SPI (I don’t remember why i chose that over I2C).

I won’t get too much into why I am using these resistor values, Just use them.
Hint: the reason for the choice is obviously ohm’s law, once for telling the current from the voltage drop using the burden resistor, the other two are a simple voltage divider (use an online voltage divider calculator if you need something different)

Step 1: Cut the endings of the SCT013current transformers to expose the wires, in my case, he SCT013-50mA came with a audio stereo jack, the tip (usually left speaker) was connected to the white wire, the sleeve (usually ground) was connected to the red wire, and the ring (middle usually right speaker) was not connected to anything, the shield on the wire exists but is not connected to any pins on the jack side.

What we need to connect in this case above is the white wire (tip) to the center of the voltage divider, and the red wire to the analogue input pin of the Arduino, the sleeve of the cable which is not connected to anything on any side should be connected directly to the ground pin of the Arduino .

Now, to see the connections, you might want to inspect this photo, I have used Photoshop to make it clearer and to point out where components are connected.

Mounting a disk image in Linux

The new way of mounting a disk image created with dd, dd_rescue, or ddrescue has become much simpler than before, all you need now is to issue the command

losetup --partscan --find --show disk.img

then above will tell you what loop device is being used, let us assume it is /dev/loop0, right after, a quick fdisk -l should show you the partitions, in my case, i have /dev/loop0p1 and /dev/loop0p2

mount /dev/loop0p1 /mnt

now, the first partition is mounted, to reverse this, you will need to first unmount /mnt then, you can delete the loop device with

losetup -d /dev/loop0

And you are done

8 Chan relay module with arduino pro mini 3.3v

To begin with, an Arduino pro mini is capable of driving the 8 port relay with optocouplers, the power required to drive the mechanical relay is provided separately with the most common relay boards on the market, this photo (And video) should demonstrate that

8 channel relay module for arduino

The image above demonstrates the wiring, the power supply is a computer power supply, the relay module uses the 5V power lines from the power supply, while the Arduino uses the 3V3 line, the board’s control lines will work on logic low, hence, it will work when we are below 2V, it works perfectly fine with the 3.3V from the Arduino.

here is the source code (Very simple code, just to pull the digital lines low, then high again, the delay in the engagement is just for fun.)


// constants won't change. Used here to set a pin number:
const int ledPin =  LED_BUILTIN;// the number of the LED pin
const int relay1 = 2;
const int relay2 = 3;
const int relay3 = 4;
const int relay4 = 5;
const int relay5 = 6;
const int relay6 = 7;
const int relay7 = 8;
const int relay8 = 9;



// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 2000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(relay5, OUTPUT);
  pinMode(relay6, OUTPUT);
  pinMode(relay7, OUTPUT);
  pinMode(relay8, OUTPUT);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
      digitalWrite(ledPin, ledState);
      digitalWrite(relay1, ledState);
      delay(200);
      digitalWrite(relay2, ledState);
      delay(200);
      digitalWrite(relay3, ledState);
      delay(200);
      digitalWrite(relay4, ledState);
      delay(200);
      digitalWrite(relay5, ledState);
      delay(200);
      digitalWrite(relay6, ledState);
      delay(200);
      digitalWrite(relay7, ledState);
      delay(200);
      digitalWrite(relay8, ledState);
      
      delay(400);
      ledState = LOW;
      digitalWrite(ledPin, ledState);
      delay(400);
      ledState = HIGH;
      digitalWrite(ledPin, ledState);
      digitalWrite(relay2, ledState);
    } else {
      ledState = LOW;
      digitalWrite(ledPin, ledState);
      digitalWrite(relay1, ledState);
      delay(100);
      digitalWrite(relay2, ledState);
      delay(200);
      digitalWrite(relay3, ledState);
      delay(300);
      digitalWrite(relay4, ledState);
      delay(400);
      digitalWrite(relay5, ledState);
      delay(500);
      digitalWrite(relay6, ledState);
      delay(600);
      digitalWrite(relay7, ledState);
      delay(150);
      digitalWrite(relay8, ledState);
      delay(150);
      ledState = HIGH;
      digitalWrite(relay8, ledState);
      delay(700);
      ledState = LOW;
      digitalWrite(relay8, ledState);
      delay(300);
      ledState = HIGH;
      digitalWrite(relay8, ledState);
      delay(700);
      ledState = LOW;
      digitalWrite(relay8, ledState);
      delay(300);
    }

    // set the LED with the ledState of the variable:
    //digitalWrite(ledPin, ledState);
  }
} 

How to tell if the arduino pro mini is 5V (16mhz) or 3.3V (8MHZ)

if it is not checked on the back side, the simplest and fastest way to do this is to look at the resonator, (Clock) – usually a Crystal oscillator, but I don’t see why it can’t be a ceramic resonator, if it has something with an 8 in it, then it is probably an 8MHZ resonator, otherwise it is probably 16, where 8 comes with the 3.3V and 16 with the 5V (Scroll down to see an example)

Another way is to connect the RAW to, let’s say 12V or even 5V, and measure the voltage at the VCC pin, that would also tell you, but surely, this involves more than just looking at the board, you need to connect wires and a power supply !

mine reads 80 u (something that looks like the letter U) so it is 3v3, here is a photo

Programming the 3.3V arduino pro mini with a CP2102 breakout

The CP2102 breakout board shown in the photo below has a selector between 3.3V and 5V.

In my case, i simply connected it the way you see it here to a USB port with 3.3V, and what do you know, it works, I have a flashing red light on the Arduino, a constant green light, and it looks like it is read to take code, the CP2102 board has a constant red light.

if you want to check that it is actually working fine, simply upload the sketch blink no delay, and then alter it a bit so that it does a double blink then wait 2 seconds, now your code is working, there you have it.

From the device manager, I can see that there is a device that looks like my adapter, namely this one

Silicon Labs CP210x USB to UART Bridge (Com3)

That thing above tells me that it has been designated the communication port number 3, which i will need in the Arduino IDE

So now i have installed and am running the Arduino IDE, selected a 3.3V Arduino board from the list and selected Com3, now i should be ready to upload a sketch, let us make a sketch that double flashes an LED every 2 seconds. here is some code to do that

The cheapest 3.3V power supply using the LD33CV (LD1117V33)

To create a tiny power supply to turn a 5V power source into 3.3V for powering the ESP8266 or ESP32, or maybe an Arduino pro mini (3.3V version), all you need to do is to couple the LD33CV-LD1117V33 with a pair of capacitors, in my case I am using the 25V/100 uf capacitor

All you need to do is the following

connect one capacitor to the pins 1 (Vin) and 3 (GND), and the other to the pins 2(Vout) and 3 (GND), and you are done.

At this stage, the ones between 1 and 3 will receive the input 5V power, While the ones closer to each other (2 and 3) will have the 3v3 output voltage that you can connect directly to your Arduino or ESP micro controller

The LD1117V33 you see above (LD33CV) comes in a TO-220 package, and uses an NPN pass transistor for efficiency to provide up to 800ma of power (Cooling may be needed to achieve maximum)

The DU command

Sometimes you need to find the largest sub directory in a directory, for this, the DU command has an argument that can work for you, max-depth

du -h --max-depth=1 backup-final

The above will simply list all sub directories inside the backup-final directory alongside the size of the directory (recursive, including all files in sub directories)

Running the mv command in the background

One of the most annoying things that can happen to you is to disconnect your laptop from the network, then realize that there was a file moving job that was running, the command is going to get disconnected before mv gets the chance to delete the source files, the new copy is a hassle, i personally use rsync to continue such a copy with the delete source files flag

But it does not have to be this way, you can move the mv command to the background, the steps are simple

First, you need to hit CTRL+z to suspend the job, once suspended, you should see a job number in the suspend acknowledgement

Now, the next step is to disown the job, because right now, if you close your terminal window, the job will still be terminated

disown -h %1 (replace one with your own job number which may be 1)

Now to get the job running again but in the background

bg 1

That is it, you can now close (logout) your terminal window

So the summery
ctrl+z
disown -h %1
bg 1
logout

Now mind you, the output to stdout will not display (In most cases), you will need to use process status ps x to see the process.

Quick 10 minute LVM Setup.

Sometimes, you realize you would want to use LVM in a computer but you want a tutorial to take you there fast, So i have put this post together to get you up and running in 10 minutes or less.

First, let us start with the tools, install the following packages in your debian installation, (Debian 10-Buster in this tutorial)

apt-get install lvm2 dmsetup mdadm reiserfsprogs xfsprogs

In this tutorial, I have two 8TB disks i want to combine with LVM to use as one

1- Create partitions of type LVM on the disks

  • Why not use the disk without a partition ? See this post

Start by running parted on every physical disk, and creating a big partition to span the whole disk (Or if you are using empty spaces on old disks, any partition is good enough really)

In my example, where i wish to combine /dev/sdb and /dev/sdc into one logical volume (To be used as one block)

parted /dev/sdb
mklabel gpt
unit mib
mkpart primary ext4 1 100%
set 1 lvm on

Now, repeat the above, but this time for /dev/sdc

1- Prepare the physical volumes to be added to volume groups (those two partitions) (For instructions on how to add disks directly without an underlying partition which is not recommended, see here)

pvcreate /dev/sdb1 /dev/sdc1

Now, you can see what we have with the commands

pvdisplay or pvs

2- Add the PVs to a logical volume

vgcreate LVMGroup /dev/sdb1 /dev/sdc1
   Volume group "LVMGroup" successfully created

this will create a volume group (VG) called LVMGroup, you can see the VGs you have with the commands (vgdisplay, vgscan, and vgs)

vgs -o +lv_size,lv_name

3- Create a logical group on the volume group

lvcreate -l 100%FREE -n bigvol LVMGroup
  Logical volume "bigvol" created.
mkfs.ext4 /dev/LVMGroup/bigvol
or
mkfs.ext4 /dev/mapper/LVMGroup-bigvol

4- Mount, and add to fstab

To mount the volume, My mount point is at /hds/lvm

using rsync

rsync is better than mv to move files because of a few reasons

First, it gives you much more control, for example the following command

rsync -a -v --ignore-existing --remove-source-files /hds/iscsi/all_new /hds/usb

Does not copy the files that are already at destination, meaning if there is a file with the same name in the same directory at the destination, it will not be overwritten, files moved will be deleted, and files that had counterparts and not moved will not be deleted

rsync -a -v --remove-source-files /hds/iscsi/all_new /hds/usb

While the command above will overwrite files, and delete whatever we have moved ! if files exist on the destination, it does not seem to be overwriting them, but it is probably somehow comparing them, then deleting the original

I had to investigate this as a move command resulting in an error did not remove the files, the error was relevant to the file name being too long