ESP8266 - подключение к Arduino

ESP8266 + Arduino

Продолжение ESP8266.




В предыдущей публикации мы познакомились с Wifi-модулем ESP, научились прошивать, и управлять им с помощью АТ-команд. Сейчас подключим к нему ардуину, которая будет управлять переферией и формировать ответ для клиента. Сам модуль (с заводской прошивкой) делать этого не умеет.

Некоторые действия, предложенные в статье, могут показаться лишними, но я решил быть последовательным в описании сабжа.



Как всё будет работать

Модуль ESP будет подключён к ардуине через программный порт (SoftwareSerial) и обмениваться с ней данными, а сама ардуина будет подключена к компьютеру стандартным способом, чтоб можно было через терминал следить за происходящим.

Компьютер подключён к домашнему роутеру (провод или wifi) и ESP будет подключаться к тому же роутеру по wifi.


Поскольку модуль будет подключаться к программному порту, то необходимо настроить ESP на скорость 9600. (вся инфа по работе с модулем находится здесь)

AT+CIOBAUD=9600

После этого не забудте переправить скорость терминала.


Ардуина

Подключите ESP к ардуине согласно рисунку…





И залейте скетч:



#include <SoftwareSerial.h>
SoftwareSerial ESPport(10, 11); 
////////////////////// RX, TX

// если у вас MEGA, то закомментируйте верхние две строчки и раскомментируйте нижеследующую.
// ESP подключите к Serial1 (18, 19), скорость можно сделать 57600
// HardwareSerial & ESPport = Serial1;

const int ledPin =  13;     
int ledState = HIGH;           
#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];
String vklotkl;
 
void setup() 
{ 
  pinMode(ledPin, OUTPUT);        
  Serial.begin(9600); // Терминал
  ESPport.begin(9600); // ESP8266  
  clearSerialBuffer(); // очистка буфера Serial
  Serial.println("RESET 3,5 sek");
  Serial.println(GetResponse("AT+RST",3400)); // перезагрузка ESP
  Serial.println(GetResponse("AT+CWMODE=1",300)); // режим клиента   
  connectWiFi("myrouter","parolparol"); // подключаемся к домашнему роутеру (имя точки, пароль) 
  Serial.println(GetResponse("AT+CIPMODE=0",300)); // сквозной режим передачи данных. 
  Serial.println(GetResponse("AT+CIPMUX=1",300)); // multiple connection.
  Serial.print("Start TCP-server: ");
  Serial.println(GetResponse("AT+CIPSERVER=1,88", 300)); // запускаем ТСР-сервер на 88-ом порту
  Serial.println(GetResponse("AT+CIPSTO=2", 300)); // таймаут сервера 2 сек
  Serial.println(GetResponse("AT+CIFSR", 300)); // узнаём адрес
  digitalWrite(ledPin,ledState);  
}
///////////////////основной цикл, принимает запрос от клиента/////////////////// 
void loop() 
{
 int ch_id, packet_len; // объявляем переменные
 char *pb;  
 ESPport.readBytesUntil('\n', buffer, BUFFER_SIZE); // читаем строку из есп в переменную "buffer"
  
 if(strncmp(buffer, "+IPD,", 5)==0) // если в "buffer" есть строка из пяти символов - "+IPD," тогда -
  {                                 // (СИшная функция "strncmp" сравнивает содержимое "buffer" с заданой строкой "+IPD,")
   sscanf(buffer+5, "%d,%d", &ch_id, &packet_len); // - вычитываем из "buffer" и засовываем в переменные (ch_id и packet_len) id клиента и длину пакета 
   if (packet_len > 0)                             // (СИшная функция "sscanf")
    {
      pb = buffer+5;
      while(*pb!=':') pb++;
      pb++;
      if(strncmp(pb, "GET / ", 6) == 0) // если в "pb" есть фраза "GET / ", то 
       {
        Serial.println(buffer); // выводим в консоль содержимое buffer (просто чтоб поглядеть чего прилетело, для работы эти пять строк можно закомментировать)
        Serial.print("get led from ch :");
        Serial.println(ch_id);
        delay(100);
        clearSerialBuffer(); 
        
        if(ledState == LOW) // узнаём состояние светика
          {
            ledState = HIGH;
            vklotkl = "VKL";
          }
        
        else 
          {
            ledState = LOW;
            vklotkl = "OTKL";
          } 
        
        digitalWrite(ledPin, ledState); // инвертируем состояние светика
        otvet_klienty(ch_id);  // отправляемся в функцию формирования ответа клиенту (и передаём ей id клиента)
       } 
    }
  }
  clearBuffer();
}
//////////////////////формирование ответа клиенту////////////////////
void otvet_klienty(int ch_id) 
{  
  // собираем строку для клиента (заголовок пакета)                       
  String Header; 
 
  Header =  "HTTP/1.1 200 OK\r\n";  
  Header += "Content-Type: text/html\r\n";
  Header += "Connection: close\r\n";  
  
  // содержимое пакета
  String Content;

  Content = "LED 13: " + vklotkl;
  
  Header += "Content-Length: ";
  Header += (int)(Content.length());
  Header += "\r\n\r\n";
  
  ESPport.print("AT+CIPSEND="); // ответ клиенту: ат-команда, id-клиента, , , длина пакета
  ESPport.print(ch_id);
  ESPport.print(",");
  ESPport.println(Header.length()+Content.length());
  delay(20);

  if(ESPport.find(">")) // ожидание от esp приглашения ввода
    {
      ESPport.print(Header); // отправка заголовка
      ESPport.print(Content); // отправка содержимого пакета
      delay(110);
    }
}
/////////////////////отправка АТ-команд/////////////////////
String GetResponse(String AT_Command, int wait)
{
  String tmpData;
  
  ESPport.println(AT_Command);
  delay(wait);
  while (ESPport.available() >0 )  
   {
    char c = ESPport.read();
    tmpData += c;
    
    if ( tmpData.indexOf(AT_Command) > -1 )         
      tmpData = "";
    else
      tmpData.trim();       
          
   }
  return tmpData;
}
//////////////////////очистка ESPport////////////////////
void clearSerialBuffer(void) 
{
       while ( ESPport.available() > 0 ) 
       {
         ESPport.read();
       }
}
////////////////////очистка буфера//////////////////////// 
void clearBuffer(void) {
       for (int i =0;i<BUFFER_SIZE;i++ ) 
       {
         buffer[i]=0;
       }
}
////////////////////подключение к wifi/////////////////////        
boolean connectWiFi(String NetworkSSID,String NetworkPASS) 
{
  String cmd = "AT+CWJAP=\"";
  cmd += NetworkSSID;
  cmd += "\",\"";
  cmd += NetworkPASS;
  cmd += "\"";
  Serial.println(cmd); 
  Serial.println(GetResponse(cmd,6500));
}


