XMOVE3.0手持终端——综述:软硬件全部自行开发的彩屏体感控制器

编者注: X-MOVE是作者在业余时间于2010年6月份启动的以运动传感开发,算法和应用的平台,目前已经发展了三个版本,第四版的开发接近尾声。发布在博客园仅为交流技术,不存在商业目的,作者保留一切权利。

 

一. 综述

  乔布斯曾经说过:做软件的人应该也制造属于自己的硬件.

  不觉得每天给电脑,手机开发程序很不爽么? 为什么总是要"给别人打工",用别人的SDK? 小时候特别羡慕有文曲星的同学,也特别梦想自己做一个。

  在大四这个理想也成为了现实。 我启动了我自己的体感项目XMOVE的2.0版本开发,其中非常重要的一部分便是手持终端的设计,抱歉到现在都没有起一个好名字。它集中了我大学四年所学的大部分学习成果,全部软硬件自行制作。时隔一年,我将该子系统的软硬件分类进行介绍,并有详细的文章介绍大家比较感兴趣的几个部分。

   X-MOVE手持系统

 与XMOVE手持终端相关的介绍文章列表如下:

  系统综述: 自制的彩屏手持动作感应终端

  软件介绍(一):精简型嵌入式系统的菜单实现和任务切换  

  软件介绍(二):在2KB内存单片机上实现的彩屏GUI控件库

  软件介绍(三):在2KB内存单片机上实现的俄罗斯方块

  软件介绍(四):在2KB内存单片机上实现的超精简五子棋算法

  软件介绍(五):在2KB内存的单片机上实现的T9中文输入法

 

二. 基本硬件描述

  为了达到尽可能优质的硬件,我进行了四次PCB改板,耗费了不少资金(当然这是小事)。达到了以下的技术指标:

  外形尺寸:80mm(长)*60mm(宽)*25mm(厚)

  质量:67g(含电池)

  电池容量:760mAH

  工作电压:3.3V 充电电压:USB输入,5V

==========================================

  CPU:TI 超低功耗MCU: MSP430F149  @8MHz

  内存: 2KB RAM

  存储器: 内置64KB Flash, 外置2Mbit图形存储器

  传感器:三轴加速度计,三轴磁场计,三轴陀螺仪,气压计,实时时钟RTC

  无线性能:2.4GHz无线射频功能,支持理论最大通信速率2Mbps,实测最大177kbps

==========================================

  屏幕:320*240 2.4寸点阵LCD液晶屏(无触摸)

  物理按键:正面6个按键,背面五个辅助按键。

  LED:一路工作LED灯

  接口:一路USB转串口输出,一路串口(最大115200bps)一路调试JTAG接口

  一个机械开关

 =========================================

  物理续航能力:实测12小时连续工作

  充电充满时间:未进行实测

