【LuatOS-sensor】3三轴罗盘仪GY271

2023-10-22 04:10

本文主要是介绍【LuatOS-sensor】3三轴罗盘仪GY271,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1 前言
  • 2 硬件连接
  • 3 官方驱动
  • 4 准备工作——角度计算
    • 4.1 测试获取与y轴夹角
    • 4.2 映射到lcd
  • 5 代码——结合传感器
  • 6 结果1——计算与北夹角
  • 7 结果2——和手机对比

1 前言

调试三轴罗盘仪,传感器获取磁场强度判定方向。

2 硬件连接

i2c通信,和其他的一样,只用到四根。
在这里插入图片描述

3 官方驱动

罗盘仪:https://doc.openluat.com/wiki/21?wiki_page_id=2750

--- 模块功能:ADC功能测试.
-- ADC测量精度(12bit)
-- 每隔1s读取一次ADC值
-- @author openLuat
-- @module adc.testAdc
-- @license MIT
-- @copyright openLuat
-- @release 2018.12.19module(...,package.seeall)PROJECT = "hmc5883l_demo"
VERSION = "1.0.0"require "log"
require "sys"
require "misc"-- i2c ID
local i2cid = 2-- i2c 速率--打开vlcd电压域
pmd.ldoset(15,pmd.LDO_VLCD)-- GPIO 0、1、2、3、4local addr = 0x1e        --addrlocal speed = 100000      --iic速率local Config_a     = 0x00    --配置寄存器a:设置的数据输出速率和测量配置  0 11 100 00  0X70
local Config_b     = 0x01    --配置寄存器b:设置装置的增益              001 00000    0Xe0
local mode         = 0x02    --模式寄存器: 默认单一测量模式01,连续00           000000 00    0X00/0x01
local Msb_x        = 0x03    --x 高位数据输出
local Lsb_x        = 0x04    --x 低位数据输出
local Msb_y        = 0x07    --x 高位数据输出
local Lsb_y        = 0x08    --x 低位数据输出
local Msb_z        = 0x05    --x 高位数据输出
local Lsb_z        = 0x06    --x 低位数据输出
local status       = 0x09    --  状态寄存器    0x00
local recogn_a     = 0x0a    --  识别寄存器a   0x48
local recogn_b     = 0x0b    --  识别寄存器b   0x34
local recogn_c     = 0x0c    --  识别寄存器c   0x33--写数据
local function I2C_Write_Byte(regAddress,val,val2)i2c.send(i2cid, addr, {regAddress,val,val2})end--读取单个字节
local function I2C_Read_Byte(regAddress)i2c.send(i2cid, addr, regAddress)local rdstr = i2c.recv(i2cid, addr, 1)log.info("rdstr:toHex()",rdstr:toHex())return rdstr:byte(1)--变成10进制数据
end--读取多个字节
local function I2C_Read_Bytes(regAddress,cnt)i2c.send(i2cid, addr, regAddress)local rdstr = i2c.recv(i2cid, addr, cnt)--log.info("rdstr:toHex()-------",rdstr:toHex())return rdstr
end-- 初始化
function init()if  i2c.setup(i2cid, speed, addr) ~= speed  thenlog.error("i2c", "setup fail", addr)i2c.close(i2cid)returnendlog.info("dev i2c init_ok")return true
endfunction hmc5883l_int()I2C_Write_Byte(Config_a,0x70)  --写配置a寄存器数据I2C_Write_Byte(Config_b,0x20)  --写配置b寄存器数据  增益660I2C_Write_Byte(mode,0x00)      --写模式寄存器数据
endfunction hmc5883l_read()local hx=I2C_Read_Byte(Msb_x)local lx=I2C_Read_Byte(Lsb_x)local x_data=hx*256+lxlocal hy=I2C_Read_Byte(Msb_y)local ly=I2C_Read_Byte(Lsb_y)local y_data=hy*256+lylocal hz=I2C_Read_Byte(Msb_z)local lz=I2C_Read_Byte(Lsb_z)local z_data=hz*256+lzif(x_data>32768)  thenx_data= -(0xFFFF - x_data + 1)   endif(y_data>32768)  theny_data = -(0xFFFF - y_data + 1)end if(z_data>32768)  thenz_data = -(0xFFFF - z_data+ 1)endlocal Angle= math.atan2(y_data,x_data)*(180/3.14159265)+180;--单位:角度 (0~360)Angle= Angle log.info("x,y,z-----------", x_data,y_data,z_data )log.info("Angle",string.format("%.1f", Angle))return x_data,y_data,z_data
endsys.taskInit(function()sys.wait(3000)while true dosys.wait(2000)if init() then --初始化hmc588配置hmc5883l_int()--读取x,y,z数值hmc5883l_read()i2c.close(i2cid)endend
end)

