加速度传感器|从零开始认识各种传感器

1. 什么是加速度传感器?

加速度传感器是一种用于测量物体在三维空间中加速度的传感器。加速度一般用a来表示,是物体速度随时间变化的量。加速度传感器可以测量物体线性运动或者旋转运动的加速度,广泛应用于汽车工业、航空航天、医疗设备、智能手机和虚拟现实等多个领域。

图1 加速度概念图

2. 加速度传感器工作原理

根据牛顿第二定律:A(加速度)=F(力)/M(质量); 加速度传感器的工作原理是通过作用力造成传感器内部敏感部件发生变形。通过测量其变形并用相关电路转化成电压输出,得到相应的加速度信号。

图2 加速度传感器工作原理

3. 常见的加速度传感器的种类

根据传感器敏感元件的不同,常见的加速度传感器包括压电式、压阻式、电容式和伺服式。由于MEMS微机电系统的发展,这几种传感器都有MEMS类型的加速度传感器。

3.1 压电式加速度传感器

压电式加速度传感器是基于压电效应工作的。某些晶体如石英,压电陶瓷在一定方向上受力变形时,其内部会产生极化现象,同时在它的两个表面上产生符号相反的电荷;当外力去除后,又重新恢复到不带电状态,这种现象称为“压电效应”。

图3 压电效应原理

压电式加速度传感器在其内部有一个刚体支撑的质量块,有运动的情况下质量块会产生压力,刚体产生应变,把加速度转变成电信号输出。

图4 压电式加速度传感器原理

3.2 压阻式加速度传感器

压阻式加速度传感器的弹性元件一般采用硅梁外加质量块,质量块由悬臂梁支撑,并在悬臂梁上制作电阻,连接成测量电桥。在惯性力作用下质量块上下运动,悬臂梁上电阻的阻值随应力的作用而发生变化,那么测量电桥会输出与加速度成比例的电压变化。

图5 压阻式加速度传感器原理

基于MEMS硅微加工技术,利用单晶硅材料的压阻效应可以制成压阻式MEMS加速度传感器,单晶硅受到应力作用,晶体的晶格产生形变,使得电阻率就会发生变化,从而测得加速度的变化。

图6 压阻式MEMS加速度传感器

3.3 电容式加速度传感器

电容式加速度传感器有一个质量块固定在弹性梁的中间,质量块的上端面是一个活动电极,它与上固定电极组成一个电容C1;质量块的下端面也是一个活动电极,它与下固定电极组成另一个电容C2。当被测物的振动导致与其固连的传感器基座振动时,质量块将由于惯性而保持静止,因此上、下固定电极与质量块之间将会产生相对位移。这使得电容C1、C2的值一个变大、另一个变小,从而形成一个与加速度大小成正比的差动输出信号。

图7 电容式(MEMS)加速度传感器

同样,随着微机电技术的发展,如今的电容式加速度传感器普遍采用MEMS技术制造。

3.4 伺服式加速度传感器

伺服式加速度传感器有一个弹性支承的质量块,质量块上附着一个位移传感器。当基座振动时,质量块也会随之偏离平衡位置,位移传感器检测到偏移产生的信号,经伺服放大电路放大后转换为电流输出,而该电流流过电磁线圈从而产生电磁力,该电磁力的作用将使质量块趋于回复到原来的平衡位置上。因此电磁力的大小正比于质量块所受加速度的大小,所以通过测量电流的大小即可得到加速度的值。由于采用了负反馈工作原理,伺服式加速度传感器通常具有极好的幅值线性度,有很高的灵敏度。

图8 伺服式加速度传感器

3.5 四种加速度传感器的比较

图9 传感器特性比较

在加速度传感器的实际使用中,要根据不同的应用场景和产品特性,来选择合理的选型方案。

4. 加速度传感器实验演示

