подскажите по Serial и esp8266

OlegM
Offline
Зарегистрирован: 14.06.2016

подскажите, делаю отправку и прием на сервер, решил протестировать код, и непонятно как сериал работает или софтсериал, и .flush

#include <SoftwareSerial.h>

SoftwareSerial esp(10, 11); // RX, TX

void setup() {
  Serial.begin(9600); //запускаем встроенный сЕриал
  while (!Serial) {;} 
  
  esp.begin(9600); //запускаем софтварный сЕриал
  
///////////////////////
char ssid[] = "Wi-Fika";
char pass[] = "123Lion45";
///////////////////////
Serial.println("1");
/// /// ///
  //проверяем готов ли к работе модуль esp8266
  esp.println("AT+RST");
  delay(250);
  while(!esp.find("ready")){
    delay(1000);
    }
    esp.flush();
    delay(250);
/// /// ///
Serial.println("2");
  //посылаем для теста команду АТ и ждем ответа ОК
  esp.println("AT");
  //delay(500);
  while((esp.available() > 0)) {
    Serial.write(esp.read());}
  while(!esp.find("OK")) delay(500); 
  esp.flush();
/// /// ///
Serial.println("3");
  //переводим модуль в режим "клиент-station", если он не в нем
  esp.println("AT+CWMODE_DEF?");
  if(!esp.find("1"))
  {
    esp.println("AT+CWMODE_DEF=1");
    delay(10);
    esp.println("AT+RST");
    delay(500);
    while(!esp.find("rsady")) delay(1000);
  }
  esp.flush();
/// /// ///
Serial.println("4");
/*
  //ищем нашу сеть ssid и если находим, то подключаемся
  while(true)
  {
    //сканируем сеть
    esp.println("AT+CWLAP"); 
    delay(1000);
    while((esp.available() > 0)) Serial.write(esp.read());
    
    while(1) {
      
      if(esp.find("OK")) break;
      Serial.println("555");
      delay(1000);
    }
     
    //если нашли нашу точку
    if(esp.find(ssid))
    {
      esp.flush();
     
      //подключаемся к нашей точке
      esp.println(printf("AT+CWJAP_DEF=\"%s\",\"%s\"", ssid, pass));
      //ждем до конца подключения
      while(!esp.find("GOT IP") && !esp.find("OK")) delay(1000);
      esp.flush();
      break;
    }
  }
  */
 Serial.println("5");
/// /// ///

}

void loop() {

  while (esp.available() > 0) { // смотрим что ответил есп после отправки
    Serial.write(esp.read()); 
  }

}

Serial.println(цифра) искал где код не работает, и пытался читать ответ между кусками кода так

while (esp.available() > 0) { // смотрим что ответил есп после отправки
87     Serial.write(esp.read());
88   }

добавлял delay(), пытался чистить ответ esp.flush(), но как то непонятно для меня ведет себя ответ, esp.find() искал ответы от модуля есп8266, до 35 строки ищет правильно, а дальше я искаверкал ответ в 44 строке, но посчитало, что ответ верный, подскажите где мои ошибки...

OlegM
Offline
Зарегистрирован: 14.06.2016

ну наверное плохо объяснил, сам незнал как спросить

1) обьясните как работает Serial.flush()

2) как мне узнать ответ, например, этой части кода

esp.println("AT+RST");
19   delay(250);
20   while(!esp.find("ready")){
21     delay(1000);
22     }
23

    esp.flush();

 

делал так:

while(esp.availlable > 0) Serial.write(esp.read);

Araris
Offline
Зарегистрирован: 09.11.2012

Если CWMODE уже равен единице, то строки 40-44 просто не будут выполняться, может в этом причина ?

OlegM
Offline
Зарегистрирован: 14.06.2016

да, вот не должны, но они почему то исполняются. Почему то тут esp.find() не ищет правильно и в следующем коде, что закоментирован

Araris
Offline
Зарегистрирован: 09.11.2012

Как Вы узнаёте, что они исполняются ?

OlegM
Offline
Зарегистрирован: 14.06.2016

я поотделял Serial.println(цифра) куски кода и смотрю где останавливается, там с "1" проходит, я посмотрел, что модуль отвечает CWMODE:1 и так пытался find найти, но следующий закоментированный ищет криво... я счас еще раз проверю, а то вначале написал код, думал все верно, а тут началось, с ардуино плохо знаком

