// це реалізація студентів, подивитись потім, що тут і як. Є проблеми з реалізацією поворотів
#include <Stepper.h>
#include <Servo.h>
#include "pair.h"
#define PI_VALUE 3.14159
#define LEFT_MOTOR_ENABLE_STATE_DPIN 9
#define LEFT_MOTOR_STEP_DPIN 8
#define LEFT_MOTOR_DIRECTION_DPIN 7
#define RIGHT_MOTOR_ENABLE_STATE_DPIN 6
#define RIGHT_MOTOR_STEP_DPIN 5
#define RIGHT_MOTOR_DIRECTION_DPIN 4
#define SCAN_SERVO_MOTOR_DPIN 10
#define SENSOR_TRIG_DPIN 3
#define SENSOR_ECHO_DPIN 2
const int min_distance = 30; // in cm(value may change)
const int wheel_radius = 4; // in cm(value may change)
const int wheels_axis_width = 15; // in cm(value may change)
const int scan_angle_deviation = 45;
const int motor_steps_for_rotate = 200;
const float step_one_degree_value = (float)motor_steps_for_rotate / 360;
Stepper left_stepper(motor_steps_for_rotate, LEFT_MOTOR_ENABLE_STATE_DPIN, LEFT_MOTOR_STEP_DPIN);
Stepper right_stepper(motor_steps_for_rotate, RIGHT_MOTOR_ENABLE_STATE_DPIN, RIGHT_MOTOR_STEP_DPIN);
Servo scanservo;
int current_servo_position = 90;
std::pair<int, int> scanPlace();
void setup()
{
Serial.begin(115200);
pinMode(SENSOR_TRIG_DPIN, OUTPUT);
pinMode(SENSOR_ECHO_DPIN, INPUT);
pinMode(LEFT_MOTOR_DIRECTION_DPIN, OUTPUT);
pinMode(RIGHT_MOTOR_DIRECTION_DPIN, OUTPUT);
scanservo.attach(SCAN_SERVO_MOTOR_DPIN);
scanservo.write(90);
digitalWrite(LEFT_MOTOR_DIRECTION_DPIN, HIGH);
digitalWrite(RIGHT_MOTOR_DIRECTION_DPIN, HIGH);
delay(1000);
}
void loop()
{
int distance = makeMeasurement();
if(distance <= min_distance)
{
std::pair<int, int> result = scanPlace();
Serial.print("Optimal angle: ");
Serial.println(result.first);
if(result.second <= distance + 5)
{
moveOnDistance(-30);
}
else
{
make_wheel_rotate(result.first);
}
}
else
{
left_stepper.step(5);
right_stepper.step(5);
}
}
void moveOnDistance(const int distance) // if value < 0 - move back. Distance in cm
{
if(distance < 0)
{
digitalWrite(LEFT_MOTOR_DIRECTION_DPIN, LOW);
digitalWrite(RIGHT_MOTOR_DIRECTION_DPIN, LOW);
}
float q_rotates = (float)distance / (2 * PI_VALUE * wheel_radius);
//Serial.print("q_rotates: ");
//Serial.println(q_rotates);
int i_step = 2 * pow(-1, distance < 0);
for(int i = 1; i <= abs(motor_steps_for_rotate * q_rotates * 4); i += abs(i_step))
{
left_stepper.step(i_step);
right_stepper.step(i_step);
delay(1);
}
//left_stepper.step(motor_steps_for_rotate * q_rotates * 4);
//right_stepper.step(motor_steps_for_rotate * q_rotates * 4);
delay(100);
if(distance < 0)
{
digitalWrite(LEFT_MOTOR_DIRECTION_DPIN, HIGH);
digitalWrite(RIGHT_MOTOR_DIRECTION_DPIN, HIGH);
}
}
int make_wheel_rotate(const int angle)
{
if(angle > 0) // left wheel rotate
{
float q_rotates = getQRotates(angle);
int i_step = 2;
for(int i = 1; i <= motor_steps_for_rotate * q_rotates * 4; i += i_step)
{
left_stepper.step(i_step);
delay(1);
}
// Serial.print("q_rotates: ");
// Serial.println(q_rotates);
// Serial.print("q_steps: ");
// Serial.println(motor_steps_for_rotate * q_rotates * 4);
//left_stepper.step(motor_steps_for_rotate * q_rotates * 4);
delay(100);
}
else if(angle < 0) // right wheel rotate
{
float q_rotates = getQRotates(abs(angle));
// Serial.print("q_rotates: ");
// Serial.println(q_rotates);
// Serial.print("q_steps: ");
// Serial.println(motor_steps_for_rotate * q_rotates * 4);
int i_step = 2;
for(int i = 1; i <= motor_steps_for_rotate * q_rotates * 4; i += i_step)
{
right_stepper.step(i_step);
delay(1);
}
//right_stepper.step(motor_steps_for_rotate * q_rotates * 4);
delay(100);
}
}
int makeMeasurement() // make one measurement and return result
{
digitalWrite(SENSOR_TRIG_DPIN, HIGH);
delayMicroseconds(10);
digitalWrite(SENSOR_TRIG_DPIN, LOW);
int duration = pulseIn(SENSOR_ECHO_DPIN, HIGH) / 58;
return duration;
}
std::pair<int, int> scanPlace() // scan the place, and return optimal angle(left: value < 0; right: value > 0)
{
int measurment_delay = 10;
std::pair<int, int> result;
int prev_optimal_distance = 0;
int optimal_distance = 0;
int optimal_angle = 0;
for(;current_servo_position >= 90 - scan_angle_deviation; current_servo_position--)
{
prev_optimal_distance = optimal_distance;
optimal_distance = makeMeasurement();
if(prev_optimal_distance > optimal_distance)
{
optimal_distance = prev_optimal_distance;
}
else
{
optimal_angle = current_servo_position - 90;
result = { optimal_angle, optimal_distance };
}
scanservo.write(current_servo_position);
delay(measurment_delay);
}
current_servo_position = 90;
scanservo.write(90);
delay(200);
for(;current_servo_position <= 90 + scan_angle_deviation; current_servo_position++)
{
prev_optimal_distance = optimal_distance;
optimal_distance = makeMeasurement();
if(prev_optimal_distance > optimal_distance)
{
optimal_distance = prev_optimal_distance;
}
else
{
optimal_angle = current_servo_position - 90;
result = { optimal_angle, optimal_distance };
}
scanservo.write(current_servo_position);
delay(measurment_delay);
}
current_servo_position = 90;
scanservo.write(90);
delay(200);
return result;
}
float getQRotates(const int angle) // return quantity of wheel rotates by angle
{
return (float)(wheels_axis_width * angle) / (360 * wheel_radius);
}
uno1:A5.2
uno1:A4.2
uno1:AREF
uno1:GND.1
uno1:13
uno1:12
uno1:11
uno1:10
uno1:9
uno1:8
uno1:7
uno1:6
uno1:5
uno1:4
uno1:3
uno1:2
uno1:1
uno1:0
uno1:IOREF
uno1:RESET
uno1:3.3V
uno1:5V
uno1:GND.2
uno1:GND.3
uno1:VIN
uno1:A0
uno1:A1
uno1:A2
uno1:A3
uno1:A4
uno1:A5
drv1:ENABLE
drv1:MS1
drv1:MS2
drv1:MS3
drv1:RESET
drv1:SLEEP
drv1:STEP
drv1:DIR
drv1:GND.1
drv1:VDD
drv1:1B
drv1:1A
drv1:2A
drv1:2B
drv1:GND.2
drv1:VMOT
stepper1:A-
stepper1:A+
stepper1:B+
stepper1:B-
vcc1:VCC
drv2:ENABLE
drv2:MS1
drv2:MS2
drv2:MS3
drv2:RESET
drv2:SLEEP
drv2:STEP
drv2:DIR
drv2:GND.1
drv2:VDD
drv2:1B
drv2:1A
drv2:2A
drv2:2B
drv2:GND.2
drv2:VMOT
stepper2:A-
stepper2:A+
stepper2:B+
stepper2:B-
vcc2:VCC
gnd1:GND
gnd2:GND
ultrasonic1:VCC
ultrasonic1:TRIG
ultrasonic1:ECHO
ultrasonic1:GND
servo1:GND
servo1:V+
servo1:PWM