Measuring (low) external currents using a PICaxe.


Senior Member

In principle, it need be no more difficult for a PICaxe to measure the (direct) current flowing in an external component (or module) as it is to measure an external voltage. Basically, we can just read the voltage across an external resistor and use Ohms Law (I = V/R) to calculate the current. In the same way that we normally measure external voltages relative to "Earth" (0 volts), the current-sensing resistor normally would be connected to Earth. But the Supply Rail (Vdd) might be used, or even a "differential" measurement using two ADC input pins is possible.

However, we may need to be more careful with the choice of component values than a simple voltage measurement, particularly if we are introducing an additional resistor into the circuit, purely for the purpose of measuring the current flow. In this case the voltage drop across the resistor is "lost" from the drive voltage, so needs to be no more than (say) 10% of the supply rail. Another factor to consider is that the power dissipation in a resistor is proportional to the SQUARE of the current (or voltage) applied, so we need to be aware of the MAXIMUM current which is likely to flow in the circuit.

If the likely maximum current is not known (or is much higher than the nominal value which needs to be measured), then a forward diode can be connected across the sensing resistor. A normal silicon diode will limit the voltage drop (and thereby the resistor power dissipation) to about 600 mV, but in some/many cases a "Schottky" diode is a better choice, typically limiting the voltage to just a few hundred millivolts.

However, if the (default) Vdd supply rail is used as the reference voltage for the ADC, and the maximum voltage that we can measure is less than 10% of the supply rail, then even a READADC10 returns a value only up to about 100. Therefore, even (or perhaps particularly) if the supply rail is regulated (e.g. to 5 volts) then it can be beneficial to increase the ADC sensitivity by using a lower reference voltage such as the 2 volt Fixed Voltage Reference (FVR2048).

The PIC(axe) data sheets specify that the 1 volt FVR should NOT be used for the ADC reference voltage, but several people have reported using it successfully. For measuring current, it may well be entirely satisfactory, because the typical source impedance is low (ohms) and only part of the full voltage range of the ADC will be used. There are issues with using FVR1024, but they are probably not relevant here, so I will describe them elsewhere.

Thus, the external current can be measured by a program snippet such as:

#picaxe 08M2 		; Or other M2s (and X2s with some modifications)

symbol IRES = 1		; Value of current-sense resistor (in Ohms)
symbol Itest = c.1	; ADC input pin to test for current (relative to Ground/Earth pin
symbol Vext = b1	; Voltage across current-sense resistor (generally a byte will be sufficient)
symbol Iext = b2	; External current in sensing resistor (milliamps)

   fvrsetup FVR1024	; Set the Fixed Voltage Reference to (nominally) 1.024V
   adcconfig 3		; Use the FVR as ADC (positive) voltage reference (M2 only)
   readadc10 Itest,Vext	; Read the voltage drop
   Iext = Vext / IRES	; Current in mA (resolution = 1 mA)
The ADC makes an "instantaneous" measurement so it's important to ensure that there is not excessive ripple on the ADC input. Generally, a decoupling (or reservoir) capacitor should be across the EXTERNAL circuit (e.g. with its negative terminal connected to the top of the current-sense resistor). A capacitor connected directly across the (low impedance) current-sense resistor is unlikely to achieve any useful filtering (i.e. averaging) action, so if ripple on the sense resistor is significant then add a R-C low-pass filter onto the ADC input of the PICaxe, as shown in the diagram below.

I had intended to include a simple diagram showing just the current-sense resistor and filter/limiting components, but it "grew" to show in context all the related components that MIGHT be used (except for the usual PICaxe serial programming circuit). However, the 1 ohm (typical) resistor is the only "fundamental" component required to measure the average current flowing from the battery and passing through the load. The "optional" voltage-limiting (Schottky) diode, low-pass filter (10K + 100 nF) and power decoupling (100 uF) have been mentioned already.


The load (e.g. a small motor) could be switched (on/off or with PWM) by the "darlington" transistor (which might be a single package or two separate components), but alternatively could be a single bipolar transistor or a FET. If the load is inductive (such as a motor) then the "Flywheel" diode is necessary, to prevent an excessive voltage being generated when the transistor switches off. The optional 10 ohm (typical) resistor is included in the supply rail to "encourage" the current to flow into the 100 uF "power" reservoir capacitor, rather than upset the voltage on the PICaxe supply rail.

Part 2, using a capacitor for smaller currents, will follow in due course. ;)

Cheers, Alan.
Last edited:


Senior Member
Part 2: Using a Capacitor to Measure Lower Currents


The method in my previous post should give useful results, but the main purpose of this thread was to describe how to use a capacitor to measure small external currents. The theory is rather more complex but the method allows a very wide range of currents (many decades) to be easily measured without large voltage or power losses.

In principle, we just replace the current-sense resistor with a capacitor of an appropriate value and generally also include a parallel diode to limit the voltage, as with the resistor. However, a capacitor cannot pass direct current so we also need a bypass switch (of some type) across the capacitor to restore its voltage to near-zero (or any other appropriate value).

For this method we need to know the RATE OF CHANGE of the voltage across the capacitor (aka dv/dt), so at least two voltage measurements must be made. For example, if we have a 1 uF capacitor and the voltage across it changes by 1 volt in 1 ms, then an (average) current of 1 mA has flowed into (or out of) the capacitor. However, a useful feature of this method is that if we (need to) wait 1 second for the 1 volt change then the current was only 1 uA. Furthermore, the resolution of the second measurement is as good (probably better) because the time is longer and more accurately known than when measuring a higher current.

