[原创] 晒设计方案+玩转陀螺仪

sjtitr   2014-2-23 07:51 楼主
STM32F429i Discovery还有一个陀螺仪,如果不能把它也搞起来,那有点太浪费STM的感情了。

好,那么本辑内容我们就来玩玩陀螺仪。

准备工程,就使用示例中的MEMS_Example

通过学习代码,了解到其中这个函数:
  1. static void Demo_MEMS(void)
  2. {   
  3.   
  4.   /* Read Gyro Angular data */
  5.   Demo_GyroReadAngRate(Buffer);

  6.   Buffer[0] = (int8_t)Buffer[0] - (int8_t)Gyro[0];
  7.   Buffer[1] = (int8_t)Buffer[1] - (int8_t)Gyro[1];
  8.   
  9.   /* Update autoreload and capture compare registers value*/
  10.   Xval = ABS((int8_t)(Buffer[0]));
  11.   Yval = ABS((int8_t)(Buffer[1]));
  12.   
  13.   if ( Xval>Yval)
  14.   {
  15.     if ((int16_t)Buffer[0] > 40)
  16.     {
  17.       /* Clear the LCD */
  18.       LCD_Clear(LCD_COLOR_WHITE);
  19.       LCD_SetTextColor(LCD_COLOR_MAGENTA);
  20.       LCD_DrawFullRect(100, 40, 40, 120);
  21.       LCD_FillTriangle(50, 190, 120, 160, 160, 310);
  22.       Delay(50);
  23.     }
  24.     if ((int16_t)Buffer[0] < -40)
  25.     {
  26.       /* Clear the LCD */
  27.       LCD_Clear(LCD_COLOR_WHITE);
  28.       LCD_SetTextColor(LCD_COLOR_RED);
  29.       LCD_DrawFullRect(100, 160, 40, 120);
  30.       LCD_FillTriangle(50, 190, 120, 160, 160, 10);
  31.       Delay(50);
  32.     }
  33.   }
  34.   else
  35.   {
  36.     if ((int16_t)Buffer[1] < -40)
  37.     {
  38.       /* Clear the LCD */
  39.       LCD_Clear(LCD_COLOR_WHITE);
  40.       LCD_SetTextColor(LCD_COLOR_GREEN);
  41.       LCD_DrawFullRect(120, 140, 100, 40);
  42.       LCD_FillTriangle(120, 120, 5, 60, 260, 160);      
  43.       Delay(50);
  44.     }
  45.     if ((int16_t)Buffer[1] > 40)
  46.     {      
  47.       /* Clear the LCD */
  48.       LCD_Clear(LCD_COLOR_WHITE);
  49.       LCD_SetTextColor(LCD_COLOR_BLUE);
  50.       LCD_DrawFullRect(20, 140, 100, 40);
  51.       LCD_FillTriangle(120, 120, 235, 60, 260, 160);
  52.       Delay(50);
  53.     }
  54.   }
  55. }
以上这些就是使用陀螺仪的关键代码啦,关于陀螺仪初始化等等的内容,我们完全可以利用示例工程的资源。

那么接下来我们就来玩转上面这个函数吧。

当然,首先根据示例,我们把三个方向的角度都取出来:
  1.   Buffer[0] = Buffer[0] - Gyro[0];
  2.   Buffer[1] = Buffer[1] - Gyro[1];
  3.   Buffer[2] = Buffer[2] - Gyro[2];

