Please add a public SSH key to your
profile to be able to clone the repository via the SSH protocol.
Pre-render was disabled for this project as it contains too many files. Please click on the files to view them.
robot.cpp
#include "robot.h"
void Robot::init()
{
//hardware
Serial::init();
Time::init();
TwiMaster::init();
MowerMotor::init();
Adc::init();
sei();
//processes
terminal_.init();
button_.init();
bumper_.init();
perimeter_sensor_.init();
led_indicator_.init();
// algorithm_.init();
mower_.init();
drive_motors_.init();
//state
status_ = 0;
//mower
mower_msg_.speed = 255; //max
mower_msg_.is_enable = false;
//drive motors
drive_motors_msg_.is_new_data = true;
drive_motors_msg_.left_set_speed = 0;
drive_motors_msg_.right_set_speed = 0;
drive_motors_msg_.left_real_speed = 0;
drive_motors_msg_.right_real_speed = 0;
drive_motors_msg_.left_counter = 0;
drive_motors_msg_.right_counter = 0;
//bumper
bumper_msg_.left = 0;
bumper_msg_.left_min = 557;
bumper_msg_.left_max = 729;
bumper_msg_.right = 0;
bumper_msg_.right_min = 403;
bumper_msg_.right_max = 577;
bumper_msg_.is_calibration = false;
bumper_msg_.is_save = false;
//perimeter sensor
perimeter_sensor_msg_.signal_offset = 512;
perimeter_sensor_msg_.lps = 0;
perimeter_sensor_msg_.magnitude = 0;
perimeter_sensor_msg_.smooth_magnitude = 0;
perimeter_sensor_msg_.is_inside = false;
perimeter_sensor_msg_.is_new_data = false;
perimeter_sensor_msg_.is_invert_sigcode = false;
perimeter_sensor_msg_.is_offset_calibration_mode = false;
//algorithm
pid_ = Pid(300.0, -300.0, 1.0, 0.0, 0.0);
//begin
state_.push(state_wait);
}
void Robot::loop()
{
// sub fsm
terminal_.run(&status_, &mower_msg_, &drive_motors_msg_, &bumper_msg_,
&perimeter_sensor_msg_);
button_.run(&status_);
bumper_.run(&bumper_msg_);
perimeter_sensor_.run(&perimeter_sensor_msg_);
led_indicator_.run(&status_);
mower_.run(&mower_msg_);
drive_motors_.run(&drive_motors_msg_);
//tick
uint8_t current_state = state_.top();
state_.pop();
switch(current_state)
{
case state_wait:
state_.push(state_perimeter);
break;
case state_stop:
stopMotors();
break;
case state_perimeter:
if(isStuffOnWay()){
stopMotors();
state_.push(state_perimeter);
state_.push(state_avoid_stuff);
}
perimeterFlow();
state_.push(state_perimeter);
break;
case state_avoid_stuff:
if(isStuffOnWay()){
int16_t left = 0;
if(bumper_msg_.left > 50){
left = -WORK_SPEED;
}
int16_t right = 0;
if(bumper_msg_.right > 50){
right = -WORK_SPEED;
}
drive_motors_msg_.setSpeed(left, right);
state_.push(state_avoid_stuff);
}
break;
case state_fill:
break;
default:
break;
}
}
void Robot::stopMotors()
{
drive_motors_msg_.setSpeed(0, 0);
}
void Robot::perimeterFlow()
{
int16_t left_speed = 0;
int16_t right_speed = 0;
int16_t value = 0;
static int16_t last_value = 0;
static uint32_t last_time = 0;
if(perimeter_sensor_msg_.magnitude < 0){
value = -1; //outside
PORTB &= ~(1<<5);
}else if(perimeter_sensor_msg_.magnitude > 0){
value = 1; //inside
PORTB |= (1<<5);
}else{
value = 0; //on wire
}
if(value != last_value){
last_time = Time::now();
last_value = value;
}
int32_t perimeter_value = (Time::now() - last_time) / 10 * value;
int16_t correction = (int16_t)pid_.update(0.0, (float)perimeter_value);
if(WORK_SPEED + correction > MAX_SPEED){
left_speed = MAX_SPEED;
}else if(WORK_SPEED + correction < -MAX_SPEED){
left_speed = -MAX_SPEED;
}else{
left_speed = WORK_SPEED + correction;
}
if(WORK_SPEED - correction > MAX_SPEED){
right_speed = MAX_SPEED;
}else if(WORK_SPEED - correction < -MAX_SPEED){
right_speed = -MAX_SPEED;
}else{
right_speed = WORK_SPEED - correction;
}
drive_motors_msg_.setSpeed(left_speed, right_speed);
}
bool Robot::isStuffOnWay()
{
return bumper_msg_.left >= 100 || bumper_msg_.right >= 100;
}
void Robot::avoidStuff()
{
}