GloveBot: Semi-active Controlled Autonomous Driving Vehicle

Team Members

Animesh Patel

Kevin Chang

Zheyuan Xu

https://i.imgur.com/gFMeTom.jpg

https://i.imgur.com/KJygtdk.jpg

Introduction

The glove bot we are making is an autonomous moving vehicle which can be controlled remotely by a magic glove and pronounce the words upon specific motion command. The vehicle has 2 motors and has a Raspberry Pi 0 powered camera which spins periodically from left to right; it also uses distance sensors to avoid collision, making it a multi-purpose moving platform eligible for various engineering uses.

Hardware Parts

Mbed

ARM LPC1768 has a built-in Cortex M3 processor and can be programmed by Mbed cloud account. In this project, 3 Mbeds are used . The controller, which is the glove terminal, uses Mbed to receive sensor output from the fingers, as well as powering uLCD and Xbee wireless module. The other two are located in the receiver, which is the vehicle. One is used to power the motor, an Emic2 text-to-speech converter, a ToF distance sensor, as well the Xbee wireless module. The other one is used to power the servo which rotates the camera periodically. https://d2kmb61w1swc5t.cloudfront.net/images/09564-05.jpg

Raspberry Pi Zero

The Raspberry Pi Zero is used to power the camera and run the picture taking program when the vehicle is powered. It has a built-in SD card which stores the picture taken for further analysis. Upon power up, it will automatically run the python scripts which can turn on the camera and take pictures at 3 different orientations. https://www.raspberrypi.org/app/uploads/2017/05/Raspberry-Pi-Zero-462x322.jpg

Xbee Modules

The Xbee modules are used for communication between the sender and receiver. They use IEEE 802.15.4 protocol, and can be effective in a circular range of 100 yards. To setup the Xbee module, you need to connect both of them on breakout boards, and connect to PC terminal. You may also need to download XCTU and Teraterm for correct setup and debugging, here is the tutorials: https://www.digi.com/products/xbee-rf-solutions/xctu-software/xctu https://osdn.net/projects/ttssh2/releases/ https://images-na.ssl-images-amazon.com/images/I/618Zno6HXzL._SX679_.jpg

Emic2 Text-to-Speech Converter

https://cdn-shop.adafruit.com/1200x900/924-02.jpg The Emic2 Text-to-speech Converter is used on the vehicle, and is powered by mbed. This modules acts as a driver to control the speaker, and is able to make 9 different voices in 3 different languages.

H-bridge Motor Driver

https://www.robotshop.com/media/catalog/product/cache/image/625x625/9df78eab33525d08d6e5fb8d27136e95/1/a/1a-motor-driver-dual-tb6612fng.jpg This module is used to power the motors of the vehicle.

Distance Sensor

We are also using VL53L0x distance sensor to detect any incoming objects. https://cdn-shop.adafruit.com/1200x900/3317-03.jpg The distance sensor will detect obstacles in front of the vehicle, and it the distance is less than 20cm, the vehicle will start to randomly turn(left or right). When it finds a direction with no obstacles, the vehicle will stop the motion.

Flex Sensors

The flex sensors used in the glove will detect bendings in the user's fingers. After it is bent the resistance value will change, resulting in a different analog input voltage. https://os.mbed.com/components/Flex-Sensor/ The flex sensors are only sensitive enough when connected in series with a 10K ohm resistor. Using a resistor of much lower resistance will greatly reduce the accuracy and introduce a lot of noises.

Heat Sensor

We are using TMP36 analog temperature sensor. The schematics for connecting can be found in the official website.

uLCD screen

The uLCD screen can display and visualize the temperature in the surroundings. The introduction scene will display several lines of text including "ECE 4180" https://os.mbed.com/media/uploads/4180_1/8185.png

Functionality

There are two functional parts in our project: Glove and Vehicle

Glove

The glove, which acts as a controller, allows user to directly interfacing with the vehicle, more specifically, the vehicle will receive inputs of 5 commands in our current code, including forward(pinky), backward(ring finger), left(middle finger), right(index finger) and stop(thumb) https://i.imgur.com/zYNLBxC.jpg upon bending or curvature of the fingers, the Mbed will be able to collect the signal and identify the correct finger. Then, upon successful completion of the identification procedure, it will fire a command via Xbee module.

