魔术方块机器人
专案起源
此专案源起于某天,士兵 B 带了魔术方块来到公司被老大撞见。
「原来你会转魔术方块阿! 那麽做个魔术方块机器人对你来说应该是小菜一碟吧!」老大说道,于是士兵 B 便被指派为此专案负责人。
功能说明
本专案利用 86Duino One、86Duino Enjoy 及 Maixduino 实作魔术方块机器人。
准备材料
- 一片 86Duino One
- 一片 Maixduino
- 8 颗 RoBoard RS-1270 伺服机
- OV2640 摄像头模组
- 一个魔术方块(此专案使用大雁展翅系列魔术方块)
- 2.4 吋 TFT LCD萤幕(可有可无)
- WS2812 LED 灯条(含 18 颗 LED 灯)
- 7.2V 的电池
- 3D 列印机
- 螺丝、螺帽与线材
硬体架设
本专案机构参考了 OTVINTA 的魔术方块机器人,所需列印材料的 STL 档如下:
cover 零件 STL 下载
建议 cover 零件以白色或黑色材料列印以免光线问题影响后续颜色辨识。
机器人详细组装步骤请参考 OTVINTA 网站,须注意在安装夹爪前须先将控制夹爪的马达位置初始化至 1100us 并垂直装上夹爪,另外将控制齿条的马达初始化至 2100us 且使滑块贴齐机器人身体边缘,如图所示:
— 伺服机初始化程式 —
#include <Servo86.h> // 使用 Servo86 函式库 Servo myservo1; // 初始化 Servo 物件 void setup() { // 设定 Servo 脚位为 21 myservo1.attach(21); // 送出 1100us 的 PWM 信号,使伺服机初始化至 1100us myservo1.write(1100); } void loop() {}
这裡介绍固定 86Duino 与 Maixduino 的层架组装,组装方式为由下到上:
首先,将零件 plate_holder 固定于机器人底部马达位置并锁上螺丝,且将零件 plate_bottom 放置于上方,如图所示:
接着将 2 个 joint1 与 joint2 零件固定于 plate_bottom 的四个角,须特别注意安装方向是否与图片一致,并将 4 个 pillar_short 接上:
将 4 个 joint3 零件装于 pillar_short 上,并装上 plate_86duino 零件与锁上 86Duino,可以比对零件上的螺丝孔位置与 86Duino 的方向是否正确,建议 86Duino 绿色电源端子台朝向图片右方,RC 伺服机接头朝向图片左方,然后将伺服机、LED 灯条的接线接上,并将 4 个 pillar 零件装上,注意接线尽量放于 plate_86duino 的左右两侧避免阻挡到相机画面。
将 joint1、joint2、joint4、join5 安装于 pillar 上,并将 plate_maixduino 装上,同样须注意方向是否与图片一致:
锁上 arm_left、arm_right 与 Maixduino,沿着两个 arm 凹槽处黏贴上 LED 灯条,然后将 OV2640 相机嵌入 plate_maixduino,并将 Maixduino 的脚位与 86Duino 接上,plate_maixduino 有挖两个孔供接线穿过。
盖上 cover 于上方,并对准位置将 cover_lock 黏在 cover 上,最后与机器人锁上。
接着介绍电路连接方式,如下图。
86Duino 与 Maixduino 共电源,因此以 7.2V 电池对 86Duino 供电即可运作,须注意 LED 灯条与马达可能产生较大的瞬间电流,因此须确保电源端电流至少能到 10A。
环境设定
Maixduino 的环境设定请参考 MaixPy 教学网站,裡面有详细的解说。
程式解说
Maixduino 支援 Micropython,可支援大部分 Python 3 语法与 openMV 函式库,在本专案中用于魔术方块的颜色辨识,而 86Duino 则用于计算魔术方块解法与马达控制,程式流程如下:
— 辨识魔术方块中心位置 —
从机构设计的角度来看魔术方块的位置是固定的,但在实际安装上难免会有误差使魔术方块无法正对于相机正中央,而此函式 findCubeCenter() 允许魔术方块在一定误差内修正中心方块的位置。
— 曝光补偿 —
为了进行颜色辨识,必须使相机在任何光源下都能拍出相同色彩资讯的照片,除了加上顶盖使光源固定由 LED 灯条提供,这裡还进行了曝光补偿,而函式 exposure_compensation() 会根据四个红色爪子的亮度作为依据自动修正相机的曝光时间。
— 收集方块六面的 HSV 色彩资讯 —
在撷取完六面的影像后,取各个方格的颜色资讯的众数,作为代表该方格的颜色,并将其颜色资讯转到 HSV 色彩空间以利后续颜色辨识。HSV 分别代表了颜色的色相(Hue)、饱和度(Saturation)、明度(Value)。
— 颜色辨识 —
由于白色(和黑色)与其他颜色在不同的维度上,因此需特别先辨识,这裡以饱和度排序,将 9 个饱和度最低的方格辨识为白色,而其馀色彩则以色相排序作为辨识依据。最后,将辨识结果传回 86Duino 计算解魔术方块的流程。
— 魔术方块移动符号 —
魔术方块共有 6 种面向,分别为 U(UP)上方、D(DOWN)下方、L(LEFT)左方、R(RIGHT)右方、F(FRONT)前方、B(BACK)后方 ,而所有面向都以朝向该面的顺时针转 90 度为正向,因此定义以下六个移动符号分别代表的转动方式为:
而可以顺时针转动当然就可以逆时针转动,定义以撇号 prime(‘) 代表逆时针转 90 度。
另外,定义数字 2 代表旋转 180 度。
魔术方块解法就是由以上这些转动方式组合而成,透过 turning() 函式即可传入以上指令使机器人转动魔术方块,值得一提的是,由于机构只有四个爪分别能转动 U、D、R、L,若要转动 F 及 B 则程式会先将魔术方块整面往上或往下转,使动作 F 或 B 都变成 U。
— 神的数字(God’s Number)—
对任何随机的解谜问题,若演算法必定能找到小于某步骤次数的解,则称此演算法为神的演算法(God’s Algorithm),而解谜的步骤次数被称为神的数字(God’s Number),在 2010 年时已有学者证明魔术方块的 God’s Number 为 20。而目前的 God’s Algorithm 为 Kociemba Algorithm(或称作 Two-Phase Algorithm),详细演算法步骤说明可参考 Cube Explorer,在此并不赘述,本专案使用了作者 Muodov 所实现的 Kociemba 演算法,此作者也製作了自己的魔术方块机器人 Meccano Rubiks Shrine。
— 马达参数调整 —
调整下述参数使魔术方块移动符号皆能正常转动,分别为:
1. DELAY_TIME:等待马达转动时间(ms)
2. CLAMP_UPPER_BOUND:夹爪转至 90 度的 PWM 位置
3. CLAMP_LOWER_BOUND:夹爪转至 0 度的 PWM 位置(即为初始化位置)
4. SLIDE_UPPER_BOUND:滑块移至机器人边缘的 PWM 位置(即为初始化位置)
5. UD_SLIDE_LOWER_BOUND:上下滑块移至夹紧魔术方块时的 PWM 位置
6. RL_SLIDE_LOWER_BOUND:左右滑块移至夹紧魔术方块时的 PWM 位置
const int DELAY_TIME = 200; const int CLAMP_UPPER_BOUND = 2100; const int CLAMP_LOWER_BOUND = 1100; const int SLIDE_UPPER_BOUND = 2100; const int UD_SLIDE_LOWER_BOUND = 965; const int RL_SLIDE_LOWER_BOUND = 760;
若个别马达仍有些许误差,可使用 setOffset() 函式做微调。
成果展示
— DEMO影片 —
相关资料
[1] 本专案 Github
[2] 本专案 STL 机构档
[3] OTVINTA 网站
[4] 魔术方块机器人作者 Muodov 的 Github
[5] 魔术方块演算法参考网站
The text of the 86Duino reference is licensed under a Creative Commons Attribution-ShareAlike 3.0 License. Code samples in the reference are released into the public domain.