13浏览
查看: 13|回复: 3

[项目] 【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人

[复制链接]
这个项目最初是来自 Thingiverse 的 Xpider。然后我说 Alex Glow 的 Archimedes。这让我大吃一惊。我非常想要一个。所以,我开始研究自己的机器人伴侣。我觉得我不是一个猫头鹰类型的人,我希望我的佣兽是特别的。然后我想起了蜘蛛 Anansi 的非洲故事,他是骗子和故事之神。我决定用故事的想法来设计这个机器人,因此 Asi 诞生了(实际上是 Asi_v4,v1-3 是原型)。

集会
最初的设计是 Xpider,但我把它提升了一个档次,通过门外的很多东西编辑了很多东西,你知道的修补。这些是您必须打印的大部分零件。

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

对于电子设备,您通常可以将它们放在头部的顶部或底部(您的调用),但必须按原样连接伺服器。请确保装备在上面。

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

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

这个头只是我在假期里得到的一个圣诞球。我后退一步,轻轻地喷上了黑色喷漆。然后取一些热胶,粘在 Asi 的脖子上,BOOM 就有了头!

最后,我怎么穿它。我只是拿了一些电枢线,把它串在 Asi 底部的整体上,然后将它们缠绕在我背包的肩包上。


【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图1

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图3

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图5

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图4

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图2

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图8

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图6

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图7

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图9

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图11

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图10

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图12

驴友花雕  中级技神
 楼主|

发表于 4 小时前

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图1

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 4 小时前

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人