При включении, ардуина настраивает модуль АТ-командами:

Сначала ресет, потом задаёт режим (клиент), конектится к домашнему роутеру, устанавливает ещё пару режимов, запускает ТСР-сервер, таймаут сервера (через сколько секунд он будет обрывать соединение) и показавает ip-адрес.

Когда клиент отправляет запрос модулю, модуль передаёт его в ардуину по UARTу, ардуина разбирает его, формирует ответ, отдаёт его обратно модулю (по UARTу) и модуль возвращает ответ клиенту. То есть реализуется обычный HTML протокол.



Откройте терминал, нажмите кнопочку ресет на ардуине и подождите несколько секунд, пока не загорится D13.

Если всё хорошо, то на все команды, модуль будет отвечать ОК. Если появятся надпись «busys» (это один из «глюков» заводской прошивки), то придётся передёрнуть питание или кратковременно закоротить пин RESET на «землю».


Всё ОК...


Зайдите в браузере по адресу 192.168.5.193:88 и увидите LED 13: OTKL, обновите страничку (нажмите F5) — надпись поменяется на LED 13: VKL и светодиод загорится. При этом в терминал будет выдаваться инфа:


Разберём поробнее информацию предоставленную модулем — +IPD,0,339:GET / HTTP/1.1.
Собственно ради этих строчек мы и подключали модуль к программному порту.


+IPD — это служебная команда ESP, сообщающая нам (в данном случае ардуине), что был получен пакет.
0 — это id соединения, как писалось выше, кол-во одновременных соединений (клиентов) может быть не больше четырёх.
339 — это длина пакета (видна только часть, остальное обрезано).
После двоеточия идут сами данные — GET-запрос и версия протокола.

Как только ардуина получает этот запрос от ESP, она его разбирает, включает/отключает светодиод:


void loop() 
{
 int ch_id, packet_len;
 char *pb;  
 ESPport.readBytesUntil('\n', buffer, BUFFER_SIZE);
  
 if(strncmp(buffer, "+IPD,", 5)==0) 
  {
   sscanf(buffer+5, "%d,%d", &ch_id, &packet_len);
...
        digitalWrite(ledPin, ledState);
        otvet_klienty(ch_id);
...


Формирует и отправляет ответ в ESP, который в свою очередь отдаёт его клиенту:


void otvet_klienty(int ch_id) 
{
  String Header;
 
  Header =  "HTTP/1.1 200 OK\r\n";
  Header += "Content-Type: text/html\r\n";
  Header += "Connection: close\r\n";  
  
  String Content;
  
  Content = "<body><form action='' method='GET'><input type='submit' value='VKL/OTKL'> " + vklotkl;
  Content += "</form></body></html>";
 
  Header += "Content-Length: ";
  Header += (int)(Content.length());
  Header += "\r\n\r\n";
  
  ESPport.print("AT+CIPSEND=");
...

И так по кругу, запрос-ответ...




Управление ардуиной с помощью обновления страницы не самое удобное решение ))), поэтому нужно приделать кнопку.

Для этого залейте новый скетч…