……为了玩转嘛,楼主又准备了一个可以转的函数,这里免费提供给大家。

  1. #include "math.h"
  2. /**************************************************************************
  3. *                 3D Cube
  4. ***************************************************************************/  
  5. #define CUBE_HALF_A        70
  6. typedef unsigned char u8_t;

  7. typedef float pos_t;                /* position */
  8. typedef float        rad_t;          /* radian */

  9. typedef struct{
  10.         pos_t        x;
  11.         pos_t        y;
  12. }d2pos_t;                                /* 2D point type */

  13. typedef struct{
  14.         pos_t        x;
  15.         pos_t        y;
  16.         pos_t        z;
  17. }d3pos_t;                                /* 3D point type */

  18. typedef struct{
  19.         rad_t        x;
  20.         rad_t        y;
  21.         rad_t        z;
  22. }d3rad_t;                        /* 3D radian type */

  23. typedef const u8_t * surface_t;

  24. typedef struct{
  25.         u8_t                vert_count;
  26.         u8_t                face_count;
  27.         d3pos_t                *vertexes;
  28.         surface_t        *surfaces;
  29.         d3pos_t                pos;
  30.         d3rad_t                rad;
  31. }poly_t;

  32. d3pos_t cube_pos[8]={
  33.         { CUBE_HALF_A,  CUBE_HALF_A,  CUBE_HALF_A},
  34.         {-CUBE_HALF_A,  CUBE_HALF_A,  CUBE_HALF_A},
  35.         {-CUBE_HALF_A, -CUBE_HALF_A,  CUBE_HALF_A},
  36.         { CUBE_HALF_A, -CUBE_HALF_A,  CUBE_HALF_A},
  37.         { CUBE_HALF_A,  CUBE_HALF_A, -CUBE_HALF_A},
  38.         {-CUBE_HALF_A,  CUBE_HALF_A, -CUBE_HALF_A},
  39.         {-CUBE_HALF_A, -CUBE_HALF_A, -CUBE_HALF_A},
  40.         { CUBE_HALF_A, -CUBE_HALF_A, -CUBE_HALF_A}
  41. };
  42. const u8_t cube_face1[]={0, 1, 2, 3, 0};
  43. const u8_t cube_face2[]={0, 3, 7, 4, 0};
  44. const u8_t cube_face3[]={0, 4, 5, 1, 0};
  45. const u8_t cube_face4[]={6, 5, 4, 7, 6};
  46. const u8_t cube_face5[]={6, 2, 1, 5, 6};
  47. const u8_t cube_face6[]={6, 7, 3, 2, 6};
  48. surface_t        cube_faces[6]={
  49.         cube_face1,cube_face2,cube_face3,cube_face4,cube_face5,cube_face6
  50. };

  51. poly_t cube_A = {
  52.         8,
  53.         6,
  54.         cube_pos,
  55.         cube_faces,
  56.         {0,0,0},
  57.         {0,0,0}
  58. };

  59. static void draw_line(int ax, int ay, int bx, int by);

  60. void d3_draw(poly_t * poly_p, float eye_z, float screen_z)     
  61. {  
  62.   d2pos_t d2p[8];
  63.   int i, j;
  64.   float Yn;
  65.   float x[8],y[8],z[8],xt,yt,zt,sinax,cosax,sinay,cosay,sinaz,cosaz;
  66.   int sx,sy,mx,my,ex,ey;
  67.    
  68.   sinax = sin(poly_p->rad.x);               // precalculate the sin and cos values  
  69.   cosax = cos(poly_p->rad.x);
  70.    
  71.   sinay = sin(poly_p->rad.y);
  72.   cosay = cos(poly_p->rad.y);
  73.    
  74.   sinaz = sin(poly_p->rad.z);
  75.   cosaz = cos(poly_p->rad.z);
  76.    
  77.   for (i = 0; i < poly_p->vert_count; i++)  // translate 3d vertex position to 2d screen position  
  78.   {  
  79.     x[i]=poly_p->vertexes[i].x;             // get current position x
  80.     y[i]=poly_p->vertexes[i].y;             // get current position y
  81.     z[i]=poly_p->vertexes[i].z;             // get current position z
  82.       

  83.     yt = y[i] * cosax - z[i] * sinax;       // rotate around X axis  
  84.     zt = y[i] * sinax + z[i] * cosax;
  85.     y[i] = yt;  
  86.     z[i] = zt;  
  87.       
  88.     xt = x[i] * cosay - z[i] * sinay;       // rotate around Y axis  
  89.     zt = x[i] * sinay + z[i] * cosay;
  90.     x[i] = xt;  
  91.     z[i] = zt;  
  92.       
  93.     xt = x[i] * cosaz - y[i] * sinaz;       // rotate around Z axis  
  94.     yt = x[i] * sinaz + y[i] * cosaz;
  95.     x[i] = xt;  
  96.     y[i] = yt;  
  97.       
  98.     x[i] += poly_p->pos.x;                                    // calc the new position x
  99.     y[i] += poly_p->pos.y;                  // calc the new position y  
  100.     z[i] += poly_p->pos.z;                  // calc the new position Z  

  101.     z[i] = (eye_z - screen_z) / (eye_z - z[i]);
  102.       
  103.     d2p[i].x = x[i] * z[i];                 // translate 3d to 2d
  104.     d2p[i].y = y[i] * z[i];                 // translate 3d to 2d
  105.   }  
  106.    
  107.   for (i = 0; i < poly_p->face_count; i++)  // draw each surface of the object  
  108.   {
  109.     sx = x[poly_p->surfaces[i][0]];
  110.     sy = y[poly_p->surfaces[i][0]];
  111.     mx = x[poly_p->surfaces[i][1]];
  112.     my = y[poly_p->surfaces[i][1]];
  113.     ex = x[poly_p->surfaces[i][2]];
  114.     ey = y[poly_p->surfaces[i][2]];

  115.     Yn = (ex-mx)*(sy-my)-(sx-mx)*(ey-my);   // check direction of the surface

  116.     if(Yn > 0)                              // draw it if face to us
  117.     {
  118.       j = 0;
  119.       
  120.       do{
  121.         j++;
  122.         sx=d2p[poly_p->surfaces[i][j-1]].x;         // set line start x
  123.         sy=d2p[poly_p->surfaces[i][j-1]].y;         // set line start y
  124.         ex=d2p[poly_p->surfaces[i][j]].x;           // set line end x
  125.         ey=d2p[poly_p->surfaces[i][j]].y;           // set line end y
  126.         draw_line(sx,sy,ex,ey);
  127.       }while(poly_p->surfaces[i][0] != poly_p->surfaces[i][j]);
  128.     }
  129.   }  
  130. }  

  131. void draw_line(int ax, int ay, int bx, int by)
  132. {
  133.         ax+=110;
  134.         ay+=110;
  135.         bx+=110;
  136.         by+=110;
  137.   LCD_DrawUniLine(ax,ay,bx,by);
  138. }
draw_line里面对坐标的修正是因为硬件的坐标原点在角落里,要移动到屏幕中间来,我比较懒,没有移到正中间,而是偏向一侧了。

使用的时候呢,只需要
  1.     cube_A.rad.x = rotatex;
  2.     cube_A.rad.y = rotatey;
  3.     cube_A.rad.z = rotatez;
  4.     d3_draw(&cube_A, 10000, 1000);
注意就是那三个参数,第一个表示描画对象;第二个是指视点的坐标,越大透视效果越差但是消隐越正确;第三个是投影面的坐标,应当小于视点坐标,并且越小画面越大。

最后就是玩转了,随个人喜好来玩吧
我就简单转了一小下吧,抛砖引玉啦



本辑没有工程分享啦,因为关键代码全部展示在上面了,自己贴一贴吧。

完。

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复