Tianli Yu
Published © MIT

The Candy Serving Robot That I Brought to CES

Build a robot that can greet people and serve candies to them, perfect for parties or convention booths, and I even tested it in CES!

IntermediateFull instructions provided1 hour930

Things used in this project

Hardware components

Morpx MoonBot Kit
×1
LEGO Technic beams
×1
Cardboard paper
×1

Software apps and online services

Morpx Mixly for MoonBot

Story

Read more

Custom parts and enclosures

Mixly code file for the demo candy server

A more complex version of the candy server

Code

Candy Server Simple - Arduino

C/C++
#include <Arduino.h>
#include <MoonBot.h>
#include <MuVisionSensor.h>

MuVisionSensor MU0(0x60);
volatile int head_angle;
volatile int state;
volatile int TRACK;
volatile int DELIVER;
volatile int THANK;
volatile long last_action_time;

void Greeting();
void Track();
void TrackPeople();
void Deliver();
void Thank();
void setup();
void loop();

void Greeting() {
  if (millis() > last_action_time + 4000) {
    last_action_time = millis();
    switch (random(0, 4)) {
     case 0:
      speaker.play((char*)"0209");
      break;
     case 1:
      speaker.play("2001");
      m_servo[kServo1].write(85);
      m_servo[kServo4].write(85);
      delay(1200);
      m_servo[kServo1].write(90);
      m_servo[kServo4].write(90);
      break;
     case 2:
      speaker.play((char*)"0210");
      break;
     case 3:
      speaker.play((char*)"0212");
      break;
    }
    switch (random(0, 4)) {
     case 0:
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      {//eyes blink
          unsigned int action_delay = 30;
          moonbot_eyes.setPixelColor(0, 0);
          moonbot_eyes.setPixelColor(6, 0);
          moonbot_eyes.show();
          delay(action_delay);
          moonbot_eyes.setPixelColor(1, 0);
          moonbot_eyes.setPixelColor(5, 0);
          moonbot_eyes.setPixelColor(7, 0);
          moonbot_eyes.setPixelColor(11, 0);
          moonbot_eyes.show();
          delay(action_delay);
          moonbot_eyes.setPixelColor(2, 0);
          moonbot_eyes.setPixelColor(4, 0);
          moonbot_eyes.setPixelColor(8, 0);
          moonbot_eyes.setPixelColor(10, 0);
          moonbot_eyes.show();
          delay(action_delay);
          moonbot_eyes.setPixelColor(3, 0);
          moonbot_eyes.setPixelColor(9, 0);
          moonbot_eyes.show();
          delay(action_delay);
          moonbot_eyes.setPixelColor(3, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(9, 0, 0xFF, 0xFF);
          moonbot_eyes.show();
          delay(action_delay);
          moonbot_eyes.setPixelColor(2, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(4, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(8, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(10, 0, 0xFF, 0xFF);
          moonbot_eyes.show();
          delay(action_delay);
          moonbot_eyes.setPixelColor(1, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(5, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(7, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(11, 0, 0xFF, 0xFF);
          moonbot_eyes.show();
          delay(action_delay);
          moonbot_eyes.setPixelColor(0, 0, 0xFF, 0xFF);
          moonbot_eyes.setPixelColor(6, 0, 0xFF, 0xFF);
          moonbot_eyes.show();
      }
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      break;
     case 1:
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      {//eyes circle
          colorWipe(moonbot_eyes, (0), 40);
          colorWipe(moonbot_eyes, 0xFFFF, 40);
      }
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      break;
     case 2:
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      MoonBotEyesLook(moonbot_eyes, kEyesLookUp, 0x00FFFF);
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      break;
     case 3:
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      {//eyes smile
          moonbot_eyes.clear();
          moonbot_eyes.setPixelColor(0, 0x00FFFF);
          moonbot_eyes.setPixelColor(1, 0x00FFFF);
          moonbot_eyes.setPixelColor(5, 0x00FFFF);
          moonbot_eyes.setPixelColor(6, 0x00FFFF);
          moonbot_eyes.setPixelColor(7, 0x00FFFF);
          moonbot_eyes.setPixelColor(11, 0x00FFFF);
          moonbot_eyes.show();
      }
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      break;
    }

  }
}

void Track() {
  while (true) {
    if (MU0.GetValue(VISION_BODY_DETECT, kStatus)) {
      LED.setPixelColor(0, 0x00ff00);
      LED.setPixelColor(1, 0x00ff00);
      LED.show();
      TrackPeople();

    } else {
      LED.setPixelColor(0, 0xff0000);
      LED.setPixelColor(1, 0xff0000);
      LED.show();
      TankBase.stop();

    }
    if (MU0.LsReadProximity() > 15) {
      state = DELIVER;
      if (true) {
        return;
      }

    }
  }
}

void TrackPeople() {
  head_angle = m_servo[kServo3].read();
  if (MU0.GetValue(VISION_BODY_DETECT, kYValue) < 45) {
    m_servo[kServo3].write(head_angle - 2);

  } else if (MU0.GetValue(VISION_BODY_DETECT, kYValue) > 55) {
    m_servo[kServo3].write(head_angle + 2);
  }
  if (MU0.GetValue(VISION_BODY_DETECT, kXValue) < 45) {
    Motor1.write(100);
    Motor2.write(-100);

  } else if (MU0.GetValue(VISION_BODY_DETECT, kXValue) > 55) {
    Motor1.write(-100);
    Motor2.write(100);
  } else {
    TankBase.stop();
    Greeting();

  }
}

void Deliver() {
  head_angle = 80;
  m_servo[kServo3].write(head_angle);
  TankBase.stop();
  moonbot_eyes.setPixelColor(0, 0x000000);
  moonbot_eyes.setPixelColor(1, 0x000000);
  moonbot_eyes.setPixelColor(2, 0xffff00);
  moonbot_eyes.setPixelColor(3, 0xffff00);
  moonbot_eyes.setPixelColor(4, 0xffff00);
  moonbot_eyes.setPixelColor(5, 0x000000);
  moonbot_eyes.setPixelColor(6, 0x000000);
  moonbot_eyes.setPixelColor(7, 0x000000);
  moonbot_eyes.setPixelColor(8, 0xffff00);
  moonbot_eyes.setPixelColor(9, 0xffff00);
  moonbot_eyes.setPixelColor(10, 0xffff00);
  moonbot_eyes.setPixelColor(11, 0x000000);
  moonbot_eyes.show();
  if (millis() - last_action_time > 2000) {
    last_action_time = millis();
    speaker.play((char*)"0214");

  }
  while (MU0.LsReadProximity() > 15) {
  }
  state = THANK;
}

void Thank() {
  moonbot_eyes.setPixelColor(0, 0x00ffff);
  moonbot_eyes.setPixelColor(1, 0x00ffff);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x00ffff);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x00ffff);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  if (millis() - last_action_time > 1000) {
    last_action_time = millis();
    speaker.play((char*)"0205");
    delay(250);
    m_servo[kServo3].write(head_angle + 7);
    delay(250);
    m_servo[kServo3].write(head_angle + 0);

  }
  state = TRACK;
}

void setup(){
  m_servo[kServo1].attach(kServo1);
  m_servo[kServo4].attach(kServo4);
  moonbot_eyes.begin();
  LED.begin();
  TankBase.begin();
  Serial3.begin(115200);
  head_angle = 90;
  m_servo[kServo3].attach(kServo3);
  MU0.begin(&Serial3);
  while(MU0.VisionBegin(VISION_BODY_DETECT) != MU_OK);
  speaker.begin(Serial2);
  pinMode(moonbotPortToPin(kPort3, kPortPin1), INPUT_PULLUP);
  pinMode(moonbotPortToPin(kPort7, kPortPin1), INPUT_PULLUP);
  TankBase.rpmCorrection(100);
  TankBase.wheelSpacingSet(165);
  m_servo[kServo3].write(head_angle);
  m_servo[kServo4].reverse(true);
  m_servo[kServo1].correction(-6);
  m_servo[kServo4].correction(3);
  m_servo[kServo1].write(90);
  m_servo[kServo4].write(90);
  moonbot_eyes.setPin(moonbotPortToPin(kPort1, kPortPin1));
  moonbot_eyes.setBrightness(66);
  for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
  {//eyes circle
      colorWipe(moonbot_eyes, (0), 40);
      colorWipe(moonbot_eyes, 0xFFFF, 40);
  }
  for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
  LED.setBrightness(66);
  MU0.LsBegin(LS_PROXIMITY_ENABLE);
  while (!((!digitalRead(MOONBOT_PIN_BUTTON_A)) || digitalRead(moonbotPortToPin(kPort3, kPortPin1)))) {
    LED.setPixelColor(0, 0xffff00);
    LED.setPixelColor(1, 0x000000);
    LED.show();
    delay(100);
    LED.setPixelColor(0, 0x000000);
    LED.setPixelColor(1, 0x000000);
    LED.show();
    delay(100);
  }
  state = 0;
  TRACK = 0;
  DELIVER = 1;
  THANK = 2;
  last_action_time = millis();
}

void loop(){
  switch (state) {
   case 0:
    Track();
    break;
   case 1:
    Deliver();
    break;
   case 2:
    Thank();
    break;
  }

}

Candy Server Full - Arduino

C/C++
#include <Arduino.h>
#include <MuVisionSensor.h>
#include <MoonBot.h>

MuVisionSensor MU0(0x60);
volatile int head_angle;
volatile int proximate_threshold;
volatile int state;
volatile int SNORE;
volatile int SEARCH;
volatile int TRACK;
volatile int DELIVER;
volatile int THANK;
volatile int LIFTED;
volatile int _search_stage;
volatile int _search_direction;
volatile int _search_step;
volatile float energy;
volatile long _last_detect_time;
volatile long greeting_stage;
volatile long _last_greeting_time;
volatile long _snore_time;
volatile long pick_time;
volatile long _last_cry;

void SearchPeople();
void Track();
void Greeting();
void BlinkRight(int blink_delay);
void Snore();
void Deliver();
void TrackPeople();
void Lifted();
void Thank();
void setup();
void loop();

void SearchPeople() {
  _search_stage = 0;
  LED.setBrightness(100);
  LED.setPixelColor(0, 0xff0000);
  LED.setPixelColor(1, 0xff0000);
  LED.show();
  Serial.println("Searching people...");
  TankBase.stop();
  while (true) {
    Serial.println(String("  Searching stage ") + String(_search_stage));
    switch (_search_stage) {
     case 0:
      _search_direction = 1;
      _search_step = 6;
      break;
     case 1:
      _search_direction = -1;
      _search_step = 12;
      break;
     case 2:
      _search_direction = 1;
      _search_step = 24;
      break;
     case 3:
      _search_direction = -1;
      _search_step = 24;
      break;
     case 4:
      _search_direction = 1;
      _search_step = 12;
      break;
    }
    Serial.println(String("  Searching step") + String((_search_step * _search_direction)));
    Serial.println("    Turning ...");
    for (int i = (1); i <= (_search_step); i = i + (1)) {
      if (MU0.GetValue(VISION_BODY_DETECT, kStatus)) {
        state = TRACK;
        if (true) {
          return;
        }

      }
      if (_search_direction > 0) {
        Motor1.write(100);
        Motor2.write(-100);

      } else {
        Motor1.write(-100);
        Motor2.write(100);

      }
    }
    TankBase.stop();
    Serial.println("    Head up/down ...");
    for (int i = 1; i <= 6; i = i + (1)) {
      if (MU0.GetValue(VISION_BODY_DETECT, kStatus)) {
        state = TRACK;
        if (true) {
          return;
        }

      }
      head_angle = m_servo[kServo3].read() + random(-2, 2);
      head_angle = constrain(head_angle, 90, 70);
      m_servo[kServo3].write(head_angle);
      delay(500);
    }
    _search_stage = _search_stage + 1;
    if (_search_stage == 5) {
      state = SNORE;
      if (true) {
        return;
      }

    }
    if (!(!digitalRead(moonbotPortToPin(kPort5, kPortPin1))) && !(!digitalRead(moonbotPortToPin(kPort5, kPortPin2)))) {
      state = LIFTED;
      if (true) {
        return;
      }

    }
  }
}

void Track() {
  LED.setPixelColor(0, 0x00ff00);
  LED.setPixelColor(1, 0x00ff00);
  LED.show();
  Serial.println("Following people...");
  energy = 100;
  _last_detect_time = millis();
  while (true) {
    if (MU0.GetValue(VISION_BODY_DETECT, kStatus)) {
      _last_detect_time = millis();
      TrackPeople();

    } else {
      TankBase.stop();
      Serial.println("  People not found.");
      if (millis() > _last_detect_time + 5000) {
        Serial.println("  Exit to people search.");
        greeting_stage = 0;
        state = SEARCH;
        if (true) {
          return;
        }

      }

    }
    if (energy < 1) {
      greeting_stage = 0;
      if (true) {
        return;
      }

    }
    if (MU0.LsReadProximity() > proximate_threshold) {
      Serial.println("Exit due to proximity detection");
      greeting_stage = 0;
      state = DELIVER;
      if (true) {
        return;
      }

    }
    if (!(!digitalRead(moonbotPortToPin(kPort5, kPortPin1))) && !(!digitalRead(moonbotPortToPin(kPort5, kPortPin2)))) {
      state = LIFTED;
      if (true) {
        return;
      }

    }
  }
}

void Greeting() {
  if (millis() > _last_greeting_time + 4000) {
    Serial.println("Generate new greeting");
    _last_greeting_time = millis();
    switch (greeting_stage) {
     case 0:
      if (random(-100, 100) > 0) {
        speaker.play((char*)"0201");

      } else {
        speaker.play((char*)"0202");

      }
      greeting_stage = greeting_stage + 1;
      break;
     case 1:
      speaker.play((char*)"0204");
      greeting_stage = greeting_stage + 1;
      break;
     case 2:
      switch (random(0, 4)) {
       case 0:
        speaker.play((char*)"0209");
        break;
       case 1:
        speaker.play("2001");
        m_servo[kServo1].write(85);
        m_servo[kServo4].write(85);
        delay(1200);
        m_servo[kServo1].write(90);
        m_servo[kServo4].write(90);
        break;
       case 2:
        speaker.play((char*)"0210");
        break;
       case 3:
        speaker.play((char*)"0212");
        break;
      }
      break;
    }
    switch (random(0, 4)) {
     case 0:
      if (MU0.GetValue(VISION_BODY_DETECT, kWidthValue) < 30) {
        for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
        {//eyes blink
            unsigned int action_delay = 30;
            moonbot_eyes.setPixelColor(0, 0);
            moonbot_eyes.setPixelColor(6, 0);
            moonbot_eyes.show();
            delay(action_delay);
            moonbot_eyes.setPixelColor(1, 0);
            moonbot_eyes.setPixelColor(5, 0);
            moonbot_eyes.setPixelColor(7, 0);
            moonbot_eyes.setPixelColor(11, 0);
            moonbot_eyes.show();
            delay(action_delay);
            moonbot_eyes.setPixelColor(2, 0);
            moonbot_eyes.setPixelColor(4, 0);
            moonbot_eyes.setPixelColor(8, 0);
            moonbot_eyes.setPixelColor(10, 0);
            moonbot_eyes.show();
            delay(action_delay);
            moonbot_eyes.setPixelColor(3, 0);
            moonbot_eyes.setPixelColor(9, 0);
            moonbot_eyes.show();
            delay(action_delay);
            moonbot_eyes.setPixelColor(3, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(9, 0, 0xFF, 0xFF);
            moonbot_eyes.show();
            delay(action_delay);
            moonbot_eyes.setPixelColor(2, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(4, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(8, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(10, 0, 0xFF, 0xFF);
            moonbot_eyes.show();
            delay(action_delay);
            moonbot_eyes.setPixelColor(1, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(5, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(7, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(11, 0, 0xFF, 0xFF);
            moonbot_eyes.show();
            delay(action_delay);
            moonbot_eyes.setPixelColor(0, 0, 0xFF, 0xFF);
            moonbot_eyes.setPixelColor(6, 0, 0xFF, 0xFF);
            moonbot_eyes.show();
        }
        for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }

      } else {
        BlinkRight(80);

      }
      break;
     case 1:
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      {//eyes circle
          colorWipe(moonbot_eyes, (0), 40);
          colorWipe(moonbot_eyes, 0xFFFF, 40);
      }
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      break;
     case 2:
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      MoonBotEyesLook(moonbot_eyes, kEyesLookUp, 0x00FFFF);
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      break;
     case 3:
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      {//eyes smile
          moonbot_eyes.clear();
          moonbot_eyes.setPixelColor(0, 0x00FFFF);
          moonbot_eyes.setPixelColor(1, 0x00FFFF);
          moonbot_eyes.setPixelColor(5, 0x00FFFF);
          moonbot_eyes.setPixelColor(6, 0x00FFFF);
          moonbot_eyes.setPixelColor(7, 0x00FFFF);
          moonbot_eyes.setPixelColor(11, 0x00FFFF);
          moonbot_eyes.show();
      }
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      break;
    }

  }
}

void BlinkRight(int blink_delay) {
  moonbot_eyes.setPixelColor(0, 0x00ffff);
  moonbot_eyes.setPixelColor(1, 0x00ffff);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x00ffff);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x00ffff);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  delay(blink_delay);
  moonbot_eyes.setPixelColor(0, 0x000000);
  moonbot_eyes.setPixelColor(1, 0x00ffff);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x00ffff);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x00ffff);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  delay(blink_delay);
  moonbot_eyes.setPixelColor(0, 0x000000);
  moonbot_eyes.setPixelColor(1, 0x000000);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x000000);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x000000);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  delay(blink_delay);
  moonbot_eyes.setPixelColor(0, 0x000000);
  moonbot_eyes.setPixelColor(1, 0x000000);
  moonbot_eyes.setPixelColor(2, 0x000000);
  moonbot_eyes.setPixelColor(3, 0x000000);
  moonbot_eyes.setPixelColor(4, 0x000000);
  moonbot_eyes.setPixelColor(5, 0x000000);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  delay(blink_delay);
  moonbot_eyes.setPixelColor(0, 0x000000);
  moonbot_eyes.setPixelColor(1, 0x000000);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x000000);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x000000);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  delay(blink_delay);
  moonbot_eyes.setPixelColor(0, 0x000000);
  moonbot_eyes.setPixelColor(1, 0x00ffff);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x00ffff);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x00ffff);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  delay(blink_delay);
  moonbot_eyes.setPixelColor(0, 0x00ffff);
  moonbot_eyes.setPixelColor(1, 0x00ffff);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x00ffff);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x00ffff);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
}

void Snore() {
  if (millis() - _snore_time > 5000) {
    _snore_time = millis();
    speaker.play((char*)"0226");

  }
  if (MU0.GetValue(VISION_BODY_DETECT, kStatus)) {
    speaker.play("2002");
    delay(1000);
    state = TRACK;
    if (true) {
      return;
    }

  }
}

void Deliver() {
  head_angle = 80;
  m_servo[kServo3].write(head_angle);
  TankBase.stop();
  moonbot_eyes.setPixelColor(0, 0x000000);
  moonbot_eyes.setPixelColor(1, 0x000000);
  moonbot_eyes.setPixelColor(2, 0xffff00);
  moonbot_eyes.setPixelColor(3, 0xffff00);
  moonbot_eyes.setPixelColor(4, 0xffff00);
  moonbot_eyes.setPixelColor(5, 0x000000);
  moonbot_eyes.setPixelColor(6, 0x000000);
  moonbot_eyes.setPixelColor(7, 0x000000);
  moonbot_eyes.setPixelColor(8, 0xffff00);
  moonbot_eyes.setPixelColor(9, 0xffff00);
  moonbot_eyes.setPixelColor(10, 0xffff00);
  moonbot_eyes.setPixelColor(11, 0x000000);
  moonbot_eyes.show();
  if (millis() - pick_time > 2000) {
    pick_time = millis();
    speaker.play((char*)"0214");

  }
  while (MU0.LsReadProximity() > 15) {
  }
  if (millis() - pick_time > 1000) {
    pick_time = millis();
    state = THANK;

  } else {
    state = SEARCH;

  }
}

void TrackPeople() {
  head_angle = m_servo[kServo3].read();
  if (MU0.GetValue(VISION_BODY_DETECT, kYValue) < 45) {
    m_servo[kServo3].write(head_angle - 2);
    energy = energy + 2;

  } else if (MU0.GetValue(VISION_BODY_DETECT, kYValue) > 55) {
    m_servo[kServo3].write(head_angle + 2);
    energy = energy + 2;
  }
  if (MU0.GetValue(VISION_BODY_DETECT, kXValue) < 45) {
    Motor1.write(100);
    Motor2.write(-100);
    energy = energy + 2;

  } else if (MU0.GetValue(VISION_BODY_DETECT, kXValue) > 55) {
    Motor1.write(-100);
    Motor2.write(100);
    energy = energy + 2;
  } else {
    TankBase.stop();
    Serial.println(String("  People Locked, energy=") + String(energy));
    if (energy >= 20) {
      Greeting();

    }
    energy = energy - 0.5;

  }
  energy = constrain(energy, 0, 100);
  LED.setBrightness(energy);
  LED.setPixelColor(0, 0x00ff00);
  LED.setPixelColor(1, 0x00ff00);
  LED.show();
}

void Lifted() {
  TankBase.stop();
  speaker.play((char*)"0227");
  _last_cry = millis();
  while (!(!digitalRead(moonbotPortToPin(kPort5, kPortPin1))) && !(!digitalRead(moonbotPortToPin(kPort5, kPortPin2)))) {
    if (millis() > _last_cry + 1500) {
      speaker.play((char*)"0230");
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
      {//eyes angry
          for (long int i = 0; i <= 200; i = i + (4)) {
              moonbot_eyes.fill(i<<16, 0, 0);
              moonbot_eyes.show();
              delay(2);
          }
          for (long int i = 200; i >= 0; i = i-4) {
              moonbot_eyes.fill(i<<16, 0, 0);
              moonbot_eyes.show();
              delay(1);
          }
          for (long int i = 0; i <= 200; i = i + (4)) {
              moonbot_eyes.fill(i<<16, 0, 0);
              moonbot_eyes.show();
              delay(2);
          }
      }
      for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
      _last_cry = millis();

    }
  }
  state = SEARCH;
}

void Thank() {
  speaker.play((char*)"0205");
  delay(250);
  m_servo[kServo3].write(head_angle + 7);
  delay(250);
  m_servo[kServo3].write(head_angle + 0);
  moonbot_eyes.setPixelColor(0, 0x00ffff);
  moonbot_eyes.setPixelColor(1, 0x00ffff);
  moonbot_eyes.setPixelColor(2, 0x00ffff);
  moonbot_eyes.setPixelColor(3, 0x00ffff);
  moonbot_eyes.setPixelColor(4, 0x00ffff);
  moonbot_eyes.setPixelColor(5, 0x00ffff);
  moonbot_eyes.setPixelColor(6, 0x00ffff);
  moonbot_eyes.setPixelColor(7, 0x00ffff);
  moonbot_eyes.setPixelColor(8, 0x00ffff);
  moonbot_eyes.setPixelColor(9, 0x00ffff);
  moonbot_eyes.setPixelColor(10, 0x00ffff);
  moonbot_eyes.setPixelColor(11, 0x00ffff);
  moonbot_eyes.show();
  state = SEARCH;
}

void setup(){
  Serial.begin(9600);
  Serial3.begin(115200);
  TankBase.begin();
  head_angle = 90;
  m_servo[kServo3].attach(kServo3);
  m_servo[kServo4].attach(kServo4);
  m_servo[kServo1].attach(kServo1);
  moonbot_eyes.begin();
  LED.begin();
  proximate_threshold = 15;
  state = 0;
  SNORE = 0;
  SEARCH = 1;
  TRACK = 2;
  DELIVER = 3;
  THANK = 4;
  LIFTED = 5;
  Serial.println("Setup Vision Sensor");
  MU0.begin(&Serial3);
  while(MU0.VisionBegin(VISION_BODY_DETECT) != MU_OK);
  Serial.println("Setup Eye, Speaker, Touch");
  speaker.begin(Serial2);
  pinMode(moonbotPortToPin(kPort3, kPortPin1), INPUT_PULLUP);
  pinMode(moonbotPortToPin(kPort7, kPortPin1), INPUT_PULLUP);
  Serial.println("Calibrate TankBase");
  TankBase.rpmCorrection(100);
  TankBase.wheelSpacingSet(165);
  Serial.println("Waiting to start...");
  m_servo[kServo3].write(head_angle);
  m_servo[kServo4].reverse(true);
  m_servo[kServo1].correction(-6);
  m_servo[kServo4].correction(3);
  m_servo[kServo1].write(90);
  m_servo[kServo4].write(90);
  moonbot_eyes.setPin(moonbotPortToPin(kPort1, kPortPin1));
  moonbot_eyes.setBrightness(66);
  for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(0); }
  {//eyes circle
      colorWipe(moonbot_eyes, (0), 40);
      colorWipe(moonbot_eyes, 0xFFFF, 40);
  }
  for (size_t i = 0; i < kServoNum; ++i) { m_servo[i].power(1); }
  LED.setBrightness(66);
  MU0.LsBegin(LS_PROXIMITY_ENABLE);
  pinMode(moonbotPortToPin(kPort5, kPortPin1), INPUT);
  pinMode(moonbotPortToPin(kPort5, kPortPin2), INPUT);
  while (!((!digitalRead(MOONBOT_PIN_BUTTON_A)) || digitalRead(moonbotPortToPin(kPort3, kPortPin1)))) {
    LED.setPixelColor(0, 0xffff00);
    LED.setPixelColor(1, 0x000000);
    LED.show();
    delay(100);
    LED.setPixelColor(0, 0x000000);
    LED.setPixelColor(1, 0x000000);
    LED.show();
    delay(100);
  }
  if (MU0.LsReadProximity() > proximate_threshold) {
    proximate_threshold = MU0.LsReadProximity();

  }
  _search_stage = 0;
  _search_direction = 0;
  _search_step = 0;
  energy = 0;
  _last_detect_time = 0;
  greeting_stage = 0;
  _last_greeting_time = 0;
  _snore_time = millis();
  pick_time = millis();
  _last_cry = 0;
}

void loop(){
  switch (state) {
   case 0:
    Snore();
    break;
   case 1:
    SearchPeople();
    break;
   case 2:
    Track();
    break;
   case 3:
    Deliver();
    break;
   case 4:
    Thank();
    break;
   case 5:
    Lifted();
    break;
  }

}

Credits

Tianli Yu

Tianli Yu

3 projects • 5 followers

Comments