With a PICaxe we still may use only one pin, because it can be used initially as an input to make the ADC measurements and then switched to an output (low) for modest currents (up to say 10 mA). We don't even need to "open" the switch before starting the measurement because the READADC{10} command automatically disconnects the output switch before reading an ADC value.

But there are limitations; The time between successive READADC measurements is not accurately specifed (it's about 1 ms with a 4 MHz clock) so typically we need to separate them by much longer, say 9 ms (10 ms total). Also, we may need to limit the voltage swing to 100 mV (or at most a few hundred) so even a 1 mA "full scale" current requires a 100 uF capacitor in the path. Therefore, this method is generally complimentary to the resistance method above, with the "break point" being somewhere around 1 mA.

The minimum current which can be measured is difficult to define. We can easily use a capacitor of 100 nF or less, which certainly should be a non-electrolytic type to reduce leakage current. Also, we can measure over a time period of one or more seconds, so theoretically can get down to nano Amps. The maximum leakage current of the PIC pins is defined as around 70 nA and generally will be much lower (particularly if the temperature is not too high), but it's worth noting that Schottky diodes have a significantly higher leakage current than normal silicon diodes.

Another issue is that it is "recommended" that the ADC inputs are fed from a source resistance of less that 10 kohms and here we have an "infinite" resistance. A higher source resistance is permitted if a capacitor is connected across the ADC input (which of course we have here) but the higher "acceptable" value doesn't seem to be defined anywhere.

This method appears to give good results well down below 1 uA, but ultimately, the internal and/or external leakage currents set a minimum limit. Also, the action of taking each ADC measurement seems to cause a small net current flow into or out of the capacitor, so it is better not to take too many consecutive measurements. A simple test program follows. Note that PICaxe Manual 2 says that the FVR is disabled after every READADC{10} so should be re-selected, but this does not appear to be necessary in practice :

#picaxe 08M2 		; Or most others

symbol CAPI = 1		; Value of current-sense capacitor (in nF or uF)
symbol Itest = c.1	; ADC input pin to test for current (relative to Ground/Earth pin)
symbol TGAP = 10	; Time period between ADC reads in ms
symbol TGAP2 = 100	; Time period between ADC reads in ms
symbol Vc1 = b1		; First Voltage measured across current-sense capacitor (generally a byte will be sufficient)
symbol Vc2 = b2		; Second Voltage measured across current-sense capacitor (generally a byte will be sufficient)
symbol Iext = b2	; External current in sensing capacitor (in nano or micro amps)

   fvrsetup FVR1024		; Set the Fixed Voltage Reference to (nominally) 1.024V
   adcconfig 3			; Use the FVR as ADC (positive) voltage reference
   low Itest			; Pull the input level near to earth
   pause 100			; Wait for voltage across capacitor to stabilise
   readadc10 Itest,Vc1		; Release the pin and measure the first voltage level
   pause 9			; Wait about 10 ms between measurements
   readadc10 Itest,Vc2		; Measure the voltage again
   Vc2 = Vc2 - Vc1		; Voltage change
   Iext = Vc2 * CAPI / TGAP 	; mV * uF / ms = uA 
   if Vc2 < 10 then		; The current is low
      pause 86				; Total about 100 ms between first and last measurements
      readadc10 Itest,Vc2		; Measure the voltage again
      Vc2 = Vc2 - Vc1			; Voltage change
      Iext = Vc2 * CAPI / TGAP2 	; mV * nF / ms = nA 

A sample schematic diagram can be simpler than in the previous post because the current is lower and decoupling arrangements can be less critical. The load is unlikely to be motor (or other inductor), more typically just a small "interface" module of some type, or a sensor. For a "continuously" active module, a (Schottky) diode across the (electrolytic) capacitor is probably essential: The PICaxe won't always be able to pull the pin low and the current probably not be exceptionally small. However, for a sensor (e.g. a photodiode), we might be more interested in sub-microamp currents, but not too concerned what happens to the voltage/current when we are NOT making a measurement. So we would avoid the use of (leaky) electrolytic capacitors or (Schottky) diodes.


With this method it's also possible sometimes to use the supply rail (decoupling capacitor) to measure a current flow. For example, I have devised a simple Low Power PWM Maximum Power Point (MPP) Solar battery charger using just one PICaxe pin! First the software sets the PWM to "overload" the PV panel to reduce the panel supply voltage. Then the PWM is switched off and a series of supply voltage measurements made. The difference between the consecutive values indicates the available current and the instanatneous power can be determined from each corresponding voltage. Then a new PWM value can be set from previous data which is continuously updated as appropriate.

A potentially even more accurate and wide-range method is to measure the time that it takes for the voltage across a capacitor to swing between two defined levels. Generally, this requires the use of an analogue comparator, which even M2s do have in their "silicon" chip hardware (accessible by SFR commands). Alternatively, "digital" inputs can be used, particularly the ST (Schmitt Trigger) type, or the PIC(axe) "Touch" hardware basically consists of a current-controlled capacitor oscillator on each pin.

Cheers, Alan.