Araris
Offline
Зарегистрирован: 09.11.2012

Я не пользуюсь esp.find(), поэтому советую попытаться увидеть ответы ESP.

После 37-й строки временно вставьте

delay(250); while(esp.availlable > 0) Serial.write(esp.read);

Если в ответе действительно нет единички, перенесите

delay(250); while(esp.availlable > 0) Serial.write(esp.read);

за 43-ю строку, посмотрите ответ там.

OlegM
Offline
Зарегистрирован: 14.06.2016

да я вот аытаюсь увидеть ответы, сегодня с утра сижу разбираюсь, тип так и смотрю ответы delay(250); while(esp.availlable > 0) Serial.write(esp.read); только делай ставлю перед некоторыми командами и 650мс, а то если меньше выкидает не полностью ответ, если в find вписываешь строку то выводит текст после найденной подстроки, так на заметку

#include <SoftwareSerial.h>

SoftwareSerial esp(10, 11); // RX, TX

void setup() {
  Serial.begin(9600); //запускаем встроенный сЕриал
  while (!Serial) {;} 
  
  esp.begin(9600); //запускаем софтварный сЕриал
  
///////////////////////
char ssid[] = "Wi-Fika";
char pass[] = "123Lion45";
///////////////////////
Serial.println("1");
/// /// ///
  //проверяем готов ли к работе модуль esp8266
  esp.println("AT+RST");
  delay(250);
  while(!esp.find("ready")){
    delay(1000);
    }
    esp.flush();
    delay(250);
/// /// ///
Serial.println("2");
  //посылаем для теста команду АТ и ждем ответа ОК
  esp.println("AT");
  while(!esp.find("OK")) {
    delay(500);
    } 
  esp.flush();
/// /// ///

Serial.println("3");
  //переводим модуль в режим "клиент-station", если он не в нем
  esp.println("AT+CWMODE_DEF?");
  esp.flush();
  if(!esp.find("1"))
  {
    esp.println("AT+CWMODE_DEF=1");
    delay(10);
    esp.flush();
    esp.println("AT+RST");
    delay(650);
    Serial.print("lllttt");
    while(!esp.find("ready")) delay(1000);
  }
  esp.flush();
/// /// ///
Serial.println("4");

  //ищем нашу сеть ssid и если находим, то подключаемся
  while(true)
  {     
    do{ //сканируем сеть
      esp.println("AT+CWLAP=\"Wi-Fika\""); 
      Serial.println("---");
      delay(650);
      } while(!esp.find("\"Wi-Fika\",-"));
     
      //подключаемся к нашей точке
      while(!esp.find("GOT IP"))
      {    
        delay(650);
        Serial.print("111");
      esp.println("AT+CWJAP_DEF=\"Wi-Fika\",\"192.168.1.109\"");
      delay(1000);
      while(esp.available() > 0) Serial.write(esp.read()); 
      }
      esp.flush();
      break;
    }
 
  //end setup()
  
  
 Serial.println("5");
/// /// ///

}

void loop() {
//Serial.print(1);
  if (esp.available() > 0) Serial.write(esp.read()); 

  if (Serial.available() > 0) esp.write(Serial.read()); 
 

}

дошел до 62 строки, этот код чет выдает busy p

OlegM
Offline
Зарегистрирован: 14.06.2016

блин, в 67 строке вместо пароля вписал ип адрес, вроде эта часть кода работает, но вот непойму почему ответ прочитать не всегда могу, поэтому тестить проблемно

delay(250); while(esp.availlable > 0) Serial.write(esp.read); 

на некотором участке читает, на некотором не полный ответ? Т.е не выводит в сериал полный ответ, как при ручном вводе команд по сериал, при ручном все приходит, или из-за маленькой скорости 9600бод.

OlegM
Offline
Зарегистрирован: 14.06.2016
while(1) {
      while(esp.available() > 0) Serial.write(esp.read()); 
      }
      delay(250);
      }
сделал так, так выводит весь ответ, подскажите, какой  там алгоритм ? 
Araris
Offline
Зарегистрирован: 09.11.2012

