A WiFiDipCortex based robot. Control is via sockets over WiFi. See also: https://github.com/mfurseman/robo-android

Dependencies:   Motordriver USBDevice cc3000_hostdriver_mbedsocket_hacked mbed

main.cpp

Committer:
mfurseman
Date:
2014-11-19
Revision:
7:ee8b630b0a33
Parent:
5:7f5fcee1737d

File content as of revision 7:ee8b630b0a33:

#include <stdint.h>
#include <mbed.h>
#include "motordriver.h"
#include "cc3000.h"
#include "TCPSocketConnection.h"
#include "TCPSocketServer.h"


/* MAC 08:00:28:57:43:b8 */

/* Quickly change debug flag to remove USB serial code */
//#define DEBUG
#ifdef DEBUG
#include "USBSerial.h"
USBSerial serial;
#define debug(x, ...) serial.printf(x, ##__VA_ARGS__);
#else
#define debug(x, ...)
#endif

/* Network constants */
#define SERVER_PORT 5678
#define CC3000_WAIT 15

/* Client commands */
#define CMD_NULL 0
#define CMD_C_ECHO 0x61  // 'a'
#define CMD_C_LED_ON 0x62 // 'b'
#define CMD_C_LED_OFF 0x63 // 'c'
#define CMD_C_PRINT_UINT32 0x64 // 'd'
#define CMD_C_MOTOR_LEFT_DUTY 0x65 // 'e'
#define CMD_C_MOTOR_RIGHT_DUTY 0x66 // 'f'
#define CMD_C_MOTOR_LEFT_COAST 0x67 // 'g'
#define CMD_C_MOTOR_RIGHT_COAST 0x68 // 'h'
#define CMD_C_MOTOR_LEFT_STOP 0x69 // 'i'
#define CMD_C_MOTOR_RIGHT_STOP 0x6a // 'j'


using namespace mbed_cc3000;


/* On board LED */
DigitalOut led(P0_1);

/* Motors: allow breaking */
Motor leftMotor(P0_8, P1_24, P0_4, true);
Motor rightMotor(P0_9, P1_13, P1_14, true);

/* Serial library for WiFi module */
cc3000 wifi(p28, p27, p30, SPI(p21, p14, p37));

/* Struct to hold connection data */
tNetappIpconfigRetArgs ipinfo;


/**
 * Prints CC3000 connection info
 */
void printConnectionInfo()
{
    if (( wifi.is_enabled() ) && ( wifi.is_dhcp_configured() )) {
        wifi.get_ip_config(&ipinfo);
    }
    if (! wifi.is_enabled() ) {
        debug("CC3000 Disabled\r\n");
    } else if ( wifi.is_dhcp_configured() ) {
        debug("SSID : %-33s|\r\n", ipinfo.uaSSID);
        debug("IP : %-35s|\r\n", wifi.getIPAddress());
    } else if ( wifi.is_connected() ) {
        debug("Connecting, waiting for DHCP\r\n");
    } else {
        debug("Not Connected\r\n");
    }
}


/**
 * WiFi DipCortex board setup
 */
void init()
{
    NVIC_SetPriority(SSP1_IRQn, 0x0);
    NVIC_SetPriority(PIN_INT0_IRQn, 0x1);

    // SysTick set to lower priority than Wi-Fi SPI bus interrupt
    NVIC_SetPriority(SysTick_IRQn, 0x2);

    // Enable RAM1
    LPC_SYSCON->SYSAHBCLKCTRL |= (0x1 << 26);

    // This may be neccassary for CC3000
    wait(1);
}


/**
 * Connects WiFi assuming existing SmartConfig
 */
void connectWifi()
{
    wifi.start(0);
    wait_ms(750);
    wifi._wlan.ioctl_set_connection_policy(0, 0, 1);
    // TODO: Timeout and switch on smart config here
    // TODO: Use static IP if possible
}


/**
 * Brute force check to see if the connection is connected.
 * CC3000 doesn't detect dropped connection until send is
 * called.
 */
bool isConnected(TCPSocketConnection *connection) {
    wait_ms(CC3000_WAIT);
    debug("Checking conneciton is connected\r\n");
    connection->set_blocking(false, 2000);
    return connection->send("xxx\r\n", 5) > 0;
}


/**
 * Reads a long from the client and returns it as a float
 * between 0.0 and 1.0, which represents the relative
 * magnitude of the byte between 0 and UINT32_MAX.
 */
float getUint32AsFloat(TCPSocketConnection* connection) {
    uint32_t int_buffer;
    connection->set_blocking(false, 2000);
    int status = connection->receive_all((char*)&int_buffer, sizeof(int_buffer)); // 4 Bytes
    debug("Command print int32 recieved: %u with status: %d\r\n", int_buffer, status);
    int_buffer = ntohl(int_buffer);
    debug("Converted to host byte order: %u\r\n", int_buffer);
    debug("Conversion of uint32_t to float: %f\r\n", ((int_buffer*1.0f) / ((uint32_t)-1)));
    return (int_buffer*1.0f) / ((uint32_t)-1);
}