问题
在lua5.3上,math.atan2()函数被弃用了,需要自己改。

4 准备工作——角度计算

4.1 测试获取与y轴夹角


-- 交换xy求与y轴的夹角
-- y = 1
-- x = -3^(1/2)y = -1
x = -3^(1/2)-- 获取与y轴的夹角
function get_y_angle(x,y)local temp_atan = 0local pi = 3.1415926if x > 0 thenif y > 0 then-- print("1")temp_atan = math.atan(x,y)/pi*180else if y<0 then-- print("2")temp_atan = math.atan(x,y)/pi*180 endendelse if x < 0 thenif y > 0 then-- print("4")temp_atan = math.atan(x,y)/pi*180 + 360else if y<0 then-- print("3")temp_atan = math.atan(x,y)/pi*180 + 360endendendendreturn temp_atan
endn = get_y_angle(x,y)
-- print(m)
print(n)

4.2 映射到lcd


-- 交换xy求与y轴的夹角
-- y = 1
-- x = -3^(1/2)y = -1
x = -3^(1/2)-- 获取与y轴的夹角
function get_y_angle(x,y)local temp_atan = 0local pi = 3.1415926if x > 0 thenif y > 0 then-- print("1")temp_atan = math.atan(x,y)/pi*180else if y<0 then-- print("2")temp_atan = math.atan(x,y)/pi*180 endif y == 0 thentemp_atan = 90endendelse if x < 0 thenif y > 0 then-- print("4")temp_atan = math.atan(x,y)/pi*180 + 360else if y<0 then-- print("3")temp_atan = math.atan(x,y)/pi*180 + 360endendif y == 0 thentemp_atan = 270endendendreturn temp_atan
endn = get_y_angle(x,y)
-- print(m)
print(n)-- 输入数值范围及当前数值,返回与y轴的夹角
function raw2angle_y(temp_x,temp_y,x_max,x_min,y_max,y_min)local R_x_max = x_maxlocal R_x_min = x_minlocal R_y_max = y_maxlocal R_y_min = y_minlocal R_range_x = R_x_max - R_x_minlocal R_range_y = R_y_max - R_y_minlocal R00_x = R_x_max - (R_range_x)/2local R00_y = R_y_max - (R_range_y)/2print(R00_x,R00_y)local R_temp_x = temp_xlocal R_temp_y = temp_ylocal R_bias_x = R_temp_x - R00_xlocal R_bias_y = R_temp_y - R00_yprint(get_y_angle(R_bias_x,R_bias_y))local lcd_x_max = 128 local lcd_y_max = 128 local R_step_x = lcd_x_max / R_range_xlocal R_step_y = lcd_y_max / R_range_ylocal lcd_x = R_bias_x * R_step_x + 64  -- R00对应(64,64)local lcd_y = R_bias_y * R_step_y + 64print("lcd",lcd_x,lcd_y)endraw2angle_y(300,400,300,-100,400,0)

5 代码——结合传感器

sen_GY271.lua

--- 模块功能:ADC功能测试.      GY271  hmc5883l 三轴罗盘
-- ADC测量精度(12bit)
-- 每隔1s读取一次ADC值
-- @author openLuat
-- @module adc.testAdc
-- @license MIT
-- @copyright openLuat
-- @release 2018.12.19--[[
VCC:电源正
GND:电源负
SCL:I2C串行时钟线
SDA:I2C串行数据线
DRDY:中断引脚      -- io11
]]PROJECT = "hmc5883l_demo"
VERSION = "1.0.0"-- require "log"
-- require "sys"
-- require "misc"-- i2c ID
local GY271_i2c_id = 0-- i2c 地址
local GY271_i2c_addr = 0x1e        --GY271_i2c_addr-- i2c 速率
local GY271_i2c_speed = 100000      --iic速率--打开vlcd电压域
-- pmd.ldoset(15,pmd.LDO_VLCD)-- GPIO 0、1、2、3、4local Config_a     = 0x00    --配置寄存器a:设置的数据输出速率和测量配置  0 11 100 00  0X70
local Config_b     = 0x01    --配置寄存器b:设置装置的增益              001 00000    0Xe0
local mode         = 0x02    --模式寄存器: 默认单一测量模式01,连续00           000000 00    0X00/0x01
local Msb_x        = 0x03    --x 高位数据输出
local Lsb_x        = 0x04    --x 低位数据输出
local Msb_y        = 0x07    --x 高位数据输出
local Lsb_y        = 0x08    --x 低位数据输出
local Msb_z        = 0x05    --x 高位数据输出
local Lsb_z        = 0x06    --x 低位数据输出
local status       = 0x09    --  状态寄存器    0x00
local recogn_a     = 0x0a    --  识别寄存器a   0x48
local recogn_b     = 0x0b    --  识别寄存器b   0x34
local recogn_c     = 0x0c    --  识别寄存器c   0x33--写数据
local function I2C_Write_Byte(regAddress,val,val2)i2c.send(GY271_i2c_id, GY271_i2c_addr, {regAddress,val,val2})end--读取单个字节
local function I2C_Read_Byte(regAddress)i2c.send(GY271_i2c_id, GY271_i2c_addr, regAddress)local rdstr = i2c.recv(GY271_i2c_id, GY271_i2c_addr, 1)-- log.info("rdstr:toHex()",rdstr:toHex())      -- 打印原始数据return rdstr:byte(1)--变成10进制数据
end--读取多个字节
local function I2C_Read_Bytes(regAddress,cnt)i2c.send(GY271_i2c_id, GY271_i2c_addr, regAddress)local rdstr = i2c.recv(GY271_i2c_id, GY271_i2c_addr, cnt)--log.info("rdstr:toHex()-------",rdstr:toHex())return rdstr
end-- 初始化
function init()if  i2c.setup(GY271_i2c_id, GY271_i2c_speed, GY271_i2c_addr) ~= GY271_i2c_speed  thenlog.error("i2c", "setup fail", GY271_i2c_addr)i2c.close(GY271_i2c_id)returnendlog.info("dev i2c init_ok")sys.wait(1000)hmc5883l_int()hmc5883l_read()x_max = x_datax_min = x_datay_max = y_datay_min = y_dataz_max = z_dataz_min = z_datareturn true
endfunction hmc5883l_int()I2C_Write_Byte(Config_a,0x70)  --写配置a寄存器数据I2C_Write_Byte(Config_b,0x20)  --写配置b寄存器数据  增益660I2C_Write_Byte(mode,0x00)      --写模式寄存器数据
endfunction judge_xyz_range()if x_data > x_max thenx_max = x_dataelse if x_data < x_min thenx_min = x_dataendendif y_data > y_max theny_max = y_dataelse if y_data < y_min theny_min = y_dataendendif z_data > z_max thenz_max = z_dataelse if z_data < z_min thenz_min = z_dataendendprint("x range: ",x_max,x_min,"y range: ",y_max,y_min,"z range: ",z_max,z_min)
endfunction get_angle()print("x "..x_data.." | y "..y_data.." | z "..z_data)x_p00 = x_max - (x_max - x_min)/2y_p00 = y_max - (y_max - y_min)/2z_p00 = z_max - (z_max - z_min)/2print("p00",x_p00,y_p00,z_p00)hmc5883l_angle = math.atan((y_data - y_p00)/(x_data - x_p00))*(180/3.14159265)+180-- hmc5883l_angle = math.atan((x_data - x_p00)/(y_data - y_p00))*(180/3.14159265)+180print("hmc5883l_angle",hmc5883l_angle)endfunction hmc5883l_read()local hx=I2C_Read_Byte(Msb_x)local lx=I2C_Read_Byte(Lsb_x)x_data=hx*256+lxlocal hy=I2C_Read_Byte(Msb_y)local ly=I2C_Read_Byte(Lsb_y)y_data=hy*256+lylocal hz=I2C_Read_Byte(Msb_z)local lz=I2C_Read_Byte(Lsb_z)z_data=hz*256+lzif(x_data>32768)  thenx_data= -(0xFFFF - x_data + 1)   endif(y_data>32768)  theny_data = -(0xFFFF - y_data + 1)end if(z_data>32768)  thenz_data = -(0xFFFF - z_data+ 1)endlog.info("x,y,z-----------", x_data,y_data,z_data )-- local Angle= math.atan(x_data,y_data)*(180/3.14159265)+180 --单位:角度 (0~360)-- Angle= Angle -- log.info("Angle",string.format("%.1f", Angle))return x_data,y_data,z_data
endfunction hmc5883l_test()sys.wait(3000)hmc5883l_status = init()print("hmc5883l_status",hmc5883l_status)while true dosys.wait(1000)if hmc5883l_status then --初始化hmc588配置-- hmc5883l_int()--读取x,y,z数值hmc5883l_read()judge_xyz_range()-- get_angle()raw2angle_y(x_data,y_data,x_max,x_min,y_max,y_min)-- i2c.close(GY271_i2c_id)endend
end-- test-- 交换xy求与y轴的夹角
-- y = 1
-- x = -3^(1/2)-- y = -1
-- x = -3^(1/2)-- 获取与y轴的夹角
function get_y_angle(x,y)local temp_atan = 0local pi = 3.1415926if x > 0 thenif y > 0 then-- print("1")temp_atan = math.atan(x,y)/pi*180else if y<0 then-- print("2")temp_atan = math.atan(x,y)/pi*180 endif y == 0 thentemp_atan = 90endendelse if x < 0 thenif y > 0 then-- print("4")temp_atan = math.atan(x,y)/pi*180 + 360else if y<0 then-- print("3")temp_atan = math.atan(x,y)/pi*180 + 360endendif y == 0 thentemp_atan = 270endendendreturn temp_atan
end-- n = get_y_angle(x,y)
-- -- print(m)
-- print(n)-- 输入数值范围及当前数值,返回与y轴的夹角
function raw2angle_y(temp_x,temp_y,x_max,x_min,y_max,y_min)local R_x_max = x_maxlocal R_x_min = x_minlocal R_y_max = y_maxlocal R_y_min = y_minlocal R_range_x = R_x_max - R_x_minlocal R_range_y = R_y_max - R_y_minlocal R00_x = R_x_max - (R_range_x)/2local R00_y = R_y_max - (R_range_y)/2print("R00",R00_x,R00_y)local R_temp_x = temp_xlocal R_temp_y = temp_ylocal R_bias_x = R_temp_x - R00_xlocal R_bias_y = R_temp_y - R00_yN_angle = get_y_angle(R_bias_x,R_bias_y) - 90if N_angle < 0 thenprint("N-E")N_angle = N_angle+360endprint("get_y_angle",N_angle)local lcd_x_max = 128 local lcd_y_max = 128 local R_step_x = lcd_x_max / R_range_xlocal R_step_y = lcd_y_max / R_range_ylocal lcd_x = R_bias_x * R_step_x + 64  -- R00对应(64,64)local lcd_y = R_bias_y * R_step_y + 64print("lcd",lcd_x,lcd_y)end-- raw2angle_y(300,400,300,-100,400,0)

main.lua

PROJECT = "sensor"
VERSION = "1.0.0"_G.sys = require("sys")require("sen_BH1750")       -- 光感
require("sen_TCS34725")     -- 色彩
require("sen_BMP180")       -- 气压
require("sen_GY271")-- 加载I²C功能测试模块
T1_BH1750 = 0
T2_TCS34725 = 0
T3_BMP180 = 0
T4_GY271 = 1-- i2c ID
esp32_i2c_id = 0        -- esp32只支持一路i2c, id为0
esp32_spi_id = 2        -- esp32只支持一路spi, id为2-- i2c 速率
esp32_i2c_speed = i2c.SLOW -- 100000sys.taskInit(function()-- ps:有wait不能放在外面if T2_TCS34725 == 1 thenTCS34725_init(esp32_i2c_id,esp32_i2c_speed) -- TCS34725地址默认为0x29endif T1_BH1750 == 1 thenBH1750_init(esp32_i2c_id)endif T3_BMP180 == 1 then-- BMP180_test(esp32_i2c_id)BMP180_init(esp32_i2c_id)endif T4_GY271 == 1 thenhmc5883l_test()end-- sys.wait(1500)while 1 doif T1_BH1750 == 1 thenBH1750_get()endif T2_TCS34725 == 1 thenTCS34725_get() -- TCS34725地址默认为0x29endif T3_BMP180 == 1 then-- BMP180_test(esp32_i2c_id)BMP180_get_temp_press()endsys.wait(100)end
end)sys.run()

6 结果1——计算与北夹角

在这里插入图片描述
这里的get_y_angle就是N,数值为0时指向正北。

和手机有一点偏差,后续再结合lcd屏幕显示数值吧。

7 结果2——和手机对比

lcd绘制出来成一根直线,看起来像是y=ymax - x 。

如图,以手机作为参考的话,还是相对符合的。
不过需要注意的是,在测试是需要校正(将xy的最值都设置为当前获取值),而且周边干扰较少,否则会影响效果,导致测试到的角度有偏差。

在这里插入图片描述
在这里插入图片描述

这篇关于【LuatOS-sensor】3三轴罗盘仪GY271的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/258978

相关文章

8 自研rgbd相机基于rk3566之sensor图像解析与AWB算法原理

自研rgbd相机基于rk3566之sensor图像解析与AWB开发 1、sensor-raw图解析介绍2、sensor-raw图解析程序详解常规raw10-to-raw16数据解析sc2310-raw10-to-raw16图像解析gc2053/gc2093 raw图像解析 3、sensor-awb及常用算法程序bayer bggr to rgb 图像解析简单白平衡算法灰度世界法白平衡算法完美

android 传感器 Sensor

/SensorTest/res/layout/activity_main.xml <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:lay

合宙LuatOS产品规格书——Air780EQ

合宙Air780EQ, 基于移芯EC716E高端平台, 集成LTE 3GPP Release 13技术,确保高速、稳定的网络连接; 广泛兼容各大运营商网络,实现真正的全网通设计,提升产品市场适应性与灵活性。 Air780EQ 4G全网通模块核心亮点: 1. 双卡单待: 支持双卡单待功能,为用户提供更多网络选择与切换便利,满足不同场景下的通信需求。 2. 高效接口与指令集:

合宙LuatOS开发板使用说明——Air700ECQ

EVB-Air700ECQ-IO 开发板是合宙通信推出的基于 Air700ECQ 模组所开发的,包含电 源, SIM 卡,USB ,天 线, 全 IO 引 出的最 小硬 件系 统。以 方便 用户 在设 计前期 对 Air700ECQ 模块进行性能评估,功能调试,软件调试,低功耗测试等用途。 Air700ECQ是一款高度集成的LTE Cat1无线通信模组,基于移芯EC716E平台设计,有着极小的

image sensor 关于像素的误解

CMOS Image Sensor一些概念误区: 误解1: 130W Pixel 像素感光单元,每个单元能感应R,G,B值; 正解: 130W个像素感光单元,每个感光单元只能感应单一颜色(RGB中某种色彩),不能同时感应R,G,B三个值; (PS: Foveon X3感光元件能同时感应RGB三个值) 误解2: 感光单元的R/G/B值只为单一像素试用 正解: 每个像素感光单元只

Android sensor列表和访问记录

命令: dumpsys sensorservice 1.dumpsys sensorservice查看最近申请记录 dumpsys sensorservice命令输出Previous Registrations. Previous Registrations:23:07:43 + 0x00000008 pid=16587 uid=10397 package=com.start.testde

RAW Sensor vs YUV Sensor:详细对比

目录 一、RAW传感器1.1 定义1.2 工作原理1.3 优点1.4 缺点1.5 应用场景 二、YUV传感器2.1 定义2.2 工作原理2.3 优点2.4 缺点2.5 应用场景 三、总结 在现代智能手机和数码相机中,图像传感器(Image Sensor)是至关重要的组件,它决定了设备的图像捕捉能力。常见的图像传感器类型有两种:RAW传感器(Raw Sensor)和YUV传感器(

android sensor 框架--Java层

一个简单的注册流程图: --调用registerListener()函数,实际调用抽象函数registerListenerImpl --子类SystemSensorManager实现了registerListenerImpl --如果有sensor事件,则JNI层android_hardware_SensorManager.cpp就调用dispatchSensorEvent()方法发送 -

模块[camera]_CMOS Sensor的调试经验分享

 转自:http://bbs.52rd.com/forum.php?mod=viewthread&tid=276351 CMOS Sensor的调试经验分享      我这里要介绍的就是CMOS摄像头的一些调试经验。   首先,要认识CMOS摄像头的结构。我们通常拿到的是集成封装好的模组,一般由三个部分组成:镜头、感应器和图像信号处理器构成。一般情况下,集成好的模组我们只看到外面的镜头

Android9.0源码学习-Sensor Framework

文章目录 FileListQuestionsSensorService初始化registerListener流程分析APPFrameworkJavaNativeClientServer How the app get sensor dataServerBitTubeClient Reference 在之前的学习中, Android Sensor概述介绍了常用传感器的功能,测量值