[嵌入式开发模块]JY61姿态角度传感器 驱动模块

我就是我 2023-02-16 01:41 128阅读 0赞

文章目录

  • 前言
  • JY61简介
    • 概述
    • 通信协议
  • 驱动文件
    • JY61Driver.h
    • JY61Recver.c
    • JY61Cmder.c
    • 依赖
  • 使用示例
  • 更新历史

前言

干活中用到了JY61姿态角度传感器,写了相应的驱动程序,放出来。

驱动被设计为拥有指令器和接收机两个部分,完全被动方式运行,与具体的平台解耦,只支持串口通讯。

JY61简介

概述

JY61姿态角度传感器 六轴模块

  • 采用高精度的陀螺加速度计MPU6050,通过处理器读取MPU6050的测量数据然后通过串口输出,免去了用户自己去开发MPU6050复杂的IIC协议,同时精心的PCB布局和工艺保证了MPU6050收到外接的干扰最小,测量的精度最高。
  • 模块内部自带电压稳定电路,可以兼容3.3V/5V的嵌入式系统,连接方便。
  • 采用先进的数字滤波技术,能有效降低测量噪声,提高测量精度。
  • 模块保留了MPU6050的IIC接口,以满足用户访问底层测量数据(加速度、角速度)的需求。
  • 模块内部集成了姿态解算器,配合动态卡尔曼滤波算法,能够在动态环境下准确输出模块的当前姿态,姿态测量精度0.05度,稳定性极高。

20200607104222847.png

通信协议

(1)串口通信参数

  • 电平:TTL
  • 波特率:9600/115200 bps
  • 停止位:1
  • 校验位0

(2)数据包
模块发送至上位机每帧数据分为3个数据包,分别为加速度包、角速度包和角度包,3个数据包顺序输出。波特率115200时每隔10ms输出一帧数据。

加速度包:
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbl9zdHJvbmc_size_16_color_FFFFFF_t_70
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbl9zdHJvbmc_size_16_color_FFFFFF_t_70 1角速度包:
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbl9zdHJvbmc_size_16_color_FFFFFF_t_70 2
20200607104937936.png

角度包:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbl9zdHJvbmc_size_16_color_FFFFFF_t_70 3
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbl9zdHJvbmc_size_16_color_FFFFFF_t_70 4

(3)控制指令

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbl9zdHJvbmc_size_16_color_FFFFFF_t_70 5
以上都是从数据手册上复制黏贴下来的,很复杂吧。

但是没事!驱动程序已经都帮你搞定了!

驱动文件

JY61Driver.h

  1. /*
  2. *******************************************************************************************
  3. *
  4. * JY61 DRIVER MODULE
  5. * JY61驱动模块
  6. *
  7. * File : JY61Driver.h
  8. * By : Lin Shijun(https://blog.csdn.net/lin_strong)
  9. * Date : 2020/05/03
  10. * version: V1.0
  11. * History: 2020/05/03 V1.0 the prototype
  12. * Note : The JY61 driver is divided into two part, i.e. cmder and recver. The cmder is for
  13. * sending the JY61 command. The recver is for resolving data from the JY61.
  14. ********************************************************************************************
  15. */
  16. #ifndef JY61DRIVER_H
  17. #define JY61DRIVER_H
  18. /*
  19. ******************************************************************************************
  20. * INCLUDE
  21. ******************************************************************************************
  22. */
  23. #include <stdint.h>
  24. /*
  25. ******************************************************************************************
  26. * DEBUG CONFIGURATION
  27. ******************************************************************************************
  28. */
  29. // to enable debug messages in this module
  30. // #define JY61_DEBUG
  31. /*
  32. ******************************************************************************************
  33. * TYPE DEFINE
  34. ******************************************************************************************
  35. */
  36. typedef enum {
  37. JY61DT_Acc, // Acceleration
  38. JY61DT_AgV, // Angular Velocity
  39. JY61DT_Ang, // Angle
  40. } JY61DataType;
  41. typedef struct JY61STRUCT_DATA{
  42. JY61DataType t;
  43. // m/s^2 when t = Acc
  44. // °/s when t = AgV
  45. // ° when t = Ang
  46. float x;
  47. float y;
  48. float z;
  49. float temp; // ℃
  50. } JY61Data;
  51. typedef void (* JY61FUNC_DATA)(const JY61Data * data);
  52. /*
  53. ************************************************************************************
  54. * INTERFACES
  55. ************************************************************************************
  56. */
  57. void JY61Cmder_Init(void (* outChannel)(uint8_t *buf, uint16_t len));
  58. void JY61Cmder_Destroy(void);
  59. void JY61Cmder_InitializeAngle(void);
  60. void JY61Cmder_CalibrateAccelerometer(void);
  61. void JY61Cmder_SleepOrWakeup(void);
  62. void JY61Cmder_SerialOutput(void);
  63. void JY61Cmder_IICOutput(void);
  64. void JY61Cmder_BaudRate115200(void);
  65. void JY61Cmder_BaudRate9600(void);
  66. void JY61Cmder_HorizontalInstall(void);
  67. void JY61Cmder_VerticalInstall(void);
  68. void JY61Recver_Init(JY61FUNC_DATA onRecvData);
  69. // Call it to modify the call-back function.
  70. void JY61Recver_RegisterCallback(JY61FUNC_DATA onRecvData);
  71. void JY61Recver_CleanupBuffer(void);
  72. // Feed the receiver every byte received so that receiver can notify user
  73. // the resolved data for each frame.
  74. void JY61Recver_Feed(uint8_t nextByte);
  75. void JY61Recver_Destroy(void);
  76. #endif // of JY61DRIVER_H

