电流传感器|从零开始认识各种传感器
1、什么是电流传感器?
电流传感器是一种用于测量电流的设备,广泛应用于各种工业、商业和民用领域。这些传感器不仅能够测量交流电(AC)和直流电(DC)的电流,还能提供关于电流波形和瞬态事件的详细信息。
2、电流传感器是如何工作的?
最简单的电流测量可通过万用表的电流档来测量。将数字万用表串联连到电路中,使其成为电路本身的一部分。电流通过万用表时它的显示屏上会显示测量结果。但是这样需要断开原来的电路,在很多实际应用中是不可能的。
所以一般来说是用电流钳来测量电流。一般来说,它采用电磁感应原理,无需接入电路就可以测量交流电流。
电磁感应是指放在变化磁通量中的导体,会产生电动势。此电动势称为感应电动势,若处于闭合回路中,则该电动势会驱使电子流动,形成感应电流。 图中由于开关的通断,左边线圈中会出现电流的不断变化,会导致左边线圈磁通量的改变,从而会在右边线圈感应出电流。
电流钳采用了电磁感应原理,它相当于一个电流互感器,穿过钳口的被测导线就相当于互感器的左边,当导线中有电流时,电流钳的内部线圈就会感应出电流,从而可以测量出被测的电流大小。
3、常见的电流传感器的种类
从工作原理来区分,常见的电流传感器有互感式电流传感器 ,霍尔效应电流传感器和磁阻式电流传感器。
3.1 互感式电流传感器
互感式电流传感器的原理,就是前面前面介绍的 电磁感应原理。其工作原理类似于变压器,即通过初级绕组中的电流产生磁场,然后在次级绕组中感应出电流。由互感器原理可知,它是不能测量直流电流的,因为一旦电流处于直流无变化状态,线圈中就无法感应出磁场来。所以电流互感器通常用于交流测量,如电力系统中的电流测量、故障保护、电能计量,包括各种电力设备和控制系统。
3.2 霍尔效应电流传感器
霍尔效应电流传感器利用霍尔效应来测量电流。所谓霍尔效应就是,当有电流垂直于外磁场通过半导体时,载流子发生偏转,垂直于电流和磁场的方向会产生一附加电场,从而在半导体的两端产生电势差,这一现象就是霍尔效应,(这个电势差也被称为霍尔电势差)。通过霍尔效应即可测得加在半导体上的电流大小。
霍尔电流传感器包括开环式和闭环式两种,高精度的霍尔电流传感器大多属于闭环式,闭环式霍尔电流传感器基于磁平衡式霍尔原理,即闭环原理,当原边电流IP产生的磁通通过高品质磁芯集中在磁路中,霍尔元件固定在气隙中检测磁通,通过绕在磁芯上的多匝线圈输出反向的补偿电流,用于抵消原边IP产生的磁通,使得磁路中磁通始终保持为零。经过特殊电路的处理,传感器的输出端能够输出精确反映原边电流的电流变化。
开环霍尔效应电流传感器的工作原理是,当原边电流IP流过一根长导线时,在导线周围将产生一磁场,这一磁场的大小与流过导线的电流成正比,产生的磁场聚集在磁环内,通过磁环气隙中霍尔元件进行测量并放大输出,其输出电压VS精确的反映原边电流IP。
由于在不同电流下,铁芯的磁导率是不一样的,因此,开环霍尔电流传感器的线性度较差,精度较低。相比之下,闭环式测量采用0磁通抵消测量的方法,不受铁芯非线性影响,精度较高。
3.3 磁阻式电流传感器
磁阻式电流传感器是一种利用磁阻效应测量电流的传感器。,磁阻效应是指某些金属或半导体材料的电阻随着外加磁场之变化而改变的效应。 利用电流在磁场中产生的磁通量对磁阻进行改变,就可以实现电流测量。
具体测量通常使用惠斯通电桥结构, 可以减少外界环境对传感器输出稳定性的影响,并提高传感器的灵敏度。惠斯通电桥由四个电阻组成,分别为两个主动电阻和两个被动电阻,它们被安排在一个平衡电桥的形式中。当被测量的电流引起的磁场作用于磁阻传感器时,电阻值会发生微小的变化,从而引起电桥的不平衡。这个不平衡信号经过信号处理电路后就可以转换成磁场的测量值。
3.4 几种电流传感器的比较
这是对于几种电流传感器的特性比较,大家可以根据自己设计和项目的需求进行选择。
4、电流传感器实验演示
我们来演示使用树莓派来读取显示电流传感器的数据 。这是一款Gravity出品的I2C数字功率计,下方连接了一个电子负载。初始时显示电路中的电流大约4毫安。开启电子负载,并调节负载的大小,可以看到,随着电子负载的电流的增大,屏幕显示读出的电流值也随之相应增大。
main.py
from breakout_colourlcd240x240 import BreakoutColourLCD240x240
from machine import ADC, Pin, Timer, PWM,I2C
from utime import sleep
import time, math,array
from INA219 import INA219
#------------------------------------------------------------------
width = BreakoutColourLCD240x240.WIDTH
height = BreakoutColourLCD240x240.HEIGHT
display_buffer = bytearray(width * height*2)
display = BreakoutColourLCD240x240(display_buffer)
timer1 = Timer()
ina219_reading_mA = 1000
ext_meter_reading_mA = 1000
'''
@param i2caddr I2C address
@n INA219_I2C_ADDRESS1 0x40 A0 = 0 A1 = 0
@n INA219_I2C_ADDRESS2 0x41 A0 = 1 A1 = 0
@n INA219_I2C_ADDRESS3 0x44 A0 = 0 A1 = 1
@n INA219_I2C_ADDRESS4 0x45 A0 = 1 A1 = 1
'''
i2c = I2C(0, scl=Pin(21), sda=Pin(20))
ina = INA219(i2c, INA219.INA219_I2C_ADDRESS4) #Change I2C address by dialing DIP switch
#begin return True if succeed, otherwise return False
while not ina.begin():
time.sleep(2)
'''
Revise the following two paramters according to actula reading of the INA219 and the multimeter
for linearly calibration
'''
ina.linear_cal(ina219_reading_mA, ext_meter_reading_mA)
ina.set_bus_RNG(ina.bus_vol_range_32V)
ina.set_PGA(ina.PGA_bits_8)
ina.set_bus_ADC(ina.adc_bits_12, ina.adc_sample_8)
ina.set_shunt_ADC(ina.adc_bits_12, ina.adc_sample_8)
ina.set_mode(ina.shunt_and_bus_vol_con)
#ina.reset() #Resets all registers to default values
current_temp = 0
#-------------------------------------------------------------------
def display_init():
display.set_pen(0,255,0)
display.rectangle(58,30,13,160)
display.circle(64,190,10)
display.set_pen(255,0,0)
display.text("current", 150, 20, 194, 2)
display.text("value", 150, 35, 194, 2)
display.text("mA", 200, 90, 194, 2)
display.update()
for i in range(6):
display.set_pen(0,200,0)
display.pixel_span(80,27 + i*30,10)
display.text(str(50 - i *10), 100, 20+i*30, 194, 2)
display.set_pen(0,0,220)
if i < 5:
for j in range(4):
display.pixel_span(80,33 + j*6 + i * 30,5)
display.update()
#---------------------------------------------------------------------
def display_change(temp, color):
global current_temp
current_temp = temp
#print(temp)
display.set_pen(color[0], color[1], color[2])
display.rectangle(58,30,13,160)
display.circle(64,190,10)
display.set_pen(0,0,150)
display.rectangle(58,20,13,7+int((50-temp)/2)*6)
display.set_pen(0,0,0)
display.rectangle(150,50,90,40)
display.set_pen(0,255,0)
display.text(str(temp), 150, 50, 5, 5)
display.update()
#----------------------------------------------------------------------
def get_temp():
Currentvalue=ina.get_current_mA()
return Currentvalue
#----------------------------------------------------------------------
def main():
color = [0,255,0]
timer1 = Timer()
display_init()
timer1.init(freq=5,mode=Timer.PERIODIC, callback=lambda t:display_change(round(get_temp(),1), color))
while True:
sleep(0.1)
main()
INA219.py
# -*- coding: utf-8 -*-
'''!
@file DFRobot_INA219.py
@brief Define the infrastructure of the DFRobot_INA219 class
@details The library is used to drive INA219 chip, which can detect the voltage, current and power of various electronic devices.
@copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
@License The MIT License (MIT)
@author [fengli](li.feng@dfrobot.com)
@version V1.0
@date 2022-03-1
@url https://github.com/DFRobot/DFRobot_INA219
'''
import time
from machine import I2C
class INA219:
_INA219_READ = 0x01
INA219_I2C_ADDRESS1 = 0x40# I2C ADDRESS 1
INA219_I2C_ADDRESS2 = 0x41# I2C ADDRESS 2
INA219_I2C_ADDRESS3 = 0x44# I2C ADDRESS 3
INA219_I2C_ADDRESS4 = 0x45# I2C ADDRESS 4
_INA219_CONFIG_RESET = 0x8000 #Config reset register
_INA219_REG_CONFIG = 0x00 #Config register
bus_vol_range_16V = 0 # Voltage range ±16V
bus_vol_range_32V = 1 # Voltage range ±32V
#GAIN and range for PGA(Shunt Voltage Only)
PGA_bits_1 = 0 # GAIN:1,Range ±40 mV
PGA_bits_2 = 1 # GAIN:/2,Range ±80 mV
PGA_bits_4 = 2 # GAIN:/4,Range ±160 mV
PGA_bits_8 = 3 # GAIN:/8,Range ±320 mV
adc_bits_9 = 0 # Resolution is 9bit
adc_bits_10 = 1 # Resolution is 10bit
adc_bits_11 = 2 # Resolution is 11bit
adc_bits_12 = 3 # Resolution is 12bit
#Size of the sample collected by adc every time
adc_sample_1 = 0
adc_sample_2 = 1
adc_sample_4 = 2
adc_sample_8 = 3
adc_sample_16 = 4
adc_sample_32 = 5
adc_sample_64 = 6
adc_sample_128 = 7
power_down = 0 # Power-down
shunt_vol_trig = 1 # Shunt voltage, triggered
bus_vol_trig = 2 # Bus voltage, triggered
shunt_and_bus_vol_trig = 3 # Shunt and bus, triggered
adc_off = 4 # ADC off (disabled)
shunt_vol_con = 5 # Shunt voltage, continuous
bus_vol_con = 6 # Bus voltage, continuous
shunt_and_bus_vol_con = 7 # Shunt and bus, continuous
_INA219_REG_SHUNTVOLTAGE =0x01#Shunt Voltage Register
_INA219_REG_BUSVOLTAGE = 0x02#Bus Voltage Register
_INA219_REG_POWER = 0x03#Power Register
_INA219_REG_CURRENT = 0x04#Current Register
_INA219_REG_CALIBRATION = 0x05#Register Calibration
def __init__(self, i2c, addr):
self.i2cbus=i2c
self.i2c_addr = addr
def begin(self):
'''!
@fn begin
@brief Initialize I2C bus and configure INA219 config register before reading data
@return True (succeeded)/False (failed)
'''
if self.i2cbus.scan():
print(self.i2cbus.scan())
self.cal_value = 4096
self.set_bus_RNG(self.bus_vol_range_32V)
self.set_PGA(self.PGA_bits_8)
self.set_bus_ADC(self.adc_bits_12, self.adc_sample_8)
self.set_shunt_ADC(self.adc_bits_12, self.adc_sample_8)
self.set_mode(self.shunt_and_bus_vol_con)
return True
def linear_cal(self, ina219_reading_mA, ext_meter_reading_mA):
'''!
@fn linear_cal
@brief Linear calibration
@param ina219_reading_mA The current measured by INA219 (before calibration)
@param ext_meter_reading_mA Actual measured current
'''
ina219_reading_mA = float(ina219_reading_mA)
ext_meter_reading_mA = float(ext_meter_reading_mA)
self.cal_value = int((ext_meter_reading_mA / ina219_reading_mA) * self.cal_value) & 0xFFFE
self._write_register(self._INA219_REG_CALIBRATION, self.cal_value)
def reset(self):
'''!
@fn reset
@brief Reset config register
'''
self._write_register(self._INA219_REG_CONFIG, self._INA219_CONFIG_RESET)
def _write_register(self, register, value):
self.i2cbus.writeto_mem(self.i2c_addr, register, bytes([value >> 8, value & 0xff]))
def _read_register(self, register):
return self.i2cbus.readfrom_mem(self.i2c_addr, register,2)
def get_bus_voltage_V(self):
'''!
@fn get_bus_voltage_V
@brief get the BusVoltage (Voltage of IN- to GND)
@return Voltage unit:V
'''
return float(self.read_ina_reg(self._INA219_REG_BUSVOLTAGE) >> 1) * 0.001
def get_shunt_voltage_mV(self):
'''
@fn get_shunt_voltage_mV
@brief get the ShuntVoltage (Voltage of the sampling resistor, IN+ to NI-)
@return Voltage unit:mV
'''
return float(self.read_ina_reg(self._INA219_REG_SHUNTVOLTAGE))
def get_current_mA(self):
'''
@fn get_current_mA
@brief get the Current(Current flows across IN+ and IN-.
@n If the current flows from IN+ to IN-, the reading is positive.
@n If the current flows from IN- to IN+, the reading is negative)
@return Current unit:mA
'''
return float(self.read_ina_reg(self._INA219_REG_CURRENT))
def get_power_mW(self):
'''
@fn get_power_mW
@brief get the ShuntVoltage (Voltage of the sampling resistor, IN+ to NI-)
@return Voltage unit:mV
'''
return float(self.read_ina_reg(self._INA219_REG_POWER)) * 20
def set_bus_RNG(self, value):
'''
@fn set_bus_RNG
@brief Set BRNG (Bus Voltage Range)
@param value bus_vol_range_16V < 16V >
@n bus_vol_range_32V < 32V >
'''
conf = 0
conf = self.read_ina_reg(self._INA219_REG_CONFIG)
conf &= ~(0x01 << 13)
conf |= value << 13
self._write_register(self._INA219_REG_CONFIG, conf)
def set_PGA(self, bits):
'''
@fn set_PGA
@brief Set PGA parameter (Shunt Voltage Only)
@param bits PGA_bits_1 <GAIN:1,Range ±40 mV>
@n PGA_bits_2 <GAIN:/2,Range ±80 mV>
@n PGA_bits_4 <GAIN:/4,Range ±160 mV>
@n PGA_bits_8 <GAIN:/8,Range ±320 mV>
'''
conf = 0
conf = self.read_ina_reg(self._INA219_REG_CONFIG)
conf &= ~(0x03 << 11)
conf |= bits << 11
self._write_register(self._INA219_REG_CONFIG, conf)
def set_bus_ADC(self, bits, sample):
'''!
@fn set_bus_ADC
@brief Set BADC parameter (Bus ADC Resolution/Averaging)
@param bits Resolution
@n adc_bits_9,
@n adc_bits_10,
@n adc_bits_11,
@n adc_bits_12
@param sample Sample size
@n adc_sample_1,
@n adc_sample_2,
@n adc_sample_4,
@n adc_sample_8,
@n adc_sample_16,
@n adc_sample_32,
@n adc_sample_64,
@n adc_sample_128
'''
conf = 0
value = 0
if(bits < self.adc_bits_12 and sample > self.adc_sample_1):
return
if(bits < self.adc_bits_12):
value = bits
else:
value = 0x80 | sample
conf = self.read_ina_reg(self._INA219_REG_CONFIG)
conf &= ~(0x0f << 7)
conf |= value << 7
self._write_register(self._INA219_REG_CONFIG, conf)
def set_shunt_ADC(self, bits, sample):
'''!
@fn set_shunt_ADC
@brief Set SADC parameter (Shunt ADC Resolution/Averaging)
@param bits Resolution
@n adc_bits_9,
@n adc_bits_10,
@n adc_bits_11,
@n adc_bits_12
@param sample Sample size
@n adc_sample_1,
@n adc_sample_2,
@n adc_sample_4,
@n adc_sample_8,
@n adc_sample_16,
@n adc_sample_32,
@n adc_sample_64,
@n adc_sample_128
'''
conf = 0
value = 0
if(bits < self.adc_bits_12 and sample > self.adc_sample_1):
return
if(bits < self.adc_bits_12):
value = bits
else:
value = 0x80 | sample
conf = self.read_ina_reg(self._INA219_REG_CONFIG)
conf &= ~(0x0f << 3)
conf |= value << 3
self._write_register(self._INA219_REG_CONFIG, conf)
def set_mode(self, mode):
'''
@fn set_mode
@brief Set operation Mode
@param mode
@n power_down, <Power-down>
@n shunt_vol_trig, <Shunt voltage, triggered>
@n bus_vol_trig, <Bus voltage, triggered>
@n shunt_and_bus_vol_trig,<Shunt and bus, triggered>
@n adc_off, <ADC off (disabled)>
@n shunt_vol_con, <Shunt voltage, continuous>
@n bus_vol_con, <Bus voltage, continuous>
@n shunt_and_bus_vol_con <Shunt and bus, continuous>
'''
conf = 0
conf = self.read_ina_reg(self._INA219_REG_CONFIG)
conf &= ~0x07
conf |= mode
self._write_register(self._INA219_REG_CONFIG, conf)
def read_ina_reg(self, reg):
buf = []
buf = self._read_register(reg)
if (buf[0] & 0x80):
return - 0x10000 + ((buf[0] << 8) | (buf[1]))
else:
return (buf[0] << 8) | (buf[1])
def scan(self):
try:
self.i2cbus.readfrom(self.i2c_addr)
return True
except:
print("I2C init fail")
return False