ESP не столь быстр на ответы, поэтому "алгоритм" - давать достаточно времени между командами и на ожидание ответа. Тогда, как Вы уже и сами увидели, не будет ни "busy p", не неполных ответов. Сколько минимально давать времени - это зависит от конкретной АТ-команды, тут метод подбора Вам в помощь.

Для примера приведу свою функцию (ре)инициализации для ESP8266 в адаптированном виде. Оба последовательных порта в данном случае "железные", оба на 9600, на мелких Ардуино работает через SoftwareSerial.

boolean ESPRestart(
{
int ESPNumberConnectRetries = 20;
Serial.println("Resetting ESP..");
Serial2.println("AT+RST");
ESPFlushSerial(300);
Serial2.println("AT+CSYSWDTENABLE");
ESPFlushSerial(100);
String ESPcmd;
ESPcmd = "AT+CWJAP=\"";
ESPcmd += "************************"; // тут имя сети
ESPcmd += "\",\"";
ESPcmd += "************************"; // тут пароль
ESPcmd += "\"";
Serial.println("Connecting to WiFi..");
for ( int i = 1; i <= ESPNumberConnectRetries; i++ )
 {
 Serial.print("Try "); Serial.println(i);
 Serial2.println(ESPcmd);
 delay(200);
 if ( Serial2.find("OK") ) // Опаньки ! Оказывается я тоже пользуюсь find(), совсем запамятовал.
  {
  Serial.println("Connected to WiFi.");
  ESPFlushSerial(200);
  Serial2.println("AT+CWMODE=1");
  ESPFlushSerial(200);
  Serial2.println("AT+CIPMUX=1");
  ESPFlushSerial(200);
  Serial2.println("AT+CIPSERVER=1,48569"); // я пользуюсь UDP, это Вам не понадобится
  ESPFlushSerial(200);
  Serial2.println("AT+CIPSTO=120");
  ESPFlushSerial(200);
  Serial2.println("AT+CIPSTART=4,\"UDP\",\"192.168.0.255\",48569,1112,0"); // опять же UDP...
  ESPFlushSerial(200);
  return true;
  }
 } 
Serial.println("Can't connect.");
return false;
}

void ESPFlushSerial(int delaymsec)
{
// ждём и вычищаем буфер
delay(delaymsec);
while ( Serial2.available() ) { Serial2.read(); }
}
OlegM
Offline
Зарегистрирован: 14.06.2016

 

busy p было из-за того, что вместо пароля ип адрес вписал по ошибке.

да там можно все проще, счас все данные для подключения можно хранить в ЕЕПРОМ есп, т.е команды есть в прошивке и только проверять подключен ли к сети модуль, так надо и сделать, а то памяти уже у меня ушло под 20%, а я еще ничего не передавал )), тяжело тестировать этот ардуино, нельзя как то тестить без заливки кода в сам МК ?  Сча буду извращатся, потом отпишусь, а то есть еще вопросы, написал парсер для приема ответов от сервера, но писал в ВижуалСтудио, а с прикрутить к ардуино еще то ))

OlegM
Offline
Зарегистрирован: 14.06.2016

и подскажите, что делает метод .flush() ? а то не совсем понятно его предназначение.

Araris
Offline
Зарегистрирован: 09.11.2012

OlegM пишет:

и подскажите, что делает метод .flush() ? а то не совсем понятно его предназначение.

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

OlegM
Offline
Зарегистрирован: 14.06.2016

так и не понял работу flush, как он работает правильно, ждет до окончания передачи, чет не заметил.

вот код, по сути этого всего и ненадо, если все настроить вручную на есп8266, но вот есть вопрос, как вывести данные от запроса подключения к сети из 67 строки

если написать так 

 delay(250);
 while(esp.available() > 0) Serial.write(esp.read()); 
 
то выводятся, наверное до 64 байта или тип того,
 WIFI DISCONECT
 WIFI CONN ну тип так
 
 
 а если так, что ниже,то выводится все
 
WIFI DISCONECT
WIFI CONNECT
WIFI GOT IP
 
OK
     
while(1){
     delay(50);
     while(esp.available() > 0) Serial.write(esp.read());
    }
то выводятся все данные с ответа.
 
#include <SoftwareSerial.h>