JY61Recver.c

  1. /*
  2. *******************************************************************************************
  3. *
  4. * JY61 RECEIVER MODULE
  5. * JY61驱动模块 - 接收机
  6. *
  7. * File : JY61Recver.c
  8. * By : Lin Shijun(https://blog.csdn.net/lin_strong)
  9. * Date : 2020/05/03
  10. * version: V1.0
  11. * History: 2020/05/03 V1.0 the prototype
  12. * Note :
  13. ********************************************************************************************
  14. */
  15. /*
  16. *********************************************************************************************
  17. * INCLUDES
  18. *********************************************************************************************
  19. */
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include "JY61Driver.h"
  23. #include "RxMac.h"
  24. /*
  25. *********************************************************************************************
  26. * CONSTANT
  27. *********************************************************************************************
  28. */
  29. #define JY61DF_LEN 11 // length of JY61 data frame
  30. /*
  31. *********************************************************************************************
  32. * TYPE DEFINITION
  33. *********************************************************************************************
  34. */
  35. typedef struct JY61FRAME_STRUCT{
  36. uint8_t headByte; // 0x55
  37. uint8_t cmdByte;
  38. uint8_t xL;
  39. uint8_t xH;
  40. uint8_t yL;
  41. uint8_t yH;
  42. uint8_t zL;
  43. uint8_t zH;
  44. uint8_t TL;
  45. uint8_t TH;
  46. uint8_t Sum;
  47. } JY61Frame;
  48. typedef struct JY61RS_STRUCT{
  49. int16_t x;
  50. int16_t y;
  51. int16_t z;
  52. int16_t temp;
  53. } JY61ResolvedInt;
  54. /*
  55. *********************************************************************************************
  56. * LOCAL FUNCTION
  57. *********************************************************************************************
  58. */
  59. #define ARRAYSIZE(arr) (sizeof(arr)/ sizeof(arr[0]))
  60. static void _onFlushed(RxMac sender,RxMacPtr buf,uint16_t len,RxState state,
  61. RxFlag HorU,RxFlag Ender);
  62. /*
  63. *********************************************************************************************
  64. * LOCAL VARIABLE
  65. *********************************************************************************************
  66. */
  67. static const char * _str_JY61Recver = "JY61Recver";
  68. static JY61FUNC_DATA _onRecvData;
  69. static const uint8_t _flag_headerAcc[] = {
  70. (uint8_t)0x55, (uint8_t)0x51};
  71. static const uint8_t _flag_headerAgV[] = {
  72. (uint8_t)0x55, (uint8_t)0x52};
  73. static const uint8_t _flag_headerAng[] = {
  74. (uint8_t)0x55, (uint8_t)0x53};
  75. static const RXFLAG_STRUCT _flags[] = {
  76. {
  77. _flag_headerAcc, sizeof(_flag_headerAcc), RXFLAG_OPTION_HEADER},
  78. {
  79. _flag_headerAgV, sizeof(_flag_headerAgV), RXFLAG_OPTION_HEADER},
  80. {
  81. _flag_headerAng, sizeof(_flag_headerAng), RXFLAG_OPTION_HEADER}
  82. };
  83. static RxMac _mac;
  84. static uint8_t _macBuf[JY61DF_LEN];
  85. /*
  86. *********************************************************************************************
  87. * INTERFACE IMPLEMENTATION
  88. *********************************************************************************************
  89. */
  90. void JY61Recver_Init(JY61FUNC_DATA onRecvData){
  91. _onRecvData = onRecvData;
  92. _mac = RxMac_Create(_flags, ARRAYSIZE(_flags), _macBuf, sizeof(_macBuf),
  93. NULL, NULL, _onFlushed);
  94. if(_mac == NULL)
  95. for(;;)
  96. ;
  97. }
  98. void JY61Recver_Destroy(){
  99. _onRecvData = NULL;
  100. RxMac_Destroy(_mac);
  101. }
  102. void JY61Recver_RegisterCallback(JY61FUNC_DATA onRecvData){
  103. _onRecvData = onRecvData;
  104. }
  105. void JY61Recver_CleanupBuffer(void){
  106. RxMac_ResetState(_mac);
  107. }
  108. void JY61Recver_Feed(uint8_t nextByte){
  109. RxMac_FeedData(_mac, nextByte);
  110. }
  111. /*
  112. *********************************************************************************************
  113. * LOCAL FUNCTION IMPLEMENTATION
  114. *********************************************************************************************
  115. */
  116. static int _frameSumRight(const uint8_t * frame){
  117. uint8_t sum = 0;
  118. int i;
  119. for(i = 0; i < 10; i++)
  120. sum += frame[i];
  121. return sum == frame[10];
  122. }
  123. static void _frameResolve(JY61ResolvedInt *rst, const JY61Frame *frame){
  124. rst->x = (((int16_t)frame->xH) << 8) | frame->xL;
  125. rst->y = (((int16_t)frame->yH) << 8) | frame->yL;
  126. rst->z = (((int16_t)frame->zH) << 8) | frame->zL;
  127. rst->temp = (((int16_t)frame->TH) << 8) | frame->TL;
  128. }
  129. static void _onFlushed(RxMac sender,RxMacPtr buf,uint16_t len,RxState state,
  130. RxFlag HorU,RxFlag Ender){
  131. JY61Data data;
  132. JY61ResolvedInt rData;
  133. if(_onRecvData == NULL || !state.headerFound)
  134. return;
  135. if(!_frameSumRight((const uint8_t *)buf))
  136. return;
  137. _frameResolve(&rData, (const JY61Frame *)buf);
  138. data.x = rData.x / 32768.0f;
  139. data.y = rData.y / 32768.0f;
  140. data.z = rData.z / 32768.0f;
  141. switch (buf[1]){
  142. case 0x51:
  143. data.t = JY61DT_Acc;
  144. data.x *= 16;
  145. data.y *= 16;
  146. data.z *= 16;
  147. break;
  148. case 0x52:
  149. data.t = JY61DT_AgV;
  150. data.x *= 2000;
  151. data.y *= 2000;
  152. data.z *= 2000;
  153. break;
  154. case 0x53:
  155. data.t = JY61DT_Ang;
  156. data.x *= 180;
  157. data.y *= 180;
  158. data.z *= 180;
  159. break;
  160. default:
  161. // will never hit here
  162. return;
  163. }
  164. data.temp = (float)rData.temp / 340.0f + 36.53f;
  165. _onRecvData(&data);
  166. }

