This code allows for an Mbed LPC1768 to be operated over the Adafruit Bluetooth controller app. Directional controls send serial commands over Bluetooth to control the motors over using an H-Bridge, and with four directional LiDAR sensors and a speaker/uLCD providing for collision warning. The user may also activate autonomous mode, in which case the code will begin scanning the LiDARs and avoiding obstacles without user intervention.
Dependencies: mbed Servo mbed-rtos 4DGL-uLCD-SE Motor VL53L0X
Revision 0:831e390ffcf8, committed 2019-12-04
- Comitter:
- HighTide
- Date:
- Wed Dec 04 15:44:11 2019 +0000
- Commit message:
- Final version of Multiple Scanning LiDAR Bot for ECE 4180.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4DGL-uLCD-SE.lib Wed Dec 04 15:44:11 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/4180_1/code/4DGL-uLCD-SE/#2cb1845d7681
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Motor.lib Wed Dec 04 15:44:11 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/simon/code/Motor/#f265e441bcd9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Servo.lib Wed Dec 04 15:44:11 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/simon/code/Servo/#36b69a7ced07
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VL53L0X.lib Wed Dec 04 15:44:11 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/teams/ST/code/VL53L0X/#8ac15bf6d635
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Dec 04 15:44:11 2019 +0000 @@ -0,0 +1,255 @@ +#include "mbed.h" +#include "rtos.h" +#include "Motor.h" +#include "Servo.h" +#include "VL53L0X.h" +#include "LSM9DS1.h" +#include "uLCD_4DGL.h" + +#define IN_RANGE(x) ((x) > 0 && (x) < 300) +#define AUTO_SPEED 0.5 + +Serial pc(USBTX, USBRX); +Serial btc(p13, p14); +volatile bool user_mode = true; + +DevI2C i2c(p9, p10); +DigitalOut shdn_left(p20), shdn_up(p17), shdn_right(p19), shdn_down(p18); +VL53L0X l_left(&i2c, &shdn_left, NC), l_up(&i2c, &shdn_up, NC), l_right(&i2c, &shdn_right, NC), l_down(&i2c, &shdn_down, NC); +PwmOut speaker(p25); +uLCD_4DGL uLCD(p28, p27, p15); +uint32_t distances[16]; +volatile bool ob_left = false, ob_up = false, ob_right = false, ob_down = false; + +Motor left(p21, p29, p30); +Motor right(p22, p23, p24); +Servo servo(p26); +LSM9DS1 IMU(p9, p10, 0xD6, 0x3C); + +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); + +void read_btc(void const * args) { + char cmd[5] = {0}, num_chars = 0; + char pressed = 0; + + while (1) { + num_chars = 0; + for (num_chars = 0; num_chars < 5; num_chars++) { + if (!btc.readable()) { + break; + } + cmd[num_chars] = btc.getc(); + } + + if (num_chars != 5) { + if (user_mode) { + left.speed(0.0); + right.speed(0.0); + } + } else if (cmd[0] == '!') { + if (cmd[1] == 'B') { + if (cmd[3] == '0') { + pressed &= ~(0x1 << (cmd[2] - '1')); + } else { + switch(cmd[2]) { + case '1': // Button 1 - Switch Running Mode + left.speed(0.0); + right.speed(0.0); + user_mode = !user_mode; + break; + case '4': // Emergency Reset + left.speed(0.0); + right.speed(0.0); + pressed = 0; + user_mode = true; + break; + case '5': // Up + case '6': // Down + case '7': // Left + case '8': // Right + pressed |= (0x1 << (cmd[2] - '1')); + break; + default: + left.speed(0.0); + right.speed(0.0); + break; + } + } + } + } + + if (user_mode) { + switch (pressed >> 4) { + case 0b0000: + case 0b0011: + case 0b1100: + case 0b1111: + left.speed(0.0); + right.speed(0.0); + break; + case 0b0001: + case 0b1101: + left.speed(1.0); + right.speed(1.0); + break; + case 0b0010: + case 0b1110: + left.speed(-1.0); + right.speed(-1.0); + break; + case 0b0100: + case 0b0111: + left.speed(1.0); + right.speed(-1.0); + break; + case 0b0101: + left.speed(0.5); + right.speed(1.0); + break; + case 0b0110: + left.speed(-0.5); + right.speed(-1.0); + break; + case 0b1000: + case 0b1011: + left.speed(-1.0); + right.speed(1.0); + break; + case 0b1001: + left.speed(1.0); + right.speed(0.5); + break; + case 0b1010: + left.speed(-1.0); + right.speed(-0.5); + break; + default: + break; + } + } + led1 = !led1; + Thread::wait(100); + } +} + +void scan_lidar(void const*args) { + while(1) { + if (user_mode) { + servo = 0.0; + l_left.get_distance(&distances[0]); + l_up.get_distance(&distances[4]); + l_right.get_distance(&distances[8]); + l_down.get_distance(&distances[12]); + } else { + for (int i = 0; i < 4; i++) { + servo = i * 0.125; + l_left.get_distance(&distances[i]); + l_up.get_distance(&distances[4+i]); + l_right.get_distance(&distances[8+i]); + l_down.get_distance(&distances[12+i]); + } + servo = 0.0; + } + led2 = !led2; + Thread::wait(100); + } +} + +void collision_warning(void const* args) { + + while(1) { + if (user_mode) { + ob_left = IN_RANGE(distances[0]); + ob_up = IN_RANGE(distances[4]); + ob_right = IN_RANGE(distances[8]); + ob_down = IN_RANGE(distances[12]); + } else { + ob_left = ob_up = ob_right = ob_down = false; + for (int i = 0; i < 4; i++) { + if (IN_RANGE(distances[(15+i)%16])) ob_left = true; + if (IN_RANGE(distances[3+i])) ob_up = true; + if (IN_RANGE(distances[7+i])) ob_right = true; + if (IN_RANGE(distances[11+i])) ob_down = true; + } + } + + if (ob_left || ob_up || ob_right || ob_down) { + speaker = 0.5; + } else { + speaker = 0.0; + } + uLCD.filled_rectangle(0, 0, 32, 128, ob_left ? RED : BLACK); + uLCD.filled_rectangle(0, 0, 128, 32, ob_up ? RED : BLACK); + uLCD.filled_rectangle(96, 0, 128, 128, ob_right ? RED : BLACK); + uLCD.filled_rectangle(0, 96, 128, 128, ob_down ? RED : BLACK); + led3 = !led3; + Thread::wait(100); + } +} + +void heartbeat(void const* args) { + while(1) { + led4 = !led4; + Thread::wait(1000); + } +} + +int main() { + + led1 = led2 = led3 = led4 = 0; + servo.calibrate(0.001, 45.0); + servo = 0.0; + left.speed(0.0); + right.speed(0.0); + uLCD.baudrate(3000000); + uLCD.cls(); + uLCD.filled_rectangle(32, 32, 96, 96, BLUE); + speaker = 0.0; + + l_left.VL53L0X_off(); + l_up.VL53L0X_off(); + l_right.VL53L0X_off(); + l_down.VL53L0X_off(); + l_left.init_sensor(0x30); + l_up.init_sensor(0x32); + l_right.init_sensor(0x34); + l_down.init_sensor(0x36); + + Thread t1(read_btc); + Thread t2(scan_lidar); + Thread t3(collision_warning); + Thread t4(heartbeat); + + while(1) { + if (!user_mode) { + if (ob_up) { + if (ob_left && ob_right) { + left.speed(-AUTO_SPEED); + right.speed(AUTO_SPEED); + wait(1.0); + left.speed(0.0); + right.speed(0.0); + } else if (ob_right) { + left.speed(AUTO_SPEED); + right.speed(-AUTO_SPEED); + } else { + left.speed(-AUTO_SPEED); + right.speed(AUTO_SPEED); + } + } else if (ob_left && ob_right) { + left.speed(AUTO_SPEED); + right.speed(AUTO_SPEED); + } else if (ob_left) { + left.speed(AUTO_SPEED); + right.speed(AUTO_SPEED / 2); + } else if (ob_right) { + left.speed(AUTO_SPEED / 2); + right.speed(AUTO_SPEED); + } else { + left.speed(AUTO_SPEED); + right.speed(AUTO_SPEED); + } + } + Thread::yield(); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Wed Dec 04 15:44:11 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed-rtos/#5713cbbdb706
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Dec 04 15:44:11 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file