blog/insect-robot

这是我发表在无线电杂志上的文章《用微信小程序遥控一只蟑螂》的原稿。据说发表后文章的版权依然在作者手里,所以把这篇放在我的博客上。我不是很懂相关的法律;所以不同于这个博客下的其他文章,这篇文章不授权他人进行再分发;本人保留一切权利。

多图。如果你正在使用蜂窝数据,请留意。

如何遥控一只蟑螂

项目地址:github.com/chuangzhu/insect-robot
作者:朱创

之前看到了 Backyard Brains 这样的一个项目,觉得很有趣,看到其高昂的价格后决定自己做一个。取名为 Insect Robot。硬件部分采用 AVR 作为主控芯片,因此兼容流行的 Arduino 平台。手机控制端则采用了更加方便的微信小程序。

基本的思路是,给蟑螂做一个小设备背在背上,并将蟑螂的触角连接至设备。手机蓝牙连接,给设备发指令使其刺激蟑螂的触角。蟑螂受到刺激后就会往相反方向爬行。

本项目是开源硬件项目,所有程序与设计文件都在代码库中可以找到。要获取一份代码库,打开项目地址,点击右侧绿色的 Clone or Download 按钮,选择 Download ZIP 下载压缩包,解压即可。

硬件

下表列出了主要使用的元件,比较普通的元件(如电阻、电容、排针等)以下并未列出。

元件型号说明
ATmega168P主控芯片
PW0316低功耗蓝牙模块
MSK-12C02拨动开关
FPC 6 pin 连接器用于 ICSP 下载程序和充电
041020 锂电池充电板接入 FPC 连接器可充电
0603 彩色 LED显示一个颜色,用于区分
0603 排阻 470Ω用于给 LED 限流

电路板使用 Eagle PCB 设计,CAM 处理为 Gerber 文件后发至 PCB 打样厂制造。

电路图

等效面包板图

电路板布线

电路板

成品

除了这个电路板外,还要将 3 pin 排针座和 3 根银丝焊在一起,做一个蟑螂和设备的桥梁。银丝将被植入蟑螂体内,排针座和电路板之间可插拔,这样蟑螂可以脱下设备,正常地生存。为什么不用铜丝呢?铜在与液体的交界处通电时易被氧化,释放出铜离子,这对于生物是有毒的。

固件

前面说过,主控芯片采用的是 AVR,因此兼容当下流行的 Arduino 平台。我既写了 AVR GCC 的 C 语言程序,也写了 Arduino 程序。为了方便读者理解,下面使用 Arduino 程序介绍。

连接手机和设备使用的是低功耗蓝牙(Bluetooth Low Energy,BLE),它和经典的蓝牙有很多区别。经典蓝牙以文件为最小传输单位,而 BLE 以字节为最小传输单位。具有蓝牙 4.0 模组的手机可兼容 BLE,作为主机连接 BLE 设备。BLE 中有设备、服务、特征三个基本概念,其中特征是承载和与其他设备交换数据的容器。下图显示了三个概念之间的关系:

graph TB
dev(BLE 设备)--- serv1[服务]
dev --- serv2[服务]
serv1 --- char1[特征]
serv1 --- char2[特征]
serv2 --- char3[特征]
serv2 --- char4[特征]
serv2 --- char5[特征]

(一个设备包含多个服务,一个服务包含多个特征)

为了区分不同的设备、服务、特征,这三者的每一个实例都有各自的 UUID。UUID 是一串十六进制数,比如 0000FFE5-0000-1000-8000-00805F9B34FB

这个项目使用的 BLE 模块是鹏为物联的 PW0316,它将主机写入服务 FFE5 中的特征 FFE9 的数据转化为串口数据,输出到自己的 TX 引脚;将 MCU 输入到模块 RX 引脚的串口数据放在服务 FFE0 中的特征 FFE4,供主机读取。这样的传输叫做透传。

除了透传,PW0316 还支持通过 “AT 指令” 更改它的一些属性,比如说名称、密码、厂家自定义广播信息等。这样的指令同样通过串口告诉 PW0316,比如发送 TTM:REN-xxx 意思是重命名模块为 xxxTTM:ADD-xxx 意思是设置广播信息为 xxx

“厂家自定义广播信息” 是 BLE 的一个功能,它在连接设备之前就可以被读取。可以将设备的一些属性、状态放进去。我一开始想着要搞很多只,然后找几个人举行一场比赛什么的。所以我在电路板上设计了一个彩色 LED,开机时随机显示一个颜色,并把这个颜色通过 BLE 广播出去。这样手机端就可以显示出与设备匹配的颜色,对不同的蟑螂进行区分。

产生一个随机颜色的 Arduino 代码:

