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

Revision:
5:7f5fcee1737d
Parent:
4:1b5c2a2cdeb7
Child:
7:ee8b630b0a33
--- a/main.cpp	Wed Nov 12 22:45:59 2014 +0000
+++ b/main.cpp	Mon Nov 17 19:26:30 2014 +0000
@@ -18,12 +18,21 @@
 #define debug(x, ...)
 #endif
 
+/* Network constants */
+#define SERVER_PORT 5678
+
 /* Client commands */
 #define CMD_NULL 0
 #define CMD_C_ECHO 0x61  // 'a'
-#define CMD_C_LED_ON 98
-#define CMD_C_LED_OFF 99
-#define CMD_C_PRINT_UINT32 100
+#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 0x70 // 'j'
 
 
 using namespace mbed_cc3000;
@@ -32,8 +41,9 @@
 /* On board LED */
 DigitalOut led(P0_1);
 
-/* External LED - Pin 1 */
-PwmOut pwm_led(P0_8);  // Pin 15
+/* 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));
@@ -42,7 +52,9 @@
 tNetappIpconfigRetArgs ipinfo;
 
 
-/* Prints CC3000 connection info */
+/**
+ * Prints CC3000 connection info
+ */
 void printConnectionInfo()
 {
     if (( wifi.is_enabled() ) && ( wifi.is_dhcp_configured() )) {
@@ -61,7 +73,9 @@
 }
 
 
-/* WiFi DipCortex board setup */
+/**
+ * WiFi DipCortex board setup
+ */
 void init()
 {
     NVIC_SetPriority(SSP1_IRQn, 0x0);
@@ -78,7 +92,9 @@
 }
 
 
-/* Connects WiFi assuming existing SmartConfig */
+/**
+ * Connects WiFi assuming existing SmartConfig
+ */
 void connectWifi()
 {
     wifi.start(0);
@@ -89,7 +105,142 @@
 }
 
 
-/* Where it all begins */
+/**
+ * Brute force check to see if the connection is connected.
+ * CC3000 doesn't detect dropped connection until send is
+ * called.
+ */
+bool isConnected(TCPSocketConnection *connection) {
+    connection->set_blocking(false, 1000);
+    return connection->send("abc\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(15);
+        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(15);
+                    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(15);
+                    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(15);
+                    {   // 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(15);
+                    leftMotor.speed(2.0f * getUint8AsFloat(connection) - 1.0f);  // Convert to +/- 1
+                    break;
+                    
+                case CMD_C_MOTOR_RIGHT_DUTY:
+                    wait_ms(15);
+                    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(15);
+                    leftMotor.stop(getUint8AsFloat(connection));
+                    break;
+                    
+                case CMD_C_MOTOR_RIGHT_STOP:
+                    wait_ms(15);
+                    rightMotor.stop(getUint8AsFloat(connection));
+                    break;
+                                          
+                default:
+                    debug("Command %d not recognised\r\n", command);
+                    break;
+            }
+        }
+
+        wait_ms(15);
+        /* Check to see if the non-blocking socket is closed */
+        if((timeout_counter++) % 100 == 0) {
+            if(!isConnected(connection)) {
+                debug("Client disconected\r\n");
+                break;
+            }
+        }
+    }
+}
+
+
+/**
+ * Where it all begins.
+ */
 int main(void)
 {
     init();
@@ -99,100 +250,29 @@
     connectWifi();
     debug("Completed connectWifi()\r\n");
     printConnectionInfo();
-    
-    debug("Setting led pwm to 0\r\n");
-    pwm_led.period_ms(1);  // 1 kHz
 
     while(1) {
         debug("\r\nOne second client attachment loop\r\n");
         printConnectionInfo();
 
-        debug("Creating server and client sockets\r\n");
-        wait_ms(15);
         TCPSocketConnection client;
         TCPSocketServer server;
-        int32_t status;
 
-        server.bind(5678);
+        wait_ms(15);
+        server.bind(SERVER_PORT);
         server.listen();
-        status = server.accept(client);
-        wait_ms(15);
-        int n_timeout = 1;
+        int32_t status = server.accept(client);
         debug("Accept client returned with status %d\r\n", status);
         if(status >= 0) {
-            client.set_blocking(false, 1000); //  5 ms time out is min for CC3000
+            wait_ms(15);
+            client.set_blocking(false, 1000);
             debug("Connection from: %s \r\n", client.get_address());
-            wait_ms(15);
+            
+            monitorConnection(&client);
 
-            while(1) {
-                debug("\r\nClient connected loop - 0 ms\r\n");
-                
-                wait_ms(15);
-                char command = 0;
-                client.set_blocking(false, 5); //  5 ms time out is min for CC3000
-                status = client.receive(&command, 1);
-                if(status == 1) {
-                    debug("Recieved data from client: %d with status %d\r\n", command, status);
-                    switch(command) {
-                        case CMD_C_ECHO:
-                            wait_ms(15);
-                            char buffer[3];
-                            client.set_blocking(false, 2000);
-                            status = client.receive_all(buffer, sizeof(buffer));
-                            debug("Echo test recieved: %s Status: %d\r\n", buffer, status);
-                            
-                            wait_ms(15);
-                            status = client.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(15);
-                            uint32_t int_buffer;
-                            client.set_blocking(false, 2000);
-                            status = client.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 int to float: %f\r\n", ((int_buffer*1.0f) / ((uint32_t)-1)));
-                            pwm_led = ((int_buffer*1.0f) / ((uint32_t)-1));
-                            break;
-                            
-                        default:
-                            debug("Command %d not recognised\r\n", command);
-                            break;
-                    }
-                }
- 
-                wait_ms(15);
-                /* Check to see if the non-blocking socket is closed */
-                if((n_timeout++) % 100 == 0) {
-                    client.set_blocking(false, 1000);
-                    status = client.send("abc\r\n", 5);
-                    debug("Single byte send returned with status %d\r\n", status);
-                    if(status < 0) {
-                        break;
-                    }
-                }
-            }
             debug("Client connection lost\r\n");
-            wait_ms(15);
         }
-        debug("Should now return to the top of while(1) after changing LED\r\n");
-        wait_ms(15);
-
-        debug("After wait_ms(15)\r\n");
         led = !led;
-        debug("After led = !led\r\n");
-        wait(1.);
-        debug("After wait(1.)\r\n");
+        wait(1);
     }
 }