#include <SoftwareSerial.h>
SoftwareSerial ESPport(10, 11); 
////////////////////// RX, TX

// если у вас MEGA, то закомментируйте верхние две строчки и раскомментируйте нижеследующую.
// ESP подключите к Serial1 (18, 19), скорость можно сделать 57600
// HardwareSerial & ESPport = Serial1;

const int ledPin =  13;     
int ledState = HIGH;           
#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];
String vklotkl;
 
void setup() 
{ 
  pinMode(ledPin, OUTPUT);        
  Serial.begin(9600); // Терминал
  ESPport.begin(9600); // ESP8266  
  clearSerialBuffer();
  Serial.println("RESET 3,5 sek");
  Serial.println(GetResponse("AT+RST",3400)); // перезагрузка ESP
  Serial.println(GetResponse("AT+CWMODE=1",300)); // режим клиента   
  connectWiFi("myrouter","parolparol"); // подключаемся к домашнему роутеру (имя точки, пароль) 
  Serial.println(GetResponse("AT+CIPMODE=0",300)); // сквозной режим передачи данных. 
  Serial.println(GetResponse("AT+CIPMUX=1",300)); // multiple connection.
  Serial.print("Start TCP-server: ");
  Serial.println(GetResponse("AT+CIPSERVER=1,88", 300)); // запускаем ТСР-сервер на 88-ом порту
  Serial.println(GetResponse("AT+CIPSTO=2", 300)); // таймаут сервера 2 сек
  Serial.println(GetResponse("AT+CIFSR", 300)); // узнаём адрес
  digitalWrite(ledPin,ledState);  
}
///////////////////основной цикл, принимает запрос от клиента/////////////////// 
void loop() 
{
 int ch_id, packet_len;
 char *pb;  
 ESPport.readBytesUntil('\n', buffer, BUFFER_SIZE);
  
 if(strncmp(buffer, "+IPD,", 5)==0) 
  {
   sscanf(buffer+5, "%d,%d", &ch_id, &packet_len);
   if (packet_len > 0) 
    {
      pb = buffer+5;
      while(*pb!=':') pb++;
      pb++;
      if((strncmp(pb, "GET / ", 6) == 0) || (strncmp(pb, "GET /?", 6) == 0))
       {
         
        Serial.println(buffer); 
        Serial.print("get led from ch :");
        Serial.println(ch_id);
        delay(100);
        clearSerialBuffer();
        
        if(ledState == LOW) 
          {
            ledState = HIGH;
            vklotkl = "VKL";
          }
        
        else 
          {
            ledState = LOW;
            vklotkl = "OTKL";
          } 
        
        digitalWrite(ledPin, ledState);
        otvet_klienty(ch_id);
       } 
    }
  }
  clearBuffer();
}
//////////////////////формирование ответа клиенту////////////////////
void otvet_klienty(int ch_id) 
{
  String Header;
 
  Header =  "HTTP/1.1 200 OK\r\n";
  Header += "Content-Type: text/html\r\n";
  Header += "Connection: close\r\n";  
  
  String Content;
  
  Content = "<body><form action='' method='GET'><input type='submit' value='VKL/OTKL'> " + vklotkl;
  Content += "</form></body></html>";
 
  Header += "Content-Length: ";
  Header += (int)(Content.length());
  Header += "\r\n\r\n";
  
  ESPport.print("AT+CIPSEND="); // ответ клиенту
  ESPport.print(ch_id);
  ESPport.print(",");
  ESPport.println(Header.length()+Content.length());
  delay(20);

  if(ESPport.find(">")) 
    {
      ESPport.print(Header);
      ESPport.print(Content);
      delay(200); 
    }
}
/////////////////////отправка АТ-команд/////////////////////
String GetResponse(String AT_Command, int wait)
{
  String tmpData;
  
  ESPport.println(AT_Command);
  delay(wait);
  while (ESPport.available() >0 )  
   {
    char c = ESPport.read();
    tmpData += c;
    
    if ( tmpData.indexOf(AT_Command) > -1 )         
      tmpData = "";
    else
      tmpData.trim();       
          
   }
  return tmpData;
}
//////////////////////очистка ESPport////////////////////
void clearSerialBuffer(void) 
{
       while ( ESPport.available() > 0 ) 
       {
         ESPport.read();
       }
}
////////////////////очистка буфера//////////////////////// 
void clearBuffer(void) {
       for (int i =0;i<BUFFER_SIZE;i++ ) 
       {
         buffer[i]=0;
       }
}
////////////////////подключение к wifi/////////////////////        
boolean connectWiFi(String NetworkSSID,String NetworkPASS) 
{
  String cmd = "AT+CWJAP=\"";
  cmd += NetworkSSID;
  cmd += "\",\"";
  cmd += NetworkPASS;
  cmd += "\"";
  Serial.println(cmd); 
  Serial.println(GetResponse(cmd,6500));
}


Изменения коснулись этих частей:


...
pb = buffer+5;
      while(*pb!=':') pb++;
      pb++;
      if((strncmp(pb, "GET / ", 6) == 0) || (strncmp(pb, "GET /?", 6) == 0))
...



...
  String Content;
  
  Content = "<body><form action='' method='GET'><input type='submit' value='VKL/OTKL'> " + vklotkl;
  Content += "</form></body></html>";
...


… и зайдите в браузер…


Нажатие на кнопку будет включать/отключать D13 и менять статус.



В силу того, что заводская прошивка несколько «сыровата» Вы столкнётесь с различными ошибками.

Например, если быстро нажимать на кнопку или зажать на клавиатуре, то модуль очень скоро зависнет. Выражается это по разному, может просто не отвечать и не выводить ничего не на страницу, не в терминал, а может ничего не выводить на страницу, но при этом управлять светодиодом на ардуине (если просто обновлять страницу). Может вывести в терминал надпись «busys» и не реагировать не на что, а может и работать при этом. Одним словом, происходит масса непонятных вещей.

Одной из причин нестабильного поведения является ардуина, а точнее низкая скорость программного UARTа (SoftwareSerial) и как следствие не способность быстро отдавать ответ в ESP. Из-за чего на ТСР-сервере ESP увеличивается кол-во соединений (а их может быть не больше четырёх) и он «отваливается».

Частично можно решить проблемы следующим способом:
Не много модифицируем скетч, а точнее переключим общение ардуины с модулем на аппаратный UART и поднимим скорость до 115200.

Предварительно необходимо изменить скорость UARTа у ESP. Сделать это можно просто сбросив модуль к заводским настройкам (при условии, что у Вас стоит прошивка из предыдущей части), после этого скорость будет 115200.

Для этого в скетче, в функции void setup() замените

Serial.println(GetResponse("AT+RST",3400));

на

Serial.println(GetResponse("AT+RESTORE",3400));

и прошейте ардуину. Теперь у модуля будет скорость 115200.


Далее залейте вот этот скетч:


HardwareSerial & ESPport = Serial;

const int ledPin =  13;     
int ledState = HIGH;           
#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];
String vklotkl;
 
void setup() 
{ 
  pinMode(ledPin, OUTPUT);        
  //Serial.begin(9600); // Терминал
  ESPport.begin(115200); // ESP8266  
  clearSerialBuffer();
 
  GetResponse("AT+RST",3400); // перезагрузка ESP
  GetResponse("AT+CWMODE=1",300); // режим клиента   
  connectWiFi("myrouter","parolparol"); // подключаемся к домашнему роутеру (имя точки, пароль) 
  GetResponse("AT+CIPMODE=0",300); // сквозной режим передачи данных. 
  GetResponse("AT+CIPMUX=1",300); // multiple connection.
  
  GetResponse("AT+CIPSERVER=1,88", 300); // запускаем ТСР-сервер на 88-ом порту
  GetResponse("AT+CIPSTO=2", 300); // таймаут сервера 2 сек
  GetResponse("AT+CIFSR", 300); // узнаём адрес
  digitalWrite(ledPin,ledState);  
}
///////////////////основной цикл, принимает запрос от клиента/////////////////// 
void loop() 
{
 int ch_id, packet_len;
 char *pb;  
 ESPport.readBytesUntil('\n', buffer, BUFFER_SIZE);
  
 if(strncmp(buffer, "+IPD,", 5)==0) 
  {
   sscanf(buffer+5, "%d,%d", &ch_id, &packet_len);
   if (packet_len > 0) 
    {
      pb = buffer+5;
      while(*pb!=':') pb++;
      pb++;
      if((strncmp(pb, "GET / ", 6) == 0) || (strncmp(pb, "GET /?", 6) == 0))
       {
        clearSerialBuffer();
        
        if(ledState == LOW) 
          {
            ledState = HIGH;
            vklotkl = "VKL";
          }
        
        else 
          {
            ledState = LOW;
            vklotkl = "OTKL";
          } 
        
        digitalWrite(ledPin, ledState);
        otvet_klienty(ch_id);
       } 
    }
  }
  clearBuffer();
}
//////////////////////формирование ответа клиенту////////////////////
void otvet_klienty(int ch_id) 
{
  String Header;
 
  Header =  "HTTP/1.1 200 OK\r\n";
  Header += "Content-Type: text/html\r\n";
  Header += "Connection: close\r\n";  
  
  String Content;
  
  Content = "<body><form action='' method='GET'><input type='submit' value='VKL/OTKL'> " + vklotkl;
  Content += "</form></body></html>";
 
  Header += "Content-Length: ";
  Header += (int)(Content.length());
  Header += "\r\n\r\n";
  
  ESPport.print("AT+CIPSEND="); // ответ клиенту
  ESPport.print(ch_id);
  ESPport.print(",");
  ESPport.println(Header.length()+Content.length());
  delay(20);

  if(ESPport.find(">")) 
    {
      ESPport.print(Header);
      ESPport.print(Content);
      delay(200); 
    }
}
/////////////////////отправка АТ-команд/////////////////////
String GetResponse(String AT_Command, int wait)
{
  String tmpData;
  
  ESPport.println(AT_Command);
  delay(wait);
  while (ESPport.available() >0 )  
   {
    char c = ESPport.read();
    tmpData += c;
    
    if ( tmpData.indexOf(AT_Command) > -1 )         
      tmpData = "";
    else
      tmpData.trim();       
          
   }
  return tmpData;
}
//////////////////////очистка ESPport////////////////////
void clearSerialBuffer(void) 
{
       while ( ESPport.available() > 0 ) 
       {
         ESPport.read();
       }
}
////////////////////очистка буфера//////////////////////// 
void clearBuffer(void) {
       for (int i =0;i<BUFFER_SIZE;i++ ) 
       {
         buffer[i]=0;
       }
}
////////////////////подключение к wifi/////////////////////        
boolean connectWiFi(String NetworkSSID,String NetworkPASS) 
{
  String cmd = "AT+CWJAP=\"";
  cmd += NetworkSSID;
  cmd += "\",\"";
  cmd += NetworkPASS;
  cmd += "\"";
  
  ESPport.println(cmd); 
  delay(6500);
  
}


