Microcontroller, JFET form low-cost, two-digit millivoltmeter
The circuit in Figure 1 offers an inexpensive alternative to commercial digital voltmeters. Although it has only two digits, it provides considerable flexibility and thus lends itself to customization by means of a microcontroller and its software. As one of Microchip's least expensive offerings, the PIC16F84A lacks an internal ADC. However, you can use a classic RC time-delay circuit to implement an analog-to-digital conversion by connecting capacitor C3 between lines RB7 (output) and RA4 (input) and in series with an equivalent "unknown" resistor consisting of Q3's drain-to-source on-resistance, plus R4, plus R5. Q3, a BF245A JFET, presents the on-resistance. Q3's "A" suffix is important because it corresponds to an on-resistance of 200Ω to 2 kΩ for a gate-to-source voltage of 0 to 1V (Figure 2). Other devices in the BF245 family exhibit a less pronounced change of resistance versus gate-to-source voltage. To correct the measurement nonlinearity inherent in Q3's gate-to-source voltage versus drain-to-source on-resistance transfer, the microprocessor's software includes a 100-point look-up table that provides correction for a two-digit display.
For an application requiring the display of readings of 0.01 to 0.99V, you can use a 4-MHz crystal and Microchip's PIC16F84A microprocessor for IC1. To display the rightmost three digits of readings in the 0.001 to 0.999V range, use a 20-MHz crystal and a PIC16F84A-20 microprocessor. Choose 15- to 33-pF values for capacitors C1 and C2, which the PIC's data sheet describes. Listing 1 includes the full assembler source code for the PIC16F84A. The most critical portion of the firmware comprises a subroutine that provides a precision time delay according to the following steps:
- Configure RA4 as an input to sense the voltage across C3 during the charging interval. When you configure RA4 as an input, it serves as a Schmitt trigger with 1.6V low-threshold and 3.2V high-threshold voltages when drain-to-drain voltage is 5V.
- Configure RB7 as an output and set it high to begin charging C3. Initialize a counter (register 0CH) to its maximum value of FFH
- Decrement the counter in a loop until RA4 senses a low state. At that time, C3 charges to nearly 66% of the power-supply voltage.
- Use the time it takes to produce a low on the RA4 input as a jump value in the linearity-correction look-up table to extract a value for the two-digit LED readout.
- Configure RB7 as an input and set it low to discharge capacitor C3.
- After a time delay, repeat Step 2.
To round out the design, another software subroutine solves the problem of driving a two-digit LED display at adequate visibility with a minimum amount of current. Although an LCD would use less current, LCDs aren't visible in darkness. The display subroutine examines the eight bits of the units and tens—registers 11H and 12H—and tests each one in sequence; if the subroutine sets a bit, then the subroutine puts a short-duration high state on its corresponding segment-driver line, RB. Doing so lights only one LED segment at a time, and, consequently, the maximum current consumption of the circuit remains relatively constant even if you add a third LED display to build a 999-count millivoltmeter.
Persistence of vision eliminates the need to keep the displayed digits continuously visible, and maintaining the segments on for approximately 33% of a 1-sec refresh interval allows a good and sufficient display effect. Transistors Q1 and Q2 are never simultaneously on, and only one display segment lights at a time. You can further optimize the hardware by removing current-limiting resistors R6 through R12, lifting the emitters of Q1 and Q2 from ground, and inserting a single 560Ω resistor between the emitters and ground.