陀螺仪传感器|从零开始认识各种传感器
1、什么是陀螺仪传感器
陀螺仪传感器又叫做角速度传感器。它是能检测到物体在空间中的姿态,朝向及转动角度的传感器。它被广泛应用于航空航天导航,便携智能设备体感检测,以及汽车姿态的传感等各个方面。陀螺仪与加速度计的主要区别就是陀螺仪主要用来测量角速度的,而加速度计是测线性加速度的。
图1 陀螺仪传感器
2、陀螺仪传感器是如何工作的
陀螺仪传感器是惯性测量元件,一个旋转物体的旋转轴所指的方向在不受外力影响时,是不会改变的。人们根据这个旋转轴保持指向不变的特性,用它来检测当前方向和角度的改变。例如,在被测物体相对于 x轴,y轴,或者z轴发生角度转变时,由于旋转轴的方向保持不变,那么通过测量万向节连接环的角度变化,即可获知被测物体当前的角度变化以及角速度。
图2 陀螺仪传感器工作原理
3、常见的陀螺仪传感器的种类
从早期的机械式陀螺仪发展到现在,市场上主流的陀螺仪可分为激光陀螺仪,光纤陀螺仪和MEMS陀螺仪三种类型。
3.1 激光陀螺仪
激光陀螺仪的实现基于塞格尼克理论:当光束在一个环形的通道中前进时,如果环形通道本身具有一个转动速度,那么光线沿着通道转动的方向转一圈的时间要比沿着这个通道反向转一圈所需要的时间要多。也就是说当光学环路转动时,在正反两个方向上,光学环路的光程相对于环路静止时都会产生变化。通过检测两条光路的相位差或干涉条纹的变化,即可得到光路旋转的角速度,这就是激光陀螺仪的工作原理。激光陀螺仪的一个缺点是:在很低的速度下会受到锁定现象的影响,从而无法正确检测旋转。
图3 激光陀螺仪原理
3.2 光纤陀螺仪传感器
光纤陀螺仪的实现也基于塞格尼克理论:但它的设计更加巧妙,它直接通过光纤来制造环形介质通道。相比激光陀螺仪,它不需要光学镜的精密加工和光腔的严格密封,而且从根本上避免了激光锁定问题,体积也可以做得更小。
图4 光纤陀螺仪传感器原理
3.3 MEMS陀螺仪传感器
MEMS 陀螺仪是用微机械加工工艺制造的陀螺仪,它通过自身振动引发科里奥利力,从而检测角速度变化。在旋转体系中进行直线运动的质点由于惯性,在旋转体系中直线运动的物体会发生偏移,这个导致偏移产生的 “虚拟” 力便被称为科里奥利力。
图5 科里奥利力产生原理
MEMS陀螺仪通过振动来诱导和探测科里奥利力,从而对角速度进行测量。它精度相对较低,但具有体积小,低成本低功耗,易于集成和数据输出简单的优点,广泛应用在消费级市场。
图6 MEMS陀螺仪工作原理
3.4 四种陀螺仪传感器的比较
图7 陀螺仪传感器特性比较
从三种陀螺仪传感器的比较表格可以看出,激光陀螺仪的精度最高,但是在低速旋转时会有闭锁效应。光纤陀螺仪由于其较低的价格和体积,广泛应用于高精度导航应用。而MEMS陀螺仪结构简单,体积最小,在消费电子中得到广泛的应用。
4、陀螺仪传感器实验演示
我们来演示使用 MCU 读取显示陀螺仪传感器的数据。实验中使用的是一款集成了3轴加速度计和3轴陀螺仪的 MAX6050 传感器,我们屏幕上的立体方块来显示其给出的陀螺仪的数据。可以看到,随着我们改变陀螺仪的位置和角度,立方体也随之发生相同方向的姿态变化,陀螺仪旋转时,方块也同步旋转。
图8 树莓派读取陀螺仪传感器展示
具体代码如下:
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 )
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 = 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
# display.fill_rect(0,0,100,100,0)
# display.fill(0)
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)
spi0.init(bits=16)
while True:
mpu_value=mpu.get_values()
drawcube(mpu_value["GyX"]/32767.5,mpu_value["GyY"]/32767.5,mpu_value["GyZ"]/32767.5)
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
其他相关文件请点此查看。