Подключите ардуину к ESP вот так:



Нажмите ресет на ардуине, откройте терминал (115200) и ступайте в браузер.

Понажимайте часто кнопку , зажмите и подержите, после этих «насильственных» действий модуль (скорее всего) будет по прежнему оставаться работоспособным.

В терминал будет сыпаться та инфа, которая «бегает» между ардуиной и ESP.


Если что-то не работает, «передёрните» питание на модуле.


В целях улучшения надёжности, можно активировать встроенный «сторожевой таймер», который будет перегружать модуль при зависаниях.
Однако нужно помнить, что после перезагрузки модуля прейдётся перегружать и ардуину, чтоб она дала команду запуска ТСР-сервера (AT+CIPSERVER=1,88).


Для активации таймера добавьте в void setup() вот эту строчку — GetResponse(«AT+CSYSWDTENABLE»,300);


...
  GetResponse("AT+RST",3400); // перезагрузка ESP
  GetResponse("AT+CWMODE=1",300); // режим клиента   
  GetResponse("AT+CSYSWDTENABLE",300); // сторож
  connectWiFi("myrouter","parolparol"); // подключаемся к домашнему роутеру (имя точки, пароль) 
...



В общем-то, если добавить в код ещё пару кнопок для управления пинами и вывод информации с каких-нибудь датчиков, то для «домашнего» использования, система вполне сойдёт…

Прошейте в ардуину новый скетч: (не забудте отключить RX,TX)


HardwareSerial & ESPport = Serial;

const int ledPin =  13; 
const int ledPin12 =  12; 
const int ledPin9 =  9;
int ledState = HIGH; 
int ledState12 = HIGH; 
int ledState9 = HIGH;           
#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];
String vklotkl;
String vklotkl12;
String vklotkl9;
int temp = 22; // переменная, которой будет присваиваться значения например с датчика температуры
 
