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
main.cpp
- Committer:
- HighTide
- Date:
- 2019-12-04
- Revision:
- 0:831e390ffcf8
File content as of revision 0:831e390ffcf8:
#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(); } }