-->
Page 1 of 1

Simple Socket Server using PIC18F87J10

PostPosted: Fri Feb 05, 2016 12:14 pm
by Ranchip
Hello, new here. Will tell you about a test project I am working on. This is a simple socket server that turns 8 LED's on and off on a Microchip PIC18F87J10 development board. I am using the CCS compiler. There is a terminal connected for debugging. It does work, but I am open to suggestions.

First, the Put Command function. The ESP8266 is connected to UART2 and a terminal is on UART1. Both running at 9600. This just shoves commands out to the The ESP8266 then calls getReply.

Code: Select all// AT Put Command
// Send AT Commands to ESP8266
// ----------------------------------------------------------------------------
void at_putCommand(char * com) {
   int8 i = 0;
   
   fputs(com, UART1);            // Print command to terminal
   
   while (com[i] > 31) {         // Send command to ESP8266
      fputc(com[i], UART2);
      delay_ms(6);               // Need delay because of echo
      i++;
   }
   
   delay_ms(6);
   fputc('\r', UART2);
   delay_ms(6);
   fputc('\n', UART2);
   
   at_getReplay();
}


Get Reply function. Listens for data coming from the ESP8266 and sends it to the terminal. Has a timeout so we don't get stuck. Also, returns quicker on a 'K' or '>'.

Code: Select all// AT Get Reply
// Get reply from ESP8266
// ----------------------------------------------------------------------------
void at_getReplay() {
   int16 tout = 0;
   char c;
   
   while (!kbhit(UART2)) {             // Check for no reply Timeout
      delay_ms(1);
      if (++tout > 3000) {
         fputs("Timeout 1\n", UART1);
         return;
      }
   }
   
   tout = 0;
   while (TRUE) {
      if (kbhit(UART2)) {
         c = fgetc(UART2);
         if (c > 10) fputc(c, UART1);  // Send to terminal, Ignore NL
         if (c == 'K') tout = 3800;    // 'OK'
         if (c == '>') return;         // Send prompt
      } else delay_us(100);
      if (++tout > 4000) {             // Timeout
         fputc('\n', UART1);
         return;
      }
   }
}


Using the two functions above we can now set up the ESP8266 (And experiment with the settings.) Here I am setting things up for a socket server.

Code: Select all// AT Setup
// ----------------------------------------------------------------------------
void at_setup() {
   at_putCommand((char*)"AT+GMR");
   at_putCommand((char*)"AT+CWMODE=2");                                 // 2=Access Point
   at_putCommand((char*)"AT+CWSAP=\"ESP8266\",\"12345678\",1,3");       // Set up access point
   at_putCommand((char*)"AT+CIPAP=\"192.168.4.4\"");                    // Set IP Address ???

   at_putCommand((char*)"AT+CIPMODE=0");                                // 1=Transparent mode     // 0
   at_putCommand((char*)"AT+CIPMUX=1");                                 // 1=Multiple connections // 1
   
   at_putCommand((char*)"AT+CIFSR");                                    // Show IP Address
   at_putCommand((char*)"AT+CIPSERVER=1,222");                          // Server Mode, Port
   at_putCommand((char*)"AT+CIPSTO=2");                                 // Timeout Seconds
   
   fputs("Setup complete\n", UART1);
}


Now, listen for a client request:
Code: Select allvoid main(void) {
   while (TRUE) {                            // Wait for client request
      if (kbhit(UART2)) at_handleClient();   // Client request
   }
}


Handle Client parses out any needed data from the client request and acts on it accordingly.

Code: Select all// AT Handle Client
// ----------------------------------------------------------------------------
void at_handleClient() {
   int16 tout = 0;
   char c, req[80], leds[9], *p;
   int8 i=0;
   
   while (TRUE) {                               // Get client request
      while (kbhit(UART2)) {
         c = fgetc(UART2);
         if (c > 10 && i < 80) req[i++] = c;    // Save first 80 chars in req
      }
      delay_ms(1);
      if (++tout > 1000) break;
   }
   
   req[i] = 0;
   fputs(req, UART1);                           // Send client request to terminal
   
   if (strstr(req, (char*)"/led") != null) {                   // '/led?v=0'
      p = strstr(req, (char*)"?v=");                           // Find pointer
      if (p == null) strcpy(leds, "00000000");                 // If null use 00000000
      else strncpy(leds, p+3, 8);                              // else use value 
      setLed(leds);                                            // Turn LED's on/off

      at_write((char*)"HTTP/1.0 200 OK\n\n");                  // Any way to make this faster?
      sprintf(req, "<html><body><h1>LED %s </h1><hr>\n", leds);
      at_write(req);
      at_write((char*)"<form id='leds' action='led' method='get'>\n");
      sprintf(req, "<input type='text' name='v'  size='8' value='%s'>\n", leds);
      at_write(req);
      at_write((char*)"<input type='submit' value='Submit'>\n");
      at_write((char*)"</form>\n");
      at_write((char*)"</body></html>\n");
      at_putCommand((char*)"AT+CIPCLOSE");
   }
}


The above uses this to send data out the socket. This way I can have the PIC find the buffer length and take care of the overhead for me. It is slower than I would like, but at least it works.

Code: Select all// AT Write
// ----------------------------------------------------------------------------
void at_write(char * s) {
   int8 i, length;
   char cb[80];
   
   length = strlen(s);
   sprintf(cb, "AT+CIPSEND=0,%u", length);
   at_putCommand(cb);
   
   for (i=0; i<length; i++) {
      fputc(s[i], UART2);
      delay_us(100);
   }
   
   at_getReplay();
}


That is pretty much it. Pretty simple for what it does I think. From here I can create all sorts of remote control devices. Hopefully someone can find this helpful.