SoftwareSerial esp(10, 11); // RX, TX

void setup() {
  Serial.begin(9600); //запускаем встроенный сЕриал
  while (!Serial) {;} 
  
  esp.begin(9600); //запускаем софтварный сЕриал
  
///////////////////////
char ssid[] = "Wi-Fika";
char pass[] = "123Lion45";
///////////////////////

int i = 0;

Serial.println("1");
/// /// ///
  //после перезагрузки ардуино перезагружаем модуль esp8266
  //и ждем готовности
    esp.println("AT+RST");
    delay(1000);
    while(!esp.find("ready")) delay(650);
  
/// /// ///
Serial.println("2");
  //посылаем для теста команду АТ и ждем ответа ОК
  esp.println("AT");
  while(!esp.find("OK")) delay(650); 

/// /// ///
Serial.println("3");
delay(250);//очищаем буфер
while(esp.available()) esp.read();

  //переводим модуль в режим "клиент-station", если он не в нем
  esp.println("AT+CWMODE?");
  
  if(!esp.find(":1"))
  {
    esp.println("AT+CWMODE_DEF=1");
    delay(650);
    esp.println("AT+RST");
    delay(1000);
    while(!esp.find("ready")) delay(650);
  }
  
/// /// ///
Serial.println("4");

delay(250);//чисттим буфер
  while(esp.available()) esp.read();

  //ищем нашу сеть ssid и если находим, то подключаемся
  while(true)
  {     
    do{ //сканируем сеть
      esp.println("AT+CWLAP=\"Wi-Fika\"");
      delay(2000);
      Serial.println("CWLAP");
      } while(!esp.find("\"Wi-Fika\",-"));
      
delay(250);//чистим буфер
while(esp.available() > 0) esp.read();

     esp.println("AT+CWJAP_DEF=\"Wi-Fika\",\"123Lion45\"");
 
      //подключаемся к нашей точке
      while(!esp.find("WIFI GOT IP"))
      { 
        Serial.println("111");     
        delay(100);
      }   
      break;
    }
    while(1){
      delay(50);
 while(esp.available() > 0) Serial.write(esp.read());
 
      }
  //end setup()
  
  
 Serial.println("5");
/// /// ///

}

void loop() {
  if (esp.available() > 0) Serial.write(esp.read());    
  if (Serial.available() > 0) esp.write(Serial.read()); 
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

OlegM пишет:

и подскажите, что делает метод .flush() ? а то не совсем понятно его предназначение.

Олег, Вы уже два дня про него спрашиваете. Неужели за это время не было минутки посмотреть на него? Вот он, блин - всего несколько строк, если комментарии не считать

void HardwareSerial::flush()
{
  // If we have never written a byte, no need to flush. This special
  // case is needed since there is no way to force the TXC (transmit
  // complete) bit to 1 during initialization
  if (!_written)
    return;

  while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) {
    if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0))
	// Interrupts are globally disabled, but the DR empty
	// interrupt should be enabled, so poll the DR empty flag to
	// prevent deadlock
	if (bit_is_set(*_ucsra, UDRE0))
	  _tx_udr_empty_irq();
  }
  // If we get here, nothing is queued anymore (DRIE is disabled) and
  // the hardware finished tranmission (TXC is set).
}

а вот, вызываемая из него функция _tx_udr_empty_irq.

void HardwareSerial::_tx_udr_empty_irq(void)
{
  // If interrupts are enabled, there must be more data in the output
  // buffer. Send the next byte
  unsigned char c = _tx_buffer[_tx_buffer_tail];
  _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE;

  *_udr = c;

  // clear the TXC bit -- "can be cleared by writing a one to its bit
  // location". This makes sure flush() won't return until the bytes
  // actually got written
  sbi(*_ucsra, TXC0);

  if (_tx_buffer_head == _tx_buffer_tail) {
    // Buffer empty, so disable interrupts
    cbi(*_ucsrb, UDRIE0);
  }
}

Всё это есть на Вашем компьютере. Даже в гугл лезть не надо. Что мешало посмотреть самому?

OlegM
Offline
Зарегистрирован: 14.06.2016

ступил жестко ))), забыл что код открытый ))), это пипец ))), пасиб

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, не за что, бывает.