Long time, no see. I’ve been quite busy, and I had little time to write here. And I’ve spent the last days fighting to get one Voltmeter click to work with an Arduino Uno, as a prerequisite to the next project that will be featured on the blog.
The Voltmeter click board I’m writing about is a mikroBUS™ add-on board for measuring voltage in an external electric circuit. The board can measure DC only, and the advertised measurement range is -24 to 24V.
A very nice piece of hardware, but I have found that the accompanying code example is utterly wrong. If one looks at the code example one sees the following two lines of code:
measurement = getADC() / 2; // Get ADC result voltage = (measurement - calibration) * 33.3405;
Well, that 33.3405 value is wrong, it should be 16.67. Also, the measurement range is wrong.
To understand why we have to take an in-depth look at the schematic:
The input voltage goes through a voltage divider made with R1, R14, R15, and R2. The voltage drop on R2 is applied to the (non-inverting) input of OP1C, while the voltage drop on R15 goes to the input of OP1B.
The voltage drop on R14 is:
Same goes for R15:
When Vin is positive we will find the following situation:
With respect to GND, the voltage applied on pin 10 of OP1C is negative, and the output of OP1C is 0V. The voltage applied to pin 5 of OP1B is positive, and the output of OP1B is Vin * 0.03. The output of OP1B and VGND are summed by OP1D, and the output voltage going to the ADC will be:
A quick side note: VGND should have been named VBIAS, as not to be confused with GND. However, in this blog post I will keep the naming convention used in the original schematic.
When Vin is negative we will find the following situation:
With respect to GND, the voltage applied on pin 10 of OP1C is positive wrt GND, and the output of OP1C is -Vin * 0.03. OP1C acts basically as an inverter in this case, as its output is positive if the input voltage applied to the voltmeter click is negative. The voltage applied to pin 5 of OP1B is negative wrt GND, and the output of OP1B is 0. OP1D subtracts the output of OP1C from VGND, and the output voltage going to the ADC will be:
We see that, regardless of the polarity of the input signal, we will have the same relation between the input voltage and the voltage that goes to the ADC:
In theory, VGND is 1.024 V as this bias voltage is obtained by dividing the reference voltage Vref = 2.048V via R9 and R10. In practice, we can find some variations due to tolerance of R9 and R10. However, that difference is a unique characteristic of each voltmeter click board and can be measured only once.
One more thing: on a quick look at the MCP609 datasheet we find an absolute rating of Analog Inputs (VIN+, VIN–) as being VSS – 1.0V to VDD + 1.0V. In our case VSS is GND, and VSS can be 3.3V or 5V, depending on the position of the power select jumper on the voltage click.
So, one should not apply a negative voltage of more than 1V on the inputs of OP1C and OP1B. As such, we can determine the maximum voltage that can be applied to the inputs of the voltmeter click without causing permanent damage to the op-amps:
So, the actual measurement range of the voltmeter click is much higher than the advertised value. Nice.
The 33.3405 scaling factor is wrong!
Again, some calculations. We start by taking a look at the ADC converter. This click board uses an MCP3201 12-bit ADC, which reports a ratiometric value. This means that the ADC assumes Vref is 4095 and anything less than Vref will be a ratio between Vref and 4095.
As such, we can express the input voltage (in mV) as:
Or we can simply approximate:
But at the same time we have:
In the particular case of Vin = 0 we will find:
Then we will have:
However, we already know the offset corresponding to VGND, and we can replace it in the above formula:
And we can simply determine the input voltage:
Voltmeter click Arduino code
With all the above computation, things are deceptively simple. The most complicated part is to write the code for reading the ADC values. Luckily, I have already done that in my blog post regarding the 4-20mA receiver click board.
So, the first piece of code I wrote is used to determine the ADC offset. One has to put the input in shortcircuit, so only the bias voltage goes to the ADC. Then run the following code:
For my particular voltmeter click board, I have found a value of ACDoffset = 2040 (vs. a theoretical 2048).
And now, the final code. I have decided to return the measured values in mV and to use int as data type. This will limit the measurement range to -32,768V to 32,767V, which is very close to the absolute ratings of the voltmeter click.
That’s all folks!