Current measurement using Hall sensor

Introduction- Why keep a galvanic separation between the 12/24V system and computer system?

Measurement of current is often and simply done by just inserting a resistor a so called shunt into the circuit. This resistor produces a voltage in accordion to Ohm's law U=R*I. A typical mV/A is produces and this voltage varies linearly with current. An simple and easy way of measuring the current. However, the method has severe drawbacks some close to a showstopper for some examples. It the scope of using the Yacht server for most of the tasks i a boat the drawbacks amount to showstoppers. The major problem is that there is no galvanic isolation between the high power 12 og 24 Volt system in the yacht. In many respects this service power is as powerful as the 230V found in domestic homes. One might easily draw a 100 Amps or more. So letting this powerful system into the low power and delicate computer system is a bad option. Any short circuit or even stray electric power might upset or severely damage the computer system.

Solving most of the isolation problems by using an Internet of Things approach

Making most of the sensors distributed and self contained and just sending SignalK messages over WIFi to the OpenPlotter/SignalK server solves most of the isolation problems.

The ESP32 module and processor have far more capabilities than ESP8266. Several ADC inputs and a powerful 3.3V supply (the ADS1115 runs on 3.3V), hence whole setup can be driven from a 5V power source. Somewhat different programming tools and libraries in the Arduino IDE than the 8266, but no major major issues. With the prices not that much higher than the 8266 based ESP12E module the ESP32 has clear advantage. The picture below show the setup. All the source code can be found on github.

By using a NodeMCU-12E ESP8266 based module with built in WiFi and far greater processing power that an Arduino Nano or Uno the current and voltage measurement can be made far simpler and there is no signal cables to be drawn around the boat. The fast that the 12 V service power is present inside the current/voltage sensor device is not really a problem as it is all selv contained within the board and it's own isolated housing. With no signal cable to the Raspberry Pi computer and all its equipment it's a far simpler solution.

As the ESP chip happily communicate over I2C all sorts of devices can be connected, like one or several ADS1115s. The ESP8266 have a single 12 bit ADC so voltage can be measured using this while current is measured using ADS1115 in differential mode and Hall element current sensors.

The picture above show a ESP 8266 based ESP-12E module and two ADS1115 boards connected using the I2C connection. All Hall sensors need to be run at 5V, hence fed from the 5V rail. The two resistors in a ladder from hole 40 to 45 provide a reference voltage at half of the 5V supply (the HKS2010 has a build in reference). This voltage is used as a zero current reference as the Hall elements provide half of the supply voltage at zero current (this is covered in the text below). Consequently the ADS1115 is operated in differential mode and only two sensors can be connected to each ADS1115 module.

The 12V service supply, and the two resistors at hole 20 to 25 step down the voltage to fit the 0-3.3 V range on the ESP8266 analog input. The 12E module can provide 3.3 V but not with enough power to power the the ADS1115s. Hence both 5V and 3.3V on the power supply is used.

As the complete setup do not in any way connected to the Raspberry Pi it can bring the 12V service voltage in. This lab prototype is powered by 220 volt, in a yacht setting the power would be supplied using an isolating 5 volt power supply and a 5 to 3.3 converter.

The data from the sensors are sent as UDP packets via WiFi to the SignalK server running together with OpenPlotter on the Raspberry.

This setup eliminates the signal cable from it to the server and hence save the trouble of pulling signal cables around and solves the isolation problems with sensors and the Raspberry Pi server once and for all.

All source code for this setup is found at at Github pages, as this is an Internet of Things it's found under the IoT pages.

Hall effect sensor is galvanically isolated

A Hall effect sensor can measure current without any electrical connection to the high amp electrical system, it rely solely on the magnetic field set up by a the current flowing through the wire. The Hall effect sensor produces a voltage that is zero when no current flow in the wire and a positive voltage when current flow in one direction and a negative voltage when current flow in the opposite direction. The voltage vary close to linear with the current making the treatment of the output simple.

I have user two different types of current sensors each with it's own analog to digital converter. The first is a high amperage (60) Hall element sensor (HKS2010) while the other is a less current range sensor (35Amp) called WCS1800, the fist uses a 16 bits ADC while the other a 10 bits ADC. Even simpler ones packed inside a small IC is available, of which one example is ACS712.

Hall element current sensors usually produce a voltage at 1/2 of the supply voltage. The figure to the left show