三. 软件功能综述

    1. 全新的体感功能:体感遥控器和内置的体感应用

  本系统设计之初就是为了体感功能,在硬件上,它搭载了几乎所有实用的MEMS传感器:加速度计,陀螺仪,磁场计和气压计,远远超越作者开发时期消费级传感器的应用水平。内部集成了动作识别和传感器融合算法,因此可以精准的识别用户的三个方向的加速度和角速度,以及准确的姿态。通过气压计,可以计算和输出海拔高度(由于天气变化,绝对值仅作参考,但相对精度可达0.25m)。

  作者在该系统的体感应用上做了两方面的努力:一方面,通过系统搭载的RF射频功能,作者将其与电脑实现无线连接,从而形成体感遥控器。

 

  •   基于体感的3D空中鼠标
  •   虚拟实景
  •   体感游戏控制器。 它作为XMOVE 2.0版中的中心节点,可以管理其他XMOVE节点协同采集人体运动数据,从而完成复杂的人机交互:例如全身体感的使命召唤,街头霸王,极品飞车等体感应用。(在XMOVE综述中有详细的介绍,有兴趣请点击这里)

  另一方面,作者在该平台上开发了诸多体感小应用。由于平台CPU和内存的限制(8MHz和2KB内存),这些应用简单而富有趣味:

  •   体感菜单:用户通过旋转系统,系统便会根据姿态移动光标选择相关功能,当需要退出时摇晃即可退出应用
  • 倾斜控制的俄罗斯方块,五子棋
  • 通过旋转和倾斜实现的虚拟全键盘:可大大弥补只有6个物理按键的不足
  • 体感旋转输入法,用户可以借助一个物理按键完成全部汉字和英文的输入操作
  • 楼层和高度检测:用户可通过该系统精确的检测高度变化,精度实测可达0.25m
  • 电子指南针和水准仪

   

  2. 超低功耗优化的精简OS以及GUI界面库

  系统搭载了作者亲自打造的嵌入式管理系统。具体的操作与实现在文集中有较详细说明。

  XMOVE手持终端界面系统

  为了在2KB单片机上尽可能高效的开发和重用代码,我实现了精简的管理系统和底层API封装。开发新应用只需声明相应的数据结构,调用相关API即可。完整的API包括了传感器控制和读写,无线射频协议,GUI界面库,中断管理操作。

  系统可以较好的管理来自键盘,RF,传感器等外部中断,并进行任务的切换和管理,在一定程度上满足实时性的要求。

  为了尽可能减小功耗,除了在CPU选用上使用了TI的MSP430系列,在软件上也使用了很多技巧:动态CPU速度调节,RF休眠,和可调屏幕背光。系统在运行时尽可能处于低功耗,在用户静默状态(无加速度)时间超过阈值时自动休眠,在用户拿起系统后自动启动,以获得远低于市面上手机的最低功耗:平均30mA.

  界面库对低频率CPU做了特别的优化,在显示上只刷新改变的部分,对图片做特殊处理,从而解决速度慢的问题。同时实现了较为人性化,使用方便的GUI界面库,具体请参考这里。

  3. 完善的系统管理机制

  除了以上的核心功能,系统提供了完整的用户接口:

  •   时间显示和时间设定功能
  • 传感器数据实时监视和校正
  • 背光时长和强度设定
  • 体感控制的设定选项
  • 可设置的无线频段和发射强度
  • CPU速度切换和管理
  • 电池电压监测和低电压报警
  • 用户管理:可设置开机密码。(真是闲的蛋疼的产物,还花了半个工作日调试)

   系统配置菜单

  用户可以根据需求动态的选择以上设定,并保存在可存储器中。

  4. 其他功能

  这些功能是作者在假期为了打发时光开发的应用,标记如下:

  •   SD卡读取和MP3,WMA播放功能:使用了外部扩展板,应用是作者独立开发的
  • 打砖块和贪吃蛇游戏

   想想这些功能花了我不少时间,到最后也仅仅是娱乐而已。

 四. 总结

  在博客园写文章养成的有综述有总结的坏习惯。

  这套系统是一个软硬件结合的案例,有其优点:软硬件开发结合紧密,互相优化。也有其缺点:封闭扩展性弱。如果还有时间,我希望能给它加入这些新功能:对文件系统的支持,多线程支持,多分辨率支持,彻底的硬件无关性,完整的无线组网协议包。

  这套系统(仅仅是本文介绍的手持终端,而非整个XMOVE)综合起来花费了作者大四一年近500小时的开发时间。由于要做PCB,要焊接,要在简洁的像文本编辑器的IDE中写代码和调试,与其他传感器的通信和协同,还要面对数不清的外部困难,最终还是完成了。

  对这个XMOVE平台的子项目而言,我本想做点商业开发的,但是,在整合和扩展才有希望的大环境之下,众多开源项目在坚持几年后都夭折了,何况是一个硬件限制极大,应用领域较窄,功能单一,接口封闭的子系统而已。也只能是作者闲暇时间的娱乐和锻炼编程水平的平台了。

  有这点时间,何不做点iOS应用发到网上赚个饭钱?哈哈。以后很难再有时间在嵌入式开发上再投入更多精力了,转战通信领域和.NET开发。

  有任何问题,欢迎随时交流。

  

 

  

  

  

 


作者:热情的沙漠
出处:http://www.cnblogs.com/buptzym/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


