Final version
Dependencies: mbed Servo Motor
main.cpp@2:15a043aa08ea, 2018-12-09 (annotated)
- Committer:
- kzar
- Date:
- Sun Dec 09 18:27:35 2018 +0000
- Revision:
- 2:15a043aa08ea
- Parent:
- 1:6d317aa0aae7
- Child:
- 3:25e57f22f970
Sets up a server and then waits for messages from connected devices. The message is then parsed and looks for commands to control the car. Currently only motor speed commands are implemented
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kzar | 0:60cec426fad9 | 1 | // This mbed code starts up a server on the esp8266 and then updates it according to inputs from the controller |
kzar | 0:60cec426fad9 | 2 | // The car will host the server, the controller will send commands to the server |
kzar | 0:60cec426fad9 | 3 | |
kzar | 0:60cec426fad9 | 4 | #include "mbed.h" |
kzar | 2:15a043aa08ea | 5 | #include "Motor.h" |
kzar | 0:60cec426fad9 | 6 | |
kzar | 0:60cec426fad9 | 7 | Serial pc(USBTX, USBRX); |
kzar | 0:60cec426fad9 | 8 | Serial esp(p28, p27); // tx, rx |
kzar | 0:60cec426fad9 | 9 | |
kzar | 2:15a043aa08ea | 10 | Motor left_motor(p25, p6, p5); // pwm, fwd, rev |
kzar | 2:15a043aa08ea | 11 | Motor right_motor(p26, p11, p10); //pwm, fwd, rev |
kzar | 0:60cec426fad9 | 12 | |
kzar | 0:60cec426fad9 | 13 | // Standard Mbed LED definitions |
kzar | 0:60cec426fad9 | 14 | DigitalOut led1(LED1); |
kzar | 0:60cec426fad9 | 15 | DigitalOut led2(LED2); |
kzar | 0:60cec426fad9 | 16 | DigitalOut led3(LED3); |
kzar | 0:60cec426fad9 | 17 | DigitalOut led4(LED4); |
kzar | 0:60cec426fad9 | 18 | |
kzar | 0:60cec426fad9 | 19 | // things for sending/receiving data over serial |
kzar | 0:60cec426fad9 | 20 | volatile int tx_in=0; |
kzar | 0:60cec426fad9 | 21 | volatile int tx_out=0; |
kzar | 0:60cec426fad9 | 22 | volatile int rx_in=0; |
kzar | 0:60cec426fad9 | 23 | volatile int rx_out=0; |
kzar | 0:60cec426fad9 | 24 | const int buffer_size = 4095; |
kzar | 0:60cec426fad9 | 25 | char tx_buffer[buffer_size+1]; |
kzar | 0:60cec426fad9 | 26 | char rx_buffer[buffer_size+1]; |
kzar | 0:60cec426fad9 | 27 | void Tx_interrupt(); |
kzar | 0:60cec426fad9 | 28 | void Rx_interrupt(); |
kzar | 0:60cec426fad9 | 29 | void read_line(); |
kzar | 0:60cec426fad9 | 30 | |
kzar | 0:60cec426fad9 | 31 | int DataRX; |
kzar | 0:60cec426fad9 | 32 | char cmdbuff[1024]; |
kzar | 0:60cec426fad9 | 33 | char replybuff[4096]; |
kzar | 0:60cec426fad9 | 34 | char webdata[4096]; // This may need to be bigger depending on WEB browser used |
kzar | 0:60cec426fad9 | 35 | char webbuff[4096]; // Currently using 1986 characters, Increase this if more web page data added |
kzar | 2:15a043aa08ea | 36 | void SendCMD(),getreply(),getcmd(),startserver(); |
kzar | 0:60cec426fad9 | 37 | char rx_line[1024]; |
kzar | 0:60cec426fad9 | 38 | |
kzar | 2:15a043aa08ea | 39 | // buffers used for taking float values from string commands |
kzar | 2:15a043aa08ea | 40 | char lm_buff[8]; |
kzar | 2:15a043aa08ea | 41 | char rm_buff[8]; |
kzar | 2:15a043aa08ea | 42 | char lsv_buff[8]; |
kzar | 2:15a043aa08ea | 43 | char rsv_buff[8]; |
kzar | 2:15a043aa08ea | 44 | char* lm; |
kzar | 2:15a043aa08ea | 45 | char* rm; |
kzar | 2:15a043aa08ea | 46 | char* lsv; |
kzar | 2:15a043aa08ea | 47 | char* rsv; |
kzar | 0:60cec426fad9 | 48 | |
kzar | 0:60cec426fad9 | 49 | int main() |
kzar | 0:60cec426fad9 | 50 | { |
kzar | 0:60cec426fad9 | 51 | pc.baud(9600); |
kzar | 0:60cec426fad9 | 52 | esp.baud(9600); |
kzar | 0:60cec426fad9 | 53 | led1=1,led2=0,led3=0, led4=0; |
kzar | 0:60cec426fad9 | 54 | // Setup a serial interrupt function to receive data |
kzar | 0:60cec426fad9 | 55 | esp.attach(&Rx_interrupt, Serial::RxIrq); |
kzar | 0:60cec426fad9 | 56 | // Setup a serial interrupt function to transmit data |
kzar | 0:60cec426fad9 | 57 | esp.attach(&Tx_interrupt, Serial::TxIrq); |
kzar | 0:60cec426fad9 | 58 | // Start up the server |
kzar | 0:60cec426fad9 | 59 | startserver(); |
kzar | 2:15a043aa08ea | 60 | |
kzar | 0:60cec426fad9 | 61 | // Everything is interrupt driven, infinite loop |
kzar | 0:60cec426fad9 | 62 | while(1) { |
kzar | 0:60cec426fad9 | 63 | // Read data if its available |
kzar | 0:60cec426fad9 | 64 | if(DataRX==1) { |
kzar | 2:15a043aa08ea | 65 | led1=!led1; |
kzar | 2:15a043aa08ea | 66 | getcmd(); |
kzar | 0:60cec426fad9 | 67 | esp.attach(&Rx_interrupt, Serial::RxIrq); |
kzar | 0:60cec426fad9 | 68 | } |
kzar | 0:60cec426fad9 | 69 | } |
kzar | 0:60cec426fad9 | 70 | } |
kzar | 0:60cec426fad9 | 71 | |
kzar | 0:60cec426fad9 | 72 | // Reads and processes GET and POST web data |
kzar | 2:15a043aa08ea | 73 | void getcmd() |
kzar | 0:60cec426fad9 | 74 | { |
kzar | 0:60cec426fad9 | 75 | wait_ms(200); |
kzar | 0:60cec426fad9 | 76 | esp.attach(NULL,Serial::RxIrq); |
kzar | 0:60cec426fad9 | 77 | DataRX=0; |
kzar | 0:60cec426fad9 | 78 | memset(webdata, '\0', sizeof(webdata)); |
kzar | 0:60cec426fad9 | 79 | strcpy(webdata, rx_buffer); |
kzar | 0:60cec426fad9 | 80 | memset(rx_buffer, '\0', sizeof(rx_buffer)); |
kzar | 0:60cec426fad9 | 81 | rx_in = 0; |
kzar | 0:60cec426fad9 | 82 | rx_out = 0; |
kzar | 0:60cec426fad9 | 83 | |
kzar | 2:15a043aa08ea | 84 | //Print command for debug |
kzar | 2:15a043aa08ea | 85 | pc.printf(webdata); |
kzar | 0:60cec426fad9 | 86 | // Modify this to check for our commands |
kzar | 0:60cec426fad9 | 87 | // check web data for form information |
kzar | 2:15a043aa08ea | 88 | lm = strstr(webdata, "left_motor="); |
kzar | 2:15a043aa08ea | 89 | rm = strstr(webdata, "right_motor="); |
kzar | 2:15a043aa08ea | 90 | if(lm != NULL ) { |
kzar | 2:15a043aa08ea | 91 | lm = lm + 11; |
kzar | 2:15a043aa08ea | 92 | for (int i = 0; i < 8; ++i){ |
kzar | 2:15a043aa08ea | 93 | if (lm != rm) |
kzar | 2:15a043aa08ea | 94 | lm_buff[i] = lm[i]; |
kzar | 2:15a043aa08ea | 95 | else |
kzar | 2:15a043aa08ea | 96 | break; |
kzar | 2:15a043aa08ea | 97 | } |
kzar | 2:15a043aa08ea | 98 | // Convert the lm_buff to a float value and clear buffer |
kzar | 2:15a043aa08ea | 99 | left_motor.speed(atof(lm_buff)); |
kzar | 2:15a043aa08ea | 100 | memset(lm_buff, '\0', sizeof(lm_buff)); |
kzar | 0:60cec426fad9 | 101 | } |
kzar | 2:15a043aa08ea | 102 | if( rm != NULL) { |
kzar | 2:15a043aa08ea | 103 | rm = rm + 12; |
kzar | 2:15a043aa08ea | 104 | for (int i = 0; i < 8; ++i){ |
kzar | 2:15a043aa08ea | 105 | if (rm[i] != '>') |
kzar | 2:15a043aa08ea | 106 | rm_buff[i] = rm[i]; |
kzar | 2:15a043aa08ea | 107 | else |
kzar | 2:15a043aa08ea | 108 | break; |
kzar | 2:15a043aa08ea | 109 | } |
kzar | 2:15a043aa08ea | 110 | // Convert the rm_buff to a float value and clear buffer |
kzar | 2:15a043aa08ea | 111 | right_motor.speed(atof(rm_buff)); |
kzar | 2:15a043aa08ea | 112 | memset(rm_buff, '\0', sizeof(rm_buff)); |
kzar | 0:60cec426fad9 | 113 | } |
kzar | 2:15a043aa08ea | 114 | |
kzar | 0:60cec426fad9 | 115 | } |
kzar | 0:60cec426fad9 | 116 | // Starts webserver |
kzar | 0:60cec426fad9 | 117 | void startserver() |
kzar | 0:60cec426fad9 | 118 | { |
kzar | 0:60cec426fad9 | 119 | // Reset the ESP8266 |
kzar | 0:60cec426fad9 | 120 | pc.printf("++++++++++ Resetting ESP ++++++++++\r\n"); |
kzar | 0:60cec426fad9 | 121 | strcpy(cmdbuff,"node.restart()\r\n"); |
kzar | 0:60cec426fad9 | 122 | SendCMD(); |
kzar | 1:6d317aa0aae7 | 123 | getreply(); |
kzar | 0:60cec426fad9 | 124 | wait(2); |
kzar | 2:15a043aa08ea | 125 | |
kzar | 0:60cec426fad9 | 126 | |
kzar | 0:60cec426fad9 | 127 | // Set up WiFi connection |
kzar | 2:15a043aa08ea | 128 | pc.printf("++++++++++ Connecting to WiFi ++++++++++\r\n"); |
kzar | 0:60cec426fad9 | 129 | |
kzar | 1:6d317aa0aae7 | 130 | strcpy(cmdbuff,"wifi.setmode(wifi.STATIONAP)\r\n"); |
kzar | 0:60cec426fad9 | 131 | SendCMD(); |
kzar | 0:60cec426fad9 | 132 | getreply(); |
kzar | 0:60cec426fad9 | 133 | wait(2); |
kzar | 0:60cec426fad9 | 134 | |
kzar | 2:15a043aa08ea | 135 | strcpy(cmdbuff,"wifi.ap.config({ssid=\"WestSide\",pwd=\"uNwieldy_cAbbage87\"})\r\n"); |
kzar | 0:60cec426fad9 | 136 | SendCMD(); |
kzar | 0:60cec426fad9 | 137 | getreply(); |
kzar | 0:60cec426fad9 | 138 | wait(2); |
kzar | 0:60cec426fad9 | 139 | |
kzar | 1:6d317aa0aae7 | 140 | strcpy(cmdbuff,"print(\"Server IP Address: \", wifi.ap.getip())\r\n"); |
kzar | 0:60cec426fad9 | 141 | SendCMD(); |
kzar | 0:60cec426fad9 | 142 | getreply(); |
kzar | 0:60cec426fad9 | 143 | wait(2); |
kzar | 0:60cec426fad9 | 144 | |
kzar | 0:60cec426fad9 | 145 | // Start up the server |
kzar | 0:60cec426fad9 | 146 | pc.printf("\n++++++++++ Starting Server ++++++++++\r\n> "); |
kzar | 0:60cec426fad9 | 147 | |
kzar | 0:60cec426fad9 | 148 | //create server |
kzar | 1:6d317aa0aae7 | 149 | strcpy(cmdbuff, "srv=net.createServer(net.TCP)\r\n"); |
kzar | 0:60cec426fad9 | 150 | SendCMD(); |
kzar | 0:60cec426fad9 | 151 | getreply(); |
kzar | 0:60cec426fad9 | 152 | wait(0.5); |
kzar | 0:60cec426fad9 | 153 | // Set the sever to listen (named conn) |
kzar | 0:60cec426fad9 | 154 | strcpy(cmdbuff,"srv:listen(80,function(conn)\r\n"); |
kzar | 0:60cec426fad9 | 155 | SendCMD(); |
kzar | 0:60cec426fad9 | 156 | getreply(); |
kzar | 1:6d317aa0aae7 | 157 | wait(2); |
kzar | 0:60cec426fad9 | 158 | // Define receive function |
kzar | 1:6d317aa0aae7 | 159 | strcpy(cmdbuff,"conn:on(\"receive\", function(conn, receivedData)\r\n"); |
kzar | 0:60cec426fad9 | 160 | SendCMD(); |
kzar | 0:60cec426fad9 | 161 | getreply(); |
kzar | 1:6d317aa0aae7 | 162 | wait(2); |
kzar | 0:60cec426fad9 | 163 | |
kzar | 0:60cec426fad9 | 164 | //print data to mbed |
kzar | 1:6d317aa0aae7 | 165 | strcpy(cmdbuff,"print(\"Received Data: \" .. receivedData)\r\n"); |
kzar | 0:60cec426fad9 | 166 | SendCMD(); |
kzar | 0:60cec426fad9 | 167 | getreply(); |
kzar | 1:6d317aa0aae7 | 168 | wait(2); |
kzar | 0:60cec426fad9 | 169 | |
kzar | 0:60cec426fad9 | 170 | // End receive function |
kzar | 0:60cec426fad9 | 171 | strcpy(cmdbuff,"end)\r\n"); |
kzar | 0:60cec426fad9 | 172 | SendCMD(); |
kzar | 0:60cec426fad9 | 173 | getreply(); |
kzar | 1:6d317aa0aae7 | 174 | wait(2); |
kzar | 0:60cec426fad9 | 175 | |
kzar | 0:60cec426fad9 | 176 | // Define sent function |
kzar | 0:60cec426fad9 | 177 | strcpy(cmdbuff,"conn:on(\"sent\",function(conn)\r\n"); |
kzar | 0:60cec426fad9 | 178 | SendCMD(); |
kzar | 0:60cec426fad9 | 179 | getreply(); |
kzar | 1:6d317aa0aae7 | 180 | wait(2); |
kzar | 0:60cec426fad9 | 181 | |
kzar | 0:60cec426fad9 | 182 | //print data to mbed |
kzar | 0:60cec426fad9 | 183 | strcpy(cmdbuff,"collectgarbage()\r\n"); |
kzar | 0:60cec426fad9 | 184 | SendCMD(); |
kzar | 0:60cec426fad9 | 185 | getreply(); |
kzar | 1:6d317aa0aae7 | 186 | wait(2); |
kzar | 0:60cec426fad9 | 187 | |
kzar | 0:60cec426fad9 | 188 | // End sent function |
kzar | 0:60cec426fad9 | 189 | strcpy(cmdbuff,"end)\r\n"); |
kzar | 0:60cec426fad9 | 190 | SendCMD(); |
kzar | 0:60cec426fad9 | 191 | getreply(); |
kzar | 1:6d317aa0aae7 | 192 | wait(2); |
kzar | 0:60cec426fad9 | 193 | |
kzar | 0:60cec426fad9 | 194 | // End server listening |
kzar | 0:60cec426fad9 | 195 | strcpy(cmdbuff,"end)\r\n"); |
kzar | 0:60cec426fad9 | 196 | SendCMD(); |
kzar | 0:60cec426fad9 | 197 | getreply(); |
kzar | 1:6d317aa0aae7 | 198 | wait(2); |
kzar | 0:60cec426fad9 | 199 | } |
kzar | 0:60cec426fad9 | 200 | |
kzar | 0:60cec426fad9 | 201 | |
kzar | 0:60cec426fad9 | 202 | // ESP Command data send |
kzar | 0:60cec426fad9 | 203 | void SendCMD() |
kzar | 0:60cec426fad9 | 204 | { |
kzar | 0:60cec426fad9 | 205 | int i; |
kzar | 0:60cec426fad9 | 206 | char temp_char; |
kzar | 0:60cec426fad9 | 207 | bool empty; |
kzar | 0:60cec426fad9 | 208 | i = 0; |
kzar | 0:60cec426fad9 | 209 | // Start Critical Section - don't interrupt while changing global buffer variables |
kzar | 0:60cec426fad9 | 210 | NVIC_DisableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 211 | empty = (tx_in == tx_out); |
kzar | 0:60cec426fad9 | 212 | while ((i==0) || (cmdbuff[i-1] != '\n')) { |
kzar | 0:60cec426fad9 | 213 | // Wait if buffer full |
kzar | 0:60cec426fad9 | 214 | if (((tx_in + 1) % buffer_size) == tx_out) { |
kzar | 0:60cec426fad9 | 215 | // End Critical Section - need to let interrupt routine empty buffer by sending |
kzar | 0:60cec426fad9 | 216 | NVIC_EnableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 217 | while (((tx_in + 1) % buffer_size) == tx_out) { |
kzar | 0:60cec426fad9 | 218 | } |
kzar | 0:60cec426fad9 | 219 | // Start Critical Section - don't interrupt while changing global buffer variables |
kzar | 0:60cec426fad9 | 220 | NVIC_DisableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 221 | } |
kzar | 0:60cec426fad9 | 222 | tx_buffer[tx_in] = cmdbuff[i]; |
kzar | 0:60cec426fad9 | 223 | i++; |
kzar | 0:60cec426fad9 | 224 | tx_in = (tx_in + 1) % buffer_size; |
kzar | 0:60cec426fad9 | 225 | } |
kzar | 0:60cec426fad9 | 226 | if (esp.writeable() && (empty)) { |
kzar | 0:60cec426fad9 | 227 | temp_char = tx_buffer[tx_out]; |
kzar | 0:60cec426fad9 | 228 | tx_out = (tx_out + 1) % buffer_size; |
kzar | 0:60cec426fad9 | 229 | // Send first character to start tx interrupts, if stopped |
kzar | 0:60cec426fad9 | 230 | esp.putc(temp_char); |
kzar | 0:60cec426fad9 | 231 | } |
kzar | 0:60cec426fad9 | 232 | // End Critical Section |
kzar | 0:60cec426fad9 | 233 | NVIC_EnableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 234 | return; |
kzar | 0:60cec426fad9 | 235 | } |
kzar | 0:60cec426fad9 | 236 | |
kzar | 0:60cec426fad9 | 237 | |
kzar | 0:60cec426fad9 | 238 | // Get Command and ESP status replies |
kzar | 0:60cec426fad9 | 239 | void getreply() |
kzar | 0:60cec426fad9 | 240 | { |
kzar | 0:60cec426fad9 | 241 | read_line(); |
kzar | 0:60cec426fad9 | 242 | sscanf(rx_line,replybuff); |
kzar | 0:60cec426fad9 | 243 | } |
kzar | 0:60cec426fad9 | 244 | |
kzar | 0:60cec426fad9 | 245 | // FUNCTIONS BELOW ARE FOR RX AND TX INTERUPTS (NOT WEB STUFF) |
kzar | 0:60cec426fad9 | 246 | |
kzar | 0:60cec426fad9 | 247 | // Read a line from the large rx buffer from rx interrupt routine |
kzar | 0:60cec426fad9 | 248 | void read_line() { |
kzar | 0:60cec426fad9 | 249 | int i; |
kzar | 0:60cec426fad9 | 250 | i = 0; |
kzar | 0:60cec426fad9 | 251 | // Start Critical Section - don't interrupt while changing global buffer variables |
kzar | 0:60cec426fad9 | 252 | NVIC_DisableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 253 | // Loop reading rx buffer characters until end of line character |
kzar | 0:60cec426fad9 | 254 | while ((i==0) || (rx_line[i-1] != '\r')) { |
kzar | 0:60cec426fad9 | 255 | // Wait if buffer empty |
kzar | 0:60cec426fad9 | 256 | if (rx_in == rx_out) { |
kzar | 0:60cec426fad9 | 257 | // End Critical Section - need to allow rx interrupt to get new characters for buffer |
kzar | 0:60cec426fad9 | 258 | NVIC_EnableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 259 | while (rx_in == rx_out) { |
kzar | 0:60cec426fad9 | 260 | } |
kzar | 0:60cec426fad9 | 261 | // Start Critical Section - don't interrupt while changing global buffer variables |
kzar | 0:60cec426fad9 | 262 | NVIC_DisableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 263 | } |
kzar | 0:60cec426fad9 | 264 | rx_line[i] = rx_buffer[rx_out]; |
kzar | 0:60cec426fad9 | 265 | i++; |
kzar | 0:60cec426fad9 | 266 | rx_out = (rx_out + 1) % buffer_size; |
kzar | 0:60cec426fad9 | 267 | } |
kzar | 0:60cec426fad9 | 268 | // End Critical Section |
kzar | 0:60cec426fad9 | 269 | NVIC_EnableIRQ(UART1_IRQn); |
kzar | 0:60cec426fad9 | 270 | rx_line[i-1] = 0; |
kzar | 0:60cec426fad9 | 271 | return; |
kzar | 0:60cec426fad9 | 272 | } |
kzar | 0:60cec426fad9 | 273 | |
kzar | 0:60cec426fad9 | 274 | |
kzar | 0:60cec426fad9 | 275 | // Interupt Routine to read in data from serial port |
kzar | 0:60cec426fad9 | 276 | void Rx_interrupt() { |
kzar | 0:60cec426fad9 | 277 | DataRX=1; |
kzar | 0:60cec426fad9 | 278 | //led3=1; |
kzar | 0:60cec426fad9 | 279 | // Loop just in case more than one character is in UART's receive FIFO buffer |
kzar | 0:60cec426fad9 | 280 | // Stop if buffer full |
kzar | 0:60cec426fad9 | 281 | while ((esp.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) { |
kzar | 0:60cec426fad9 | 282 | rx_buffer[rx_in] = esp.getc(); |
kzar | 0:60cec426fad9 | 283 | // Uncomment to Echo to USB serial to watch data flow |
kzar | 0:60cec426fad9 | 284 | pc.putc(rx_buffer[rx_in]); |
kzar | 0:60cec426fad9 | 285 | rx_in = (rx_in + 1) % buffer_size; |
kzar | 0:60cec426fad9 | 286 | } |
kzar | 0:60cec426fad9 | 287 | //led3=0; |
kzar | 0:60cec426fad9 | 288 | return; |
kzar | 0:60cec426fad9 | 289 | } |
kzar | 0:60cec426fad9 | 290 | |
kzar | 0:60cec426fad9 | 291 | |
kzar | 0:60cec426fad9 | 292 | // Interupt Routine to write out data to serial port |
kzar | 0:60cec426fad9 | 293 | void Tx_interrupt() { |
kzar | 0:60cec426fad9 | 294 | //led2=1; |
kzar | 0:60cec426fad9 | 295 | // Loop to fill more than one character in UART's transmit FIFO buffer |
kzar | 0:60cec426fad9 | 296 | // Stop if buffer empty |
kzar | 0:60cec426fad9 | 297 | while ((esp.writeable()) && (tx_in != tx_out)) { |
kzar | 0:60cec426fad9 | 298 | esp.putc(tx_buffer[tx_out]); |
kzar | 0:60cec426fad9 | 299 | tx_out = (tx_out + 1) % buffer_size; |
kzar | 0:60cec426fad9 | 300 | } |
kzar | 0:60cec426fad9 | 301 | //led2=0; |
kzar | 0:60cec426fad9 | 302 | return; |
kzar | 0:60cec426fad9 | 303 | } |