Mbed project to control a hoverboard

Dependencies:   mbed wave_player Servo 4DGL-uLCD-SE LSM9DS1_Library_cal HC_SR04_Ultrasonic_Library

main.cpp

Committer:
msafwan3
Date:
2020-04-28
Revision:
0:808403b99108
Child:
1:de52879ff5ec

File content as of revision 0:808403b99108:

#include "mbed.h"
#include "wave_player.h"
#include "SDFileSystem.h"
//#include "Motor.h"
//#include "RGBLed.h"
#include "Servo.h"
#include "ultrasonic.h"
#include "uLCD_4DGL.h"
#include "LSM9DS1.h"

#define PI 3.14159
#define DECLINATION -4.94 // Declination (degrees) in Atlanta,GA.
int sonar_flag = 0; //1 = display distance, 0 = avoid colission
float range = 0.0005; // for servo/motors calibration
float position = 0.5; // for servo/motors calibration

Serial pc(USBTX, USBRX);
uLCD_4DGL uLCD(p13,p14,p11); // serial tx, serial rx, reset pin;
//ultrasonic mu(p15, p16, .1, 1, &dist); //sonar
DigitalOut led1(p18);
DigitalOut led2(p19);

Servo dcmotorBottom(p21); // pwm
Servo servoBottom(p22); // pwm
Servo dcmotorBack(p23); // pwm

// Setup to play wav file from SD Card
AnalogOut DACout(p26);
wave_player waver(&DACout);
SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
 
// Setup for bluetooth
Serial blue(p28,p27);
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);

void playSound(char * wav)
{
    FILE *wave_file;
    wave_file = fopen(wav,"r");
    waver.play(wave_file);
    fclose(wave_file);
}

void bottom_motor_on()
{
    for (float i=0; i<=0.8; i+=0.1) {
        dcmotorBottom = i;
        wait(0.1);
    }
}

void dist(int distance) 
{   if(sonar_flag ==1) { //display distance
    //put code here to happen when the distance is changed
    printf("Distance changed to %dmm\r\n", distance); //print to pc for debugging
    uLCD.cls();
    uLCD.printf("Distance changed to %dmm\r\n", distance); //print to uLCD
    wait(2);
    } else { //avoid colision: beep and stop motor
        if(distance < 2){   
        playSound("/sd/Beeping.wav");
        dcmotorBack = 0.0;
        }
    }
    
}

float printAttitude(float ax, float ay, float az, float mx, float my, float mz)
{
    float roll = atan2(ay, az);
    float pitch = atan2(-ax, sqrt(ay * ay + az * az));
// touchy trig stuff to use arctan to get compass heading (scale is 0..360)
    mx = -mx;
    float heading;
    if (my == 0.0)
        heading = (mx < 0.0) ? 180.0 : 0.0;
    else
        heading = atan2(mx, my)*360.0/(2.0*PI);
    //pc.printf("heading atan=%f \n\r",heading);
    heading -= DECLINATION; //correct for geo location
    if(heading>180.0) heading = heading - 360.0;
    else if(heading<-180.0) heading = 360.0 + heading;
    else if(heading<0.0) heading = 360.0  + heading;


    // Convert everything from radians to degrees:
    //heading *= 180.0 / PI;
    pitch *= 180.0 / PI;
    roll  *= 180.0 / PI;

    pc.printf("Pitch: %f,    Roll: %f degress\n\r",pitch,roll);
    pc.printf("Magnetic Heading: %f degress\n\r",heading);
    return heading;
}

void display_compass()
{   
    while(!IMU.tempAvailable());
    IMU.readTemp();
    while(!IMU.magAvailable(X_AXIS));
    IMU.readMag();
    while(!IMU.accelAvailable());
    IMU.readAccel();
    while(!IMU.gyroAvailable());
    IMU.readGyro();
    pc.printf("\nIMU Temperature = %f C\n\r",25.0 + IMU.temperature/16.0);
    pc.printf("        X axis    Y axis    Z axis\n\r");
    pc.printf("gyro:  %9f %9f %9f in deg/s\n\r", IMU.calcGyro(IMU.gx), IMU.calcGyro(IMU.gy), IMU.calcGyro(IMU.gz));
    pc.printf("accel: %9f %9f %9f in Gs\n\r", IMU.calcAccel(IMU.ax), IMU.calcAccel(IMU.ay), IMU.calcAccel(IMU.az));
    pc.printf("mag:   %9f %9f %9f in gauss\n\r", IMU.calcMag(IMU.mx), IMU.calcMag(IMU.my), IMU.calcMag(IMU.mz));
    float heading = printAttitude(IMU.calcAccel(IMU.ax), IMU.calcAccel(IMU.ay), IMU.calcAccel(IMU.az), IMU.calcMag(IMU.mx),
                    IMU.calcMag(IMU.my), IMU.calcMag(IMU.mz));
    double a = heading * 0.0174533; //deg to rad
    x2 = x_c + r*cos(a);
    y2 = y_c + r*sin(a);
    uLCD.cls();
    uLCD.circle(x_c, y_c, r, WHITE);
    uLCD.line(x_c, y_c, (int)x2, (int)y2, BLUE);
    wait(0.001);
}