Vehicle

The vehicle receives command from glove, and performs the corresponding action accordingly. It can pronounce "left" or "right" when it's turning after receiving a command, or "stop" if it is commanded to stop from its current motion. https://i.imgur.com/XOMDBXZ.jpg

Code Snippet

Glove Code

Import programTransmitter

This code will be implemented on the receiving end of the device, which contains a speaker, an Emic2 text-to-speech converter, as well as a vehicle module that can move or rotate upon request

Code used by glove Mbed

#include "mbed.h"
#include "emic2.h"
#include "uLCD_4DGL.h"
#include<string>

using namespace std;
//serial RX,TX pins to emic
uLCD_4DGL uLCD(p28,p27,p5); // serial tx, serial rx, reset pin;
#define length_sprite 20
#define width_sprite 75
#define width_sprite2 47
#define length_sprite2 18

#define Q 0x808000 //OLIVE
#define I 0x008000 //GREEN
#define S 0xC0C0C0 //SILVER
#define R 0xF1C40F //YELLOW
#define O 0xF39C12 //ORANGE
#define X 0xFFFFFF //WHITE
#define B 0x0000FF //BLUE
#define G 0xAAB7B8 //GREY
#define D 0x797D7F //DARK GREY
#define L 0x00FF00 //LIME
#define P 0xFF00FF //K
#define _ 0x000000 //BLACK
#define r 0xFF0000 //RED


class TMP36{
public:
TMP36(PinName pin);
 TMP36();
float read();
private:
//class sets up the AnalogIn pin
AnalogIn _pin;
};
TMP36::TMP36(PinName pin) : _pin(pin) {} //This is an initializer list
float TMP36::read()
{
//convert sensor reading to temperature in degrees C
return ((_pin.read()*3.3)-0.500)*100.0;
//read() function returns a normalized value of the voltage from 0 to 1 as a float }
//instantiate new class to set p15 to analog input //to read and convert TMP36 sensor's voltage output
}
TMP36 myTMP36(p20); // analog in pin for temp sensor


// make 3 different sprites
// decrease the sprite dimensions to increasing processing speed
// for the glove sprite appearing in the beginning
int Glove[length_sprite*width_sprite] = {
    _,_,_,_,R,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,R,_,S,S,S,S,S,S,_,O,_,_,_,_,_,r,r,r,r,r,_,D,D,D,D,D,D,_,I,I,_,_,_,_,_,_,_,I,I,_,R,R,R,R,R,R,_,_,_,_,_,_,
    _,_,_,_,_,R,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,R,_,_,S,_,_,_,_,_,_,O,_,_,_,_,_,r,_,_,_,_,_,D,_,_,_,_,D,_,I,_,I,_,_,_,_,_,I,_,I,_,R,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,R,_,_,_,_,_,R,R,_,_,_,_,_,_,R,_,_,_,S,_,_,_,_,_,_,O,_,_,_,_,_,r,_,_,_,_,_,D,_,_,_,_,D,_,I,_,_,I,_,_,_,I,_,_,I,_,R,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,R,_,_,_,R,_,_,R,_,_,_,_,R,_,_,_,_,S,S,S,S,_,_,_,O,_,_,_,_,_,r,_,_,_,_,_,D,_,_,_,_,D,_,I,_,_,_,I,_,I,_,_,_,I,_,R,R,R,R,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,R,_,R,_,_,_,_,R,_,_,R,_,_,_,_,_,S,_,_,_,_,_,_,O,_,_,_,_,_,r,_,_,_,_,_,D,_,_,_,_,D,_,I,_,_,_,_,I,_,_,_,_,I,_,R,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,R,_,_,_,_,_,_,R,R,_,_,_,_,_,_,S,_,_,_,_,_,_,O,_,_,_,_,_,r,_,_,_,_,_,D,_,_,_,_,D,_,I,_,_,_,_,_,_,_,_,_,I,_,R,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,S,S,S,S,S,S,_,O,O,O,O,O,_,r,r,r,r,r,_,D,D,D,D,D,D,_,I,_,_,_,_,_,_,_,_,_,I,_,R,R,R,R,R,R,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,G,G,G,G,G,G,G,G,_,_,B,B,B,B,B,B,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,_,_,_,_,_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,_,_,_,_,_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,_,_,_,_,_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,_,_,_,_,_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,_,_,_,_,_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,_,_,_,_,_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,_,_,_,_,_,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,G,_,_,_,_,_,_,B,B,B,B,B,B,B,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
};