char ledColor[3];
for (int i = 0; i<3; i++) {
    // 使用模拟输入引脚读数作为随机种子
    randomSeed(analogRead(3) + analogRead(6));
    ledColor[i] = random(256);
}
analogWrite(5, ledColor[0]);
analogWrite(6, ledColor[1]);
analogWrite(11, ledColor[2]);

将这个颜色广播出去的代码:

Serial.begin(9600);
delay(128);
// 写入 AT 指令前缀
Serial.print("TTM:ADD-");
//写入颜色
Serial.print(ledColor);
// 给时间让 BLE 模块处理一下
delay(255);

手机连接成功后,要控制蟑螂就要对设备发送信息。这里我规定设备接收到 EL:LLL 则启动左边的电极,刺激蟑螂的左触角,使其向右行走;反之 EL:RRR 刺激右触角,使其向左走。

const int LEFT = 9;
const int RIGHT = 10;
String inString = ""; // 用于储存接收数据
// 该函数在串口接收到数据时被调用
void serialEvent() {
    while (Serial.available()) {
        // 读出收到的字符
        char inChar = Serial.read();
        // 将字符加入字符串
        inString += inChar;
        if (inString == "EL:LLL") {
            inString = "";
            impulsePin = LEFT; // 左电极
            pinMode(impulsePin, OUTPUT);
            impulse = true; // 开始电击
        } else if (inString == "EL:RRR") {
            inString = "";
            impulsePin = RIGHT;
            pinMode(impulsePin, OUTPUT);
            impulse = true;
        }
    }
}

微信小程序

为什么要使用微信小程序做为控制台呢?首先是因为它是跨平台的,同时支持 Android 和 iOS;其次是因为小程序的使用不用安装,展出时谁想体验扫一下二维码即可。扫描以下二维码就可以打开该控制端小程序:

微信小程序本质上就是 HTML 5 网页,只不过简化了一些语法,赋予了开发者更多 API 而已。微信小程序使用了 Vue.js 技术来取代传统 DOM 的 document.getValById,这种技术在 HTML 结构中标记 {{label}} 字样,然后在 JavaScript 中使用 this.setData({ label: '内容' }) 的方法更改 label 的数据。因此微信小程序 API 函数要求传入的参数为一个 JavaScript 对象,这个对象要包含参数和处理成功调用的处理函数,就像这样:

var self = this
wx.openBluetoothAdapter({
    fail: function (res) { // 处理错误
        self.setData({ label: '蓝牙适配器打开错误' })
        console.log(res)
    },
    success: function (res) {
        self.setData({ label: '成功打开蓝牙适配器' })
    }
})

我们这里用到的就是低功耗蓝牙 API。它的主要函数包括:打开蓝牙适配器 wx.openBlueToothAdapter(),开始搜索蓝牙设备 wx.startBluetoothDevicesDiscovery(),连接 BLE 设备 wx.createBLEConnection() ,获取 BLE 服务 wx.getBLEDevicesServices(),获取 BLE 特征 wx.getBLEDeviceCharacteristics(),写入BLE 特征 wx.writeBLECharacteristicValue()

要发送数据到设备,小程序 API 需要使用一个 ArrayBuffer 对象。比起字符串,ArrayBuffer 更加接近于机器层面,它相当于 C 语言中 malloc 出的一块内存。我们无法直接操作这个对象,但可以通过以下函数将字符串转化为 ArrayBuffer:

function str2buf(str) {
    var buf = new ArrayBuffer(str.length)
    var bufView = new Uint8Array(buf)
    for (var i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i)
    }
    return buf
}

然后将它发送到设备的特征中:

var self = this
wx.writeBLECharacteristicValue({
    // 设备的 UUID,在搜索设备时得到
    deviceId: self.connectDev,
    // 服务的 UUID,通过 wx.getBLEDeviceServices 得到
    serviceId: self.txService,
     // 特征的 UUID,通过 wx.getBLEDeviceCharacteristics 得到
    characteristicId: self.txCharacter,
    value: str2buf('EL:LLL'),
    success: function (res) {
        wx.showToast({
            title: '操作成功',
            icon: 'none'
        })
    },
    fail: function (res) {
        wx.showToast({
            title: '操作失败', icon: 'none'
        })
        console.log(res)
    }
})

前面说到了使用 BLE “厂家自定义广播信息” 广播颜色的想法。小程序的 BLE API 接收广播信息时返回的也是一个 ArrayBuffer 对象,可以通过以下函数把它转化为表示表示十六进制数的字符串:

function buf2hex(buf) {
    var res = ''
    for (var x of new Uint8Array(buf))
        res += ('00' + x.toString(16)).slice(-2)
    return res
}

然后就可以将这个颜色设置到 CSS 样式中显示出来:

<block wx:for='{{devList}}'
       wx:for-item='devItem'>
    <!-- devItem 是 devList 中的一项 -->
    <button bindtap='devClick'
            style='background-color: #{{devItem.color}};'
            id='{{devItem.id}}'>
        {{devItem.name}}
    </button>
</block>
var self = this
//发现设备时的相应事件
wx.onBluetoothDeviceFound(function(res){
    //将找到的设备加入数组
    for (var item of res.devices) {
        self.devList.push({
            name: item.name,
            id: item.deviceId,
            color: buf2hex(item.advertisData)
        })
    }
    // 将数组设置到页面上
    self.setData({ devList: self.devList })
})

最后一步

当然是把这个东西安装到蟑螂身上,首先我们得选择一种蟑螂。家中常见的蟑螂为美洲大蠊或德国小蠊,繁殖能力强并且会携带疾病,我们当然不会选择这样的蟑螂。常作为宠物或宠物饲料的蟑螂品种有樱桃蟑螂、杜比亚蟑螂和马达加斯加发声蟑螂。其中杜比亚蟑螂体长可达 4 cm,马岛发声蟑螂体长可达到 7 cm,是用于控制的理想对象。

我们要给蟑螂进行一个小手术,首先我们得麻醉它。昆虫是变温动物,没有自身调节体温的机制。环境温度较低时,它们会进入冬眠。找一杯冰水,将蟑螂泡在其中,2~5 分钟就乖乖地一动不动了。一开始我没找对方法,将蟑螂直接放在冰箱中冷藏,结果常温下不一会儿又恢复活蹦乱跳的了。找到方法前,为了让它安静下来,真的是把全家都用上了(非常感谢母亲的支持)。

彻底麻醉后,用万能胶水将排针粘在蟑螂的头上。在约 1 厘米处剪断触角,小心的将两侧的银丝插入它的触角,并用胶水固定。

然后将中间的银丝植入蟑螂的翅膀下面、“脖子” 后面,它将作为地线发挥作用。可以用硅橡胶最后固定一下排针。

我搞了很多只,在学校科技节举办了一场 “比赛”。因为一些突发状况(蟑螂触角突然挣脱银丝之类的)比赛时可以被遥控的蟑螂变得很少。加上学校平时不允许使用手机,现场参加的人很少,旁观者却较多。其实可以再制作一个 “蓝牙遥控器”;背上的电路板如果去除一些无用的功能,缩小电池容量,还可以做得更轻。总之还有改进的空间。

伦理问题

这一段是我放在我的博客上之前加上的。互联网的环境和杂志上的环境有所不同,因此我必须事先作出相关声明。

这个问题 Backyard Brains 有声明过,让我粗略地翻译其中的一部分:

When working with animals in science, one has to calculate a "cost/benefit ratio". Meaning, what is the cost to the animal vs. what is the benefit from the experiment.

使用动物进行科学研究时,研究人员必须确定 “伤害与获益的比例”。即,对动物的伤害有哪些,实验带来的益处有哪些。

We actually do not know if insects feel pain during leg removal, but we make the assumption that they would if they were not anesthetized. Whether the insect feels pain when it wakes up from the surgery and detects a missing leg, we do not know. All we is know is that the wound does heal, and that the cockroaches are walking around within hours, eating lettuce, drinking water crystals, and making more cockroaches. This is the same behavior as our other cockroaches. We therefore conclude that the cost to the cockroach is relatively low.

事实上我们不知道昆虫在被切掉腿时会不会痛,但是我们假设它会。我们也不知道昆虫从手术中醒来后会不会痛,会不会发现自己少了一条腿。我们只知道它的伤口会愈合,蟑螂几个小时内就可以正常地走动、吃生菜、喝水以及繁殖。这和其他蟑螂的表现一致,我们因此推断实验对蟑螂的伤害相对较小。

We live in a society where 25% of the world is affected by a mental or neurological disorders at some point in their lives (source: World Health Organization) and there are no known cures. ... Most people do not have even a basic understanding of how the brain works.

我们生活的社会中 25% 的人都或多或少地受过心理上的或神经学上的紊乱影响,但我们没有已知的治疗方法。...... 而多数人对大脑如何工作连最基本的了解都没有。

These courses are taught to neuroscience graduate students who have already decided to focus their studies on the brain. The rest of society are left with a poor understanding of how the brain works, and more importantly are not aware of a vast field of neuroscience research that needs our brightest minds to advance.

这些(神经学)课程只教给早已决定了要潜心研究大脑的神经学研究生。而社会上的其他人却对大脑如何工作了解甚少;更重要的是这些人没有意识到,神经学研究的广阔领域需要我们最精明的头脑才能发展。

... we feel the benefit to society is high.

...... 因此我们认为(这些实验)对社会的益处是较高的。

About Me