Wireless Voltmeter
I picked this up at a garage sale. It's a G.E.C. switchboard voltmeter, made by the British General Electric Company, probably in the 1950s. Cast iron and heavy as (5.2 kg). It would have sat in the front of a switchboard showing the incoming mains. Someone marked 415 V on the glass, the old Australian three-phase voltage, so I reckon it came off a three-phase board here.
I wanted it on the wall showing something more interesting than mains voltage, so now an ESP32 moves the needle over Wi-Fi.
Its first job is showing how much power our solar panels are making right now. But it listens to MQTT, so it can show anything you can get a number for.
There's no rewinding or modding the old movement. Just one wire inside, and a handful of cheap parts on the outside.
Supplies
- An old analogue meter. Mine is a G.E.C. moving-iron switchboard voltmeter.
- ESP32 dev board (DOIT DEVKIT V1) - or probably any 3.3 V MicroPython capable board with Wi-Fi
- XL6009 boost converter module
- LM324N op-amp
- 2N5551 transistor
- Resistors: 51 Ω, 1 kΩ, 10 kΩ, 22 kΩ
- 1N4148 diode
- USB power supply and lead
- Breadboard to try it out, veroboard for keeps
What's Inside
The front comes off to show mostly empty space. The movement sits at the bottom with the needle and a half-moon box. The porcelain former wound with wire is the meter's internal resistor, at the top.
The dial says "must be used with external resistance". That resistor is long gone. The serial number on the front is also written by hand in pencil on the back of the dial.
How it works: Inside the coil are two bits of soft iron, one fixed and one on the needle's spindle. Current through the coil magnetises them both the same way, so they push apart and the needle swings. Reverse the current and both flip together, so they still push apart. That's why it works on AC, and why it doesn't care which way round it's wired. The case has + and − cast into it, but I swapped the wires and it reads exactly the same. My guess is G.E.C. used the same case for their DC meters, where it does matter.
Bypass the Resistor
With the internal resistor in circuit the meter needed far too many volts.
I measured:
- Across the terminals: 13.5 kΩ
- The internal resistor: 11.9 kΩ
- So the coil itself is about 1.6 kΩ
Full scale takes about 18 mA, which through 13.5 kΩ is over 240 V. I soldered a short wire (yellow) across the resistor. That leaves just the coil, and full scale then takes about 30 V.
With the resistor bypassed, I turned the voltage up and noted the current at each mark:
- 100: 5 V, 2 mA
- 200: 10 V, 5 mA
- 300: 15 V, 9 mA
- 400: 20 V, 12 mA
- 500: 25 V, 15 mA
- 600: 30 V, 18 mA
Constant Current
My first test used a fixed voltage. The needle sat on 600, then slowly sagged as the coil warmed up. The coil is copper, and copper's resistance goes up as it warms, so less current flows.
The fix is to control the current, not the voltage. The ESP32 only puts out 3.3 V, so a few cheap parts are needed.
The Electronics
Power comes in on the ESP32's USB lead. Its Vin pin passes the 5 V on to the LM324, and to the XL6009, which boosts it to 35 V for the meter.
Following the signal:
- Pin D25 puts out PWM, switching between 0 and 3.3 V. The 22k/10k divider brings that down to about 1 V. That's the setpoint.
- The LM324 op-amp compares the setpoint with the voltage across the 51 Ω resistor, and drives the 2N5551 transistor through the 1k until they match.
- So the coil current is the setpoint divided by 51 Ω, about 20 mA, however warm the coil gets.
- The transistor handles the 35 V side, which the op-amp on 5 V can't.
- The 1N4148 diode across the coil catches the kick each time the current switches off.
Taming the Needle
Overshoot. Any change, even a small one, sent the needle swinging past and wobbling for several seconds. So the needle never jumps the code glides it to each new value along an S-shaped curve, slow at the start and slow at the end.
It remembered where it came from. Coming up to 500 from 0 it would stop short at about 490. Coming down it landed on 500, with exactly the same current.
My first version ran the PWM at 20 kHz, above hearing so the coil wouldn't whine, with a 1 µF capacitor across the 10k to smooth the setpoint into a steady voltage. So the coil got smooth DC. The iron in the movement holds onto a bit of magnetism on steady DC, and that's what was pulling the reading. The meter was built for AC, where the current never sits still.
The fix was to drop the PWM to 100 Hz and take the capacitor out. Now the coil gets full 20 mA pulses, back to zero every cycle. Each pulse resets the iron, and the needle is too slow to follow, so it just shows the average.
Calibrate
The scale isn't even. 0 to 100 is squashed up and the rest spreads out. So I set the PWM by hand until the needle sat on each 100 mark and wrote the numbers down. The code joins the dots with straight lines.
The Code
It's MicroPython - https://github.com/MarkMakies/Wireless-Voltmeter
- pointer.py moves the needle: the PWM, the calibration table and the glide.
- meter.py joins Wi-Fi and MQTT and shows the number.
- demo.py puts on a show with no Wi-Fi needed.
- SecretsExample.py: copy to Secrets.py and fill in your Wi-Fi and MQTT broker.
- physics.py: the jumps and glides from the video in Step 11.
Flash MicroPython onto the ESP32, or really any 3.3 V MicroPython board with Wi-Fi.
Copy the files across. I used mpremote (pip install mpremote):
To try the demo first, copy pointer.py and demo.py, then type
at the console.
Showing Solar Power
Our solar system reports its power over MQTT. The meter divides it by 10, so 600 on the dial is 6000 W.
To show something else, put your topics in Secrets.py, and change the name of the value and the scale at the top of meter.py.
Demo Mode
For showing it off, or after the sun goes down, demo.py plays a pretend day. Sunrise to midday and back to sunset in about two minutes, with the odd cloud drifting over.
Using a Different Meter
Every old meter is different, so measure first: the current that gives full scale, and the coil's resistance.
The 51 Ω resistor sets the peak current: 1.03 V divided by the resistor. Pick it so the peak is a bit above your full-scale current. Mine reaches 600 at about 92 % PWM.
The boost voltage needs to be at least the peak current times the coil resistance, plus a couple of volts. My XL6009 module is rated up to 36 V.
Then calibrate and put your dial's marks in the table in pointer.py. The code takes the range of the dial from the table.
The Physics Bit
Getting an old needle to behave turned into a little physics lesson. Here's why Step 3 and 5 went the way they did.
Pendulum
There's no spring in this meter. Small weights are soldered on below the pivot, and gravity pulls the needle back to zero. That makes the needle a pendulum, like a grandfather clock. It also means it only reads zero when the meter is dead level and upright. Tilt it and "down" moves, so zero moves too. Switchboard meters like this were made to hang on a wall, and mine needs to hang straight.
Overshoot and undershoot
Change the current suddenly and the magnetic push changes instantly. The needle speeds up and reaches the new spot still moving, so its momentum carries it past: overshoot. Gravity pulls it back, and momentum carries it too far the other way: undershoot. The needle swings back and forth a few times, oscillating, but a little less each time until it settles.
The S-curve
The cure is never to surprise it. The code moves the needle along an S-shaped curve. Its speed is zero at the start, quickest in the middle and zero again on arrival. With no speed left at the end, there's no momentum to carry it past. Each move also takes a few seconds, slow compared with the pendulum's own swing, so the needle just follows along.
In the video the first part shows how the needle behaves without an S-curve, and then with one. The DMM shows the average voltage of the pulses.
Iron with a memory
Stroke a nail with a magnet and it stays a bit magnetic afterwards. Inside the iron are tiny regions that line up with the field, and some stay lined up when the field drops. Coming down the scale, the iron still had a bit extra and pushed harder. Coming up from zero, it lagged behind and stopped short. My first version gave the coil steady DC, and it never landed in the same place from both directions. Switching to 100 Hz pulses fixed it.
Pulses and a lazy needle
With pulses a hundred times a second, the current goes from nothing to full and back every time. The iron does the same thing every pulse, so it forgets where the needle came from. AC does much the same, and that's what the meter was built for. The needle is far too heavy to follow pulses that fast, so it settles where the average push puts it. The momentum that caused all the overshoot is now what smooths the pulses into a steady reading.
Warm copper
The push on the needle depends on the current through the coil, not the voltage across it. The coil is a long run of very fine copper wire, and that current warms it a little. As copper warms, its atoms jiggle more and the electrons bump into them more often, so its resistance rises, about 0.4 % for every degree. Ohm's law does the rest: same voltage, more resistance, less current. So on a fixed voltage the needle slowly sagged (Step 3), even though the coil probably only warmed a few degrees. Fixing the current cures it. The op-amp watches the current and pushes harder as the coil warms, so the current and the reading stay put. That's why the boost voltage needs a bit to spare (Step 10).
Lesson
A coil, a bit of iron and a needle. It looks about as simple as a device gets, but every part of it has physics going on. Gravity sets the zero, momentum makes it overshoot, the iron remembers where it's been, and the copper's resistance rises as it warms. Each one impacting the reading in its own way, and each needed its own fix: the S-curve, the pulses and the constant current. On the AC mains it was built for, I reckon most of this never showed up. Drive it from a microcontroller and you get to learn it all over again.
Display Case
The meter has to sit dead level and upright, or zero moves. It's also heavy, so it needs something solid to stand in.
I had an old whiskey display cabinet lying around, and it fitted the bill. It's sturdy, it sits flat, and the dark wood suits this old meter. All it needed was the door off, the meter bolted in, and the electronics hidden underneath.
The meter connects with two wires and crimped ring terminals. Ignore the + and − cast into the back of the case: this meter reads the same either way round.
Everything else is on one strip of prototype board, with the drive circuit at one end, the boost module in the middle and the ESP32 at the other. The meter's cable comes through a hole in the base to a screw terminal on the board, so the meter can come out without any soldering. The board screws to the inside of the base, out of sight, and a single USB lead powers the lot. The 140 on the ESP32 is the end of its IP address, so I never have to look it up.
Levelling turned out to be easy. The meter's three mounting holes are slotted, so I loosened the bolts, twisted the meter until the needle sat on zero, and tightened them up again. If it moves to another shelf, it may need another twist.