ITTT - Attention Wanting Robot - Mike Veldkamp 1D

by InfernoMV in Circuits > Arduino

1067 Views, 9 Favorites, 0 Comments

ITTT - Attention Wanting Robot - Mike Veldkamp 1D

ITTT Robot

HKU Assignment

Welcome to this "If This Than That" project.

For the final result of this project I made a small little wooden robot. The robot has different facial emotions depending on what's happening, if he is awake and you press the button on his head he becomes happy. If you don't stand infront of the sensor or give him attention he will become sad, and eventually even mad!

In this Instructable I will talk about why I decided for this to be my end design / project and the steps I took to make this.

Supplies

Materials:

- Arduino Uno R3

- Ultrasonic Sensor

- 2x Micro Servomotor

- LCD Display

- 2x Button

- Wooden planks (For body and arms)

- Wood glue

- Bolts

Tools:

- Hot glue gun

- Screwdriver

- Drill

- Solderer

Technical

- PC / Laptop

- Arduino Program (For code)

Learning to Work With Arduino

Arduino-Traffic-Light-Project-0001-hero-scaled.jpg
Skecth_Traffic_Light.png
elnino21.jpg

I had build up some experience with Arduino because of the lessons of "Using Arduino For Evil". Which meant that the starting lessons were mostly the same for me. I still did everything again, just to remind myself about how everything works. It took me a while to actually start working on more difficult creations, but I quickly got the hang of it.

Arduino is a fun thing to work with, but also causes a lot of annoyance until you finally fix that one small problem. But then again, you will be sooo relieved when it does work.

I started way to late with doing actual research for ideas, which meant I had less time to actually make the project that I was going to choose.

But when I actually started, I thought of letting two arduino's communicate with eachother and make it so you can use them to send messages and emotions to one another. While doing research for this I found a similar project, with a small white robot and a button on his chest. It was also a little later after this that I decided that I wouldn't be able to create this with my available budget and time, so I decided to keep it simple and only make one of them.

So after this I started on the project while using the white Arduino robot as a base.

Link to inspiration

Starting Project

LCD_Base_bb_Fritz.png

I started off with some old code I used before that gives the lcd some different eye expressions. This code made it so it switches between the different expressions with a delay between them. This wasn't what I wanted for this project of course, but it was a good starting point.

From here on I changed it in such a way that the buttons made sure he woke up and became happy, since you gave him attention. If you don't do anything for a while I wanted him to go back to sleep, and eventually be sad or angry, since he wants your attention. I just needed to figure out how to do all of this.

// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int  sleepyFace[2][16]={
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0}
};
int  happyFace[2][16]={
{0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0},
{0,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0}
};
int  angryFace[2][16]={
{0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0}
};
int  sadFace[2][16]={
{0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0},
{0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0}
};
int  normalFace[2][16]={
{0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0},
{0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0}
};
void setup() {
 Serial.begin(9600);
 lcd.begin(16, 2);// set up the LCD's number of columns and rows: 
 analogWrite(8,15);
}
void loop() {
 neutral();
 delay(2000);
 
 happy();
 delay(2000);
 
 sleepy();
 delay(2000);  
 angry();
 delay(2000);  
 sad();
 delay(2000); 
 lcd.clear();
}
void neutral(){
 printFace(normalFace);
}
void happy(){
 printFace(happyFace);
}
void angry(){
 printFace(angryFace);
}
void sad(){
 printFace(sadFace);
}
void sleepy(){
 printFace(sleepyFace);
}
void printFace(int emo[][16]){
 lcd.clear();
 for(int i=0;i<2;i++){
   for(int j=0; j<16;j++){
     lcd.setCursor(j, i);    
     if(emo[i][j]==1){
       lcd.write(255);
     }
   }
 }
}

Of course only making the face change is boring, which is why I wanted to add some arms too, how to add those is something I will talk about in the next step. Since it's not really that hard, but can be pretty confusing and annoying if you do it wrong.

Adding Sensor and Arms

ultrasonic-sensor-wiring-diagram.png
servo-motor-with-arduino-uno-wiring-diagram-schematic-circuit-tutorial.png

I started with adding the Sensor, using an if-statement to figure out how far away you can be from it, but also to figure out what emotion it should show depending on a specific situation.

I decided to simply add into the code that if there is something in front of the sensor it will wake the robot, I wanted it to wake up either when it is sleeping, or when it's sad.

To calculate the distance I used a simple calculation of the time * the speed it travels at, dividing it by two since it travels somewhere and back, so if you want the distance you need to have half the value of the calculation.

**Code for the Sensor**

 distance = duration*0.034/2;

 if (distance <= 60 && distance >= 0 && (isAwake == true) && (buttonState == HIGH)) {
    neutral();
    isClose = true;
    if(statCounter >= 20) {
      statCounter = 0;
    }
    isHappy = false;
   }

    if (distance <= 60 && distance >= 0 && (isAwake == true) && (buttonState == HIGH) && (isSad == true)) {
    neutral();
    isClose = true;
    if(statCounter >= 20) {
      statCounter = 0;
    }
    isSad = false;
    isHappy = false;
   }
   
   if (distance >= 60 && distance >= 0 && (isAwake == true) && (isSad == false)) {
     sleepy();
     isClose = false;
     isHappy = false;
   }
  }

For the arms the code is pretty simple, with the use of two for-loops we make them rotate from their beginposition to 180 degrees, which is down. Doing this makes the arms move up and down, by adding an if statement I made sure it would only move them when the robot was happy.

The Servomotor only moves in one way, but since I had two arms that meant I had to rotate the other one so it went in the same direction, I did this by doing the position minus 180 degrees so it would move reverse from normal.

**Code for the arms**

leftArm.attach(10);
rightArm.attach(13);

if(isHappy == true && (motorActive == true)) {
  for(pos = 0; pos < 180; pos++){
    leftArm.write(180 - pos);
    rightArm.write(pos);
    delay(2);
  }
  for(pos = 180; pos > 0; pos--) {
    leftArm.write(180 - pos);
    rightArm.write(pos);
    delay(2);
  }
 }

Soldering the Arduino and Wires

20210809_032141.jpg

For the soldering I luckily got some help from a friend of mine, he already made his project meaning he knew what he was doing. This made it so that I did all of it a lot quicker then if I had to do it alone, I also didn't have the tools for it, so that was even better.

At first the cables didn't seem to work since my LCD Display didn't show the eyes, but eventually it did. I glued and also used tape to stick some wires together just so they wouldnt accidentally get loose or anything.

You need to connect all the ground wires together, and all the 5V cables together. I didn't need to solder the other ones since I could connect them to the stuff with male to female wires.

Creating the Wooden Body

For the body you don't need a specific shape, it's really up to the maker. I chose a square and rectangle body but you can also make it round, or triangular or anything really.

I decided to use a drill to make holes and use bolts to keep it all together, since I have had multiple situations where the wood didn't stay together with glue, so I only used it to glue the buttons and arms stuck to the body, and the head since it was hard to screw it onto the body. The arduino is located in the lower part, while PCB is inside of the body, there is a hole in most of the body parts to drag the wires through. The buttons can also be placed at different places, but I really liked the belly button and the head, since pressing it on the head might feel like petting it, like an animal.

Final Product

20210808_195422.jpg

And there you have it!

This is my final product, a small but still heavy robot made out of wood.

Once I was finally done with my project I really regretted not having enough time to show it off during the presentations, but I really chose a waayyyy to big of a project and only after not finishing it I changed it to this.

Showing of my cute robot to people would've been very fun, but I am just glad I was able to create something myself with the time that I had.

I do wish I could've made two connecting arduino's but sadly I don't have the many for everything I need.

I have learned a lot from this, and I do hope that you also learned some stuff about how to make this :3

Here is the full code I used, it might not be fully optimised, but I am still learning after all.

#include <LiquidCrystal.h>
#include <Servo.h>

Servo leftArm;
Servo rightArm;
int pos = 0;

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

#define echoPin 7 // attach pin D2 Arduino to pin Echo of HC-SR04
#define trigPin 8 //attach pin D3 Arduino to pin Trig of HC-SR04

int  sleepyFace[2][16] = {
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}
};
int  happyFace[2][16] = {
  {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0},
  {0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0}
};
int  angryFace[2][16] = {
  {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
  {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}
};
int  sadFace[2][16] = {
  {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0},
  {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}
};
int  normalFace[2][16] = {
  {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0},
  {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}
};

unsigned long previousMillis;
int interval = 1000;

bool isAwake = true;
bool isClose = false;
bool buttonPressed = false;
bool button2Pressed = false;
bool isSad = false;
bool isHappy = false;
bool motorActive = false;

const int buttonPin = 9; 
const int buttonPin2 = 6;
int buttonState = 0; 
int button2State = 0; 

void setup() {
  Serial.begin(9600); 
  lcd.begin(16, 2);// set up the LCD's number of columns and rows:
  analogWrite(8, 15);

  leftArm.write(0);
  rightArm.write(0);
  
  leftArm.attach(10);
  rightArm.attach(13);

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
  pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
}

void loop() {
 int duration, distance;
 buttonState = digitalRead(buttonPin);
 button2State = digitalRead(buttonPin2);
 digitalWrite(trigPin, HIGH);
 delay(1);
 digitalWrite(trigPin, LOW);

 static byte statCounter = 0;

 if(isHappy == true && (motorActive == true)) {
  for(pos = 0; pos < 180; pos++){
    leftArm.write(180 - pos);
    rightArm.write(pos);
    delay(2);
  }
  for(pos = 180; pos > 0; pos--) {
    leftArm.write(180 - pos);
    rightArm.write(pos);
    delay(2);
  }
 }

 if(isHappy = false) {
  leftArm.write(0);
  rightArm.write(0);
 }

 duration = pulseIn(echoPin, HIGH);

 if (millis() - previousMillis >= interval)
  {
    if (statCounter == 36)
    {
       statCounter = 0;
    }
    statCounter++;
    Serial.println(statCounter);
    
    previousMillis = millis();
    
    distance = duration*0.034/2;
    
    if (distance <= 60 && distance >= 0 && (isAwake == true) && (buttonState == HIGH)) {
    neutral();
    isClose = true;
    if(statCounter >= 20) {
      statCounter = 0;
    }
    isHappy = false;
   }

    if (distance <= 60 && distance >= 0 && (isAwake == true) && (buttonState == HIGH) && (isSad == true)) {
    neutral();
    isClose = true;
    if(statCounter >= 20) {
      statCounter = 0;
    }
    isSad = false;
    isHappy = false;
   }
   
   if (distance >= 60 && distance >= 0 && (isAwake == true) && (isSad == false)) {
     sleepy();
     isClose = false;
     isHappy = false;
   }
  }

  if (buttonState == LOW &&(isAwake == true) && (isClose == false)) {
     neutral();
     isAwake = false;
     delay(500);
     buttonPressed = true;
     buttonState = HIGH;
     statCounter = 0;
     isHappy = false;
  }

   if (buttonState == LOW &&(isAwake == true) && (isClose == false) && (isSad == true)) {
     neutral();
     isAwake = false;
     delay(500);
     buttonPressed = true;
     buttonState = HIGH;
     isSad = false;
     statCounter = 0;
     isHappy = false;
  }

   if (buttonState == LOW && (buttonPressed == true)) {
     happy();
     isAwake = false;
     statCounter = 0;
     isHappy = true;
     buttonState = HIGH;
  }

   if (buttonState == LOW &&(isAwake == true) && (isClose == true)) {
     happy();
     statCounter = 0;
     isHappy = true;
     buttonState = HIGH;
  }

  if(statCounter == 6) {
    neutral();
    buttonPressed = true;
    isHappy = false;
  }
  
  if (statCounter == 24) {
    sad();
    isSad = true;
    isHappy = false;
  }

  if (statCounter == 36) {
    angry();
    isSad = true;
    isHappy = false;
  }

  if(button2State == LOW && (button2Pressed == false)) {
    motorActive = true;
    button2Pressed = true;
    button2State = HIGH;
  }

  if(button2State == LOW && (button2Pressed == true)) {
    motorActive = false;
    button2Pressed = false;
    button2State = HIGH;
  }
}

void doEmote() {
//  neutral();
//  delay(2000);
//
//  happy();
//  delay(2000);
//  
//  angry();
//  delay(2000);
//
//  sad();
//  delay(2000);
// 
//  lcd.clear();
}

void doHappy(){
  happy();
}

void neutral() {
  printFace(normalFace);
}

void happy() {
  printFace(happyFace);
}

void angry() {
  printFace(angryFace);
}

void sad() {
  printFace(sadFace);
}

void sleepy() {
  printFace(sleepyFace);
}

void printFace(int emo[][16]) {
  lcd.clear();
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 16; j++) {
      lcd.setCursor(j, i);
      if (emo[i][j] == 1) {
        lcd.write(255);
      }
    }
  }
}