int Fourty_One_Eighty[width_sprite2*length_sprite2]= {
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,G,G,G,G,G,G,G,G,_,_,_,B,B,B,B,B,B,B,B,B,_,
    _,_,_,_,_,_,_,_,_,_,_,L,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,L,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,L,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,L,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,L,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,L,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,L,L,L,L,L,L,L,L,_,_,_,_,O,O,O,_,_,_,_,_,G,G,G,G,G,G,G,G,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,G,G,G,G,G,G,G,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,_,_,_,_,_,_,_,G,_,_,_,B,_,_,_,_,_,_,_,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,L,_,_,_,_,O,O,O,_,_,_,_,_,G,G,G,G,G,G,G,G,G,_,_,_,B,B,B,B,B,B,B,B,B,_,
    _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,

};
 
 
Serial xbee1(p9,p10);
DigitalOut rst1(p11);

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
//emic2 myTTS(p13, p14);
AnalogIn a1(p15);
AnalogIn a2(p16);
AnalogIn a3(p17);
AnalogIn a4(p18);
AnalogIn a5(p19);
Serial pc(USBTX, USBRX);
float i1;
float i2;
float i3;
float i4;
float i5;
float ref1;
float ref2;
float ref3;
float ref4;
float ref5;
float avg1;
float avg2;
float avg3;
float avg4;
float avg5;
float diff1, diff2, diff3, diff4, diff5;
int counter;
float sum;
int main() {
    float tempC, tempF;
    int i = 0;
    uLCD.BLIT(30,30,width_sprite, length_sprite, Glove);
    wait(1);
    uLCD.cls();

    uLCD.BLIT(30,30, width_sprite2, length_sprite2, Fourty_One_Eighty);

    wait(1.0);


    for (unsigned int j = 0; j <= 128; j+=7){
        // DRAW ----  animation of walls
    uLCD.line(j,127,j+7,0,RED); // horizontal  animation
    uLCD.line(j+1, 127, j+8, 0, RED);

    uLCD.line(127 - j, 0, 127 - (j+7), 127, BLUE);
    uLCD.line(127-j-1,0,127 - (j+8), 127, BLUE);

    // Erase
    wait(.1);
    uLCD.line(j,127,j+7,0,BLACK);
    uLCD.line(j+1, 127, j+8, 0, BLACK);
    uLCD.line(127 - j, 0, 127 - (j+7), 127, BLACK);  // vertical  animation
    uLCD.line(127-j-1,0,127 - (j+8), 127, BLACK);
    }

    uLCD.cls();

    
    
    ref1 = 0;
    ref2 = 0;
    ref3 = 0;
    ref4 = 0;
    ref5 = 0;
    counter = 0;
    rst1 = 0;
    wait_ms(1); 
    rst1 = 1;
    wait_ms(1);
    char o;
    while(1) {
        wait(0.5);
        i1 = a1;
        i2 = a2;
        i3 = a3;
        i4 = a4;
        i5 = a5;
        ref1 += i1;
        ref2 += i2;
        ref3 += i3;
        ref4 += i4;
        ref5 += i5;
        avg1 = ref1 / counter;
        avg2 = ref2 / counter;
        avg3 = ref3 / counter;
        avg4 = ref4 / counter;
        avg5 = ref5 / counter;
        o = 'I';
        myled1 = 0;
        myled2 = 0;
        myled3 = 0;
        myled4 = 0;
        diff1 = i1 - avg1;
        diff2 = i2 - avg2;
        diff3 = i3 - avg3;
        diff4 = i4 - avg4;
        diff5 = i5 - avg5;
        if (diff1 > 0.01) {
            o = 'A';
            ref1 -= i1;
            myled1 = 1;
        } else if (diff2 > 0.01)
        {
            o = 'B';
            ref2 -= i2;
            myled2 = 1;
        } else if (diff3 > 0.01)
        {
            o = 'C';
            ref3 -= i3;
            myled3 = 1;
        } else if (diff4 > 0.01)
        {
            o = 'D';
            ref4 -= i4;
            myled4 = 1;
        } else if (diff5 > 0.01)
        {
            o = 'E';
            ref5 -= i5;
            myled1 = 1;
            myled2 = 1;
        } else {
            counter++;
        }
        xbee1.putc(o);
        
        pc.printf("%4.2f,  %4.2f\r\n", avg4, diff4);
        uLCD.filled_circle(63,63,63, 0x0000ff);

        uLCD.baudrate(3000000);
        //uLCD.set_font_size(3,3);
        /*
        uLCD.text_char('B', 9, 8, BLACK);
        uLCD.text_char('I',10, 8, BLACK);
        uLCD.text_char('G',11, 8, BLACK);
        uLCD.text_italic(ON); */
        if (i == 0){
        uLCD.locate(40,40);
        uLCD.text_italic(ON);
        uLCD.text_string("Welcome to 4180", 0, 5, FONT_7X8, WHITE);
        uLCD.text_italic(ON);
        wait(0.2);
        uLCD.cls();
        uLCD.text_string("Final", 0, 9, FONT_7X8, WHITE);
        uLCD.text_string("Project", 0, 11, FONT_7X8, WHITE);

        i++; uLCD.cls();
        uLCD.filled_circle(63,63,63, 0x0000ff);
        wait(0.2);
        }
    
        tempC = myTMP36.read(); //convert to degrees F
        tempF = (9.0*tempC)/5.0 + 32.0; //print current temp
    
        uLCD.locate(0,0);
        uLCD.printf("%5.2f C %5.2f F \n\r", tempC, tempF);
    
    
        uLCD.filled_rectangle(40, 127, 50, 127 - 2*tempC , 0xFF0000); // MAX- Celcius 64 for celcius bar
        uLCD.filled_rectangle(60, 127, 70, 127 - tempF, 0xFFFF00); // MAX- farenheit yellow for farenheit bar
        wait(0.2);
       // uLCD.cls();
       uLCD.filled_rectangle(0,0,127, 7, 0x000000);
       uLCD.filled_circle(63,63,63, 0x0000ff);
       uLCD.filled_rectangle(40, 127, 50, 127 - 2*tempC , 0x000000); // ERASE
       uLCD.filled_rectangle(60, 127, 70, 127 - tempF, 0x000000); // MAX- farenheit yellow for farenheit bar
    }
}

