9回答

0收藏

[原创] 【CY8CKIT-003手记】天冷,跑几步

英飞凌 英飞凌 4993 人阅读 | 9 人回复 | 2012-12-04

本帖最后由 nemon 于 2012-12-4 17:42 编辑

冬天到了,今年挺冷的,北风一刮,脸上嗖嗖的。
话说上学的的时候,一到冬天,学校就会组织象征性长跑,其实就是给冬季长跑找个目标,最开始是革命圣地,比如延安什么的,后来长大点了,又赶上改革开放,就跑得远了:去过汉城接亚运火炬、去过九龙迎香港回归、还去过雅典取奥运圣火。体育老师画张地图,每隔几天就把全校每个人跑的总里程数加起来,看能到哪,就在地图上标出来。有的学校操场小,就让学生钻胡同跑,老师在边上看有没有掉队的。要是赶上校长有兴致过来看的日子,体育老师就会大声吆喝“快跑,马上到莫斯科了”。跑着跑着,身上就暖和了,肉体不僵硬,心思也就跟着活动起来“跑到莫斯科,回来的火车票给报销吗?”
又是一个冬天到了……
现在,一个有3维加速度传感器的板子放在面前,我一定要珍惜,
不能等到积灰的时候才后悔莫及,
坛子里最猥琐的事莫过于此......
既然爱版网给了我一个为所欲为的机会,
我就对这psoc板说三个字:
“计步器。”
如果非要在这里加一个期限,
我希望是.....就今天!
下面就是psoc板华丽变身山寨二进制计步器的经过,列位看官上眼:
首先找到KXSC7-2050的手册:
KXSC7-2050 Specifications Rev 4.pdf (447.37 KB, 下载次数: 558)

鉴于板子上已经都替你接好了,那么手册中最重要的就是这个了:

根据这个表,我们知道xyz输出的范围是0.99-2.31v,3维坐标是这样的:

据说加速度传感器需要对数据做平滑处理,否则噪声太大。下面这2张图引自动力老男孩  的博客《运动状态中的加速度传感器》:

钟摆运动下的加速度传感器读数


看上去确实是够棘手的,不过想起在CY8CKIT-003有一个冒泡的的例子,里面没有使用常用的移动平滑的算法,而是用右移来降低抖动的幅度,经过实验,基本满足需要,毕竟计步器不是制导用的。【a】
然后就看了一下ADI的《利用3轴数字加速度计实现功能全面的计步器设计》:
pedometer_cn.pdf (468.61 KB, 下载次数: 164)

当然啦,里面讲的都是如何用ADI的器件来实现的,关于抖动,他的解决方法是用数字滤波器。不过既然已经决定了用右移来处理,那么这篇文章给我的最重要的提示就是“最活跃轴”这个概念:

不可能因为要取Z轴的输出,就要求使用者举着板子保持水平,这也太过分了。所以,决定取3轴中的最大值,以此作为“最活跃轴”进行判断。【b】
还有,可能出现某一步迈的时间略长的情况。我这里解决的办法有2个,一个是增加采样间隔,另一个是增加阈值的判断,即只有当采样值高于阈值时,才认为做出了相应动作。这里提到的动作有2种,一种是加速的加速度超过阀值,一种是减速的加速度超过阀值。这样算起来只有2个动作都做了,这1步才算是走完。【c】
由于psoc中只能有1个ADC,因此需要用一个模拟多路复用器(AMuxHw)来逐个获取3轴的数据,这个组件的用法是:
如果MuxTYpe为Switch,那么每路数字输入作为开关对应一个模拟输入;如果MuxTYpe为Mux,那么多路数字输入的二进制值就是选中的模拟输入的通道号。
下面是原理图:

管脚的配置:

上代码:
  1. #include <device.h>

  2. /*Cypress根据KXSC7-2050和12位ADC计算的常数*/
  3. #define G_MEAN_VALUE            ((int16) 3300)
  4. #define GAIN                    ((int16) 7)

  5. /* 加速度传感器的控制位 ENABLE=1, MODE=1, ST/MODE=LOW */
  6. #define ACCL_SET_CONTROL    ((uint8) 0x06)

  7. /*三轴的宏定义*/
  8. #define TYPE_X  ((int16) 0x01)
  9. #define TYPE_Y  ((int16) 0x02)
  10. #define TYPE_Z  ((int16) 0x04)

  11. //取绝对值
  12. int16 abs(int16 i){return i>=0?i:-i;}

  13. //取最大值
  14. int16 max(int16 i,int16 j){return i>=j?i:j;}

  15. //获得某一轴的读数,改编自Cy的例子,请参考前文【a】的解释
  16. int16 getAcclResult16(int16 i_typ){
  17.         int16 Value=0;
  18.         
  19.         ADC_Control_Reg_Write(i_typ);
  20.         
  21.         /* Wait for ADC conversion to be completed */
  22.         ADC_IsEndConversion(ADC_WAIT_FOR_RESULT);

  23.         /* Read and process the acceleration value with offset and gain to update LED*/
  24.         Value= ADC_GetResult16();
  25.         Value = (Value - G_MEAN_VALUE)>>GAIN;
  26.         
  27.         return Value ;
  28. }

  29. void main()
  30. {
  31.    //3轴各自读数
  32.     int16 i_x=0;
  33.     int16 i_y=0;
  34.     int16 i_z=0;

  35.     int16 i_all=0;//“最活跃轴”的读数
  36.     int16 i_dir=1;//方向标志
  37.     int16 i_cnt=0;//步数

  38.     CYGlobalIntEnable;//使能全局中断
  39.     LED_Control_Reg_Write(0);//灭led
  40.     dPort_AcclControl_Write(ACCL_SET_CONTROL);//配置传感器

  41.     /* 启动ADC */
  42.     ADC_Start();
  43.     ADC_StartConvert();

  44.     while(1)
  45.     {
  46.         CyDelay(10);
  47.         i_x=abs(getAcclResult16(TYPE_X));
  48.         i_y=abs(getAcclResult16(TYPE_Y));
  49.         i_z=abs(getAcclResult16(TYPE_Z));
  50.         i_all = max( i_x , max( i_y , i_z) );//请参考前文【b】的解释

  51.         
  52.         //请参考前文【c】的解释
  53.         if(i_all>=7){
  54.                 if(i_dir==0){//up
  55.                         i_cnt++;
  56.                         i_dir=1;
  57.                 }else{//down
  58.                         i_dir=0;
  59.                 }
  60.         }
  61.         LED_Control_Reg_Write(i_cnt);//计算结果输出为led,看来使用者需要认识二进制的数
  62.     }
  63. }

  64. /* [] END OF FILE  Cy的这个习惯不错留着吧 */
复制代码
代码就这些,揣着这货在屋里蹦达了几下,效果还说的过去。不过动作很大的时候会多跳1、2个,看来右移还是没平滑靠谱。ADI的设计里还有动态调整记步阀值参数的功能,而上面的设计连“重新计数”的功能都没有,真可谓比山寨更山寨的是山寨的原型。元芳,还冷吗,你也揣着它出去跑几步?
分享到:
回复

使用道具 举报

回答|共 9 个

倒序浏览

沙发

小菜儿

发表于 2012-12-4 15:37:04 | 只看该作者

沙发,顶一个!!!
板凳

小菜儿

发表于 2012-12-4 16:47:09 | 只看该作者

ht868788 发表于 2012-12-4 16:19
竟然在我看文章准备请教问题时抢了沙发,太不厚道了

哈哈~抢完沙发再看文章~~~
地板

nemon

发表于 2012-12-6 19:24:17 | 只看该作者

ht868788 发表于 2012-12-4 17:45
呵,果然很详细。前段时间我也跟着板子跑了一遍加速度计的实验,没你那么上心。
关于【1】“但是,我看到 ...

这两天有点忙,就不多说了,回复简单不要见怪。
【1】进debug看了一下,发现ADC对超出量程的取值是0x1000。
【2】比较随意吧,有点倾斜的,但角度也不太大。
那个图是用windows下的画图手绘的。
5#

ming1006

发表于 2012-12-16 01:54:29 | 只看该作者

你用的是软件是1.0还是2.0呢
6#

ming1006

发表于 2012-12-16 01:54:32 | 只看该作者

你用的是软件是1.0还是2.0呢
7#

nemon

发表于 2012-12-17 09:37:25 | 只看该作者

ming1006 发表于 2012-12-16 01:54
你用的是软件是1.0还是2.0呢

2.0
8#

ming1006

发表于 2012-12-17 11:22:57 | 只看该作者

nemon 发表于 2012-12-17 09:37
2.0

这种端口在2.0应该编译通不过吧

9#

nemon

发表于 2012-12-17 11:36:26 | 只看该作者

可以的,但是会有warning。
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条