Maker Pro
Maker Pro

Make available text from ESP 8266

Hi.

I'm trying to make working a ESP8266 (ESP-01).
The goal would be to send some text from a PIC µC and make it accessible to any WiFi device in the room in "real time".

I have very few knowledge in networks. It could explain many thinks I don't understand with this module.

Currently, I only manage to send some AT commands to the WiFi module and read back the responses.
My program just try to configure it but I already enconter some problems.

  • First, some of commands found in documentation answers "ERROR". I don't know why : for example AT+CWCOUNTRY_CUR, AT+CWCOUNTRY_DEF, AT+CWHOSTNAME and much others.
  • Second. If I understand well, I think I'll need to configure it as SoftAP to create an opened WiFi network if there isn't one available in the house. And to configure it as Station which is connected to the SoftAP to share some HTML pages.
    So it's configured in Mode "3" (Station + SoftAP).

    My WiFi devices correctly detect the ESP and can connect to it as it's an access point.
    I wrote a little function to list all available WiFi network detected by the ESP and it correctly detects my home's router… but not itself : in the list the SoftAP doesn't appear.
    I tried to connect ESP Station to my home's router and it's OK. Strange no ?
  • Third. I don't understand how can I share HTML page on the created network. Using "AT+CIPSEND, how/where is saved data ?
    Do I have to execute AT+CIPSEND each time any device will ask for the page or would it be accessible permanently ?
    Right now, when ESP is connected to my home network, writing it's IP address in my computer's address bar doen't respond nothing.

Thanks for your explanations.

Code:
typedef struct {
    ESP_Encryption encryption;
    char ssid[__IDLengths__+1];
    signed char rssi;
    char mac[15];
    char channel;
} WIFI_AP;

// RESPONSE
typedef enum {
    ESP_OK = 0,
    // Messages texte
    ESP_READY = -1,
    ESP_LINKED = -2,
    ESP_UNLINK = -3,
    ESP_TRUNCATE  = -4,
          
    // Erreurs (see CWJAP)
    ESP_TIMEOUT = 1,
    ESP_PASSERR = 2,
    ESP_UNREACHABLE = 3,
    ESP_FAIL = 4,
    ESP_ERROR = 5,
    ESP_NOCHANGE = 6
} ESP_RESULT;

// TYPE
#define ESP_CURRENT "_CUR"
#define ESP_DEFAULT "_DEF"
// Semblent non implémentés
//#define ESP_CURRENT ""
//#define ESP_DEFAULT ""


// SET / GET
#define ESP_TEST    "=?"
#define ESP_GET     "?"
#define ESP_SET     "="
//#define ESP_EXEC    ""

// COMMANDS
#define ESP_ENDCMD      "\r\n"

#define ESP_SysTest     "AT"
#define ESP_Restart     "AT+RST"
#define ESP_Echo        "ATE"
#define ESP_Uart        "AT+UART"

#define AP_Mode         "AT+CWMODE"
#define AP_Country      "AT+CWCOUNTRY"
#define AP_Join         "AT+CWJAP"
#define AP_ListConf     "AT+CWLAPOPT"
#define AP_List         "AT+CWLAP"
#define AP_Quit         "AT+CWQAP"
#define AP_Config       "AT+CWSAP"
#define AP_DHCP         "AT+CWDHCP"

#define IP_HostName     "AT+CWHOSTNAME"
#define IP_Status       "AT+CIPSTATUS"
#define IP_Multiplex    "AT+CIPMUX"
#define IP_Server       "AT+CIPSERVER"
#define IP_Start        "AT+CIPSTART"
#define IP_Send         "AT+CIPSEND"    // "AT+CIPSENDBUF"

 /**
  * Function to get one byte of date from UART
  * @param i:   -1 for infinite loop, else number of iterations
  * @return character or 0xFF (timeout)
  */
static char _esp_getch(signed int i)   
{
    if(RCSTA1bits.OERR) // check for Error
    {
        RCSTA1bits.CREN = 0; //If error -> Reset
        RCSTA1bits.CREN = 1; //If error -> Reset
    }
  
    while(!PIR1bits.RC1IF && i > 0) i--;  // hold the program till RX buffer is free
  
    if (i) return RCREG1; //receive the value and send it to main function
    else return 0xFF;
}