void setup() 
{ 
  pinMode(ledPin, OUTPUT); 
  pinMode(ledPin12, OUTPUT); 
  pinMode(ledPin9, OUTPUT);   
  ESPport.begin(115200); // ESP8266  
  clearSerialBuffer();
  GetResponse("AT+RST",3400); // перезагрузка ESP
  GetResponse("AT+CWMODE=1",300); // режим клиента   
  GetResponse("AT+CSYSWDTENABLE",300); // сторож
  connectWiFi("myrouter","parolparol"); // подключаемся к домашнему роутеру (имя точки, пароль) 
  GetResponse("AT+CIPMODE=0",300); // сквозной режим передачи данных. 
  GetResponse("AT+CIPMUX=1",300); // multiple connection.
  GetResponse("AT+CIPSERVER=1,88", 300); // запускаем ТСР-сервер на 88-ом порту
  GetResponse("AT+CIPSTO=3", 300); // таймаут сервера 3 сек
  GetResponse("AT+CIFSR", 300); // узнаём адрес
  digitalWrite(ledPin,ledState);  
  digitalWrite(ledPin12,ledState12);
  digitalWrite(ledPin9,ledState9);
}
///////////////////основной цикл, принимает запрос от клиента/////////////////// 
void loop() 
{
 int ch_id, packet_len;
 char *pb;  
 ESPport.readBytesUntil('\n', buffer, BUFFER_SIZE);
  
 if(strncmp(buffer, "+IPD,", 5)==0) 
  {
   sscanf(buffer+5, "%d,%d", &ch_id, &packet_len);
   if (packet_len > 0) 
    {
      pb = buffer+5;
      while(*pb!=':') pb++;
      pb++;
      
      if(strncmp(pb, "GET / ", 6) == 0)
       {
        clearSerialBuffer();
        otvet_klienty(ch_id);
       }      
      
      //D13
      if(strncmp(pb, "GET /a", 6) == 0)
       {
        clearSerialBuffer();
        
        if(ledState == LOW) 
          {
            ledState = HIGH;
            vklotkl = "VKL";
          }
        
        else 
          {
            ledState = LOW;
            vklotkl = "OTKL";
          } 
        
        digitalWrite(ledPin, ledState);
        otvet_klienty(ch_id);
       } 
       
      //D12 
      if(strncmp(pb, "GET /b", 6) == 0)
       {
        clearSerialBuffer();
        
        if(ledState12 == LOW) 
          {
            ledState12 = HIGH;
            vklotkl12 = "VKL";
          }
        
        else 
          {
            ledState12 = LOW;
            vklotkl12 = "OTKL";
          } 
        
        digitalWrite(ledPin12, ledState12);
        otvet_klienty(ch_id);
       }   
  
      //D9 
      if(strncmp(pb, "GET /c", 6) == 0)
       {
        clearSerialBuffer();
        
        if(ledState9 == LOW) 
          {
            ledState9 = HIGH;
            vklotkl9 = "VKL";
          }
        
        else 
          {
            ledState9 = LOW;
            vklotkl9 = "OTKL";
          } 
        
        digitalWrite(ledPin9, ledState9);
        otvet_klienty(ch_id);
       }       
       
    }
  }
  clearBuffer();
}
//////////////////////формирование ответа клиенту////////////////////
void otvet_klienty(int ch_id) 
{
  String Header;

  Header =  "HTTP/1.1 200 OK\r\n";
  Header += "Content-Type: text/html\r\n";
  Header += "Connection: close\r\n";  
  
  String Content;
  
  Content = "<html><body>";
  Content += "<form action='a' method='GET'>D13 <input type='submit' value='VKL/OTKL'> " + vklotkl + "</form>";
  Content += "<form action='b' method='GET'>D12 <input type='submit' value='VKL/OTKL'> " + vklotkl12 + "</form>";
  Content += "<form action='c' method='GET'>D9   <input type='submit' value='VKL/OTKL'> " + vklotkl9 + "</form>";
  Content += "<br />Temp: " + String(temp) + " C";
  Content += "</body></html>";
  
  Header += "Content-Length: ";
  Header += (int)(Content.length());
  Header += "\r\n\r\n";
  
  ESPport.print("AT+CIPSEND="); // ответ клиенту
  ESPport.print(ch_id);
  ESPport.print(",");
  ESPport.println(Header.length()+Content.length());
  delay(20);

  if(ESPport.find(">")) 
    {
      ESPport.print(Header);
      ESPport.print(Content);
      delay(200); 
    }
}
/////////////////////отправка АТ-команд/////////////////////
String GetResponse(String AT_Command, int wait)
{
  String tmpData;
  
  ESPport.println(AT_Command);
  delay(wait);
  while (ESPport.available() >0 )  
   {
    char c = ESPport.read();
    tmpData += c;
    
    if ( tmpData.indexOf(AT_Command) > -1 )         
      tmpData = "";
    else
      tmpData.trim();       
          
   }
  return tmpData;
}
//////////////////////очистка ESPport////////////////////
void clearSerialBuffer(void) 
{
       while ( ESPport.available() > 0 ) 
       {
         ESPport.read();
       }
}
////////////////////очистка буфера//////////////////////// 
void clearBuffer(void) {
       for (int i =0;i<BUFFER_SIZE;i++ ) 
       {
         buffer[i]=0;
       }
}
////////////////////подключение к wifi/////////////////////        
boolean connectWiFi(String NetworkSSID,String NetworkPASS) 
{
  String cmd = "AT+CWJAP=\"";
  cmd += NetworkSSID;
  cmd += "\",\"";
  cmd += NetworkPASS;
  cmd += "\"";
  
  ESPport.println(cmd); 
  delay(6500);
}



Подключите обратно RX,TX, перегрузите модуль, зайдите в браузер и увидите...




На этом пока всё, добавить ещё кнопок или датчиков, я думаю не составит труда.



Как говорилось выше, заводская прошивка пока ещё «сырая», поэтому не стоит доверять ей ответственные задачи.


Обсудить на форуме...


  • 0
  • 50565

Комментарии (31)

0
великолепно!!! спасибо!
0
Пожалуйста.
0
Привет. При просмотре выполнения программы в ардуино «Монитор порта» вместо нормальных слов вижу всякие кракозябы. Менял скорость ничего не изменилось. Подключение arduino due + esp8266. Win 7 64.
0
Может Вы где-то русские символы использовали?
0
Разобрался, скорее всего не прошла команда AT+CIOBAUD=9600. Вторичное ее использование решило проблему.
Еще момент, если у меня роутер требует для подключения ip адрес и DNS, как их указать модулю перед подключением?
0
Я думаю проще всё-таки на роутере настроить dhcp.
0
вот мой скетч. не выводит в serial данные. выводит только строку с AT+CWJAP=«Evgen»,«985223ea». сам я пользуюсь socket test. знаю ip через cool term. не могу подключиться к порту 666. мне кажется, что at команды не выполняются.
В чем дело?