最后,我们来演示使用 MCU 读取显示加速度传感器的数据。实验中使用的是一款集成了3轴加速度计和3轴陀螺仪的 MAX6050 传感器,我们我们屏幕上的立体方块来显示其给出的加速度计的数据。可以看到,随着实验板各个方向的运动变化,立方体也随之发生相同运动变化,从而指示出设备的运动轨迹。

图11 树莓派读取加速度传感器展示

具体代码点此查看

main.py

import uos

import machine

import st7789 as st7789

from fonts import vga2_8x8 as font1

from fonts import vga1_16x32 as font2

import random

import framebuf

machine.freq(200_000_000 )

#from DMA import DMA

import time

from math import pi,sin,exp,sqrt,floor,cos

import time, array, uctypes, rp_devices as devs

import mpu6050

#########################################################

###

w, h = 240, 220

j=0

i=0

x,y=0,0

offset_adc=0

offset_dis=0

x_Value=0

y_Value=0

disp_width = 240

disp_height = 240

def sine(x,offset):

return (sin(x/120*pi+offset)+1)*120

############################################################

###

xAxis = machine.ADC(machine.Pin(28))

yAxis = machine.ADC(machine.Pin(29))

st7789_res = 0

st7789_dc = 1

CENTER_Y = int(disp_width/2)

CENTER_X = int(disp_height/2)

spi_sck=machine.Pin(2)

spi_tx=machine.Pin(3)

reset=machine.Pin(st7789_res, machine.Pin.OUT)

dc=machine.Pin(st7789_dc, machine.Pin.OUT)

###

spi0=machine.SPI(0,baudrate=62500000, phase=1, polarity=1,bits = 8 , sck=spi_sck, mosi=spi_tx)

display = st7789.ST7789(spi0, disp_width, disp_width,reset,dc,xstart=0, ystart=0, rotation=3)

#############################################################

dis_h = 150

dis_w = 150

dis_buff_0 = array.array('H', (0 for _ in range(dis_h*dis_w*2)))

dis_a=bytearray(150)

dis_b=bytearray(150)

###

DMA_CHAN_0 = 0

dma_chan_0 = devs.DMA_CHANS[DMA_CHAN_0]

#dma_0 = devs.DMA_DEVICE

dma_chan_0.READ_ADDR_REG = uctypes.addressof(dis_buff_0)

dma_chan_0.WRITE_ADDR_REG = devs.SPI0_SSPDR

dma_chan_0.TRANS_COUNT_REG = len(dis_buff_0)#int(len(dis_buff_0)/2)

dma_chan_0.CTRL_TRIG_REG = 0

dma_chan_0.CTRL_TRIG.BUSY = 0

#print(dma_chan_0.CTRL_TRIG.BUSY)

dma_chan_0.CTRL_TRIG.CHAIN_TO = DMA_CHAN_0

dma_chan_0.CTRL_TRIG.INCR_WRITE = 0

dma_chan_0.CTRL_TRIG.INCR_READ = 1

dma_chan_0.CTRL_TRIG.TREQ_SEL = devs.DREQ_SPI0_TX

# dma_chan_0.CTRL_TRIG.DATA_SIZE = 1

#############################################################

i2c = machine.I2C(0,scl=machine.Pin(21), sda=machine.Pin(20)) #initializing the I2C method for ESP32

mpu= mpu6050.accel(i2c)

def line( x0, y0, x1, y1, color):

"""

Draw a single pixel wide line starting at x0, y0 and ending at x1, y1.

Args:

x0 (int): Start point x coordinate

y0 (int): Start point y coordinate

x1 (int): End point x coordinate

y1 (int): End point y coordinate

color (int): 565 encoded color

"""

global dis_buff_0,dis_h,dis_w

steep = abs(y1 - y0) > abs(x1 - x0)

if steep:

x0, y0 = y0, x0

x1, y1 = y1, x1

if x0 > x1:

x0, x1 = x1, x0

y0, y1 = y1, y0

dx = x1 - x0

dy = abs(y1 - y0)