Vehicle Code

Import programReceiver

receiver code which helps the vehicle to move forward, backward, left and right

Code used by vehicle Mbed powered by Motor and Xbee receiver

#include "Motor.h"
#include "mbed.h"
#include "emic2.h"
#include "XNucleo53L0A1.h"
#include <stdio.h>
#include "rtos.h"


Serial pc(USBTX, USBRX);
DigitalOut shdn(p26);
AnalogOut led(p18);
//I2C sensor pins
#define VL53L0_I2C_SDA   p28
#define VL53L0_I2C_SCL   p27


static XNucleo53L0A1 *board=NULL;
emic2 myTTS(p13, p14);
Serial xbee1(p9, p10);
DigitalOut rst1(p11);

Motor B(p23, p6, p5); // pwm, fwd, rev, can brake, right
Motor A(p24, p7, p8); // left motor

char input;
int counter;
int direction;
int main() {
    //initialize distance sensor
    int status;
    uint32_t distance;
    DevI2C *device_i2c = new DevI2C(VL53L0_I2C_SDA, VL53L0_I2C_SCL);
    /* creates the 53L0A1 expansion board singleton obj */
    board = XNucleo53L0A1::instance(device_i2c, A2, D8, D2);
    shdn = 0; //must reset sensor for an mbed reset to work
    wait(0.1);
    shdn = 1;
    wait(0.1);
    /* init the 53L0A1 board with default values */
    status = board->init_board();
    while (status) {
        pc.printf("Failed to init board! \r\n");
        status = board->init_board();
    }
    
    
    
    counter = 0;
    // reset the xbees (at least 200ns)
    rst1 = 0;
    wait_ms(1); 
    rst1 = 1;
    wait_ms(1); 
    input = 'I';
    
    A.speed(0);
    B.speed(0);
    wait(2);
    direction = 1;
    while(1) {
        if(xbee1.readable()) {
            input = xbee1.getc();
            wait(0.2);
        }
        status = board->sensor_centre->get_distance(&distance);
        if (status == VL53L0X_ERROR_NONE) {
            pc.printf("D=%ld mm\r\n", distance);
            
        }
        
        while (distance < 200) {
                direction = rand()*100;
                if (direction > 50)
                {
                    A.speed(-0.5);
                    B.speed(-0.5);
                    led = 0;
                    wait(0.1);
                } else
                {
                    
                    A.speed(0.5);
                    B.speed(0.5);
                    led = 1;
                    wait(0.1);
                }
                status = board->sensor_centre->get_distance(&distance);
                led = 0;
                A.speed(0);
                B.speed(0);
        }
        if (input == 'A')
        {
            //myTTS.speakf("S");//Speak command starts with "S"
            //myTTS.speakf("forward");
            //myTTS.speakf("\r"); //marks end of speak command
            //myTTS.ready();
            A.speed(-0.5);
            B.speed(0.5);
            wait(0.2);
        } else if (input == 'B')
        {
            //myTTS.speakf("S");//Speak command starts with "S"
            //myTTS.speakf("back");
            //myTTS.speakf("\r"); //marks end of speak command
            //myTTS.ready();
            A.speed(0.5);
            B.speed(-0.5);
            wait(0.2);
        } else if (input == 'C')
        {
            myTTS.speakf("S");//Speak command starts with "S"
            myTTS.speakf("left");
            myTTS.speakf("\r"); //marks end of speak command
            myTTS.ready();
            A.speed(0.5);
            B.speed(0.5);
            wait(0.2);
        } else if (input == 'D')
        {
            myTTS.speakf("S");//Speak command starts with "S"
            myTTS.speakf("right");
            myTTS.speakf("\r"); //marks end of speak command
            myTTS.ready();
            A.speed(-0.5);
            B.speed(-0.5);
            wait(0.2);
        } else if (input == 'E')
        {
            myTTS.speakf("S");//Speak command starts with "S"
            myTTS.speakf("stop");
            myTTS.speakf("\r"); //marks end of speak command
            myTTS.ready();
            A.speed(0);
            B.speed(0);
            wait(0.2);
        }
    }
}