#include <SoftwareSerial.h>
SoftwareSerial ESPport(10, 11);

void setup() {
Serial.begin(9600);
ESPport.begin(9600);
Serial.println(GetResponse(«AT+RST»,3400));
Serial.println(GetResponse(«AT+CWMODE=1»,300));
connectWiFi(«Evgen»,«985223ea»);
Serial.println(GetResponse(«AT+CIPMODE=0»,300));
Serial.println(GetResponse(«AT+CIPMUX=1»,300));
Serial.println(GetResponse(«AT+CIPSERVER=1,666»,300));
Serial.println(GetResponse(«AT+CIFSR», 300));
}

boolean connectWiFi(String NetworkSSID,String NetworkPASS)
{
String cmd = «AT+CWJAP=\»";
cmd += NetworkSSID;
cmd += "\",\"";
cmd += NetworkPASS;
cmd += "\"";
Serial.println(cmd);
Serial.println(GetResponse(cmd,6500));
}

String GetResponse(String AT_Command, int wait)
{
String tmpData;
ESPport.println(AT_Command);
delay(wait);
while (ESPport.available() >0 )
{
char c = ESPport.read();
Serial.println(1);
tmpData += c;
if ( tmpData.indexOf(AT_Command) > -1 )
tmpData = "";
else
tmpData.trim();
}
return tmpData;
}

void loop() {
Serial.println(GetResponse(«AT+CIpsend=0,10»,2000));
Serial.println(GetResponse(«Privet»,2000));

}
0
что at команды не выполняются

Попробуйте давать команды через serial monitor, что будет?
комментарий был удален
комментарий был удален
0
Я так понял, что serial monitor — это монитор порта. Я только через него и вводил. То есть я набирал at команду и нажимал enter или отправить. К сожалению в этом окне не отобаражалось даже то, что отправлял я, не говоря уже об ответе. Делал это так как описано на этом сайте tim4dev.com/arduino-esp8266-true-start/
0
Попробуйте сделать как написано здесь.
0
дак я и использовал ваши функции. не работает ничего.
0
Значит что-то Вы делаете не так. Начните вот с этой статьи.
0
Второй день не могу подружить с ардуиной UNO. С FT232Rl «общается». Пытаюсь разобраться с 1-м примером. Что-то похожее из вашего скрина(reset 3,5 sek… ) выходит если HardwareSerial & Serial1 = Serial1; добавить, но ответа с esp не выдает, без Ок. Другие примеры с uno тоже не идут.(скорость выставлена 9600. Единственный пример в котором приходит ответ это последний пример отсюда, но и то мне в ответ вместо Ок приходит error. Делитель напряжения ставил на ТХ. Из-за того что с RX вместо 5в ответа приходит низкое 3.3 из esp быть не может? прошивки заводская
AT+GMR AT version:0.40.0.0(Aug 8 2015 14:45:58)
SDK version:1.3.0
Ai-Thinker Technology Co.,Ltd.
Build:1.3.0.2 Sep 11 2015 11:48:04
0
Забыл написать что с того примера где приходит ответ error я подключал не на 4,5 разъем как по скетчу, а tx-tx, rx-rx, и это единственный раз когда моргает светодиод rx на uno.
0
Добрый вечер а ты не пробовали прикрутить SD карту? чтобы код html страницы лежал в корне карты память?
я попробовал сделать по этому примеру ESPToyИтог: модуль к роутеру цепляеться и пингуеться но упорно не отображает страницу. хотя если просмотреть самой библиотекой sdfat то файл виден и читается
0
Здравствуйте, нет не пробовал, нестабильная работа еспэшки отбила у меня всякое желание с ней возиться.
0
А не проще было б подключаться к ардуинке по i2с с ESP и просто запрашивать данные?
А все остальное на ESP повесить? ESP гораздо богаче чем 328-я, и памяти и ром.
И учитывая ;) что юзается 3 пина на выход + 1 датчик температуры, можно одной ESP-01 обойтись.
0
При компиляции вашего примера возникают следующие ошибки. В чем причина?
Arduino: 1.6.11 (Windows 10), Плата:"Arduino/Genuino Uno"

A:\Мои документы\Arduino\Proverka\Proverka.ino: In function 'void setup()':

Proverka:20: error: 'clearSerialBuffer' was not declared in this scope

Proverka:22: error: 'GetResponse' was not declared in this scope

Proverka:24: error: 'connectWiFi' was not declared in this scope

A:\Мои документы\Arduino\Proverka\Proverka.ino: In function 'void loop()':

Proverka:54: error: 'clearSerialBuffer' was not declared in this scope

Proverka:69: error: 'otvet_klienty' was not declared in this scope

Proverka:73: error: 'clearBuffer' was not declared in this scope

