- 这篇文章是机器人实验课的项目记录。这个项目的目标是制作一个校园雨伞租赁系统,师生只需要刷校园卡就可以从伞架借走一把伞,还伞的时候只需要刷卡就可以归还。功能看起来很简单,但让这个系统稳定合理的工作却花了我不少时间。
## 系统的工作流程 1. 用户需要在借伞前注册自己的IC卡信息,否则会在刷卡时提示该用户未注册,不能享受此服务。用户刷卡后读取IC卡信息,当确定该用户没有恶意不还伞记录并且之前没有借过伞后,会同意该用户的借伞请求,打开锁伞设备的开关,记录该用户已借伞。 2. 用户刷卡还伞时,同样打开开关,提示用户将伞放入设备内,确认放入后,关闭开关,此时若有开关无法正常闭合,或者检测出设备内物品与标准伞有出入,会提示用户重新放伞,直到检测到标准伞正确放入,记录用户已还伞。 3. 若用户在还伞截止时间前并未还伞,则将该用户列入黑名单,不再为该用户提供借伞服务。
P.S 目前还伞的检测还没有做,现在是还伞刷一下卡系统开锁,开完锁就会认为你把伞还了,我相信大家还是比较有素质的(´・_・`),附上一张很早以前画的流程图:
系统的硬件设计
硬件组成
- Raspberry 2B+
- RFID读卡模块
- 稳压电源模块
- 电磁铁
电路设计
由于Raspberry Pi本身已经集成了各种各样的引脚功能,所以电路设计上就没有很多值得提的地方。
220v交流电压输入经过稳压电路得到5v直流电压给Raspberry Pi和RFID读卡模块供电,12v直流电压提供给电磁铁。Raspberry Pi提供3.3v的高电平控制MOS管开关电磁铁回路。我主要负责软件,这些电路的事情就交给靠谱的小伙伴们了。
系统的软件设计
- 软件设计部分是我负责的,所以我尽量说的详细一些。
软件环境
- ubuntu 14.04 for ARM
- wiringPi
- MySQL
系统工作流程的再探究
租赁系统看起来很简单,要弄清楚的无非是下面的这几个问题:
- 来者何人?
- 借还是还?
- 能借给他不?
首先我们分析第一个问题:判断用户身份由很多种方法,我们选择了较为经济的一种方式—在食堂,水房,门禁随处可见的射频读卡技术。我们只需要阅读购买的RFID读卡模块的使用文档,由串口即可获得ID的信息,通过比对ID,第一个问题解决了。
第二个问题看似很无脑,但事实上正是为了可靠的解决第二个问题,我们需要多写50行左右的代码使用数据库。解释下使用数据库的原因:数据库的数据是存在硬盘(Raspi是SD卡)里的,而程序运行过程中开辟的空间是存在RAM里面的。如果我们不能把用户的借出归还标志存入磁盘,断电重启系统后会丢失数据。举个例子:老王昨天借了把伞,借完就停电了。第二天准备去还伞的老王看到机器又扔给他一把伞。这显然是需要避免的情况。而数据库技术很好的解决了这个问题。
第三个问题讲的是规则设定。在我们的系统中借伞时间超过两天则会被视为违规,取消你借伞的权利。为了便于课上演示,在实际程序中我调用的系统时间是分钟级,也就是借伞超过两分钟你就被ban了。
### 数据库的设计 数据库选用了比较流行的MySQL,具有良好的C语言接口。下面是数据库的建立过程: 首先在终端中连接数据库,并创建umbrella_db的数据库。
mysql -u root -p
create database umbrella_db
;
由于下面的这个语句比较长,所以我们写一个小小的脚本来生成users表,建立createtable.sql
文件,内容为:
|
|
之后在MySQL控制台输入source createtable.sql
即可,注意文件路径。
建立成功后的表单如图所示:
程序设计
为了可能存在的读者按顺序贴代码,便于有兴趣的朋友验证:
这里是代码的头文件和变量定义部分,由于这个系统实在是太小了,没有采用分文件的形式,或者cpp面向对象的编程风格。time.h
包含了我们需要使用的操作系统时间的函数。wiringPi.h
和wiringSerial.h
是raspi的函数库,可以它们来控制pi的GPIO和串口功能,用于读卡和电磁铁的开关电路控制,也是软件和硬件之间的桥梁。mysql.h
提供了丰富的MySQL数据库的C语言APi,我们可以方便的通过C语言操作数据库。
全局变量主要有一个用户结构体:包含了用户ID、借还状态、姓名、借出时间四个成员。还有一些MySQL的结构体。他们使用全局变量的原因在于几乎所有的函数都在使用他们,在函数间传递反而会让程序变的冗长。
|
|
这里是解决上述所谓问题1的代码,传入值为一个指针指向数组的首地址。这个值将由串口读回的数据传递。在系统启动时将数据库中的用户信息加载入内存,存入User[]
数组结构体。这个函数遍历了所有数据库中用户的ID并和传入的数组比较,若配对成功则返回用户编号,配对失败返回-1。
|
|
这是解决所谓问题3的代码,传入两个参数,借伞时间和还伞时间。若还伞时间与借伞时间相差的数值大与2,则认为违规。在tm
结构体中p->tm_min
表示离当前小时0分钟的时间。若遇到整点前借伞整点后还伞的情况,两值之差为负数,只验证还伞时间是否大与2即可。我们将用户初始时间均置为1000。在用户时间值为默认的情况下不会认为用户违规。
|
|
连接数据库的函数,不用多说,每次对用户进行信息修改的时候都必须调用。如果连接不成功则返回-1并输出连接错误原因。
|
|
读数据库信息函数。在程序启动后调用,rc = mysql_real_query(&mysql, query_str, strlen(query_str));
提交请求,如果请求成功,则数据库的值会存放在row
这个变量中。我们按照之前定义的数据库规则用户结构体赋值。完成后断开连接,返回整型数1。
|
|
写数据库用户状态函数。传入参数为要修改的用户序号和用户借还伞的状态。我们需要构造相应的MySQL语句来实现对应的功能。在这里我使用了 strcpy(*str1,*str2)
函数来连接字符串。将完整的MySQL语句分为下面四部分:UPDATE users SET return_state=
,*re_state
,WHERE id_0=
,id
,其中id使用sprintf(temp,"%d",id+1);
转换为字符串,连接后提交请求,验证成功后断开数据库连接。
|
|
和上面的内容几乎完全一样,只是将借还表示更改为了时间。
|
|
用户功能部分,也是上面函数综合使用。传入用户序号和借还标志。首先判断用户是否被ban和用户借还伞,若借伞则屏幕显示相应内容,写数据库借伞标志,写借伞时间。若还伞屏幕显示相应内容,数据库写还伞标志,置时间为默认(1000)。结束后调用GPIO功能,打开相应位置的锁扣。
|
|
主函数部分,首先初始化GPIO功能,打开串口,给串口模块发自动读卡指令,打印一些无关紧要的信息,好像很炫酷的样子。在循环部分,检测读卡信号,上升沿触发。读串口数据,首先验证ID,若未注册显示相关信息。若比对成功就按照上文提到的流程处理。
小结
系统的运行图如下:
这里用LED小灯来测试GPIO电平翻转是否正确 >最后感慨一下:大概就是去年的这个时候我有了自己的Raspberry Pi,当时用了
RPi.GPIO
点亮了一盏小灯就开心的不行。现在终于可以熟练的使用Pi的两个GPIO库,可以自己用它做一个小系统了。当然做这个系统遇到了不少困难,好在Linux编程资料不少,