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.
Leave a Reply
You must be logged in to post a comment.