/** For short responses, I read it immediately **/
/**
 * Get full response in buffer
 * @param respStr :     dest string
 * @param bFull   :     0 : return only 1 line
 *                      1 : return all immediate response
 *                      2 : fill all buffer size, without watching result
 * return   bFull = 0 : return pointer to last char
 *          bFull = 1 : return ESP_TRUNCATE if buff full, ESP_OK else
 *          bFull = 2 : return ESP_OK
*/
static ESP_RESULT _esp_getFullResponse(char* respStr, char bFull) {
    char byte;
    char bufSize = __MaxResponsesLength__ - 1;
  
    while (bufSize) {
        byte = _esp_getch(10000);
        if (byte != 0xFF || (!bFull && byte != '\n')) {
            *respStr = byte;
            respStr++; bufSize--;
        }
        else if (bFull < 2) break;
    }
  
    *(respStr) = '\0';
    //if (bFull == 0) return respStr;
    /*else */if (bufSize || bFull == 2) return ESP_OK;
    else return ESP_TRUNCATE;
}

/**
 *
 * @param respStr : response string
 * @return ESP_RESULT
 */
static ESP_RESULT _esp_getResult(char* respStr) {
  
        if (strspn(respStr, "OK") == 2)               return ESP_OK;
        else if (strspn(respStr, "ready") == 5)       return ESP_READY;
        else if (strspn(respStr, "FAIL") == 4)        return ESP_FAIL;
        else if (strspn(respStr, "ERROR") == 5)       return ESP_ERROR;
        else if (strspn(respStr, "CONNECTED") == 9)   return ESP_LINKED;
        else if (strspn(respStr, "DISCONNECTED") == 10) return ESP_UNLINK;
      
        else return ESP_NOCHANGE;
}

/**
 * Read last return code
 * param respStr : string to check
 * @return
 */
static ESP_RESULT _esp_readLastResponse(char* respStr) {
    char *token;
    ESP_RESULT response;
  
    token = strtok(respStr, " \r\n");     
    while (token != false) {
        response = _esp_getResult(token);
        token = strtok(NULL, " \r\n");
    }
    return response;
}

/**
 * Wait for final response of ESP and return ESP_RESULT
 * @param wait :   seconds to wait for response
 * @return ESP_RESULT
 */
static ESP_RESULT _esp_getLastResponse(void) {
    char responses[__MaxResponsesLength__];
    char * token;
    ESP_RESULT response;
  
    response = _esp_getFullResponse(responses, 1);
    if (response != ESP_OK) return response;

    return _esp_readLastResponse(responses);
}
/**
 * Configure default settings of the ESP8266 - Run it one time via setting __CONFIGURE = 1 in Config.h
 * @return ESP_RESULT
 */
ESP_RESULT esp_Configure() {
    ESP_RESULT result;
    char message[255];

#if !__DEBUG
    sprintf(message, "%u", 0);
    _esp_print(ESP_Echo);
    _esp_print(message);
    _esp_print(ESP_ENDCMD);
    result = _esp_getLastResponse();
    if (result > 0) return result;
#else
    //sprintf(message, "%u", 1);
#endif
  
    // Set as AccessPoint
    sprintf(message, "%u", ESP_STATION|ESP_SOFTAP);
    _esp_print(AP_Mode);
    _esp_print(ESP_DEFAULT);
    _esp_print(ESP_SET);
    _esp_print(message);
    _esp_print(ESP_ENDCMD);
    result = _esp_getLastResponse();
    if (result > 0) return result;
 
    // Configure AccessPoint
    sprintf(message, "%u,%u", Default_Channel, 0);
    _esp_print(AP_Config);
    _esp_print(ESP_DEFAULT);
    _esp_print(ESP_SET);
    _esp_print("\"");
    _esp_print(Default_SSID);
    _esp_print("\",\"\",");
    _esp_print(message);
    _esp_print(ESP_ENDCMD);
    result = _esp_getLastResponse();
    if (result > ESP_OK) return result;
      
    return result;
}

////////////////////////////
/*** Interfaces scanning, ESP's response is saved in interrupt routine in a circular buffer **/
/**
 * Wait for reading a "\n" in the buffer while using interrupts
 * @param wait : max wait time in seconds
 * return 0 if time out, pointer to destString else
 */
