亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

Asi (Anansi) Robot Companion

组件和用品

Arduino Nano R3
× 1
SG90 微伺服电机
× 1
MAX7219 红色 LED 点阵显示模块
× 1
4xAA 电池座
锂离子电池 3.7 200mah 也可以使用
× 1
螺丝
× 1
透明塑料亚克力浴缸炸弹模具壳
× 1
Adafruit Trinket - 迷你微控制器 - 5V 逻辑
× 1

必要的工具和机器

3D 打印机(通用)
热胶枪(通用)

关于这个项目

故事

这个项目最初是来自 Thingiverse 的 Xpider。然后我说 Alex Glow 的 Archimedes。它让我大吃一惊。我非常想要一个。所以,我开始研究自己的机器人伴侣。我想我不是猫头鹰类型,我希望我的魔宠很特别。然后我想起了蜘蛛、骗子和故事之神阿南西的非洲故事。我决定用一个故事的想法来设计这个机器人,于是Asi诞生了(实际上是Asi_v4,v1-3是原型)。

组装

最初的设计是一个 Xpider,但我在门外对它进行了大量编辑,你知道修补。这些是您必须打印的大部分部件。

组装是不言自明的,但无论如何这里有一些图片。

对于电子设备,您通常可以将它们放在头部的顶部或底部(您的要求),但必须如此连接伺服。请确保齿轮在上面。

Asi 由两个微控制器控制,一个 Trinket 和一个 Arduino Nano。 Trinket 控制眼睛的运动,这要归功于它以随机间隔来回转动的伺服系统。 Arduino Nano 控制眼睛。当他环顾四周时,这也是随机的,通常人们认为他在看着他们。

请注意,我将它们放在两个用 4 节 AA 电池菊花链连接的小面包板上。 (您也可以使用锂离子电池 3.7 200mAh。使用锂电池时,由于某些原因,我有时无法正常工作,因此我会使用两个单独的锂电池并将它们连接到同一个开关所以一切都立即开始。)

头部只是我在假期中得到的圣诞球。我后退了一步,用黑色喷漆轻轻地喷了上去。然后用热胶把它粘在Asi的脖子上,BOOM就是头!

最后,我怎么穿。我只是拿了一些电枢线,把它穿过阿西底部的整体,然后把它们包在我背包的双肩包上。

代码

  • 阿西之眼
  • 带小饰品的阿西项链
