魔术方块机器人





专案起源

此专案源起于某天,士兵 B 带了魔术方块来到公司被老大撞见。
「原来你会转魔术方块阿! 那麽做个魔术方块机器人对你来说应该是小菜一碟吧!」老大说道,于是士兵 B 便被指派为此专案负责人。



功能说明

本专案利用 86Duino One86Duino Enjoy 及 Maixduino 实作魔术方块机器人。


准备材料

  1. 一片 86Duino One
  2. 一片 Maixduino
  3. 8 颗 RoBoard RS-1270 伺服机
  4. OV2640 摄像头模组
  5. 一个魔术方块(此专案使用大雁展翅系列魔术方块)
  6. 2.4 吋 TFT LCD萤幕(可有可无)
  7. WS2812 LED 灯条(含 18 颗 LED 灯)
  8. 7.2V 的电池
  9. 3D 列印机
  10. 螺丝、螺帽与线材



硬体架设

本专案机构参考了 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 度为正向,因此定义以下六个移动符号分别代表的转动方式为:

U

D

L

R

F

B


而可以顺时针转动当然就可以逆时针转动,定义以撇号 prime(‘) 代表逆时针转 90 度。


U

D

L

R

F

B


另外,定义数字 2 代表旋转 180 度。


U2

D2

L2

R2

F2

B2


魔术方块解法就是由以上这些转动方式组合而成,透过 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.