Robot team project

Dependencies:   QEI Motordriver ros_lib_melodic

main.cpp

Committer:
dnulty
Date:
2019-12-10
Revision:
20:074a3638c702
Parent:
19:56bc8226b967
Child:
21:2dcd6d0d004d
Child:
23:d1dc248b4e54

File content as of revision 20:074a3638c702:

#include "mbed.h"
#include <ros.h>
#include <std_msgs/Empty.h>
#include <std_msgs/Int32.h>
#include <std_msgs/String.h>
#include <mbed_custom_msgs/motor_msg.h>
#include <motordriver.h>
#include "QEI.h"
#include <cstdlib>
#include "Sensor.h"

// Set up serial to pc
//Serial pc(SERIAL_TX, SERIAL_RX); 

//Threading for sensor readings
Thread thread1;
Thread thread2;
Mutex SerialMutex;
        
// Set up I²C on the STM32 NUCLEO-401RE 
#define addr1   (0x29) 
#define addr2   (0x2A)  
#define addr3   (0x2B)
#define addr4   (0x2C)

#define S1 PC_8
#define S2 PC_9
#define S3 PC_10
#define S4 PC_11
#define S5 PC_12
#define S6 PD_2
#define S7 PG_2
#define S8 PG_3 

// VL6180x sensors
Sensor sensor_back(I2C_SDA, I2C_SCL, S1);
Sensor sensor_left(I2C_SDA, I2C_SCL, S3);
Sensor sensor_forward(I2C_SDA, I2C_SCL, S5);
Sensor sensor_right(I2C_SDA, I2C_SCL, S7);

// Floats for sensor readings
float sensor_forward_reading;
float sensor_back_reading;
float sensor_left_reading;
float sensor_right_reading;

//Initialised motor speed
double speed=0.6;
//used to change control to set distances of continous movement
bool control_type = 1;;
//used for the switch cases and the distance travelled
int32_t motor_option;
int32_t pulse = 6000;

// Set motorpins for driving
Motor A(PB_13, PB_15, PC_6, 1); // pwm, fwd, rev, can brake
Motor B(PB_4, PC_7, PA_15, 1); // pwm, fwd, rev, can brake
QEI wheel_A (PB_12, PA_4, NC, 3576, QEI::X4_ENCODING); //counts per rev = 12 * 298:1, use quadrature encoding
QEI wheel_B (PB_5, PB_3, NC, 3576, QEI::X4_ENCODING); //counts per rev = 12 * 298:1, use quadrature encoding

//Thread function to update sensor readings
void flip() {
    while(1) {
        SerialMutex.lock();
        
        // Sensor readings
        sensor_forward_reading = sensor_forward.read();
        sensor_back_reading = sensor_back.read();
        sensor_left_reading = sensor_left.read();
        sensor_right_reading = sensor_right.read(); 
        
        SerialMutex.unlock();
        thread1.wait(2);
    }
}

void motor_callback(const mbed_custom_msgs::motor_msg& msg)
{
    motor_option = msg.dir;
    if( (msg.distance <= 0) or (msg.distance > 120) ) {
        pulse = 6000;
    } else {
        pulse = msg.distance * 200; // Est 200 pulses per cm
    }
    
    //motor_option = motor_dir.data;
    thread2.signal_set(1);
}

// Function to move robot
void move(float motorA, float motorB, int distance) {
    float current_pulse_reading = 0;
    
    // Set motors speed
    A.speed(motorA);
    B.speed(motorB);
    
    while(abs(current_pulse_reading) <= distance) {
        current_pulse_reading = wheel_A.getPulses();
        //Stops Robot moving forward if front sensor detects
        if (sensor_back_reading <255 and motorA>0 and motorB>0){
            return;
        }

        //Stops robot reversing if back sensors detects
        if (sensor_forward_reading <255 and motorA<0 and motorB<0){
            return;
        }
    }
}

void square()
{
    float current_pulse_reading = 0;
    
    // - is forward on our robot
    
    for(int i = 0; i<4 ; i++)
        
        {
        current_pulse_reading = 0;
        while(abs(current_pulse_reading) <= 6000)
        {
            A.speed(-speed);
            B.speed(-speed);
            
            current_pulse_reading = wheel_A.getPulses();
            //Stops Robot moving forward if front sensor detects
            if (sensor_forward_reading <255)
                {
                return;
                }
        }
        // need to set motor speed to 0 
        A.speed(0);
        B.speed(0);
        wait(0.05);
        
        A.speed(-speed);
        B.speed(speed);
        while(abs(current_pulse_reading) <= 8688)
        {
            current_pulse_reading = wheel_A.getPulses();
        }
        wheel_B.reset();
        wheel_A.reset();
        }
        A.speed(0);
        B.speed(0);
        wait(0.05);
}