err = dx // 2

if y0 < y1:

ystep = 1

else:

ystep = -1

while x0 <= x1:

if steep:

# self.pixel(y0, x0, color)

dis_buff_0[(y0-1)*dis_h+x0] = color

else:

# self.pixel(x0, y0, color)

dis_buff_0[(x0-1)*dis_h+y0] = color

err -= dy

if err < 0:

y0 += ystep

err += dx

x0 += 1

cube=[[-40,-40,-40],[-40,40,-40],[40,40,-40],[40,-40,-40],[-40,-40,40],[-40,40,40],[40,40,40],[40,-40,40]]

lineid=[1,2,2,3,3,4,4,1,5,6,6,7,7,8,8,5,8,4,7,3,6,2,5,1]

def matconv(a,matrix):

res=[0,0,0]

for i in range(0,3):

res[i]=matrix[i][0]*a[0]+matrix[i][1]*a[1]+matrix[i][2]*a[2]

for i in range(0,3):

a[i]=res[i]

return a

def rotate(obj,x,y,z):

x=x/pi

y=y/pi

z=z/pi

rz=[[cos(z),-sin(z),0],[sin(z),cos(z),0],[0,0,1]]

ry=[[1,0,0],[0,cos(y),-sin(y)],[0,sin(y),cos(y)]]

rx=[[cos(x),0,sin(x)],[0,1,0],[-sin(x),0,cos(x)]]

matconv(matconv(matconv(obj,rz),ry),rx)

buff_1=bytearray(24)

buff_2=bytearray(24)

buff_pre_1=bytearray(24)

buff_pre_2=bytearray(24)

def drawcube(x,y,z):

global buff_1,buff_2,buff_pre_1,buff_pre_2,mpu_value

for i in range (0,24,2):

line(buff_pre_1[i],buff_pre_1[i+1],buff_pre_2[i],buff_pre_2[i+1],st7789.BLACK)

for i in range(0,8):

rotate(cube[i],x,y,z)

for i in range(0,24,2):

buff_1[i]=int(75+cube[lineid[i]-1][0])

buff_1[i+1]=int(75+cube[lineid[i]-1][1])

buff_2[i]=int(75+cube[lineid[i+1]-1][0])

buff_2[i+1]=int(75+cube[lineid[i+1]-1][1])

for i in range (0,24,2):

line(buff_1[i],buff_1[i+1],buff_2[i],buff_2[i+1],st7789.BLUE)

buff_pre_1 = buff_1

buff_pre_2 = buff_2

#############################################################

display.clear( 0x0000)

mpu_value = {}

display.set_window(125,45,150,150)

value_pre_x=0

X_sum=0

value_pre_y=0

Y_sum=0

value_pre_z=0

Z_sum=0

a=0

while True:

drawcube(0.2,0.2,0.2)

mpu_value=mpu.get_values()

X_sum=X_sum + value_pre_x - mpu_value["AcX"]/327.675

Y_sum=Y_sum + value_pre_y - mpu_value["AcY"]/327.675

Z_sum=Z_sum + value_pre_z - mpu_value["AcZ"]/327.675

if (45+X_sum) < 0 :

X_sum = -45

if (45+X_sum) >90 :

X_sum = 45

if (125+Y_sum) < 0 :

Y_sum = -125

if (125+Y_sum) >170 :

Y_sum = 45

if (40+Z_sum) < 0 :

Z_sum = -40

if (40+Z_sum) >40 :

Z_sum = 0

display.set_window(125+int(Y_sum),45+int(X_sum),150,150)

dc.off()

display.write(st7789.ST7789_RAMWR, b"" )

dma_chan_0.READ_ADDR_REG = uctypes.addressof(dis_buff_0)

dc.on()

dma_chan_0.CTRL_TRIG.EN = 1

while dma_chan_0.CTRL_TRIG.BUSY:

pass

dma_chan_0.CTRL_TRIG.EN = 0