本文转自FerventDesert博客园博客,原文链接:http://www.cnblogs.com/buptzym/archive/2012/07/01/2570546.html,如需转载请自行联系原作者
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用 Kotlin 编写的 RecyclerView 左滑显示删除按钮并删除 item 的完整代码实现: 1. 在你的布局文件中添加 RecyclerView 组件和一个删除按钮的布局(在这里我们使用了 ConstraintLayout): ``` <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/delete_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorAccent" android:visibility="gone"> <TextView android:id="@+id/delete_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="8dp" android:text="Delete" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> ``` 2. 创建一个 RecyclerView 的 Adapter,并在 onCreateViewHolder() 方法中设置每个 item 的布局和点击事件。在 onBindViewHolder() 方法中设置每个 item 的数据,并添加滑动删除的逻辑: ``` class MyAdapter(private val list: List<String>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.itemView.setOnClickListener { // item 的点击事件 } holder.bind(list[position]) holder.itemView.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { // 记录按下的位置和时间 xDown = event.x yDown = event.y timeDown = System.currentTimeMillis() } MotionEvent.ACTION_MOVE -> { // 根据滑动距离和时间计算速度 val xMove = event.x val yMove = event.y val distanceX = xMove - xDown val distanceY = yMove - yDown val time = System.currentTimeMillis() - timeDown if (distanceX > touchSlop && Math.abs(distanceY) < touchSlop) { // 当滑动距离大于 touchSlop 时,显示删除按钮 showDeleteLayout(holder) return@setOnTouchListener true } else if (distanceX < -touchSlop && Math.abs(distanceY) < touchSlop) { // 当滑动距离小于 -touchSlop 时,隐藏删除按钮 hideDeleteLayout(holder) return@setOnTouchListener true } } MotionEvent.ACTION_UP -> { // 当手指离开屏幕时,根据滑动距离和时间判断是否删除 item val xUp = event.x val yUp = event.y val distanceX = xUp - xDown val distanceY = yUp - yDown val time = System.currentTimeMillis() - timeDown if (distanceX > touchSlop && Math.abs(distanceY) < touchSlop && time < clickTimeout) { // 当滑动距离大于 touchSlop,时间小于 clickTimeout,且没有上下滑动时,删除 item deleteItem(holder) return@setOnTouchListener true } else { // 否则,隐藏删除按钮 hideDeleteLayout(holder) return@setOnTouchListener true } } } false } } override fun getItemCount(): Int = list.size inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(data: String) { itemView.findViewById<TextView>(R.id.item_text).text = data } } private fun showDeleteLayout(holder: ViewHolder) { // 显示删除按钮 val layoutParams = holder.itemView.layoutParams as ConstraintLayout.LayoutParams layoutParams.width = holder.itemView.width - dpToPx(60) holder.itemView.layoutParams = layoutParams holder.itemView.findViewById<ConstraintLayout>(R.id.delete_layout).visibility = View.VISIBLE } private fun hideDeleteLayout(holder: ViewHolder) { // 隐藏删除按钮 val layoutParams = holder.itemView.layoutParams as ConstraintLayout.LayoutParams layoutParams.width = holder.itemView.width + dpToPx(60) holder.itemView.layoutParams = layoutParams holder.itemView.findViewById<ConstraintLayout>(R.id.delete_layout).visibility = View.GONE } private fun deleteItem(holder: ViewHolder) { // 删除 item list.toMutableList().removeAt(holder.adapterPosition) notifyItemRemoved(holder.adapterPosition) } private fun dpToPx(dp: Int): Int { val density = Resources.getSystem().displayMetrics.density return (dp * density).toInt() } companion object { private const val touchSlop = 10 // 滑动的最小距离 private const val clickTimeout = 200 // 点击的最大时间 private var xDown = 0f // 按下的 x 坐标 private var yDown = 0f // 按下的 y 坐标 private var timeDown = 0L // 按下的时间 } } ``` 3. 在 Activity 或 Fragment 中使用 RecyclerView 和 Adapter: ``` class MainActivity : AppCompatActivity() { private lateinit var recyclerView: RecyclerView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView = findViewById(R.id.recycler_view) val list = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5") recyclerView.adapter = MyAdapter(list) recyclerView.layoutManager = LinearLayoutManager(this) } } ``` 这样,你就可以实现一个带左滑删除功能的 RecyclerView 了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值