One of the most essential tools for anybody interested in electrical engineering is certainly a Digital Multi Meter (DMM). The problem is you really never have enough of these – there is always one more voltage or one more current that you need to measure when testing a circuit. So about a year ago I thought, why not try making one? And now, finally, I have a presentable result, which is by no means perfect, but I think it is a really interesting and usable device. So here’s a short video of what I have after three revisions and countless hours of programming and developing:
That’s a good question. If you look on Ebay, you’ll find hundreds of multimeters there, from cheap 7 USD no-name ones to a several hundred dollars Fluke ones. So if I want more multimeters, why not just buy more of those cheap ones?
Well, there are other reasons why I decided to make my own. First is of course curiosity – I wanted to see what I can achieve with a 32-bit processor, some programming and about 10 dollars worth of parts. Then there are features – those cheap multimeters almost never have digital data output for automated measurements, they don’t measure RMS, they cannot measure power (ie voltage and current at the same time), you need to turn a large dial to switch ranges and so on.
This is meant mostly as an educational project. While it is totally usable (in fact, I have been using this as my “daily multimeter” for a while now), it is not meant to replace a commercially bought multimeter, more like complement it.
Also, because of safety, the maximal input voltage is ±60 V. Sure, you could just change the resistive divider so that it can accept even mains voltage, but don’t do that. There is very little in terms of safety isolation, that’s why I limited the input to such a low voltage – according to internationally recognized standards, voltages below 50 V AC and 120 V DC are still relatively safe to touch, so even if something goes wrong, you still should be fine. But anyways, I very rarely work with voltages above 60 V, so this is not really a limitation for me.
Features (rev. 1.2B)
As I said, I am not aiming at fully replacing a commercially made multimeter – my goal is mostly having something small, cheap and accurate, capable of measuring voltage and current, because those things usually change in your circuit-under-test and you need to measure multiple of these at the same time. The meter features 6 “modes”, shown on the picture below:
Voltage & current
Voltage can be measured in two ranges: ±60 V and ±6 V. I choose these ranges because very often I work with circuits powered by 5 V, so the 6 V range is very handy. Current has two ranges as well, ±60 mA and ±500 mA.
First design challenge was designing a bipolar input. Most of these “DIY hobby Arduino voltmeters” accept only positive voltages and blow up if you accidentally switch polarities, which is obviously something I did not want. Another approach (more professional) is to generate a negative rail and then use an opamp to offset the voltage. But again, generating a negative voltage rail requires additional parts and introduces a ton of noise. So I’ve designed an AFE (Analog Front End) which doesn’t require any negative voltage whatsoever and still supports bipolar input. The only downside is that the “ground” is offset by 1.25 V in this case, so we need to subtract that when we sample it with the ADC.
Another design challenge was that I wanted the range to be electrically selectable – so no hardware switches, like on these cheap multimeters. Electrically selectable range allows you to do autoranging, which is handy especially when controlling the multimeter from a PC. This is achieved using an 74-3157 analog switch for voltage and a relay for current, and I think this is another interesting part of this circuit.
Finally, after the signal is conditioned using the AFE, it is fed thru a buffer into the microcontroller’s ADC. Unfortunately, the ADC does not support differential input (which is a pity, we could really use it here), so it always takes two samples and subtracts them. The ADC is also 4x oversampled, resulting in a theoretical resolution of 14 bits. Finally, there are two acquisition modes – AVG and RMS.
AVG, which stands for average, as you’ve probably guessed, measures the DC or average voltage/current. So if you have a sinewave with 2 Vpp and 0 V offset, it will return 0. If you have the same sinewave, but with 1 V offset, it will return 1. So it’s basically what would be called “VDC” or “IDC” on your multimeter. This device also measures True RMS (effective value) – it takes about 30 000 samples every second and calculates the RMS value from that, according to a well known formula. So the first sinewave would return 0.7 volts, the second 1.7 volts. But it works on all kind of waveforms, it is by no means limited to sine. You can switch acquisition modes by pressing the RMS/DC button.
Another feature I lack on most multimeters is the ability to measure voltage and current at the same time. So if you want to test, let’s say, effectiveness of a power supply, you need to use 4 multimeters at once. 4! Getting 4 multimeters is costly, it takes a ton of space on your desk and makes wiring a nightmare. And I am not even talking about the fact that you still need to multiply the corresponding voltages and currents to get power.
Implementing this was actually quite easy, you can see the screen below. Again, you can switch ranges (all 4 combinations possible), change acquisition mode (DC or RMS) or freeze the display using the hold button.
If I was to name three functions I use the most on a multimeter, it would be (in no particular order) voltage, current and continuity. So I implemented it as well – it shows the detected resistance and sounds a buzzer if it is below 50 Ω. Also the voltage drop across the device-under-test is shown, this is very useful for testing diodes.
The last testing mode is a component test. As of now, it only supports resistors, capacitors and diodes, even though the hardware is compatible with the venerable “AVR component tester”. But as of now testing 3 pin semiconductors is not implemented, because I simply do not find it that useful. Also I attempted to make a SMD test pad (the hole right from the buttons), which works (and it is actually useful for testing like SMD capacitors, because they don’t have capacity ratings written on them), but the pad is too sunk into the enclosure.
The multimeter features fully isolated USB port (acts as a serial emulator), which periodically sends data to the host PC. It can also receive data from the PC.
Then there is also an I2C port, which can be used for some additional modules (from the top of my head, some sort of EEPROM, radio/WiFi module for remote logging, external display like my 7 seg multifunction display) and also a SWD port for programming.
Now for the most important part – of course this whole thing would be useless, if it wasn’t accurate or reliable. When I made the first revision, I was blown by how accurate it actually was! Here a chart, showing the relative accuracy on the 6 V range:
Of course this is for DC. This multimeter can also measure RMS of different waveforms, which can be seen for example in the video at the top of the page. Also here’s the accuracy for current measurement:
The accuracy for the remaining modes is OK, the component test can usually get within 5 % of the real value. Here the code could surely use some improvements.
Possible future upgrades
- data logging to SD card
- counting miliamphours and miliwatthours
- measuring phase angle (cos φ) and calculating apparent & reactive power
- 600 mV range & higher current range (coming in rev. 1.3, hopefully)
- polish the software to better display very small or very large values
- frequency counting
- use a more powerful and precise STM32F3 series processor (those are nice, but not particularly easy to get)
The meter itself consists of three PCBs – the main board, where all the processing and analog acquisition happens, the button board, which just extends buttons and the SMD test pad and the USB board, which deals with charging and protecting the battery and isolating the USB interface. There is a switch which connects power from USB to the charging circuit. When not switched, the circuit is totally isolated from the USB.
All of this is housed in a 3D printed case which I designed. Button names etc. are printed on self-adhesive paper and glued to the case. This looks ugly, but so far it is the easiest method of putting small print onto 3D printed objects. Everything is then screwed together using M2 screws and brass M2 threaded insert nuts. I also recommend that you stick rubber feet on the designated spots on the case, since 3D printed PLA has very little friction with hard surfaces and so the whole meter would tend to move around your table, if you for example pulled slightly on one of the leads.
I am very satisfied with the result – as I stated above, I’ve been using this device as a multimeter almost daily for the past month or so. There are still improvements which could be done and functions, which could be added (it is mostly a question of writing them just in software).
License: everything is licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International)