MiNLabSys搭建和各种坑

MiNLabSys是宁波中学创客空间实验室系统的简称
该系统目前已实现中央服务器和门禁系统的部分功能(虽然完成度很低orz)
介绍和代码请移步GitHub:
MakersInNingZhong/MiNLabSys-Server
MakersInNingZhong/MiNLabSys-Door

本文主要着重于搭建该系统时遇到的各种坑


好了按惯例先扯上一会儿 跳过就好w
好久不见 我(大概)来月更了orzzz
临近期末事情越来越多 各种比赛和社团要收尾 根本没时间刷SICP和习题
更何况我又入了C++ Premier Plus的坑
所以.....................
SICP的第一篇读书笔记可能要鸽很久很久啦(大概高三暑假)(你还真有脸说)
当然习题还是会抽空刷的 在GitBook上不定期诈尸Exersices Solutions of SICP
公开课也一直在刷 虽然每天看不到十分钟就要睡觉了orz

真紧张明天我的桌子和椅子就要参加高考了
看了一下ZUI DAYS
还有88天物竞
还有131天选考
还有365天高考
时间有时候真是令人生厌

物理还是没有进150名
不过暑假要去质心决赛班 终于可以亲眼见到蔡子星啦嘿嘿嘿
我爱物理我爱物理我爱物理我爱物理我爱物理我爱物理我爱物理

物理免修后多出来五节自修课最近浪得很开心 刷刷题看看书泡泡实验室什么的
但不知道为什么时间还是那么少 事情还是那么多

不知不觉扯了这么多orz 还是回归一下正题吧

人生中第一次在Github上写这么长的英文README
人生中第一次Arduino写多文件模块化程序(没有用类啦因为觉得没必要orz)

这个项目史无前例地遇到了各种巨坑 坑多到报警
到现在都还没有完全解决(大概也没空解决了呃)

其实本来这个项目是很宏大的 还计划了智能窗帘、智能橱柜、分布式传感器系统
但因为人手和时间的原因 可能就只能这样了....
创客空间也没几个人真正在做事情 无奈

这个项目目前已经参加了宁波中科院创客空间举办的比赛 相关参赛视频和链接什么的在文末

好了 接下来 我们谈谈各种坑


服务器部分

来张(半)全家福

从左下到右上分别是 ESP8266、MFRC522、Arduino Uno、Banana Pi

服务器部分我采用的是香蕉派(最经典的那款)(也就是最弱的那款)(连板载WiFi都没有)
没错 就是这么简单的一个node应用 我都遇到了巨坑
而且第一个坑就是在安装node上

首先说明 我用的系统是32位的Raspbian jessie for bananapi
在安装之前 我就看见网上大佬们各种警告 不要用包管理器安装
那好吧 那就下载源码编译吧
可我万万没想到的是 我光make就花了整整一天的时间
喵喵喵???
更可怕的是 我make install了整整一天都没装上.....
CPU一直跑在100%但我并不知道它到底在干啥 只能^C了
最后 我是下载了别人编译好的二进制包才成功装了上去

第二个坑是对这次开发影响最小的但是让我感受到了绝望
我本来想打算借着这个项目接触一下MongoDB
于是我在开始做之前看了大半个月的教程和文档
好了你们应该猜到什么了吧
MongoDB只支持64位系统!!!
这只香蕉派只有32位系统镜像!!!(至少我没找到64位)
那好吧 我大半个月只能算白看了 毕竟再次应用肯定不知道要等到什么时候去到时候肯定早就忘了
于是只能屈服于MySQL 安慰自己关系型数据库挺好的 稳定安全又好弄(雾)

第三个坑是一个十分naive的坑(咳)
node和mysql连接的库只有英文文档 还写得有点乱糟糟的
我修改了一下复制的示例 然后发现如果查询命中就没问题 但如果没有命中就会报错 直接退出
当时以为是库的原因 没有命中就throw error
然后就各种看文档和怀疑自己的英语水平
直到我看见了if(err) throw err;
........
于是我神经错乱到在回调函数外写了try-carch..........
然后我看到了错误提示Cannot read property of undefined
.................
我可能是要重新学一遍js
总结:

  1. 类型检查一定要做 尤其是和数据库相关的时候
  2. 遇到错误千万要仔细读几遍 确定了错哪再去调bug
    不过这次是因为由于error是在回调函数里面被抛出 所以错误信息被模块又封装了一层所以特别不起眼orzzz