Asi Eye Arduino
Asi eye的代码
#include //我们总是必须包含LedControl库#include "LedControl.h"/* 创建LetControl对象,定义引脚连接我们有2个MAX72XX用于眼睛。 */#define PIN_EYES_DIN 12#define PIN_EYES_CS 11#define PIN_EYES_CLK 10LedControl lc =LedControl(PIN_EYES_DIN, PIN_EYES_CLK, PIN_EYES_CS, 2);// rotationbool rotateMatrix0 =false; // 将 0 矩阵旋转 180 度布尔 rotateMatrix1 =false; // 将 1 个矩阵旋转 180 度// 定义没有瞳孔的眼球 byte eyeBall[8]={ B001111100, B01111110, B11111111, B11111111, B11111111, B11111111, B011111110, B0111110, B01111110, B0111110 存储当前状态 B01111110;1110 字节LEDsbyte eyeCurrent[8];int currentX;int currentY;int cntLoop =0;int cntEffect =0;// 最小和最大位置#define MIN -2#define MAX 2// delays#define DELAY_BLINK 40// 每执行一个效果# 循环迭代次数,0 表示禁用#define EFFECT_ITERATION 4/* Arduino setup*/void setup() { // MAX72XX 在启动时处于省电模式,我们必须执行唤醒调用 lc.shutdown(0,false); lc.shutdown(1,false); // 将亮度设置为低 lc.setIntensity(0,1); lc.setIntensity(1,1); // 清除两个模块 lc.clearDisplay(0); lc.clearDisplay(1); // LED 测试 // 垂直线字节 b =B10000000; for (int c=0; c<=7; c++) { for (int r=0; r<=7; r++) { setRow(0, r, b); setRow(1, r, b); } b =b>> 1;延迟(50); } // 完整模块 b =B11111111; for (int r=0; r<=7; r++) { setRow(0, r, b); setRow(1, r, b); } 延迟(500); // 清除两个模块 lc.clearDisplay(0); lc.clearDisplay(1);延迟(500); // 随机种子 randomSeed(analogRead(0)); // 眼睛居中,疯狂眨眼 displayEyes(0, 0);延迟(2000);眨眼(真,假);眨眼(假,真); delay(1000);}/* Arduino loop*/void loop() { // 移动到随机位置,等待随机时间 moveEyes(random(MIN, MAX + 1), random(MIN, MAX + 1), 50);延迟(随机(5, 7)* 500); // 闪烁时间?如果(随机(0,5)==0){延迟(500);眨眼();延迟(500); } // 生效时间? if (EFFECT_ITERATION> 0) { cntLoop++; if (cntLoop ==EFFECT_ITERATION) { cntLoop =0;如果 (cntEffect> 6) cntEffect =0; switch(cntEffect) { case 0:// 交叉眼睛 crossEyes();延迟(1000);休息; case 1:// 圆旋转 roundSpin(2);延迟(1000);休息; case 2:// 疯狂旋转 crazySpin(2);延迟(1000);休息; case 3:// 冰毒眼睛 methEyes();延迟(1000);休息; case 4:// 懒惰眼lazyEye();延迟(1000);休息; case 5:// 疯狂眨眼blinkEyes(true, false);眨眼(假,真);延迟(1000);休息; case 6:// 发光glowEyes(3);延迟(1000);休息;默认值:中断; } cntEffect++; } }}/* 该方法眨眼*/voidblinkEyes(){blinkEyes(true, true);}/* 该方法根据提供的参数眨眼*/voidblinkEyes(booleanblinkLeft, booleanblinkRight){ // 眨眼?如果 (!blinkLeft &&!blinkRight) 返回; // 闭上眼睑 for (int i=0; i<=3; i++) { if (blinkLeft) { setRow(0, i, 0); setRow(0, 7-i, 0); } if (blinkRight) { setRow(1, i, 0); setRow(1, 7-i, 0); } 延迟(DELAY_BLINK); } // 打开眼睑 for (int i=3; i>=0; i--) { if (blinkLeft) { setRow(0, i, eyeCurrent[i]); setRow(0, 7-i, eyeCurrent[7-i]); } if (blinkRight) { setRow(1, i, eyeCurrent[i]); setRow(1, 7-i, eyeCurrent[7-i]); } 延迟(DELAY_BLINK); }}/* 此方法将眼睛移动到中心位置,然后水平移动并环绕边缘。*/void crazySpin(int times){ if (times ==0) return; moveEyes(0, 0, 50);延迟(500);字节行 =eyePupil; for (int t=0; t> 1;行 =行 | B10000000; setRow(0, 3, 行); setRow(1, 3, 行); setRow(0, 4, 行); setRow(1, 4, 行);延迟(50);如果(t ==0)延迟((5-i)* 10); // 增加第一次滚动的延迟(加速效果) } // 从 R 旋转到中心 for (int i=0; i<5; i++) { row =row>> 1;如果 (i>=2) 行 =行 | B10000000; setRow(0, 3, 行); setRow(1, 3, 行); setRow(0, 4, 行); setRow(1, 4, 行);延迟(50); if (t ==(times-1)) delay((i+1)*10); // 增加最后一次滚动的延迟(减速效果)} }}/* 该方法交叉眼睛*/void crossEyes(){ moveEyes(0, 0, 50);延迟(500);字节瞳孔R =eyePupil;字节瞳孔L =eyePupil; // 一起移动学生 for (int i=0; i<2; i++) { studentR =studentR>> 1;瞳孔R =瞳孔R | B10000000;瞳孔=瞳孔L<<1;瞳孔L =瞳孔L | B1; setRow(0, 3, 瞳孔R); setRow(1, 3, 瞳孔L); setRow(0, 4, 瞳孔R); setRow(1, 4, 瞳孔L);延迟(100); } 延迟(2000); // 将学生移回中心 for (int i=0; i<2; i++) { studentR =studentR <<1;瞳孔R =瞳孔R | B1;瞳孔L =瞳孔L>> 1;瞳孔L =瞳孔L | B10000000; setRow(0, 3, 瞳孔R); setRow(1, 3, 瞳孔L); setRow(0, 4, 瞳孔R); setRow(1, 4, 瞳孔L);延迟(100); }}/* 此方法显示瞳孔从中心位置偏移 X、Y 值的眼球。有效的 X 和 Y 范围是 [MIN,MAX] 两个 LED 模块将显示相同的眼睛*/void displayEyes(int offsetX, int offsetY) { // 确保偏移在有效范围内 offsetX =getValidValue(offsetX); offsetY =getValidValue(offsetY); // 计算瞳孔行的索引(执行偏移 Y) int row1 =3 - offsetY; int row2 =4 - offsetY; // 定义瞳孔行字节 studentRow =eyePupil; // 执行偏移 X // 位移位并用 1 填充新位 if (offsetX> 0) { for (int i=1; i<=offsetX; i++) { studentRow =studentRow>> 1;瞳孔行 =瞳孔行 | B10000000; } } else if (offsetX <0) { for (int i=-1; i>=offsetX; i--) { studentRow =studentRow <<1;瞳孔行 =瞳孔行 | B1; } } // 瞳孔行不能有 1s,其中 eyeBall 有 0s 字节 studentRow1 =studentRow &eyeBall[row1];字节瞳孔行 2 =瞳孔行 &eyeBall[row2]; // 在 LCD 矩阵上显示,更新到 eyeCurrent for(int r=0; r<8; r++) { if (r ==row1) { setRow(0, r, studentRow1); setRow(1, r, studentRow1); eyeCurrent[r] =瞳孔行 1; } else if (r ==row2) { setRow(0, r, studentRow2); setRow(1, r, studentRow2); eyeCurrent[r] =瞳孔行 2; } else { setRow(0, r, eyeBall[r]); setRow(1, r, eyeBall[r]); eyeCurrent[r] =eyeBall[r]; } } // 更新当前 X 和 Y currentX =offsetX; currentY =offsetY;}/* 此方法修正提供的坐标值*/int getValidValue(int value){ if (value> MAX) return MAX;否则如果(值 =1; i--) { lc.setIntensity(0,i); lc.setIntensity(1,i);延迟(25); } 延迟(150); }}/* 这个方法将眼睛移到中心,移出然后回到中心*/void methEyes(){ moveEyes(0, 0, 50);延迟(500);字节瞳孔R =eyePupil;字节瞳孔L =eyePupil; // 将学生移出 (int i=0; i<2; i++) { studentR =studentR <<1;瞳孔R =瞳孔R | B1;瞳孔L =瞳孔L>> 1;瞳孔L =瞳孔L | B10000000; setRow(0, 3, 瞳孔R); setRow(1, 3, 瞳孔L); setRow(0, 4, 瞳孔R); setRow(1, 4, 瞳孔L);延迟(100); } 延迟(2000); // 将学生移回中心 for (int i=0; i<2; i++) { studentR =studentR>> 1;瞳孔R =瞳孔R | B10000000;瞳孔=瞳孔L<<1;瞳孔L =瞳孔L | B1; setRow(0, 3, 瞳孔R); setRow(1, 3, 瞳孔L); setRow(0, 4, 瞳孔R); setRow(1, 4, 瞳孔L);延迟(100); }}/* 该方法将双眼从当前位置移动到新位置*/void moveEyes(int newX, int newY, int stepDelay){ // 设置当前位置为起始位置 int startX =currentX; int startY =currentY; // 修复无效的新 X Y 值 newX =getValidValue(newX); newY =getValidValue(newY); // 评估步骤 int stepsX =abs(currentX - newX); int stepY =abs(currentY - newY); // 至少需要改变一个位置 if ((stepsX ==0) &&(stepsY ==0)) return; // 评估移动方向,步数,每 X Y 步变化,执行移动 int dirX =(newX>=currentX) ? 1:-1; int dirY =(newY>=currentY) ? 1:-1; int step =(stepsX> stepsY) ?步骤X:步骤Y; int intX, intY; float changeX =(float)stepsX / (float)steps;浮动变化Y =(浮动)步数/(浮动)步数; for (int i=1; i<=steps; i++) { intX =startX + round(changeX * i * dirX); intY =startY + round(changeY * i * dirY); displayEyes(intX, intY);延迟(步延迟); }}/* 此方法只降低和升高右瞳孔*/void lazyEye(){ moveEyes(0, 1, 50);延迟(500); // 左下瞳孔缓慢 for (int i=0; i<3; i++) { setRow(1, i+2, eyeBall[i+2]); setRow(1, i+3, eyeBall[i+3] &eyePupil); setRow(1, i+4, eyeBall[i+4] &eyePupil);延迟(150); } 延迟(1000); // 快速抬高左瞳孔 for (int i=0; i<3; i++) { setRow(1, 4-i, eyeBall[4-i] &eyePupil); setRow(1, 5-i, eyeBall[5-i] &eyePupil); setRow(1, 6-i, eyeBall[6-i]);延迟(25); } }/* 这个方法顺时针旋转瞳孔*/void roundSpin(int times){ if (times ==0) return; moveEyes(2, 0, 50);延迟(500); for (int i=0; i 
带小饰品的 Asi Neck Arduino
这是我用来确保 Asi 颈部前后移动
 // 伺服参数的方法。小饰品上的 Pin 必须是 1 或 4。伺服位置// 以原始计时器/计数器刻度指定(1 个刻度 =0.128 毫秒)。// 伺服脉冲计时通常为 1-2 毫秒,但// 伺服之间可能略有不同,因此您可能需要调整这些限制以符合您的现实。#define SERVO_PIN 4 // Trinket 支持引脚 1 或 4 #define SERVO_MIN 4 // ~1 ms 脉冲#define SERVO_MAX 26 // ~2 ms 脉冲 Adafruit_TiCoServo 伺服; void setup(void) {#if (F_CPU ==16000000L) // 16 MHz Trinket 需要设置预分频才能正确计时。 // 这必须在servo.attach()之前完成! clock_prescale_set(clock_div_1);#endifservo.attach(SERVO_PIN); pinMode(LED_PIN,输出); digitalWrite(LED_PIN, HIGH);} uint32_t lastLookTime =0; // 最后一次转头的时间 void loop(void) { unsigned long t =millis(); // 当前时间 // 如果自上次头部转动以来已经过去了 1/2 秒以上... if((t - lastLookTime)> 500) { if(random(10) ==0) { // 有一个 1- in-10 机会... // ...在新方向上随机移动头部:servo.write(random(SERVO_MIN, SERVO_MAX)); lastLookTime =t; // 保存转头时间以备将来参考 } } // 与转头检查无关, if(random(10) ==0) { // 有十分之一的机会... // .. .of“眨眼”:digitalWrite(LED_PIN, LOW); // LED 关闭延迟(random(50, 250)); // 只是一个短暂的随机时刻 digitalWrite(LED_PIN, HIGH); // 然后返回 ON } delay(100); // 重复 loop() 大约 10 次/秒}

定制零件和外壳

实际的腿部末端忘记为伺服添加转动齿轮,我通常打印出来并将伺服附件安装到中间然后将其拧在伺服主体上 Asithe 大腿底部 Asithe 的主体到 Asileg 关节我用来连接 Asi 腿的螺丝螺母与螺丝一起使用的齿轮伺服用于使Asi头部转动,建议使用伺服片并将其放在asi GearAsi颈板伺服的Asithe支架中间的中间,这是丙烯酸球粘在脖子

示意图

我用于 Asi Neck 的电路 这些是我用来让Asi入门的。你可以用菊花链将它们从小电路板上连接起来

制造工艺

  1. 如何制作 Arduino+Raspberry Pi 机器人平台
  2. Raspberry Pi CD Box Robot
  3. PiCy – 微型树莓派动力机器人!
  4. 滚动报警机器人
  5. 制作 Minecraft Creeper Robot
  6. 阿基米德:人工智能机器人猫头鹰
  7. 打开简历机器人
  8. ROS 机器人
  9. 简单的 Pi 机器人
  10. 什么是饮料机器人?
  11. 机器人和电池制造:正相关
  12. 应对电池需求激增