/**
 * Reads a byte from the client and returns it as a float
 * between 0.0 and 1.0, which represents the relative
 * magnitude of the byte between 0 and UINT8_MAX.
 */
float getUint8AsFloat(TCPSocketConnection* connection) {
    uint8_t char_buffer;
    connection->set_blocking(false, 2000);
    int status = connection->receive_all((char*)&char_buffer, sizeof(char_buffer)); // 1 Byte
    debug("Command left motor duty received: %d with status %d\r\n", char_buffer, status);
    debug("Converstion from uint8_t to float: %f\r\n", ((char_buffer*1.0f) / ((uint8_t)-1)));
    return ((char_buffer*1.0f) / ((uint8_t)-1));
}


/**
 * Client connection loop. This monitors the socket for
 * connections and proccesses them when they are
 * recieved. It returns when the client disconnects.
 */
 void monitorConnection(TCPSocketConnection* connection) {
    int timeout_counter = 1;
    while(1) {      
        wait_ms(CC3000_WAIT);
        char command = 0;
        connection->set_blocking(false, 5); //  5 ms time out is min for CC3000
        int status = connection->receive(&command, 1);
        if(status == 1) {
            debug("Recieved data from connection: %d with status %d\r\n", command, status);
            switch(command) {
                case CMD_C_ECHO:
                    wait_ms(CC3000_WAIT);
                    char buffer[3];
                    connection->set_blocking(false, 2000);
                    status = connection->receive_all(buffer, sizeof(buffer));
                    debug("Echo test recieved: %s Status: %d\r\n", buffer, status);
                    
                    wait_ms(CC3000_WAIT);
                    status = connection->send_all(buffer, sizeof(buffer));
                    debug("Echo test send completed with status: %d\r\n");
                    break;
                    
                case CMD_C_LED_ON:
                    led = 1;
                    break;
                    
                case CMD_C_LED_OFF:
                    led = 0;
                    break;
                    
                case CMD_C_PRINT_UINT32:
                    wait_ms(CC3000_WAIT);
                    {   // Variable declerations inside switch must be in higher scope.
                        // This is only okay as it's debugging code.
                        float printFloat = getUint32AsFloat(connection);
                        debug("Print uint32 got float with value %f\r\n", printFloat);
                    }
                    break;

                case CMD_C_MOTOR_LEFT_DUTY:
                    wait_ms(CC3000_WAIT);
                    leftMotor.speed(2.0f * getUint8AsFloat(connection) - 1.0f);  // Convert to +/- 1
                    break;
                    
                case CMD_C_MOTOR_RIGHT_DUTY:
                    wait_ms(CC3000_WAIT);
                    rightMotor.speed(2.0f * getUint8AsFloat(connection) - 1.0f);  // Convert to +/- 1
                    break;
                    
                case CMD_C_MOTOR_LEFT_COAST:
                    leftMotor.coast();
                    break;
                          
                case CMD_C_MOTOR_RIGHT_COAST:
                    rightMotor.coast();
                    break;
                    
                case CMD_C_MOTOR_LEFT_STOP:
                    wait_ms(CC3000_WAIT);
                    leftMotor.stop(getUint8AsFloat(connection));
                    break;
                    
                case CMD_C_MOTOR_RIGHT_STOP:
                    wait_ms(CC3000_WAIT);
                    rightMotor.stop(getUint8AsFloat(connection));
                    break;
                                          
                default:
                    debug("Command %d not recognised\r\n", command);
                    break;
            }
        }

        /* Check to see if the non-blocking socket is closed */
        if((timeout_counter++) % 100 == 0) {
            if(!isConnected(connection)) {
                debug("Client disconected\r\n");
                leftMotor.coast();
                rightMotor.coast();
                break;
            }
        }
    }
}


/**
 * Where it all begins.
 */
int main(void)
{
    init();
    debug("Completed init()\r\n");
    printConnectionInfo();

    connectWifi();
    debug("Completed connectWifi()\r\n");
    printConnectionInfo();

    while(1) {
        debug("\r\nOne second client attachment loop\r\n");
        printConnectionInfo();

        TCPSocketConnection client;
        TCPSocketServer server;

        wait_ms(CC3000_WAIT);
        server.bind(SERVER_PORT);
        server.listen();
        int32_t status = server.accept(client);
        debug("Accept client returned with status %d\r\n", status);
        if(status >= 0) {
            wait_ms(CC3000_WAIT);
            client.set_blocking(false, 1000);
            debug("Connection from: %s \r\n", client.get_address());
            
            monitorConnection(&client);

            debug("Client connection lost\r\n");
        }
        led = !led;
        wait(1);
    }
}