Camera Code

Left Side Picture

https://i.imgur.com/B5Jfpyx.jpg

Middle Picture

https://i.imgur.com/utyVqSk.jpg

Right Side Picture

https://i.imgur.com/HEsSFZ2.jpg

Code used for Raspberry Pi Zero in taking pictures

# Camera Code
# Author:  Animesh Patel                     12/11/2018

import picamera

from time import sleep
import sys
camera = picamera.PiCamera()

powerOn = 1

# Servo default position: left side
camera_side_current = "left"
camera_side_next = "center"

counter = 1

while powerOn:
    
    if camera_side_current == "left":
        print("picture from left side\n")
        camera_side_next = "center"

    elif camera_side_current == "center":
        print("picture from center side\n")
        camera_side_next = "right"

    elif camera_side_current == "right":
        print("picture from right side\n")
        camera_side_next = "left"

    sleep(.5)
    camera.start_preview()
    sleep(.5)
    camera.stop_preview()


    if camera_side_current == "left":
        camera.capture('/home/pi/Desktop/Pictures/Left_Side_%s.jpg' %counter)

    elif camera_side_current == "center":
        camera.capture('/home/pi/Desktop/Pictures/Center_Side_%s.jpg' %counter)

    elif camera_side_current == "right":
        camera.capture('/home/pi/Desktop/Pictures/Right_Side_%s.jpg' %counter)


    print('done with ' + camera_side_current + ' side\n')
    sleep(1.5)
    camera_side_current = camera_side_next

    if camera_side_current == "left":
        counter = counter + 1
        sleep(2.5)

Project Schematic

https://i.imgur.com/TnmF3uL.jpg

Control Scheme

The glove currently has 5 commands: forward(pinky), backward(ring finger), left(middle finger), right(index finger), and thumb.