void dance()
{
    wait(5);// required for audacity to play music
    
    for (int i =0; i<5; i++)
    {
        int distance  = (rand()%16000+2000);
        float A_speed = (rand()%2-1);
        float B_speed = (rand()%2-1);
        if((A_speed < 0.4) and (A_speed > -0.4)){
            A_speed = 0.4;
            }
        if((B_speed < 0.4) and (B_speed > -0.4)){
            B_speed = -0.4;
            }
        move(A_speed,B_speed,distance);
        wheel_B.reset();
        wheel_A.reset();
    }    
}

/*    float current_pulse_reading = 0;
    while(abs(current_pulse_reading) <= 5388)
    {
    current_pulse_reading = wheel_A.getPulses();
    A.speed(-speed);
    B.speed(0.0);
    }
    wait(0.05);
    current_pulse_reading = 0;
    wheel_B.reset();
    wheel_A.reset();
    while(abs(current_pulse_reading) <= 5388)
    {
    current_pulse_reading = wheel_A.getPulses();
    A.speed(speed);
    B.speed(0);
    }
    wait(0.05);
    wheel_B.reset();
    wheel_A.reset();
    current_pulse_reading = 0;
    while(abs(current_pulse_reading) <= 5388)
    {
    current_pulse_reading = wheel_B.getPulses();
    A.speed(0);
    B.speed(-speed);
    }
    wait(0.05);
    wheel_B.reset();
    wheel_A.reset();
    current_pulse_reading = 0;
    while(abs(current_pulse_reading) <=5388)
    {
    current_pulse_reading = wheel_B.getPulses();
    A.speed(0);
    B.speed(speed);
    }
    wait(0.05);
    wheel_B.reset();
    wheel_A.reset();
    current_pulse_reading = 0;
    while(abs(current_pulse_reading) <21504)
    {
    current_pulse_reading = wheel_A.getPulses();
    A.speed(-speed);
    B.speed(speed);
    }
    wait(0.05);
    wheel_B.reset();
    wheel_A.reset();
    current_pulse_reading = 0;
    while(abs(current_pulse_reading) <6000)
    {
    current_pulse_reading = wheel_A.getPulses();
    A.speed(-speed);
    B.speed(-speed);
    }
    wait(0.05);
    wheel_B.reset();
    wheel_A.reset();
    current_pulse_reading = 0;
    while(abs(current_pulse_reading) <6000)
    {
    current_pulse_reading = wheel_A.getPulses();
    A.speed(speed);
    B.speed(speed);
    }
    wait(0.05);
    A.speed(0);
    B.speed(0);
    */
    

// Function to set robot direction and distance according to data published on motor_control topic
void control_motor(void) {
    
    while (1){   
        thread2.signal_wait(1);
        
        switch(motor_option) {
            
        // Do nothing - default value published on motor_contorl topic
        case 0: 
            break;
            
        //Forward
        case 1://49
            if (control_type == 1){
                move(-speed, -speed, pulse);
            }
            else if (control_type ==0){
                move(-speed, -speed, 50);                    
            } 
            break;

        //Left 
        case 2://50
            if (control_type == 1 ){
                move(speed, -speed, pulse/6.7); // Divide by 6.7 to convert to degrees
            }
            else if (control_type == 0){
                move(speed, -speed, 100);
            } 
            break;
                    
        //Right 
        case 3://51
            if (control_type == 1 ){
                move(-speed, speed, pulse/6.7);
            }
            else if (control_type == 0 ){
                move(-speed, speed, 60);
            }     
            break;
                    
        // Reverse
        case 4://52
            if (control_type ==1 ){
                move(speed, speed, pulse);
            }
            else if (control_type ==0 ){
                move(speed, speed, 50); 
            }
            break;
               
        // Speed up        
        case 5:
            if (speed < 1.0){
                speed += 0.2;
            }
            break;
               
        // Speed down     
        case 6:
            if (speed>0.2){
                 speed -= 0.2;
            }
            break;
    
        // Switch control type
        case 7: 
            control_type =! control_type;
            break;
                
        // Turn around
        case 8:
            if (control_type == 1 ){
                move(-speed, speed, 5376);
            }
            break; 
    
        // Draw a square        
        case 9:
            square();
            break;
        
        case 10:
            dance();
            break;
        }
                   
        //Reset speed and pulse count
        A.speed(0);
        B.speed(0);
            
        wheel_B.reset();
        wheel_A.reset();
    }
}

int main() 
{
    ros::NodeHandle  nh;
    nh.initNode();
    
    // ROS subscriber for motors control
    ros::Subscriber<mbed_custom_msgs::motor_msg> motor_sub("motor_control", &motor_callback);
    nh.subscribe(motor_sub);
    
    // load settings onto VL6180X sensors 
    sensor_forward.init();
    // change default address of sensor 2
    sensor_forward.changeAddress(addr2);
    
    sensor_right.init();
    // change default address of sensor 3
    sensor_right.changeAddress(addr3);

    sensor_back.init();
    // change default address of sensor 4
    sensor_back.changeAddress(addr4);
    
    sensor_left.init();
    
    thread1.start(callback(&flip));
    thread2.start(callback(&control_motor));
    
    while(1) {
        nh.spinOnce(); 
    }
}