项目代码

  1. #include <LedControl.h>
  2. //We always have to include the LedControl library
  3. #include "LedControl.h"
  4. /*
  5. Create LetControl object, define pin connections
  6. We have 2 MAX72XX for eyes.
  7. */
  8. #define PIN_EYES_DIN 12
  9. #define PIN_EYES_CS 11
  10. #define PIN_EYES_CLK 10
  11. LedControl lc = LedControl(PIN_EYES_DIN, PIN_EYES_CLK, PIN_EYES_CS, 2);
  12. // rotation
  13. bool rotateMatrix0 = false;  // rotate 0 matrix by 180 deg
  14. bool rotateMatrix1 = false;  // rotate 1 matrix by 180 deg
  15. // define eye ball without pupil  
  16. byte eyeBall[8]={
  17.   B00111100,
  18.   B01111110,
  19.   B11111111,
  20.   B11111111,
  21.   B11111111,
  22.   B11111111,
  23.   B01111110,
  24.   B00111100
  25. };
  26. byte eyePupil = B11100111;
  27. // stores current state of LEDs
  28. byte eyeCurrent[8];
  29. int currentX;
  30. int currentY;
  31. int cntLoop = 0;
  32. int cntEffect = 0;
  33. // min and max positions
  34. #define MIN -2
  35. #define MAX  2
  36. // delays
  37. #define DELAY_BLINK 40
  38. // perform an effect every # of loop iterations, 0 to disable
  39. #define EFFECT_ITERATION 4
  40. /*
  41.   Arduino setup
  42. */
  43. void setup()
  44. {
  45.   // MAX72XX is in power-saving mode on startup, we have to do a wakeup call
  46.   lc.shutdown(0,false);
  47.   lc.shutdown(1,false);
  48.   // set the brightness to low
  49.   lc.setIntensity(0,1);
  50.   lc.setIntensity(1,1);
  51.   // clear both modules
  52.   lc.clearDisplay(0);
  53.   lc.clearDisplay(1);
  54.   // LED test
  55.   // vertical line
  56.   byte b = B10000000;
  57.   for (int c=0; c<=7; c++)
  58.   {
  59.     for (int r=0; r<=7; r++)
  60.     {
  61.       setRow(0, r, b);
  62.       setRow(1, r, b);
  63.     }
  64.     b = b >> 1;
  65.     delay(50);
  66.   }
  67.   // full module
  68.   b = B11111111;
  69.   for (int r=0; r<=7; r++)
  70.   {
  71.     setRow(0, r, b);
  72.     setRow(1, r, b);
  73.   }
  74.   delay(500);
  75.   
  76.    // clear both modules
  77.   lc.clearDisplay(0);
  78.   lc.clearDisplay(1);
  79.   delay(500);
  80.   // random seed
  81.   randomSeed(analogRead(0));
  82.   // center eyes, crazy blink
  83.   displayEyes(0, 0);
  84.   delay(2000);
  85.   blinkEyes(true, false);
  86.   blinkEyes(false, true);
  87.   delay(1000);
  88. }
  89. /*
  90.   Arduino loop
  91. */
  92. void loop()
  93. {
  94.   // move to random position, wait random time
  95.   moveEyes(random(MIN, MAX + 1), random(MIN, MAX + 1), 50);
  96.   delay(random(5, 7) * 500);
  97.   
  98.   // blink time?
  99.   if (random(0, 5) == 0)
  100.   {
  101.     delay(500);
  102.     blinkEyes();
  103.     delay(500);
  104.   }
  105.   
  106.   // effect time?
  107.   if (EFFECT_ITERATION > 0)
  108.   {
  109.     cntLoop++;
  110.     if (cntLoop == EFFECT_ITERATION)
  111.     {
  112.       cntLoop = 0;
  113.       if (cntEffect > 6) cntEffect = 0;
  114.       switch(cntEffect)
  115.       {
  116.         case 0: // cross eyes
  117.           crossEyes();
  118.           delay(1000);
  119.           break;
  120.    
  121.         case 1: // round spin
  122.           roundSpin(2);
  123.           delay(1000);
  124.           break;
  125.         
  126.         case 2: // crazy spin
  127.           crazySpin(2);
  128.           delay(1000);
  129.           break;
  130.         
  131.         case 3: // meth eyes
  132.           methEyes();
  133.           delay(1000);
  134.           break;
  135.                
  136.         case 4: // lazy eye
  137.           lazyEye();
  138.           delay(1000);
  139.           break;
  140.          
  141.         case 5: // crazy blink
  142.           blinkEyes(true, false);
  143.           blinkEyes(false, true);
  144.           delay(1000);
  145.           break;
  146.         case 6: // glow
  147.           glowEyes(3);
  148.           delay(1000);
  149.           break;
  150.         default:
  151.           break;
  152.       }
  153.       cntEffect++;
  154.     }
  155.   }
  156. }
  157. /*
  158.   This method blinks both eyes
  159. */
  160. void blinkEyes()
  161. {
  162.   blinkEyes(true, true);
  163. }
  164. /*
  165.   This method blinks eyes as per provided params
  166. */
  167. void blinkEyes(boolean blinkLeft, boolean blinkRight)
  168. {
  169.   // blink?
  170.   if (!blinkLeft && !blinkRight)
  171.     return;
  172.   
  173.   // close eyelids
  174.   for (int i=0; i<=3; i++)
  175.   {
  176.     if (blinkLeft)
  177.     {
  178.       setRow(0, i, 0);
  179.       setRow(0, 7-i, 0);
  180.     }
  181.     if (blinkRight)
  182.     {
  183.       setRow(1, i, 0);
  184.       setRow(1, 7-i, 0);
  185.     }
  186.     delay(DELAY_BLINK);
  187.   }
  188.   
  189.   // open eyelids
  190.   for (int i=3; i>=0; i--)
  191.   {
  192.     if (blinkLeft)
  193.     {
  194.       setRow(0, i, eyeCurrent[i]);
  195.       setRow(0, 7-i, eyeCurrent[7-i]);
  196.     }
  197.     if (blinkRight)
  198.     {
  199.       setRow(1, i, eyeCurrent[i]);
  200.       setRow(1, 7-i, eyeCurrent[7-i]);
  201.     }
  202.     delay(DELAY_BLINK);
  203.   }
  204. }
  205. /*
  206.   This methods moves eyes to center position,
  207.   then moves horizontally with wrapping around edges.
  208. */
  209. void crazySpin(int times)
  210. {
  211.   if (times == 0)
  212.     return;
  213.   
  214.   moveEyes(0, 0, 50);
  215.   delay(500);
  216.   
  217.   byte row = eyePupil;
  218.   for (int t=0; t<times; t++)
  219.   {
  220.     // spin from center to L
  221.     for (int i=0; i<5; i++)
  222.     {
  223.       row = row >> 1;
  224.       row = row | B10000000;
  225.       setRow(0, 3, row);  setRow(1, 3, row);  
  226.       setRow(0, 4, row);  setRow(1, 4, row);
  227.       delay(50);
  228.       if (t == 0)
  229.         delay((5-i)*10); // increase delay on 1st scroll (speed up effect)
  230.     }
  231.     // spin from R to center
  232.     for (int i=0; i<5; i++)
  233.     {
  234.       row = row >> 1;
  235.       if (i>=2)
  236.         row = row | B10000000;
  237.       setRow(0, 3, row);  setRow(1, 3, row);  
  238.       setRow(0, 4, row);  setRow(1, 4, row);
  239.       delay(50);
  240.       if (t == (times-1))
  241.         delay((i+1)*10); // increase delay on last scroll (slow down effect)
  242.     }
  243.   }
  244. }
  245. /*
  246.   This method crosses eyes
  247. */
  248. void crossEyes()
  249. {
  250.   moveEyes(0, 0, 50);
  251.   delay(500);
  252.   byte pupilR = eyePupil;  
  253.   byte pupilL = eyePupil;
  254.   
  255.   // move pupils together
  256.   for (int i=0; i<2; i++)
  257.   {
  258.     pupilR = pupilR >> 1;
  259.     pupilR = pupilR | B10000000;
  260.     pupilL = pupilL << 1;
  261.     pupilL = pupilL | B1;
  262.    
  263.     setRow(0, 3, pupilR); setRow(1, 3, pupilL);
  264.     setRow(0, 4, pupilR); setRow(1, 4, pupilL);
  265.    
  266.     delay(100);
  267.   }
  268.   
  269.   delay(2000);
  270.   
  271.   // move pupils back to center
  272.   for (int i=0; i<2; i++)
  273.   {
  274.     pupilR = pupilR << 1;
  275.     pupilR = pupilR | B1;
  276.     pupilL = pupilL >> 1;
  277.     pupilL = pupilL | B10000000;
  278.    
  279.     setRow(0, 3, pupilR); setRow(1, 3, pupilL);
  280.     setRow(0, 4, pupilR); setRow(1, 4, pupilL);
  281.    
  282.     delay(100);
  283.   }
  284. }
  285. /*
  286.   This method displays eyeball with pupil offset by X, Y values from center position.
  287.   Valid X and Y range is [MIN,MAX]
  288.   Both LED modules will show identical eyes
  289. */
  290. void displayEyes(int offsetX, int offsetY)
  291. {
  292.   // ensure offsets are  in valid ranges
  293.   offsetX = getValidValue(offsetX);
  294.   offsetY = getValidValue(offsetY);
  295.   
  296.   // calculate indexes for pupil rows (perform offset Y)
  297.   int row1 = 3 - offsetY;
  298.   int row2 = 4 - offsetY;
  299.   // define pupil row
  300.   byte pupilRow = eyePupil;
  301.   // perform offset X
  302.   // bit shift and fill in new bit with 1
  303.   if (offsetX > 0) {
  304.     for (int i=1; i<=offsetX; i++)
  305.     {
  306.       pupilRow = pupilRow >> 1;
  307.       pupilRow = pupilRow | B10000000;
  308.     }
  309.   }
  310.   else if (offsetX < 0) {
  311.     for (int i=-1; i>=offsetX; i--)
  312.     {
  313.       pupilRow = pupilRow << 1;
  314.       pupilRow = pupilRow | B1;
  315.     }
  316.   }
  317.   // pupil row cannot have 1s where eyeBall has 0s
  318.   byte pupilRow1 = pupilRow & eyeBall[row1];
  319.   byte pupilRow2 = pupilRow & eyeBall[row2];
  320.   
  321.   // display on LCD matrix, update to eyeCurrent
  322.   for(int r=0; r<8; r++)
  323.   {
  324.     if (r == row1)
  325.     {
  326.       setRow(0, r, pupilRow1);
  327.       setRow(1, r, pupilRow1);
  328.       eyeCurrent[r] = pupilRow1;
  329.     }
  330.     else if (r == row2)
  331.     {
  332.       setRow(0, r, pupilRow2);
  333.       setRow(1, r, pupilRow2);
  334.       eyeCurrent[r] = pupilRow2;
  335.     }
  336.     else
  337.     {
  338.       setRow(0, r, eyeBall[r]);
  339.       setRow(1, r, eyeBall[r]);
  340.       eyeCurrent[r] = eyeBall[r];
  341.     }
  342.   }
  343.   
  344.   // update current X and Y
  345.   currentX = offsetX;
  346.   currentY = offsetY;
  347. }
  348. /*
  349.   This method corrects provided coordinate value
  350. */
  351. int getValidValue(int value)
  352. {
  353.   if (value > MAX)
  354.     return MAX;
  355.   else if (value < MIN)
  356.     return MIN;
  357.   else
  358.     return value;
  359. }
  360. /*
  361.   This method pulsates eye (changes LED brightness)
  362. */
  363. void glowEyes(int times)
  364. {
  365.   for (int t=0; t<times; t++)
  366.   {
  367.     for (int i=2; i<=8; i++)
  368.     {
  369.       lc.setIntensity(0,i);
  370.       lc.setIntensity(1,i);
  371.       delay(50);
  372.     }
  373.     delay(250);
  374.     for (int i=7; i>=1; i--)
  375.     {
  376.       lc.setIntensity(0,i);
  377.       lc.setIntensity(1,i);
  378.       delay(25);
  379.     }
  380.     delay(150);
  381.   }
  382. }
  383. /*
  384.   This method moves eyes to center, out and then back to center
  385. */
  386. void methEyes()
  387. {
  388.   moveEyes(0, 0, 50);
  389.   delay(500);
  390.   byte pupilR = eyePupil;  
  391.   byte pupilL = eyePupil;
  392.   // move pupils out
  393.   for (int i=0; i<2; i++)
  394.   {
  395.     pupilR = pupilR << 1;
  396.     pupilR = pupilR | B1;
  397.     pupilL = pupilL >> 1;
  398.     pupilL = pupilL | B10000000;
  399.    
  400.     setRow(0, 3, pupilR); setRow(1, 3, pupilL);
  401.     setRow(0, 4, pupilR); setRow(1, 4, pupilL);
  402.    
  403.     delay(100);
  404.   }
  405.   delay(2000);
  406.   
  407.   // move pupils back to center
  408.   for (int i=0; i<2; i++)
  409.   {
  410.     pupilR = pupilR >> 1;
  411.     pupilR = pupilR | B10000000;
  412.     pupilL = pupilL << 1;
  413.     pupilL = pupilL | B1;
  414.    
  415.     setRow(0, 3, pupilR); setRow(1, 3, pupilL);
  416.     setRow(0, 4, pupilR); setRow(1, 4, pupilL);
  417.    
  418.     delay(100);
  419.   }
  420. }
  421. /*
  422.   This method moves both eyes from current position to new position
  423. */
  424. void moveEyes(int newX, int newY, int stepDelay)
  425. {
  426.   // set current position as start position
  427.   int startX = currentX;
  428.   int startY = currentY;
  429.   
  430.   // fix invalid new X Y values
  431.   newX = getValidValue(newX);
  432.   newY = getValidValue(newY);
  433.   
  434.   // eval steps
  435.   int stepsX = abs(currentX - newX);
  436.   int stepsY = abs(currentY - newY);
  437.   // need to change at least one position
  438.   if ((stepsX == 0) && (stepsY == 0))
  439.     return;
  440.    
  441.   // eval direction of movement, # of steps, change per X Y step, perform move
  442.   int dirX = (newX >= currentX) ? 1 : -1;
  443.   int dirY = (newY >= currentY) ? 1 : -1;
  444.   int steps = (stepsX > stepsY) ? stepsX : stepsY;
  445.   int intX, intY;
  446.   float changeX = (float)stepsX / (float)steps;
  447.   float changeY = (float)stepsY / (float)steps;
  448.   for (int i=1; i<=steps; i++)
  449.   {
  450.     intX = startX + round(changeX * i * dirX);
  451.     intY = startY + round(changeY * i * dirY);
  452.     displayEyes(intX, intY);
  453.     delay(stepDelay);
  454.   }
  455. }
  456. /*
  457.   This method lowers and raises right pupil only
  458. */
  459. void lazyEye()
  460. {
  461.   moveEyes(0, 1, 50);
  462.   delay(500);
  463.   
  464.   // lower left pupil slowly
  465.   for (int i=0; i<3; i++)
  466.   {
  467.     setRow(1, i+2, eyeBall[i+2]);
  468.     setRow(1, i+3, eyeBall[i+3] & eyePupil);
  469.     setRow(1, i+4, eyeBall[i+4] & eyePupil);
  470.     delay(150);
  471.   }
  472.   
  473.   delay(1000);
  474.   
  475.   // raise left pupil quickly
  476.   for (int i=0; i<3; i++)
  477.   {
  478.     setRow(1, 4-i, eyeBall[4-i] & eyePupil);
  479.     setRow(1, 5-i, eyeBall[5-i] & eyePupil);
  480.     setRow(1, 6-i, eyeBall[6-i]);
  481.     delay(25);
  482.   }  
  483. }
  484. /*
  485.   This method spins pupils clockwise
  486. */
  487. void roundSpin(int times)
  488. {
  489.   if (times == 0)
  490.     return;
  491.   
  492.   moveEyes(2, 0, 50);
  493.   delay(500);
  494.   
  495.   for (int i=0; i<times; i++)
  496.   {
  497.     displayEyes(2, -1); delay(40); if (i==0) delay(40);
  498.     displayEyes(1, -2); delay(40); if (i==0) delay(30);
  499.     displayEyes(0, -2); delay(40); if (i==0) delay(20);
  500.     displayEyes(-1, -2); delay(40);if (i==0) delay(10);
  501.     displayEyes(-2, -1); delay(40);
  502.     displayEyes(-2, 0); delay(40);
  503.     displayEyes(-2, 1); delay(40);if (i==(times-1)) delay(10);
  504.     displayEyes(-1, 2); delay(40);if (i==(times-1)) delay(20);
  505.     displayEyes(0, 2); delay(40); if (i==(times-1)) delay(30);
  506.     displayEyes(1, 2); delay(40); if (i==(times-1)) delay(40);
  507.     displayEyes(2, 1); delay(40); if (i==(times-1)) delay(50);
  508.     displayEyes(2, 0); delay(40);
  509.   }
  510. }
  511. /*
  512.   This method sets values to matrix row
  513.   Performs 180 rotation if needed
  514. */
  515. void setRow(int addr, int row, byte rowValue)
  516. {
  517.   if (((addr == 0) && (rotateMatrix0)) || (addr == 1 && rotateMatrix1))
  518.   {
  519.     row = abs(row - 7);
  520.     rowValue = bitswap(rowValue);
  521.   }
  522.   lc.setRow(addr, row, rowValue);
  523. }
  524. /*
  525.   Reverse bits in byte
  526.   http://www.nrtm.org/index.php/2013/07/25/reverse-bits-in-a-byte/
  527. */
  528. byte bitswap (byte x)
  529. {
  530.   byte result;
  531.     asm("mov __tmp_reg__, %[in] \n\t"
  532.       "lsl __tmp_reg__  \n\t"   /* shift out high bit to carry */
  533.       "ror %[out] \n\t"  /* rotate carry __tmp_reg__to low bit (eventually) */
  534.       "lsl __tmp_reg__  \n\t"   /* 2 */
  535.       "ror %[out] \n\t"
  536.       "lsl __tmp_reg__  \n\t"   /* 3 */
  537.       "ror %[out] \n\t"
  538.       "lsl __tmp_reg__  \n\t"   /* 4 */
  539.       "ror %[out] \n\t"
  540.       "lsl __tmp_reg__  \n\t"   /* 5 */
  541.       "ror %[out] \n\t"
  542.       "lsl __tmp_reg__  \n\t"   /* 6 */
  543.       "ror %[out] \n\t"
  544.       "lsl __tmp_reg__  \n\t"   /* 7 */
  545.       "ror %[out] \n\t"
  546.       "lsl __tmp_reg__  \n\t"   /* 8 */
  547.       "ror %[out] \n\t"
  548.       : [out] "=r" (result) : [in] "r" (x));
  549.       return(result);
  550. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 4 小时前

【Arduino 动手做】Anansi:一个很酷的蜘蛛状机器人

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail