Summary

Randy the Robot is a self-contained open cube with a personality! He has two IR sensors: one on top and one behind him. Without any human interaction, he likes to turn in circles. However, if you get closer to his top IR sensor, he will react by doing one of three things: move faster, move slower, or wave his hand at you to say hello. If you get closer to his back IR sensor, he will wonder what is there and turn around quickly to see what (or who!) is behind him.

Video

Arduino Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <Servo.h>
 
// A -> left motor
// B -> right motor
#define MOT_B1_PIN 6
#define MOT_B2_PIN 5
#define MOT_A1_PIN 10
#define MOT_A2_PIN 11
#define LEFT_MOTOR_CIRCLE_SPEED 100
#define RIGHT_MOTOR_CIRCLE_SPEED 130
static int wheel_speed_left = LEFT_MOTOR_CIRCLE_SPEED;
static int wheel_speed_right = RIGHT_MOTOR_CIRCLE_SPEED;
 
#define SERVO_PIN 9
#define SERVO_UPPER_LIM 60
#define SERVO_LOWER_LIM 5
#define SERVO_INCR_AMOUNT 5
 
#define IR_BACK_PIN A2
#define IR_TOP_PIN A0
static int back_ir_threshold = int(random(1, 6));
static int back_ir_counter = 0;
static int top_ir_counter = 0;
 
Servo small_servo;
int servo_pos = 0;
int servo_dir = 1;
 
#define RANDOM_SEED A1
 
void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN) {
  if (pwm < 0) { // reverse speeds
    analogWrite(IN1_PIN, -pwm);
    digitalWrite(IN2_PIN, LOW);
 
  } else { // stop or forward
    digitalWrite(IN1_PIN, LOW);
    analogWrite(IN2_PIN, pwm);
  }
}
 
void incrementServo() {
  int tmp_pos = servo_pos + servo_dir * SERVO_INCR_AMOUNT;
 
  if (((servo_dir == 1) && (tmp_pos > SERVO_UPPER_LIM)) ||
    ((servo_dir == -1) && (tmp_pos < SERVO_LOWER_LIM))) {
    servo_dir = servo_dir * -1;
    incrementServo();
  }
  else {
    servo_pos = tmp_pos;
    small_servo.write(servo_pos);
  }
}
 
// check if sensed distance is between specified threshold
bool check_IR(int IR_PIN){
  float vol = analogRead(IR_PIN)*(5.0/1024);
  float dist = 2914/(vol + 5) - 1;
  return (dist < 500);
}
 
float read_IR(int IR_PIN){
  float vol = analogRead(IR_PIN)*(5.0/1024);
  float dist = 2914/(vol + 5) - 1;
  return dist;
}
 
void idle_movement(){
// move in figure 8 or circle pattern
  set_motor_pwm(wheel_speed_left, MOT_A1_PIN, MOT_A2_PIN);
  set_motor_pwm(wheel_speed_right, MOT_B1_PIN, MOT_B2_PIN);
}
 
void wave_hand(){
  unsigned long start_time = millis();
  while ((millis()-start_time) < 1000){
    incrementServo();
    delay(30);
  }
}
 
void turn_around(){
  unsigned long start_time = millis();
  while ((millis()-start_time) < 1000){
    set_motor_pwm(LEFT_MOTOR_CIRCLE_SPEED, MOT_A1_PIN, MOT_A2_PIN);
    set_motor_pwm(-RIGHT_MOTOR_CIRCLE_SPEED, MOT_B1_PIN, MOT_B2_PIN);
  }
  while ((millis()-start_time) < 1000){
    set_motor_pwm(-LEFT_MOTOR_CIRCLE_SPEED, MOT_A1_PIN, MOT_A2_PIN);
    set_motor_pwm(RIGHT_MOTOR_CIRCLE_SPEED, MOT_B1_PIN, MOT_B2_PIN);
  }
}
 