JY61Cmder.c

  1. /*
  2. *******************************************************************************************
  3. *
  4. * JY61 COMMANDER MODULE
  5. * JY61驱动模块 - 指令器
  6. *
  7. * File : JY61Cmder.c
  8. * By : Lin Shijun(https://blog.csdn.net/lin_strong)
  9. * Date : 2020/05/03
  10. * version: V1.0
  11. * History: 2020/05/03 V1.0 the prototype
  12. * Note :
  13. ********************************************************************************************
  14. */
  15. /*
  16. *********************************************************************************************
  17. * INCLUDES
  18. *********************************************************************************************
  19. */
  20. #include <stdio.h>
  21. #include "JY61Driver.h"
  22. /*
  23. *********************************************************************************************
  24. * LOCAL VARIABLE
  25. *********************************************************************************************
  26. */
  27. static void (* _out)(uint8_t *buf, uint16_t len) = NULL;
  28. /*
  29. *********************************************************************************************
  30. * CONSTANT
  31. *********************************************************************************************
  32. */
  33. #define JY61CMDBYTE_INITANGLE 0x52
  34. #define JY61CMDBYTE_CALIACCMETER 0x67
  35. #define JY61CMDBYTE_SLEEPORWAKE 0x60
  36. #define JY61CMDBYTE_OUTPUTSERIAL 0x61
  37. #define JY61CMDBYTE_OUTPUTIIC 0x62
  38. #define JY61CMDBYTE_BAUDRATE115200 0x63
  39. #define JY61CMDBYTE_BAUDRATE9600 0x64
  40. #define JY61CMDBYTE_HORINSTALL 0x65
  41. #define JY61CMDBYTE_VERINSTALL 0x66
  42. /*
  43. *********************************************************************************************
  44. * INTERFACE IMPLEMENTATION
  45. *********************************************************************************************
  46. */
  47. void JY61Cmder_Init(void (* outChannel)(uint8_t *buf, uint16_t len)){
  48. _out = outChannel;
  49. }
  50. void JY61Cmder_Destroy(){
  51. _out = NULL;
  52. }
  53. static void _sendCmd(uint8_t cmdByte){
  54. static uint8_t frame[3] = {
  55. 0xFF, 0xAA};
  56. if(_out == NULL)
  57. return;
  58. frame[2] = cmdByte;
  59. _out(frame, sizeof(frame));
  60. }
  61. void JY61Cmder_InitializeAngle(){
  62. _sendCmd(JY61CMDBYTE_INITANGLE);
  63. }
  64. void JY61Cmder_CalibrateAccelerometer(void){
  65. _sendCmd(JY61CMDBYTE_CALIACCMETER);
  66. }
  67. void JY61Cmder_SleepOrWakeup(void){
  68. _sendCmd(JY61CMDBYTE_SLEEPORWAKE);
  69. }
  70. void JY61Cmder_SerialOutput(void){
  71. _sendCmd(JY61CMDBYTE_OUTPUTSERIAL);
  72. }
  73. void JY61Cmder_IICOutput(void){
  74. _sendCmd(JY61CMDBYTE_OUTPUTIIC);
  75. }
  76. void JY61Cmder_BaudRate115200(void){
  77. _sendCmd(JY61CMDBYTE_BAUDRATE115200);
  78. }
  79. void JY61Cmder_BaudRate9600(void){
  80. _sendCmd(JY61CMDBYTE_BAUDRATE9600);
  81. }
  82. void JY61Cmder_HorizontalInstall(void){
  83. _sendCmd(JY61CMDBYTE_HORINSTALL);
  84. }
  85. void JY61Cmder_VerticalInstall(void){
  86. _sendCmd(JY61CMDBYTE_VERINSTALL);
  87. }

依赖

接收器的实现依赖于我写的通用接收机:
通用接收状态机模块

使用示例

使用此模块基本分几步:

  1. 初始化模块
  2. 如需要发送指令则实现并注册信道给指令器;注册回调函数给接收器,这样接收器在发现完整的数据帧时就会通过回调函数进行通知。
  3. 不断接收数据,并喂(Feed)给接收器;如需要发指令,随时调用指令器的接口。

以下代码示例了在上电后发送校准指令,然后进入自动模式,之后不断读取数据并进行解析(假设使用标准输入输出上的串口和JY61通信):

  1. #include "JY61Driver.h"
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. ……
  5. // 收到数据的回调函数
  6. static void onDataResolved(const JY61Data * data);
  7. // 发送信道
  8. static void sendChannel(uint8_t *buf, uint16_t len);
  9. void main(){
  10. uint8_t b;
  11. ……
  12. JY61Recver_Init(onDataResolved);
  13. JY61Cmder_Init(sendChannel);
  14. // 可以发送各种命令,比如
  15. // JY61Cmder_HorizontalInstall();
  16. for(;;){
  17. // 不断得到下一个字节并喂给接收机
  18. // 接收机会通过回调函数实时传递解析出来的值
  19. b = (uint8_t)getchar();
  20. JY61Recver_Feed(b);
  21. }
  22. }
  23. static void onDataResolved(const JY61Data * data){
  24. // 这里会得到实时解析到的各个包的数据
  25. switch(data->t){
  26. case JY61DT_Acc:
  27. // 加速度包的处理
  28. break;
  29. case JY61DT_AgV:
  30. // 角速度包的处理
  31. break;
  32. case JY61DT_Ang:
  33. // 角度包的处理
  34. break;
  35. default:
  36. // 不应该会到这
  37. break;
  38. }
  39. }
  40. static void sendChannel(uint8_t *buf, uint16_t len){
  41. // 往标准输出输出这个字节
  42. while(len-- > 0)
  43. putchar((char)*buf++);
  44. }

更新历史

2020/06/07 放出V1.0

发表评论

表情:
评论列表 (有 0 条评论,128人围观)

还没有评论,来说两句吧...

相关阅读