迈过了三座大坑 我写完了服务端
但是 我万万没有想到的是 这还只是个开始......


客户端部分


MFRC522和ESP8266

调MFRC522一切顺利 用了@miguelbalboa的库
谢天谢地 这是我最靠谱的时刻

然后就是ESP8266了 这家伙真我是见过的最难调的模块
尤其是当你一开始没有开软串口来调试的时候
(不要问我为什么不用软串口连ESP8266 软串口波特率最高只有9600...)

我这个项目是使用HTTP协议完成客户端和服务端的通信
数据交换格式是json
这也是我整个项目最作死的地方......

数据只有十几二十字节 但加上了HTTP头瞬间变成了两百字节...
然后Arduino就瞬间爆炸
什么串口缓冲区溢出啦 内存不足啦 全都来了
关键是这个错误没有报错一开始还意识不到 白做了很多debug尝试

第一个坑就是串口缓冲区溢出
而且这个坑让我明白了 什么叫做为什么调通了程序都不知道自己做了什么操作

一开始我读取数据时 使用的函数大概是这样的

1
2
3
4
while (ESP8266.available() > 0){
msg += char(ESP8266.read());
delay(4);
}

然后一般只接收到70来个字节就收不到了(Arduino默认缓冲区只有64字节)
很显然是缓冲区溢出了

但很神奇的是 我把缓冲区调大也并没有什么卵用 消息始终收不全
尤其是当我把缓冲区调到256字节以上的时候 毛都收不到了.........

没办法 我只能从接收函数下手了
我怀疑接收函数一个一个字节实在太慢了尤其还停顿了4毫秒(虽然我把delay注释了也读不全虽然会稍微好一点)
然后我就看文档有没有直接收整个缓冲区的函数 于是我看到了readString
虽然这个操作把我带向了另外一个深坑

于是我的接收函数就变成了这样

1
2
3
4
5
6
7
8
9
10
void ESP8266_ReadData(String& temp, int delay_time = 4) {
#ifdef USE_DEBUG_MODE
DEBUG.println("Reading data...");
#endif
while(!ESP8266.available());
while(ESP8266.available()){
temp += ESP8266.readString();
delay(delay_time);
}
}

看上去非常正确是不是 可还是不行
但当我把缓冲区调到128字节的时候就特喵的行了......
work perfectly
这让我很绝望....
到底是为什么orz

第二个坑又是文档的问题
我在用ArduinoJson库的时候 用了DynamicBuffer
可谁知道DynamicBuffer是不会自动释放的......
于是立马内存溢出 运行几轮后就程序错乱
当时不是很肯定是ArduinoJson的问题
而且我又看了两遍文档也注意到什么 直到我搜了Issue才解决
只要把DynamicBuffer定义在全局就行了
可这么重要的事情为什么就不能写在文档里呢
要么是我太小白了?(非常有可能orz)

好了 来到最后一个巨坑 内!存!不!足!
对这个巨坑 我想到的唯一办法就是上Arduino Mega2560
实在解决不了了

为了解决第一个坑 我(迫不得已)用了String类(或者说只是因为懒而已String用起来好方便啊qwqqqq)
然后?然后内存就炸了

虽然明明我删掉了所有调试信息后烧进去提示只占用了30%左右的内存
可能我局部String用得实在太多了吧
逼得我传String只能传引用(这才是正确的写法好吗直接返回String是真的非常小白的做法) 于是程序终于勉勉强强地跑起来了

但是接下来就是我最绝望的时刻
因为这个程序 它不稳定
不稳定到什么程度呢
你完全不知道什么时候它是正常运行的
有的时候完全没法用
有的时候只能跑一轮两轮
极少数时候能一直正常运行
所以我按了无数遍的重启.........
最难受的是我还看不见调试信息 为了省内存....

总结:没事别拿Uno折腾自己 该上Mega就果断上 不要和内存优化死磕 尤其是当你还在用String类的时候


其实还踩了很多很多小坑 但这篇充满吐槽风格的文章还是就到这吧
已经毛4000字了....第一次一口气写这么多....

好了 最后附点视频

调试信息还活着的时候拍的演示视频

最终的比赛视频

晚好
2017/6/7 20:30
LEAFERx

如果这篇文章对你有帮助,那么不妨?
0%