the output voltage as a function of the current passing through a wire passing through the hole in the element.

At zero voltage the output voltage is Vdd/2 or +2.5V for a typical +5V power supply. If the current flow in one direction the voltage rises from 2.5V and if the current flow in the opposite direction the voltage decrease from 2.5V. Using a differential input will yield count in the analog to digital converter from -maxcount to +maxcount, typically -1024 to 1023 for a 10 bit converter or -32768 to 32767 for a 16 bit converter.

The figure on the left is for the WCS 1800 Hall effect current sensor, it can measure from -35A where the output would be zero and would yield a voltage of 0V - 2.5 = -2.5 V (-35A), through 2.5-2.5=0V (0A) and finally 5V-2.5V=2.5V (35A). The differential mode is simple to set up and by feeding a midpoint between to resistors to the N- input will yield the above numbers. Setting the range to +/- 2.048 V should cover a suitable range. The MCP3008 uses a reference voltage to set the range hence an external voltage reference is needed and will only read positive voltages, from 0 to Vref, 0 count at 0V and 1024 count at Vref voltage, so only current in one direction can be measured. This is fine for simple one directional current measurements.

A simple solution when current is only flowing in one direction is to just measure the voltage using a single ended input on the analog to digital converter. The resolution will be lower.

A not about resolutions with the different setups and ADCs. A 10 bit ADC have a total of 2¹⁰ or 1024 levels. We assume a full range of the current sensor at 35A. Using the numbers we arrive to a resolution of 35A/1024=34mA. There will be 1024 steps of 34mA each, and for many applications where just an indication of current is needed this should be ok. This does however assume a differential setup with an ADC range matching the output range. If we use a single ended setup and use a zero amp out at Vdd (2.5V) have have used half the range just to reach the zero point as in this single ended setup we start at -35A. With only 512 levels we arrive at a resolution of 35A/512=68mA, this might be a bit low for many and maybe the 16 bits ADC is a better option ?

If we use the 16 bit ADC in differential mode we have +/- 32768 levels and with a +/-35A max as before we arrive at a resolution at 1mA which should be fine. Even if we run this in single ended mode we'll still have a 2mA resolution. In the case of a current sensor with 200A full range the numbers would be 6.1 mA resolution.

Bilderesultat for WCS1800 output

In addition, there is another problem using single ended measurements of current, there is no reference voltage when using the ADS1115 single ended. One merely measure a voltage and just assume the Vdd equal 5 Volt and do calculation accordingly. In practice the +5V supply fluctuate quite abit. More than a stable voltage reference should do. By measuring in differential mode the current sensor either supply a reference, the HKS2010 or you need to supply it yourself like in my example using the MCP 3008. In any case it yield better, more stable and reliable results when using differential measurements.

Using a 16 bit (high precision) ADS1115 analog to digital converter in differential mode and 60 AMP HKS2010 current sensor

Below is a breadboard layout of a setup I use to measure the voltage output from the Hall effect sensor (seach for HKS2010). The ADS 1115 analog to digital converter is used in a differential setup where voltage difference between two inputs are measured. This ha the benefit that zero voltage is equal to zero current as the sensor outputs both a reference voltage which is 1/2 of the supply voltage, Vdd, and the output from the sensor is Vdd/2 at zero current. Hence a positive voltage is current in one direction and a negative voltage is current in the opposite direction. Connections to the Raspberry is very simple, just connect +5V and 0V and the two I2C bus lines, SLC and SDA.

Below my prototyping board show how I set the Hall sensor and ADS1115 up for testing. It is somewhat different from the breadboard above.

This setup uses ADS 1115 in differential mode and can measure from -70 Amp to +70A, which is the same as measuring current in either direction. The number count from the ADC is negative from current in one direction and positive in the other direction. The HKS2010 provide a reference voltage pin which is Vdd/2 (Vdd is the supply voltage) and an output pin which is zero at zero current.

The pictures are also showing a DC solid state reply (SSR) to control12/24V loads, SSRs are a bit more reliable and have switching time far below their mechanical counterparts. They enjoy popularity when rapid switching is needed like pulse width modulations (PWM).

Converting from Analog voltage to digital counts.