exit status 1
'clearSerialBuffer' was not declared in this scope

Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"
0
А Вы весь скетч скопировали?
0
Да
0
У меня складывается впечатление, что Вы не весь скетч скопировали, нету некоторых функций.
0
Нет, код скопировал полностью. Функции есть, просто компилятор почему-то отказывается их понимать. Может быть с библиотекой какие-то проблемы?
0
Библиотека ни при чём, он ругается на не задекларированные функции. Странно как-то, попробуйте скачать последнюю версию IDE Arduino.
0
Установил самую новую Arduino IDE, не помогло. Вот полное сообщение об ошибке:
Arduino: 1.6.12 (Windows 10), Плата:"Arduino/Genuino Uno"

C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\Anton\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\Anton\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries A:\Мои документы\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10612 -build-path C:\Users\Anton\AppData\Local\Temp\arduino_build_440244 -warnings=none -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino6 -verbose A:\Мои документы\Arduino\Proverka\Proverka.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\Anton\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\Anton\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries A:\Мои документы\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10612 -build-path C:\Users\Anton\AppData\Local\Temp\arduino_build_440244 -warnings=none -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino6 -verbose A:\Мои документы\Arduino\Proverka\Proverka.ino
Using board 'uno' from platform in folder: C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14
Using core 'arduino' from platform in folder: C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14
Detecting libraries used...
"C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10612 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\cores\arduino" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\variants\standard" "C:\Users\Anton\AppData\Local\Temp\arduino_build_440244\sketch\Proverka.ino.cpp" -o "nul"
"C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10612 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\cores\arduino" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\variants\standard" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\libraries\SoftwareSerial\src" "C:\Users\Anton\AppData\Local\Temp\arduino_build_440244\sketch\Proverka.ino.cpp" -o "nul"
"C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10612 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\cores\arduino" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\variants\standard" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\libraries\SoftwareSerial\src" "C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\libraries\SoftwareSerial\src\SoftwareSerial.cpp" -o "nul"
Generating function prototypes...
"C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10612 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\cores\arduino" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\variants\standard" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\libraries\SoftwareSerial\src" "C:\Users\Anton\AppData\Local\Temp\arduino_build_440244\sketch\Proverka.ino.cpp" -o "C:\Users\Anton\AppData\Local\Temp\arduino_build_440244\preproc\ctags_target_for_gcc_minus_e.cpp"
"C:\Program Files (x86)\Arduino\tools-builder\ctags\5.8-arduino10/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\Users\Anton\AppData\Local\Temp\arduino_build_440244\preproc\ctags_target_for_gcc_minus_e.cpp"
Компиляция скетча...
"C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10612 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\cores\arduino" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\variants\standard" "-IC:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\libraries\SoftwareSerial\src" "C:\Users\Anton\AppData\Local\Temp\arduino_build_440244\sketch\Proverka.ino.cpp" -o "C:\Users\Anton\AppData\Local\Temp\arduino_build_440244\sketch\Proverka.ino.cpp.o"
A:\Мои документы\Arduino\Proverka\Proverka.ino: In function 'void setup()':

Proverka:20: error: 'clearSerialBuffer' was not declared in this scope

Proverka:22: error: 'GetResponse' was not declared in this scope

Proverka:24: error: 'connectWiFi' was not declared in this scope

A:\Мои документы\Arduino\Proverka\Proverka.ino: In function 'void loop()':

Proverka:54: error: 'clearSerialBuffer' was not declared in this scope

Proverka:69: error: 'otvet_klienty' was not declared in this scope

Proverka:73: error: 'clearBuffer' was not declared in this scope

Используем библиотеку SoftwareSerial версии 1.0 из папки: C:\Users\Anton\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.14\libraries\SoftwareSerial 
exit status 1
'clearSerialBuffer' was not declared in this scope
0
Автор, может я что то пропустил, но почему то просто при обновлении страницы D12 меняет показания вкл откл без нажатия кнопки, где собака порылась?
0
сори, не заметил, при обновлении меняет значение последняя нажатая кнопка.
0
Спасибо за пример. Все получилось… Но чисто на практике установил, что после команды AT+RST скорость ESP возвращается к 115200 (заводской установке и поэтому примеры с использованием программного serial не работают. На монитор ардуино выводятся только реплики самой ардуино. В общем, делайте сразу предпоследний пример с одним ледом и все сразу получится и на заводской прошивке. Конечно, может если сразу после сброса модуля настроить его на 9600, то и первые скетчи заработают, но это для тех кто любит учиться…
0
Спасибо за пример. Все получилось…
Пожалуйста.
0
Всем привет!
У меня с кодом вроде все получилось, но не соединяется.
В сериал написан последующие

AT+CWJAP=«qwe»,«098767890»
AT+CIPMODE=0
AT+CIPMUX=1
AT+CIPSERVER=1,88
AT+CIPSTO=3
AT+CIFSR

в чем проблема?
заранее спасибо
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.