void turn_around_fast(){
  unsigned long start_time = millis();
  while ((millis()-start_time) < 1000){
    set_motor_pwm(LEFT_MOTOR_CIRCLE_SPEED*1.5, MOT_A1_PIN, MOT_A2_PIN);
    set_motor_pwm(-RIGHT_MOTOR_CIRCLE_SPEED*1.5, MOT_B1_PIN, MOT_B2_PIN);
  }
  while ((millis()-start_time) < 1000){
  set_motor_pwm(-LEFT_MOTOR_CIRCLE_SPEED*1.5, MOT_A1_PIN, MOT_A2_PIN);
  set_motor_pwm(RIGHT_MOTOR_CIRCLE_SPEED*1.5, MOT_B1_PIN, MOT_B2_PIN);
  }
}
 
void back_ir_behavior(){
  if (back_ir_counter < back_ir_threshold) {
    turn_around();
  } else {
    turn_around_fast();
    randomSeed(analogRead(RANDOM_SEED));
    back_ir_threshold = int(random(1,6));
    back_ir_counter = 0;
  }
}
 
void top_ir_behavior(){
  randomSeed(analogRead(RANDOM_SEED));
  int rand_val = int(random(100));
  Serial.println(rand_val % 3);
 
  if (rand_val % 3 == 0){
    set_motor_pwm(0, MOT_A1_PIN, MOT_A2_PIN);
    set_motor_pwm(0, MOT_B1_PIN, MOT_B2_PIN);
    wave_hand();
  }else if (rand_val % 3 == 1){
    wheel_speed_left = LEFT_MOTOR_CIRCLE_SPEED * 0.8;
    wheel_speed_right = RIGHT_MOTOR_CIRCLE_SPEED * 0.8;
    idle_movement();
    delay(1000);
  }else{
    wheel_speed_left = LEFT_MOTOR_CIRCLE_SPEED * 1.2;
    wheel_speed_right = RIGHT_MOTOR_CIRCLE_SPEED * 1.2;
    idle_movement();
    delay(1000);
  }
 
  wheel_speed_left = LEFT_MOTOR_CIRCLE_SPEED;
  wheel_speed_right = RIGHT_MOTOR_CIRCLE_SPEED;
}
 
void setup() {
  // Initialize IR sensors
  // pinMode(IR_TOP_PIN, INPUT);
  // pinMode(IR_BACK_PIN, INPUT);
 
  // Initialize the motor driver control pins to output drive mode.
  pinMode(MOT_B1_PIN, OUTPUT);
  pinMode(MOT_B2_PIN, OUTPUT);
  pinMode(MOT_A1_PIN, OUTPUT);
  pinMode(MOT_A2_PIN, OUTPUT);
 
  // Initialize servo pin
  small_servo.attach(SERVO_PIN);
 
  // Start with drivers off, motors coasting.
  digitalWrite(MOT_B1_PIN, LOW);
  digitalWrite(MOT_B2_PIN, LOW);
  digitalWrite(MOT_A1_PIN, LOW);
  digitalWrite(MOT_A2_PIN, LOW);
 
  Serial.begin(9600);
}
 
void loop() {
  static int state_index = 0;
 
  switch(state_index) {
    case 0:
      Serial.println("State 0");
      idle_movement();
      if (check_IR(IR_BACK_PIN)){
        state_index = 1;
      } else if (check_IR(IR_TOP_PIN)){
        state_index = 2;
      }
      break;
    case 1:
      Serial.println("State 1");
      back_ir_behavior();
      if (check_IR(IR_BACK_PIN)){
        state_index = 1;
      } else if (check_IR(IR_TOP_PIN)){
        state_index = 2;
      } else {
        state_index = 0;
      }
      break;
    case 2:
      Serial.println("State 2");
      top_ir_behavior();
      if (check_IR(IR_BACK_PIN)){
        state_index = 1;
      } else if (check_IR(IR_TOP_PIN)){
        state_index = 2;
      } else {
        state_index = 0;
      }
      break;
  }
  // Serial.println(read_IR(IR_BACK_PIN));
  // Serial.println(check_IR(IR_BACK_PIN));
}

CAD Files

You can find the CAD files here.