一、陀螺仪传感器
陀螺仪:
是一种用来感测与维持方向的装置,基於角动量不灭的理论设计出来的。 陀螺仪一旦开始旋转,由於轮子的角动量,陀螺仪有抗拒方向改变的趋向。一般在无人机、平衡车上使用,我们再用个各种型号手机,基本都包含这个组件。
三轴陀螺仪和六轴的区别
三轴陀螺仪是分别感应Roll(左右倾斜)、Pitch(前后倾斜)、Yaw(左右摇摆)的全方位动态信息。而6轴陀螺仪是指三轴加速器和三轴陀螺仪合在一起的称呼。
三轴加速器是检测横向加速的,三轴陀螺仪是检测角度旋转和平衡的,合在一起称为六轴传感器。
三轴加速器就是感应XYZ(立体空间三个方向,前后左右上下)轴向上的加速,当装有6轴陀螺仪的设备受到外力运动时,可以根据力的方向和大小,计算出对应的加速度
简单的说,6轴比3轴增加了额外的加速度功能,稍微高级一些。
六轴的区别和九轴陀螺仪的区别
所谓的六轴陀螺仪叫六轴动作感应器比较合适 是三轴陀螺仪和加速计的合称。如果有三轴陀螺仪也有加速计那就具有六轴动作感应。
而九轴感测组件是:三轴加速度计、三轴陀螺仪、三轴磁强计,然后欧拉角加四元数数据融合。
二、实验设备
本次我们将使用6轴传感器,实现串口与Unity3D的通信,并通过传感器控制Unity3D场景中的游戏物体,检验角度传感器的实际性能,以便在未来的项目中使用。本次演示不包含Arduino设备,在以后有空我们再进行Arduino对角度传感设备的操控。
1.串口6轴加速度计/陀螺仪MPU6050模块
本次我们测试和使用的是6轴陀螺仪,这个设备支持51/AVR/Arduino/STM8/STM32,自身自带卡尔曼滤波,支持串口输出滤波数据同时也支持高端玩家访问底层原始数据。
直接使用串口输出倾角(懒人模式),通过TTL转USB与计算机进行通信,通过对数据的解析,完成对场景种物体的控制。
2.USB转TTL 3.3V 5V
USB转TTL模块,如下图所示。该模块一端接入PC机的USB接口,另一端有TXD、RXD、GND、5V、3.3V五个引脚,分别与单片机的RXD、TXD、GND、5V引脚相连,注意:TXD和RXD是要互相反接。对于采用3.3V供电的单片机则把5V改为3.3V即可。首次使用需要安装对应的驱动,具体驱动类型根据所采购的设备,安装即可。
如下使用CH340+单片机控制,
3.硬件设备准备
以下为实物接线图
USB转TTL
三、代码编写
因为不使用Arduino作为硬件模块的接入设备,所以不写硬件代码,只需要对Unity 3D进行场景搭建和串口通信代码编写。
1.场景搭建
很简单的场景,3D场景中的X、Y轴;屏幕Canvas的X、Y、Z数据展示。
2.串口通信
using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;
public delegate void OnMessageArrived(float[] angle);
public class PortControl : MonoBehaviour
{
#region 定义串口属性
//定义基本信息
public string portName = “COM3”;//串口名
public int baudRate = 115200;//波特率
public Parity parity = Parity.None;//效验位
public int dataBits = 8;//数据位
public StopBits stopBits = StopBits.One;//停止位
SerialPort sp = null;
Thread dataReceiveThread;
//发送的消息
string message = “”;
public List《byte》 listReceive = new List《byte》();
char[] strchar = new char[100];//接收的字符信息转换为字符数组信息
string str;
public OnMessageArrived messageListener;
#endregion
void Start()
{
OpenPort();
dataReceiveThread = new Thread(new ThreadStart(DataReceiveFunction));
dataReceiveThread.Start();
}
void Update()
{
}
#region 创建串口,并打开串口
public void OpenPort()
{
//创建串口
sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
sp.ReadTimeout = 400;
try
{
sp.Open();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
#region 程序退出时关闭串口
void OnApplicationQuit()
{
ClosePort();
}
public void ClosePort()
{
try
{
sp.Close();
dataReceiveThread.Abort();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
/// 《summary》
/// 打印接收的信息
/// 《/summary》
void PrintData()
{
for (int i = 0; i 《 listReceive.Count; i++)
{
strchar[i] = (char)(listReceive[i]);
str = new string(strchar);
}
Debug.Log(str);
}
#region 接收数据
void DataReceiveFunction()
{
#region 按单个字节发送处理信息,不能接收中文
#endregion
float[] a = new float[3];
float[] w = new float[3];
float[] angle = new float[3];
float T=0;
#region 按字节数组发送处理信息,信息缺失
byte[] Re_buf = new byte[11];
int step = 0;
int bytes = 0;
while (true)
{
if (sp != null && sp.IsOpen)
{
try
{
bytes = sp.Read(Re_buf, 0, Re_buf.Length);//接收字节
if (bytes == 0)
{
continue;
}
else
{
// string strbytes = Encoding.Default.GetString(buffer);
string[] esStr=new string[Re_buf.Length];
string hexStr = “”;
for(int i=0;i《 Re_buf.Length; i++)
{
esStr[i]= Re_buf[i].ToString(“X2”) + “”;
hexStr += esStr[i]+“”;
}
if (esStr[0] != “55”)
{
for(int k=0;k《 esStr.Length; k++)
{
if(esStr[k] == “55”)
{
step = k;
byte[] thr = new byte[step];
int iss= sp.Read(thr, 0, thr.Length);//接收字节
break;
}
}
}
byte[] data = HexStrTobyte(hexStr);
// Debug.Log(.Length);
if (data[0] == 0x55) //检查帧头
{
switch (data[1])
{
//根据客服给的参考案例,修改为C#的数据解析方式
case 0x51:
a[0] = ((short)(data[3] 《《 8 | data[2])) / 32768.0f * 16;
a[1] = ((short)(data[5] 《《 8 | data[4])) / 32768.0f * 16;
a[2] = ((short)(data[7] 《《 8 | data[6])) / 32768.0f * 16;
T = ((short)(data[9] 《《 8 | data[8])) / 340.0f + 36.25f;
break;
case 0x52:
w[0] = ((short)(data[3] 《《 8 | data[2])) / 32768.0f * 2000;
w[1] = ((short)(data[5] 《《 8 | data[4])) / 32768.0f * 2000;
w[2] = ((short)(data[7] 《《 8 | data[6])) / 32768.0f * 2000;
T = ((short)(data[9] 《《 8 | data[8])) / 340.0f + 36.25f;
break;
case 0x53:
angle[0] = ((short)(data[3] 《《 8 | data[2])) / 32768.0f * 180;
angle[1] = ((short)(data[5] 《《 8 | data[4])) / 32768.0f * 180;
angle[2] = ((short)(data[7] 《《 8 | data[6])) / 32768.0f * 180;
T = ((short)(data[9] 《《 8 | data[8])) / 340.0f + 36.25f;
break;
}
messageListener(angle);
}
}
}
catch (Exception ex)
{
if (ex.GetType() != typeof(ThreadAbortException))
{
}
}
}
// Thread.Sleep(10);
}
#endregion
}
#endregion
private byte[] HexStrTobyte(string hexString)
{
hexString = hexString.Replace(“ ”, “”);
if ((hexString.Length % 2) != 0)
hexString += “ ”;
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i 《 returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
return returnBytes;
}
#region 发送数据
public void WriteData(string dataStr)
{
if (sp.IsOpen)
{
sp.Write(dataStr);
}
}
#endregion
}
控制脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SerialListener : MonoBehaviour
{
public PortControl portMessage;
public Transform obj;
public Text xAngle;
public Text yAngle;
public Text zAngle;
Queue《float[]》 message;
// Start is called before the first frame update
void Start()
{
message = new Queue《float[]》(20);
portMessage.messageListener = OnMessageArrived;
}
public void OnMessageArrived(float[] angle)
{
/* string s = “”;
foreach (float bb in angle)
s += bb + “_”;
Debug.Log(s + “”);*/
message.Enqueue(angle);
// Debug.Log(message.Count);
}
// Update is called once per frame
void Update()
{
if (message.Count 》 0)
{
float[] angle = message.Dequeue();
xAngle.text = angle[0] + “”;
yAngle.text = angle[1] + “”;
zAngle.text = angle[2] + “”;
obj.eulerAngles = new Vector3( angle[1], angle[2], angle[0]);
}
}
}
3.效果
四、总结
以上仅是今天我们测试和展示的整体内容,陀螺仪设备的串口通信以及和Unity 3D的互动。
通过本次个人的体验,这款智能硬件模块可以比较稳定、实时的进行数据回传,精确控制3D场景中的物体。
可以用在如定机位的游戏互动,比如线下捕鱼达人,望远镜、AR打怪之类的互动,如果您有什么新奇的想法,也可参与评论互动。
一、陀螺仪传感器
陀螺仪:
是一种用来感测与维持方向的装置,基於角动量不灭的理论设计出来的。 陀螺仪一旦开始旋转,由於轮子的角动量,陀螺仪有抗拒方向改变的趋向。一般在无人机、平衡车上使用,我们再用个各种型号手机,基本都包含这个组件。
三轴陀螺仪和六轴的区别
三轴陀螺仪是分别感应Roll(左右倾斜)、Pitch(前后倾斜)、Yaw(左右摇摆)的全方位动态信息。而6轴陀螺仪是指三轴加速器和三轴陀螺仪合在一起的称呼。
三轴加速器是检测横向加速的,三轴陀螺仪是检测角度旋转和平衡的,合在一起称为六轴传感器。
三轴加速器就是感应XYZ(立体空间三个方向,前后左右上下)轴向上的加速,当装有6轴陀螺仪的设备受到外力运动时,可以根据力的方向和大小,计算出对应的加速度
简单的说,6轴比3轴增加了额外的加速度功能,稍微高级一些。
六轴的区别和九轴陀螺仪的区别
所谓的六轴陀螺仪叫六轴动作感应器比较合适 是三轴陀螺仪和加速计的合称。如果有三轴陀螺仪也有加速计那就具有六轴动作感应。
而九轴感测组件是:三轴加速度计、三轴陀螺仪、三轴磁强计,然后欧拉角加四元数数据融合。
二、实验设备
本次我们将使用6轴传感器,实现串口与Unity3D的通信,并通过传感器控制Unity3D场景中的游戏物体,检验角度传感器的实际性能,以便在未来的项目中使用。本次演示不包含Arduino设备,在以后有空我们再进行Arduino对角度传感设备的操控。
1.串口6轴加速度计/陀螺仪MPU6050模块
本次我们测试和使用的是6轴陀螺仪,这个设备支持51/AVR/Arduino/STM8/STM32,自身自带卡尔曼滤波,支持串口输出滤波数据同时也支持高端玩家访问底层原始数据。
直接使用串口输出倾角(懒人模式),通过TTL转USB与计算机进行通信,通过对数据的解析,完成对场景种物体的控制。
2.USB转TTL 3.3V 5V
USB转TTL模块,如下图所示。该模块一端接入PC机的USB接口,另一端有TXD、RXD、GND、5V、3.3V五个引脚,分别与单片机的RXD、TXD、GND、5V引脚相连,注意:TXD和RXD是要互相反接。对于采用3.3V供电的单片机则把5V改为3.3V即可。首次使用需要安装对应的驱动,具体驱动类型根据所采购的设备,安装即可。
如下使用CH340+单片机控制,
3.硬件设备准备
以下为实物接线图
USB转TTL
三、代码编写
因为不使用Arduino作为硬件模块的接入设备,所以不写硬件代码,只需要对Unity 3D进行场景搭建和串口通信代码编写。
1.场景搭建
很简单的场景,3D场景中的X、Y轴;屏幕Canvas的X、Y、Z数据展示。
2.串口通信
using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;
public delegate void OnMessageArrived(float[] angle);
public class PortControl : MonoBehaviour
{
#region 定义串口属性
//定义基本信息
public string portName = “COM3”;//串口名
public int baudRate = 115200;//波特率
public Parity parity = Parity.None;//效验位
public int dataBits = 8;//数据位
public StopBits stopBits = StopBits.One;//停止位
SerialPort sp = null;
Thread dataReceiveThread;
//发送的消息
string message = “”;
public List《byte》 listReceive = new List《byte》();
char[] strchar = new char[100];//接收的字符信息转换为字符数组信息
string str;
public OnMessageArrived messageListener;
#endregion
void Start()
{
OpenPort();
dataReceiveThread = new Thread(new ThreadStart(DataReceiveFunction));
dataReceiveThread.Start();
}
void Update()
{
}
#region 创建串口,并打开串口
public void OpenPort()
{
//创建串口
sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
sp.ReadTimeout = 400;
try
{
sp.Open();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
#region 程序退出时关闭串口
void OnApplicationQuit()
{
ClosePort();
}
public void ClosePort()
{
try
{
sp.Close();
dataReceiveThread.Abort();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
/// 《summary》
/// 打印接收的信息
/// 《/summary》
void PrintData()
{
for (int i = 0; i 《 listReceive.Count; i++)
{
strchar[i] = (char)(listReceive[i]);
str = new string(strchar);
}
Debug.Log(str);
}
#region 接收数据
void DataReceiveFunction()
{
#region 按单个字节发送处理信息,不能接收中文
#endregion
float[] a = new float[3];
float[] w = new float[3];
float[] angle = new float[3];
float T=0;
#region 按字节数组发送处理信息,信息缺失
byte[] Re_buf = new byte[11];
int step = 0;
int bytes = 0;
while (true)
{
if (sp != null && sp.IsOpen)
{
try
{
bytes = sp.Read(Re_buf, 0, Re_buf.Length);//接收字节
if (bytes == 0)
{
continue;
}
else
{
// string strbytes = Encoding.Default.GetString(buffer);
string[] esStr=new string[Re_buf.Length];
string hexStr = “”;
for(int i=0;i《 Re_buf.Length; i++)
{
esStr[i]= Re_buf[i].ToString(“X2”) + “”;
hexStr += esStr[i]+“”;
}
if (esStr[0] != “55”)
{
for(int k=0;k《 esStr.Length; k++)
{
if(esStr[k] == “55”)
{
step = k;
byte[] thr = new byte[step];
int iss= sp.Read(thr, 0, thr.Length);//接收字节
break;
}
}
}
byte[] data = HexStrTobyte(hexStr);
// Debug.Log(.Length);
if (data[0] == 0x55) //检查帧头
{
switch (data[1])
{
//根据客服给的参考案例,修改为C#的数据解析方式
case 0x51:
a[0] = ((short)(data[3] 《《 8 | data[2])) / 32768.0f * 16;
a[1] = ((short)(data[5] 《《 8 | data[4])) / 32768.0f * 16;
a[2] = ((short)(data[7] 《《 8 | data[6])) / 32768.0f * 16;
T = ((short)(data[9] 《《 8 | data[8])) / 340.0f + 36.25f;
break;
case 0x52:
w[0] = ((short)(data[3] 《《 8 | data[2])) / 32768.0f * 2000;
w[1] = ((short)(data[5] 《《 8 | data[4])) / 32768.0f * 2000;
w[2] = ((short)(data[7] 《《 8 | data[6])) / 32768.0f * 2000;
T = ((short)(data[9] 《《 8 | data[8])) / 340.0f + 36.25f;
break;
case 0x53:
angle[0] = ((short)(data[3] 《《 8 | data[2])) / 32768.0f * 180;
angle[1] = ((short)(data[5] 《《 8 | data[4])) / 32768.0f * 180;
angle[2] = ((short)(data[7] 《《 8 | data[6])) / 32768.0f * 180;
T = ((short)(data[9] 《《 8 | data[8])) / 340.0f + 36.25f;
break;
}
messageListener(angle);
}
}
}
catch (Exception ex)
{
if (ex.GetType() != typeof(ThreadAbortException))
{
}
}
}
// Thread.Sleep(10);
}
#endregion
}
#endregion
private byte[] HexStrTobyte(string hexString)
{
hexString = hexString.Replace(“ ”, “”);
if ((hexString.Length % 2) != 0)
hexString += “ ”;
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i 《 returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
return returnBytes;
}
#region 发送数据
public void WriteData(string dataStr)
{
if (sp.IsOpen)
{
sp.Write(dataStr);
}
}
#endregion
}
控制脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SerialListener : MonoBehaviour
{
public PortControl portMessage;
public Transform obj;
public Text xAngle;
public Text yAngle;
public Text zAngle;
Queue《float[]》 message;
// Start is called before the first frame update
void Start()
{
message = new Queue《float[]》(20);
portMessage.messageListener = OnMessageArrived;
}
public void OnMessageArrived(float[] angle)
{
/* string s = “”;
foreach (float bb in angle)
s += bb + “_”;
Debug.Log(s + “”);*/
message.Enqueue(angle);
// Debug.Log(message.Count);
}
// Update is called once per frame
void Update()
{
if (message.Count 》 0)
{
float[] angle = message.Dequeue();
xAngle.text = angle[0] + “”;
yAngle.text = angle[1] + “”;
zAngle.text = angle[2] + “”;
obj.eulerAngles = new Vector3( angle[1], angle[2], angle[0]);
}
}
}
3.效果
四、总结
以上仅是今天我们测试和展示的整体内容,陀螺仪设备的串口通信以及和Unity 3D的互动。
通过本次个人的体验,这款智能硬件模块可以比较稳定、实时的进行数据回传,精确控制3D场景中的物体。
可以用在如定机位的游戏互动,比如线下捕鱼达人,望远镜、AR打怪之类的互动,如果您有什么新奇的想法,也可参与评论互动。
举报