Funpack第六期——基于MAX32660的智能手表计步器设计
基于MAX32660,实现了计步器以及时间计时功能。使用了MPU6050以及OLED作为外设。资源用到了硬件I2C,软件SPI以及一个通用定时器。
标签
MAX32660
奈奎斯特不稳定
更新2021-03-18
1018

说明文档

本代码主要实现了显示时间,以及对步数的记录。顺便加了个小的下位机,用来修改时间。

项目地址

硬件连接

#define SPI_CS_Pin                              PIN_12
#define SPI_CS_GPIO_Port PORT_0
#define SPI_DC_Pin PIN_13
#define SPI_DC_GPIO_Port PORT_0
#define SPI_RES_Pin PIN_4
#define SPI_RES_GPIO_Port PORT_0
#define SPI_DIN_Pin PIN_3
#define SPI_DIN_GPIO_Port PORT_0
#define SPI_CLK_Pin PIN_2
#define SPI_CLK_GPIO_Port PORT_0

image-20210216221845791

时间显示

这次还是用了OLED的文字库,用到了显示文字,和画图功能。


DrawNum(0,0,step_cnt,5);
SetFontSize(3);
DrawChar(30,24,':');
DrawNum(0,24,hour,2);
DrawNum(42,24,min,2);
fresh_g();
RoundClock(hour,min,sec);

其中画时钟的函数是我之前有用过,参照的是另外一个up主的内容,程序里有提到。具体的使用可以参照我之前的项目

下面源码,主要用了简单的画图函数。


void RoundClock(int hours ,int minute ,int sec)
{
unsigned char i=0;

TypeXY hourspoint,minutepoint,secpoint,tmp1,tmp2;

center_pos.x = 104;
center_pos.y = 39;

//时针
SetRotateValue(center_pos.x,center_pos.y,hours*30+(minute*30)/60+clock_angle,1); //设定旋转中心,旋转角度,旋转方向
hourspoint=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+12);         //给出一个不在中心的点,计算出其旋转后的坐标
DrawLine(center_pos.x,center_pos.y,hourspoint.x,hourspoint.y);//画线
//分针
SetRotateValue(center_pos.x,center_pos.y,minute*6+(sec*6)/60+clock_angle,1);
minutepoint=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+6);
DrawLine(center_pos.x,center_pos.y,minutepoint.x,minutepoint.y);
//秒针
SetRotateValue(center_pos.x,center_pos.y,sec*6+clock_angle,1);
secpoint=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+2);
DrawLine(center_pos.x,center_pos.y,secpoint.x,secpoint.y);
//表盘
for(i=0;i<12;i++)
{
SetRotateValue(center_pos.x,center_pos.y,i*30+clock_angle,1);
tmp1=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+1);
tmp2=GetRotateXY(center_pos.x,center_pos.y-CLOCK_R+1+CLOCK_LEN);
DrawLine(tmp1.x,tmp1.y,tmp2.x,tmp2.y);
}
DrawFillCircle(center_pos.x,center_pos.y,2);//中心圆点
DrawCircle(center_pos.x,center_pos.y,CLOCK_R);
UpdateScreen();
ClearScreen();
}

步数记录

代码设计过程参考了CSDN上的一篇博客

前面是一些基本的滤波以及求峰值,后面才是计算是否走步。


filter_acc();
peak_caculate();
slid_update(&temp_acc,&mpu);
detect_step(&peak_acc,&temp_acc,&mpu);

下面是判断是否走步的代码:


void detect_step(peak_info *peak, slid_reg_t *slid, axis_info *cur_sample)
{
char res = is_most_active(peak);
switch (res) {
case MOST_ACTIVE_NULL: {
//fix
break;
}
case MOST_ACTIVE_X: {
short threshold_x = (peak->max_x + peak->min_x) / 2;
if (slid->old_sample.acc_x > threshold_x && slid->new_sample.acc_x < threshold_x) {
step_cnt ++;
}
break;
}
case MOST_ACTIVE_Y: {
short threshold_y = (peak->max_y + peak->min_y) / 2;
if (slid->old_sample.acc_y > threshold_y && slid->new_sample.acc_y < threshold_y) {
step_cnt ++;
}
break;
}
case MOST_ACTIVE_Z: {
short threshold_z = (peak->max_z + peak->min_z) / 2;
if (slid->old_sample.acc_z > threshold_z && slid->new_sample.acc_z < threshold_z) {
step_cnt ++;
}
break;
}
default:
break;
}
}

简易下位机

参照我之前的项目,这次的下位机更加简单,没有头文件和结束语句,原因是max的串口我用的不是很明白,所以简化了


void fresh_s_time(char *temp)
{
   while(*temp != '\0')
  {
       switch(*temp++)
      {
case 'h':
hour = (*temp-'0')*10 + (*(temp+1)-'0');
temp+=2;
break;
case 'm':
min = (*temp-'0')*10 + (*(temp+1)-'0');
temp+=2;
break;
case 's':
sec = (*temp-'0')*10 + (*(temp+1)-'0');
temp+=2;
break;
     
      }
  }
}

上位机

也是和之前一样用的python编写

#-*- coding: UTF-8 -*- 

import serial # pyserial
import datetime

try:
   # 端口:CNU; Linux上的/dev /ttyUSB0等; windows上的COM3等
   portx = "COM3"

   # 波特率,标准值有:50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,57600,115200
   bps = 115200

   # 超时设置,None:永远等待操作;
   #         0:立即返回请求结果;
   #       其他:等待超时时间(单位为秒)
   timex = 5

   # 打开串口,并得到串口对象
   ser = serial.Serial(portx, bps, timeout=timex)

   # 写数据
   curr_time = datetime.datetime.now()
   result = ser.write(datetime.datetime.strftime(curr_time,'h%Hm%Ms%S').encode("gbk"))

   result = ser.write(datetime.datetime.strftime(curr_time,'s%S').encode("gbk"))

   ser.close() # 关闭串口

except Exception as e:
   print("error!", e)
   

程序流图以及各个模块

流程图v1.1

模块关系图:

逻辑关系系统框图

 

心得体会

关于max32660,由于有直接的接口函数,所以上手相对会快一些。官方提供了手册相关使用方法。虽然硬件IIC和常见的接口函数写的稍微有点不一样,不过在群里进行一系列的讨论以及别人的点拨后。也总算是能够上手了。

非常感谢电子森林和硬禾科技提供这样的活动,我的寒假过的非常的充实。也收获到了很多知识,如果不做这样类似的项目,可能是不会想到硬件IIC有这样的表达方式吧,哈哈。

附件下载
GPIO_Demo.hex
用于验证的文件
上位机.py
团队介绍
哈尔滨理工大学
团队成员
张辰
大三考研狗
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号