By bending the fingers, the flex sensors data will change. The Mbed will detect that change and propagate the signals by Xbee module. The Xbee module on the vehicle side will receive the signal and reports to another Mbed which is connected to the power pack. The Mbed will change the motion of the vehicle accordingly as well as pronouncing the motion with the assistance of the text-to-speech converter.

The vehicle also detects obstacles in front of it by distance sensor, and if the obstacle is in vicinity( < 20cm), the vehicle will stop and try to turn away.

The Raspberry Pi camera is constantly rotating from left to right and taking pictures at 3 positions(left, middle and right). The pictures taken will be stored in a microSD card for acquisition and image processing.

Project Demo

Future Improvements

Packaging

The vehicle consists of a breadboard on top of a Magician Bot chassis. In the future we decide to 3D print a transparent, plastic casing to hide all the ugly wirings. The wirings can be also be replaced with PCBs.

Finishing Imaging Processing Features

We spent a lot of time in setting up camera module on Raspberry Pi Zero, and due to some minor technical issues we are currently unable to import openCV library onto Raspberry Pi. However, we already have the code for edge detection working on our PCs. Once openCV importation issue is fixed, we can add object recognition features.

Below is the Python code with openCV working

Raspberry Pi camera with openCV

import picamera
#import cv2
#import numpy as np
#from matplotlib import pyplot as plt
from time import sleep
import sys

from skimage import io
from skimage import feature
camera = picamera.picamera()

powerOn = 1

camera_side_current = "left"
camera_side_next = "center"

counter = 1

while (powerOn and counter < 3):
    camera.start_preview()
    if camera_side_current == "left":
        print("picture from left side\n")
        camera_side_next = "center"

    elif camera_side_current == "center":
        print("picture from center side\n")
        camera_side_next = "right"

    elif camera_side_current == "right":
        print("picture from right side\n")
        camera_side_next = "left"


    sleep(.3)
    camera.stop_preview()
#sleep(1.7)

    if camera_side_current == "left":
        camera.capture('/home/pi/Desktop/Pictures/Left_Side_%s.jpg' %counter)
        image = io.imread('/home/pi/Desktop/Pictures/Left_Side_%s.jpg')

    elif camera_side_current == "center":
        camera.capture('/home/pi/Desktop/Pictures/Center_Side_%s.jpg' %counter)
        image = io.imread('/home/pi/Desktop/Pictures/Center_Side_%s.jpg')

    elif camera_side_current == "right":
        camera.capture('/home/pi/Desktop/Pictures/Right_Side_%s.jpg' %counter)
        image = io.imread('/home/pi/Desktop/Pictures/Right_Side_%s.jpg')

    print('done with ' + camera_side_current + ' side\n')

    edge = feature.canny(image)
    io.imshow(edge)
    io.show()
    sleep(1.7)
    camera_side_current = camera_side_next

    if camera_side_current == "left":
        counter = counter + 1
        sleep(3)

Communication between MCUs

It would be much better if we can make different microcontrollers on the vehicle communicate with each other. For example, the camera which is controlled by Raspberry Pi Zero can provide information for the Mbed connected to the power pack, and alter the vehicle's motion accordingly. We even plan to add more Xbee modules on multiple vehicles and setup a network among them, so each vehicle is able to inform all the others about the obstacles in front of it.

Smart Lighting

Turns on the lights depending on the certain threshold of RGB values from images and turns off for bright enough environment.

Implementing Multi-threading

The vehicle can use Mbed rtos library to implement multi-threading. As a result, the Mbed can utilize its processing power more efficiently.

Incorporating AR/VR, and IMU control

We are planning to add IMU motion sensors to the glove and use sensor fusion to provide more accurate control of the vehicle. We also consider the addition of AR/VR to allow the user to visualize cart movements in a gaming-like environment in addition to sound effects involving cart screeching, accelerating, turning, etc.

Adding PID Control for the motors

We do not have a Hall sensor in our motors, and currently unable to keep the vehicle moving in a straight line. In the future, we plan to mount Halls sensors to and implement PID control system to maintain the vehicle's course.

Github Repository

https://github.com/CharlesXu1124/Embedded-Projects.git


Please log in to post comments.