static char* _waitForFullLine(char* destString, int wait) {
    char * endOfLine = NULL;
    char tmpHead, tmpTail;
    int length = -1;
    wait *= 100;
  
    while (wait) {
        if (!length) length = -1;
        else {
            __delay_ms(10);
            wait--;
        }
      
        tmpHead = iRxHead;
        tmpTail = iRxTail;
      
        if (tmpHead == tmpTail) {
            if (PIE1bits.RC1IE == 0) endOfLine = tmpHead; // software buffer overrun happened
            else continue;    // no character received
        }
      
        // else search for first '\n' in receipted characters
        if (tmpHead > tmpTail) {
            if (endOfLine == NULL) endOfLine = memchr(&incomingMessages[tmpTail], '\n', tmpHead - tmpTail);
            if (endOfLine == NULL) continue;
          
            // copy line to buffer
            length = endOfLine - incomingMessages + tmpTail;
            memcpy(destString, &incomingMessages[tmpTail], length);
            break;
        }
        else {
            if (endOfLine == NULL) endOfLine = memchr(&incomingMessages[tmpTail], '\n', RxBufSize - tmpTail);
            if (endOfLine == NULL) endOfLine = memchr(incomingMessages, '\n', tmpHead);
            if (endOfLine == NULL) continue;
          
            // copy line to buffer
            if (endOfLine > (incomingMessages + tmpTail)) {
                length = endOfLine - incomingMessages + tmpTail;
                memcpy(destString, &incomingMessages[tmpTail], endOfLine - incomingMessages + tmpTail);
            }
            else {
                length = RxBufSize - tmpTail;
                memcpy(destString, &incomingMessages[tmpTail], length);
                memcpy(destString + length, incomingMessages, endOfLine - incomingMessages);
                length += (endOfLine - incomingMessages);
            }
            break;
        }
    }
  
    // time out
    if (!wait) return 0;
    // add end string character
    *(destString + length) = '\0';
    iRxTail = endOfLine + 1;
    return destString;
}

/**
 * Scan and save __MaxSavedNetworks__ detected networks in KnownWifi, sorted by more powerfull
 * @return number of available WiFi found
 */
char scanInterfaces() {
    char i;
    char interface[__MaxResponsesLength__];
    char * token;
    char buff;
    long waitTimer;
    ESP_RESULT retour = ESP_OK;
  
    for (i=0; i<__MaxSavedNetworks__; i++) {
        KnownWifi[i].encryption = ECN_NOAP;
    }
  
    // Let's use buffer reception (Enable interrupt)
    _Init_RxInterrupt();
  
    _esp_print(AP_List);
    _esp_print(ESP_ENDCMD);
  
    for (i=0; i<__MaxSavedNetworks__; i++) {
      
        token = _waitForFullLine(interface, 5);
        if (token == 0) {
            retour = ESP_TIMEOUT;
            break;
        }
        if (!PIE1bits.RC1IE) {
            PIE1bits.RC1IE = 1;
            // Overrun, on n'a pris que cette partie de la ligne actuelle on attend simplement sa fin sans l'ajouter (interface est plein)
            _waitForFullLine(interface, 5);
        }
      
        /*
        waitTimer = 70 * 5;
        do {
            _esp_getFullResponse(interface, 0);
            waitTimer--;
        } while (interface[0] == '\0' && waitTimer);
      
        if (!waitTimer) {
            retour = ESP_TIMEOUT;
            break;
        }*/
      
        retour = _esp_getResult(interface);
        if (retour != ESP_NOCHANGE) break;
  
        token = strtok(&interface, ":");
        if (token == false) i--;
      
        while (token != false) {
            token = strtok(NULL, "(,");           
            if (token == false) {
                i--; break;
            }
            KnownWifi[i].encryption = strtol(*token, NULL, 10);
          
            token = strtok(NULL, ",\"");
            if (token == false) break;
            strcpy(KnownWifi[i].ssid, token);
          
            token = strtok(NULL, ",");
            if (token == false) break;
            KnownWifi[i].rssi = strtol(token, NULL, 10);
          
            token = strtok(NULL, "\"");
            if (token == false) break;
            strcpy(KnownWifi[i].mac, token);
          
            token = strtok(NULL, ",)");
            if (token == false) break;
            KnownWifi[i].channel = strtol(token, NULL, 10);
            break;
        }
    }

    // Stop interrupts
    PIE1bits.RC1IE = 0;
    if (retour == ESP_OK) return i;
    else return -1;
}
 
Top