int main()
{   
    // this part of the display compass script only needs to be set up once
    int x_c = 60;
    int y_c = 60;
    int r = 30;
    uLCD.circle(x_c, y_c, r, WHITE);
    int z = 0;
    double x2 = x_c + r*cos((double)z);
    double y2 = x_c + r*sin((double)z);
    uLCD.line(x_c, y_c, (int)x2, (int)y2, BLUE);
    LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
    IMU.begin();
    if (!IMU.begin()) {
        pc.printf("Failed to communicate with LSM9DS1.\n");
    }
    IMU.calibrate(1);
    IMU.calibrateMag(0);

    //calibrate motors
    dcmotorBack.calibrate(range, position);
    dcmotorBottom.calibrate(range, position);
    servoBottom.calibrate(range, position)
    
    bottom_motor_on(); // bottom motor always on
    float servoAngle = 90.0; // ranges from 0 to 180 degrees where 90 is center
    mu.startUpdates(); // start mesuring the distance
    char bnum = 0;
    char bhit = 0;
    while(1) 
    {   
        sonar_flag = 0;
        mu.checkDistance();
        display_compass(); // this part of the compass script needs to be done repeatedly
        servoBottom.position(servoAngle);
        if (blue.getc() == '!') {
            if (blue.getc() == 'B') { //button data packet
                bnum = blue.getc(); //button number
                bhit = blue.getc(); //1=hit, 0=release
                if (blue.getc() == char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
                    myled = bnum - '1'; //current button number will appear on LEDs
                    switch (bnum) {
                        case '1': //number button 1: speeds up motor
                            if (bhit=='1') {
                                //add hit code here
                                motorSpeed += 0.2; // speed up
                                myRGBled.write(0.0,1.0,0.0); //green
                            } else {
                                //add release code here
                            }
                            break;
                        case '2': //number button 2: slows down motor
                            if (bhit=='1') {
                                //add hit code here
                                motorSpeed -= 0.2; // speed down
                                myRGBled.write(0.0,0.0,1.0); //blue
                            } else {
                                //add release code here
                            }
                            break;
                        case '3': //number button 3: display distance from sonar
                            if (bhit=='1') {
                                //add hit code here   
                                sonar_flag = 1; 
                                mu.checkDistance();
                            } else {
                                //add release code here
                            }
                            break;
                        case '4': //number button 4: play honking sound
                            if (bhit=='1') {
                                //add hit code here                              
                                playSound("/sd/Honk.wav"); //write name of sound file
                            } else {
                                //add release code here
                            }
                            break;
                        case '5': //button 5 up arrow: turn on bottom servo and back motor
                            if (bhit=='1') {
                                //add hit code here  
                                for(float p=0; p<1.0; p += 0.1) {
                                    dcmotorBack = p;
                                    wait(0.2);
                                }
                                myled1 = 1;                             
                            } else {
                                //add release code here
                            }
                            break;
                        case '6': //button 6 down arrow: switch it off (turn off back motor)
                            if (bhit=='1') {
                                //add hit code here
                                dcmotorBack = 0.0;
                                myled1 = 0;
                                myled2 = 1;
                            } else {
                                //add release code here
                            }
                            break;
                        case '7': //button 7 left arrow: turns servo leftwards
                            if (bhit=='1') {
                                //add hit code here
                                if (servoAngle > 0.0) {
                                    servoAngle -= 30; //turn servo left
                                }
                                myled3 = 1;
                                myled4 = 0;
                            } else {
                                //add release code here
                            }
                            break;
                        case '8': //button 8 right arrow: turns servo rightwards
                            if (bhit=='1') {
                                //add hit code here
                                if (servoAngle < 180.0) {
                                    servoAngle += 30.0; //turn servo right
                                }
                                myled4 = 1;
                                myled3 = 0;
                            } else {
                                //add release code here
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }
}