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
Diff: main.cpp
- 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); } }