The ADS 1115 is a 16 bits digital to analog converter that can be programmed to use a different set of voltage intervals to produce full range. The input range are both positive and negative, ranges are typical +/- 1.024 or +/- 4.096 Volt (also a few others) for full range. 16 bits with sign yield a number from -2¹⁵ to 2¹⁵-1 or -32768 to 32767, see wikipedia about 16-bit. See also the datasheet for ADS1115 at TI.

The ADS 1115 measure +/- voltages with output from -32767 to 32768 the conversion is relatively simple.

From the output of the ADC the conversion to current in Ampere is done by a small Python function

def get_i():

val=adc.read_adc_difference(0, gain=GAIN_I, data_rate=SAMPLES_I)


# Large Hall element, 50A version.

# Pins from edge Vref Vout 0V Vdd

# Linear regression, cal using multimeter.

# y (current) = -0.52372 + 0.0025559 * x (counts)

i = -0.52061 + 0.0024236 * val

if abs(i)<0.1: # Cheating, but avoiding non zero values at zero.


return i

Using a 10 bit (low precision) MCP3008 analog to digital converter in differential mode and a WCS1800 35A current sensor.

Below is a breadboard layout of a setup using MPC3008 in differential mode use to measure the voltage output from the MCP3008 analog to digital converter. Even if the measurement is only measuring the positive current (flowing in one direction) the full 10 bit range is used. One could set it up in single ended end be happy with only 9 bit resolution (512 levels).

The LM-385 provide a reference to set the voltage for full scale. The resistor ladder provide a reference for N- input at Vdd/2 which is 2.5 volt and should be the same as the current sensor provide at zero current.

The MCP3008 connects to the Raspberry Pi via the SPI interface, this is a 4 wire interface, using SCLK, MISO, MOSI and CE0 pins. Adafruit publish a Python library to with driver functions to setup the MCP3008 and to read out the variables. As I usually suggest I choose differential measurement as this is better suited for Hall element sensors and also less sensitive to electric noise.

The picture on the left show both a ACS712 sensor that has screw terminals and a range and a 5 A range (that come in 5, 20 and 30 A) and a bigger one WCS1800 with a wire feed through providing even simpler connection.

The breadbord at the left show a differential setup. where reference for midpoint (Vdd/2) is provided by two resistors. The range is set by the 1.2 V reference.

The code to measure electric current is quite simple, after installing Adafruit MCP3008 library the code to measure current is relatively simple. This simple test code is based on the example code :

import time

import Adafruit_GPIO.SPI as SPI

import Adafruit_MCP3008

# Hardware SPI configuration:



mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))

print('Press Ctrl-C to quit...')

while True:

# Grab the difference between channel 0 and 1 (i.e. channel 0 minus 1).

# Note you can specify any value in 0-7 to grab other differences:

# - 0: Return channel 0 minus channel 1

# - 1: Return channel 1 minus channel 0

value = mcp.read_adc_difference(1)

print 'Channel 1 minus 0: {0}'.format(value),' equal ',format(float((value-28)/1023.0)*20,'.2f'),'A'


The voltage is measured as the difference between input pin 1 and input 0. Ideally the difference from the Vdd/2 used a reference on input 0 should match the output from the current sensor at zero current (it does produce Vdd/2 at zero current). This is not always the case and a small offset is needed, in this example 28. Full range is controlled by the LM385 voltage reference, in this case I have used a 1.2V reference which implies a full range of 1.2 V, e.g. 1023 count at 1.2V. I used a value of 20 for the current at full scale, slightly more than the theoretical at about 17.

In order to export the values to SignalK without using Openplotter I just send the SignalK identification string and the values to the socket that the SignalK server is listening on. The hard part is to build the string to send to SignalK. The two interesting lines are :

SignalK='{"updates": [{"$source": "SPI.MCP3008","values":[ {"path": "","value":'+format(i,'5.3f')+'}]}]}'

sock.sendto(SignalK, ('', 55557))

This is mostly it, the whole file is found on github, providing a working example on using the MCP3008 in differential mode to measure current.

So far I have noticed that the MCP3008 show more fluctuation of the measurements than the ADS115 using a larger Hall sensor. The later has it's own reference voltage which is equal to the output at zero current while the MCP3008 setup uses a resistor ladder to make Vdd/2. There is probably no reason to use the MCP3008 at all since the ADS1115 is cost effective and provide 16 bit as opposed to 10 with the MCP3008.