疫情宅家琢磨好玩的东西改善自己的课余生活和心理健康的时候偶然发现了 Arduino 这个东西。作为软件出生的人来说比较常听到的是 Raspberry Pi,这个东西其实就是一个比较小比较便宜的电脑板子,里面有一个完整的 Linux 系统,一方面来讲它的功能更强大,就是电脑能做的它都能做,但另一方面似乎也让它觉得有点鸡肋,比如如果家里已经有电脑了,为啥要用它?也许做一些简易机器人或者小车子之类的时候会比较有用,但是我看网上介绍的一些常见的 Raspberry Pi 的 project,诸如做一个家庭的媒体服务器之类的,如果家里已经有台式机或者空余电脑的话,就比较牵强。当然,也许它的主要目的不是有多大的实用价值,而是让大家能动手去玩,起到学习、玩耍和提升兴趣之类的。
相比起来,Arduino 是一个更加底层的东西,并没有一个完整的操作系统跑在里面,所以做简单的事情 overhead 没有那么大,而且没有 USB 供电的时候用普通的 5V 电池就能驱动。此外定制的过程除了编程之外,还需要通过面包板用线把不同的针脚接起来,或者甚至直接用焊锡焊起来,对我来说是比 Linux 编程更加未知的领域,所以听起来更好玩一些。
上图是三个 Arduino 板子(其中有两个已经做成了蓝牙小键盘加上了按钮)和一些乱入物件的体积对比。Arduino 板子的类型比 Raspberry Pi 要多很多,不过如果作为入门上手的话,在亚马逊或者其他很多网站上都能买到各种不同的 starter kit,提供板子和相应的各种小零件(线啊、LED 小灯、面包板、各种 sensor、按钮之类的),并且会附送一个包含几十个入门项目的 tutorial 文档和相应的 code,让你上手了解操作流程,以及可以用板子来做些什么事情之类的。比如我入手的 starter kit 里有湿度计、加速度计、超声波距离探测之类的 sensor,还有小马达、摇杆按钮、红外遥控器之类的输入设备。
Arduino 板子有一些针脚可以提供数字或者模拟信号的输入和输出,用面包板或者直接插线的方式把板子跟 sensor、以及输入和输出设备接起来,然后就可以通过写程序来读取 sensor 或者输入设备的数据,进行处理之后再通过输出设备给出反馈了。虽然 Arduino 不是像 Raspberry Pi 那样有整个操作系统,但是它是一个 microcontroller,并不需要写像 Verilog 那种程序,如果用 Arduino IDE 的话,基本上可以用 C++ 来写程序。例如下面一段代码:
- // Define Pins
- #define BLUE 3
- #define GREEN 5
- #define RED 6
- void setup()
- {
- pinMode(RED, OUTPUT);
- pinMode(GREEN, OUTPUT);
- pinMode(BLUE, OUTPUT);
- digitalWrite(RED, HIGH);
- digitalWrite(GREEN, LOW);
- digitalWrite(BLUE, LOW);
- }
展示了如何控制一个彩色 LED 灯,把 LED
灯代表红绿蓝输入的三个针脚分别接到程序中常量指定的 pin
上(把接地的针脚也接到板子的 ground 那里),然后在 setup
函数中设置好三个 pin 为输出模式,就可以通过 digitalWrite
写入使 LED 显示红色。板子在初始化的时候调用 setup
函数,之后会不停地调用 loop
函数,在 loop
函数里就可以写一个循环来更新 LED 灯的颜色(用 analogWrite
可以写入 0 到 255
之间的颜色值,三原色组合起来就可以形成很多种不同的颜色),或者查询某些接到板子上的按钮或者
sensor 的状态来设置 LED 灯的颜色之类的。
总之具体做什么玩意就看自己的想象力了,对于熟悉软件开发的人来说,可能这种混合程序和接线的方式更有种“动手玩”的感觉。不过总体来说还是玩的成分更大一些,如果真的要做出比较实用的东西,感觉还是相当费劲的。
不过最开始下决心玩一玩 Arduino 其实也是基于一个比较实际的需求:Procreate Art Keyboard。Procreate 是一个非常棒的 iOS 上的绘画 app,配合 Apple Pencil 使用简直是最棒的体验,当然其强大和灵活性方面还和桌面电脑上的重量级程序还有一点差距,但是 iPad 随手拿起来就可以开始画,和电脑要接数位板,一大堆线,还要启动程序之类的相比就太无阻力了。但是 iOS 是一个比较新并且非常封闭的系统,所以其灵活性非常有限。
在绘画(或者其他相关的诸如照片处理、视频编辑之类)相关的工作流程里有一个非常重要的元素就是快捷键:比如在笔刷、橡皮、选择工具之间快速切换,快速调整笔刷大小、透明度,快速取色、选色等等,对于绘画流程的流畅程度影响很大。在使用电脑进行绘画的时候有很多辅助工具可以选择,比如老牌的 Wacom ExpressKey(下图左上)有按钮可以触发快捷键,也有旋钮可以触发连续值改变(比如笔刷大小),可以针对不同的软件分别定制;比较新颖的也有 Surface Dial(下图右上),硬件上就是一个 dial,但是配合软件实现也有非常高的可定制性,不过 Surface 弃用 Wacom 开始用自己的压感笔技术之后许多年一直没有改进,写字记笔记还可以,画画感觉就不是特别胜任。下图右下是 Razer Tartarus V2 单手键盘。特别是 Razer 的单手键盘,本身是设计来给电脑游戏玩家用的,但是由于桌面操作系统的开放性,导致很强的可定制性,于是各种不同的设备和程序都可以结合起来使用,比如这里我们就可以通过定制单手键盘的按键来映射到 Photoshop 或者其他绘画程序所使用的快捷键上来实现想要的功能。此外,桌面操作系统还允许有诸如 AutoHotkey 之类的程序来对快捷键做更高的定制,比如根据上下文来判断触发什么样的行为。
相比之下 iOS 简直是封闭系统之典范,比如时至今日外接键盘仍然是无法使用第三方输入法的。回到画画的问题上,iOS 的强项是触屏,各种 Art App 其实也都提供了触屏的“快捷键”,比如 Procreate 在触屏左边有两个 slider 可以分别调整笔刷的大小和透明度,也有一个快捷键按钮,可以有一些可定制功能,比如按下的时候就可以用笔进行取色,还有一些快捷手势,比如两个指头 tap 就是 undo。听上去很美好,但是实际使用的时候触屏按键问题多多,按键没有反馈还是小事,主要的问题是触屏按键经常会失灵,我猜测应该是 palm rejection 功能导致的,因为系统一方面希望用户可以在画画的时候把手放在屏幕上,而不会误把手掌当做手指 tap 而出发“快捷键”功能,所以会对一些被认为是 false alarm 的 tap 有抑制作用。实际上整个 palm rejection 功能虽然已经比较厉害了,但是只要还没有到 100% 精确的程度,就总会有 annoy 用户的地方,除了会让“快捷按键”经常失灵无法按出来之外,还会不时错误地由于手掌而出发快捷按键,即使戴上了上图左下那样的“Art Glove”遮住小指、无名指和下面那部分手掌能很大程度上解决误触发的问题,但是由于系统没有提供完全禁用 palm rejection 功能的选项,所以“无法触发”的问题依然存在。
总之基于触摸屏的快捷键虽然潜力很大——因为不受硬件按钮形状的控制,可以提供任意复杂形状和功能的 UI,但是目前的可用性还有相当大的改进空间,所以如果有一个硬件的快捷键盘能在 iOS 上使用的话,会很大地提升绘画的愉悦程度。当然,显而易见地,上面提到的各种产品,以及其他各种诸如 ClipStudio Tabmate 之类的第三方产品没有一个是能在 iOS 上用的。
这就是用 Arduino 手工制作 Art Keyboard 的动机了,虽然 iOS 系统限制很大,想和 app 通讯基本只能单向发送简单的按键和组合键,但是也算勉强够用把。当然毫无 Arduino 经验的我也不会想到可以做这种东西,还是看到 Procreate 论坛上一个叫 Jorge Verdugo 的网友发了一个帖子展示了一下他自己 DIY 的 keyboard。跟确切地来说应该是一个 remote 一样的东西,可以单手拿着操作。
使用的 Arduino 板子是 Adafruit Feather
nRF52832,这是一个带蓝牙功能的板子,所以可以通过蓝牙和 iPad
连接起来,而不用接线。供电可以使用普通的电池,不过如果使用可充电电池的话,接好电池之后就可以用板子上自带的
micro USB 接口进行充电。其实原理上非常简单,输入是一些按钮,按钮连到
Arduino 的输入
pin,板子监听到特定的按键之后,将定制的键盘组合键通过蓝牙发送到
iOS。其中最复杂的部分大概还是在于按钮了。首先,最直接的连接方式是每个按钮连接板子的一个
pin,但是这样 pin
的数目必须跟按钮一样多才行,比较常用的办法是将按钮线路排布成一个矩阵,每一行和每一列分别占用一个
pin,然后行列组合出可以接一个开关(按钮),通过查看第 i
行和第 j
列是否接通,就可以解码出第 (i,j)
个按钮是否被按下,这样 2N 个 pin 就可以处理 N*N 个按钮。详情可以参考
Wikipedia 的 Keyboard
matrix circuit 和这个 Arduino
9x9 Keyboard Matrix Tutorial。
即使通过矩阵编码的方式可以减少 pin 使用数量,但是布线其实更加复杂,如果完全用线来接估计会绕成一团,为了让做出来的设备还能保持手持大小,就需要跟高效的布线方式。这里之前那位 DIY 网友做了一个 PCB 板子——工作原理很简单,就是做一个和 Arduino 板子规格匹配的一个电路板,外部的 pin 可以和 Arduino 板子直接配对连起来,然后板子上根据标准规格的按钮大小实现设计好布局,哪里放哪个按钮,然后提供按钮连接的针脚,最后设计好板子内部的电路布线,使你插上按钮并把电路板和 Arduino 板子连在一起之后,按钮们在逻辑上是按照矩阵排列的方式连到 Arduino 的——当然,原理虽然听起来简单,但是实际操作我也不知道怎么搞,用什么软件来设计 PCB 电路板,如何调试测试,设计好图纸之后去哪里订购实际的板子之类的……好在 Jorge 有提供 他自己做的板子供购买,同时还提供了代码,不过他并没有开源,我就不贴代码了,搞清楚蓝牙、键盘等相关的 API 函数之后其实是很简单的代码。
做出来的键盘(或者说遥控器)如上图,一个是“大号”的,按键比较多,一个是迷你版(图中被拆成两半了),按键比较少,但是因为电池是贴在下面的,所以也更厚一些。整个制作过程其实是很好玩的,因为 Jorge 给的 instruction 其实很不详细,而我有几乎毫无电路板的经验,包括买哪种按钮,什么样的针脚头,什么样的电池等等都不太清楚。到出售电子元件的网站上一看,真是惊呆了,简直有成千上万种按钮,好在似乎有几种固定的标准,所以大小和针脚形状都差不多。电池也是最后随便买了个相机的充电电池,用一根 Arduino 的电池线直接把正负极用焊锡接上。
至于焊锡,这是整个制作过程中让我最头大的部分,虽然大学金工实习课上焊过电焊,但应该不太一样吧……总之我在网上看了一些视频,买了焊枪、焊锡这些玩意,最后……还是靠 N 帮忙了。不过以前听人说焊板子,我一直以为焊板子是用焊枪直接在板子上画一个电路布线出来,原来只是把针脚连起来啊,瞬间觉得简单了很多倍,不过手抖的我还是很不喜欢搞这个玩意。下图左:N 在焊针脚;中:旧菜板改装的焊接工作台;右:安装按钮中。
最后一大一小两个键盘遥控器都顺利完成,在尝试将程序上传到板子上的时候还碰到了一些额外的困难,不过软件方面的 debug 我比较擅长,总之最后查阅了一些文档和蛛丝马迹之后,安装了某几个特定版本的驱动,再配合上“连续 reset 两次的 trick”之类的诡异方法最后还是搞定了。连上 iPad 的蓝牙的时候是非常激动人心的!Work like a charm 可能还不至于,但是至少是 work as expected。不完美的其实主要是一些小地方了,那些小按钮元件的按键手感并没有特别好,而且没有滑轮之类的可以用来改变连续值(比如笔刷大小)的输入控件(当然,即使有,也由于 iOS 和 procrete 本身的限制,目前还没有办法实现这样的功能)。最严重的问题还是 Procreate 本身,UI 上的 slider 改变笔刷大小是 log scale 的,但是通过键盘快捷键改变笔刷大小却是 linear scale 的,比较不能接受。想象一下如果你要以 1% 的线性增量将笔刷从 5% 的大小增加到 50% 的大小要按多少下按钮,反过来如果选择使用 10% 的增量,则无法选择小于 10% 的笔刷大小。总之还不是特别完美,但是目前来说还是比较够用的。而且制作过程还是比较 exciting 的,虽然现在还想不到还能用 Arduino 做一些其他什么玩意(也许可以做定制的电脑键盘之类的),但是感觉也算是打开了新世界的大门。
最后贴两张近期的 Procreate 画:一张是临摹,另一张是静物(虽然两张都是在做完键盘遥控器之前画的)。😃
如果基于 Disqus 的评论系统无法加载,可以使用下面基于 Github 的评论系统(需要使用 Github 账号登陆)。