Ir ao conteúdo
  • Cadastre-se

ESP8266 - A Pequena Maravilha para Comunicação WIFI


aphawk

Posts recomendados

@ViniciusKruz ,

 

Sim, já deixei dois projetinhos diferentes rodando durante dois dias, e não tive problemas.

 

Tive um problema maluco pois sem querer gravei errado alguma coisa, ou o nome da minha rede Wifi, ou a senha, e a partir daí não consegui mais acessar de jeito nenhum o Nodemcu.

 

Isso foi o começo de uma novela que começou ontem à noite, foi até as 3 da manhã, sem ter conseguido formatar totalmente o Nodemcu... Aí percebí que tem um monte de posts sobre a dificuldade de se fazer uma formatação dos 4Mb de flash do ESP-12, que é a base do Nodemcu...

 

Tentei uns 5 métodos diferentes, e toda vez que regravava o ESP8266Basic, ele aparecia com alguma coisa esquisita, pois insistia em manter o IP de minha rede, em vez do IP padrão.... O que significa que ainda não consegui formatar totalmente o Nodemcu.

 

Curiosamente, consigo instalar sem problemas o firmware nativo do Lua do Nodemcu, e consigo de dentro dele apagar toda a área de armazenamento,  mas ainda assim tem alguma coisa que não foi apagada.

 

Agora vou continuar essa maratona, que já passou de 5 horas de buscas na Internet, e mais de uma dezena de formatações e regravações.....

 

Paulo

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

@ViniciusKruz ,

 

Sem comentários .... das 8:30 da noite até quase a meia noite .... descobri que a memória Flash do meu Nodemcu está com defeito em alguns endereços !!! Eu gravei o Ip nela 192.168.0.99, e com um utilitário localizei a placa  no 192.168.0.19 .... Repeti a sequencia apagar / regravar / reconfigurar umas 3 vezes, e sempre ficava no final 192.168.0.19 .

 

Aí , peguei um outro Nodemcu que eu nunca havia usado, fiz a mesma sequência, e foi direitinho pro final .99 como era previsto, e voltou a funcionar tudo direitinho, todas as telas, os programas, tudo uma maravilha .....

 

Maldito ESP-12E bichado .....

 

Paulo

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Estou tendo problemas é com o comando Esp.restart(), pelo que lí, pra esse comando funcionar, o GPIO0 precisa estar em nível alto e o GPIO15 em nível baixo, meu sistema já está assim e não dá o restart, não vou ficar quebrando a cabeça com isso não, se não der certo, vou designar um pino pra fazer o restart via hardware. O estranho é que antes quando o código estava pequeno esse comando funcionava, agora o código está grande, parou! Afff ... Depois vou testar com um código bem pequeno pra ver se volta a funcionar, se não funcionar pode ser algum defeito no ESP.

Link para o comentário
Compartilhar em outros sites

O Foxit PhantomPDF voltou a funcionar, e não tenho ideia do porque. Vou deixar quieto e aproveitar.

 

Baixei o Eclipse para Windows, mas por alguma razão toda vez que tento expandir o arquivo tar.gz recebo uma mensagem de arquivo corrompido do Sevenzip (e eu baixei o arquivo várias vezes), já estou desconfiando que o arquivo compactado não está corrompido e o problema é com o Sevenzip. Vou com calma e em algum momento vou acabar conseguindo.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Bom, estou com meu projetinho começando a ficar como deve, embora o ESP não tenha sido desenvolvido para web server(segundo os desenvolvedores do NodeMcu), eu acho que uma interface simples não vai atrapalhar em nada no sistema, até porque, eles mesmos sugeriram que o ESP fosse usado para, entre outras coisas, câmeras de monitoramento de bebês, ora, se o ESP tem capacidade para transmissão de imagem em "tempo real", porque que ele não poderia prover uma interface visual para seus usuários? Pelo pouco que conheço destes módulos, já estou mais que convencido de que estão subestimando estas gracinhas. Com este pensamento, estou certo que qualquer coisa que seja feita com o ESP, precisa de uma base padrão (Web Server) com algumas características:

 

Login de acesso

Meios para "resetar" as configurações em um padrão pre-definido

Meios para se efetuar as configurações básicas sem a necessidade de programas externos

Meios para que ele seja autônomo e de uma forma ou de outra, deve dar acesso ao Web Server

Meios de segurança para que o ESP não saia simplesmente respondendo ou acionando IOs sem uma autenticação

 

Eu fiz esta base, está muito simplesinha, mas já é o suficiente para começar, futuramente vou impementar umas telinhas mais "bonitinhas" com recursos como CSS, JS... Nesta minha base, conforme podem ver nas imagens, tem todas estas características citadas acima. O login não é criptografado (será implementado no futuro), porém o sistema é bem seguro mesmo sem a criptografia, sendo que o mesmo login usado para entrar no sistema, também é exigido nos comandos para acionar IOs ou obter informações. Também implementei uma opção de boot a mais, ou seja, o ESP tenta primeiro se conectar em uma rede cadastrada, caso não consiga, ele inicializa em modo AP e a pessoa pode se conectar à rede Wifi dele e ter acesso ao Web Server para alterar as configurações. Vou postar também o Sketch usado, está meio bagunçado, mas dá pra analisarem as funções. Até que pra quem nunca tinha programado na linguagem do Arduíno, eu acho que está de bom tamanho.

 



/*
 * 
 * Posições da memória eeprom:
 * Usuario e senha Wifi: 0 a 96
 * Usuário do login web: 100 a 119
 * Senha do login web: 120 a 189
 * IP: 200 a 203
 * Gateway: 204 a 207
 * Sub-rede: 208 a 211
 * 
 */


#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <PCF8583.h>
#include <IPAddress.h>
#include <Esp.h>

extern "C"{
#include "user_interface.h"
}

char dia[]="01";
char _mes[]="01";
char ano[]="2010";
char hora[]="00";
char minuto[]="00";
char segundo[]="00";

int correct_address = 0;
PCF8583 p (0xA0);
#define MEM_ALOC_SIZE 512 //tamanho da memória eeprom

char ssid[] = "Atual";
char password[] = "acesso301";

String user;//usuario da web
String pwd;//senha da web
boolean restart=false;

ESP8266WebServer server(80);

os_timer_t mTimer;
bool  _timeout = false;

int Rele1 = 14;    
int Rele2 = 16;   

// config static IP
IPAddress ip(192, 168, 0, 35); 
IPAddress gateway(192, 168, 0, 1); 
IPAddress subnet(255, 255, 255, 0); 

unsigned int contaTimer=0;
//rotina de interrupção
void tCallback(void *tCall){
    _timeout = true;
    contaTimer++;
}

void usrInit(void){
    os_timer_setfn(&mTimer, tCallback, NULL);
    os_timer_arm(&mTimer, 1000, true);
}

char *convStrToCharArr(String str){
  int str_len = str.length() + 1; 
  char char_array[str_len];
  str.toCharArray(char_array, str_len);    
  return char_array;  
}

void loadLoginWeb(){
  int i=0;
  for(i=100;i<120;i++){ //usuario: da posição 100 até a 105
    if(char(EEPROM.read(i))!= '\0')
      user += char(EEPROM.read(i));  
  }
  for(i=120;i<190;i++){//senha: da posição 106 até a 111
    if(char(EEPROM.read(i))!= '\0'){
      pwd += char(EEPROM.read(i));  
    }
  }
}


void loadDefault(){

  //Grava usuario e senha
  user="admin";
  pwd="admin";
  for (int i = 100; i < 120; ++i) { EEPROM.write(i, 0); }//apaga o usuario atual da eeprom
  for (int i = 0; i < user.length(); ++i){//grava o novo nome de usuario na eeprom
    EEPROM.write(i+100, user[i]);
    Serial.println(user[i]);
  }
  EEPROM.commit();
  for (int i = 120; i < 190; ++i) { EEPROM.write(i, 0); }//apaga a senha atual
  for (int i = 0; i < pwd.length(); ++i){//grava a nova senha de usuario na eeprom
    EEPROM.write(i+120, pwd[i]);
    Serial.println(pwd[i]);
  }
  EEPROM.commit();

  //grava rede padrão
  gravaIpLocal("192.168.0.30");
  gravaSubrede("255.255.255.0");
  gravaGateway("192.168.0.1");

  //grava o nome padrão da rede wifi a ser conectada
  gravaSsid("RedeWifi","pass" );
  
}



String DisplayAddress(IPAddress address)//conversão de endereço ip para string
{
 return String(address[0]) + "." + 
        String(address[1]) + "." + 
        String(address[2]) + "." + 
        String(address[3]);
}
//Check if header is present and correct
bool is_authentified(){
  Serial.println("Enter is_authentified");
  if (server.hasHeader("Cookie")){   
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
    if (cookie.indexOf("ESPSESSIONID=1") != -1) {
      Serial.println("Authentification Successful");
      return true;
    }
  }
  Serial.println("Authentification Failed");
  return false;  
}

//login page, also called for disconnect
void handleLogin(){
  String msg;
  if (server.hasHeader("Cookie")){   
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
  }
  if (server.hasArg("DISCONNECT")){
    Serial.println("Disconnection");
    String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){
    String _user = server.arg("USERNAME");
    String _pwd = server.arg("PASSWORD");
    
    Serial.println("Usuario gravado:");
    Serial.println(user);
    Serial.println("Senha gravada:");
    Serial.println(pwd);
    
    if (_user.equals(user)  &&  _pwd.equals(pwd)){
      String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=1\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n";
      server.sendContent(header);
      Serial.println("Logado com sucesso");
      return;
    }
  msg = "Login incorreto.";
  Serial.println("Log in Failed");
  }

  String content = "<html><body> <title>ESP-Control</title>";
  content+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'><br>";
  content+="<div class='reformed-form'>";
  content+="<form method='post' name='login' id='login' action='/login'><H1>ACESSO AO SISTEMA</H1>";
  content+="<dl><dt><label for='usuario'>Usuário</label></dt>";
  content+="<dd><input type='text' id='usuario' name='USERNAME' placeholder='Nome do usuário' /></dd></dl><dl><dt>";
  content+="<label for='senhalogin'>Senha</label></dt>";
  content+="<dd><input type='password' id='senhalogin' name='PASSWORD' placeholder='Senha' /></dd>";
  content+="</dl><div id='submit_buttons'><button type='submit'>Entrar</button></div></form></div>"+ msg +"<br>";
 
  content += "<a href='/inline'>Monitor</a></body></html>";
  server.send(200, "text/html", content);
}

void reboot(){
  Serial.println("Entrou nas configurações");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  int statusCode=0;
  String content="Reiniciando...";
  if (server.hasArg("REBOOT")){//comando para reiniciar o sistema
    if(server.arg("REBOOT")=="REBOOT"){
      String ip_;//= DisplayAddress(WiFi.localIP());
      //lê o ip na eeprom
      for (int i = 0; i < 4; ++i)
      {
        ip_[i]= char(EEPROM.read(i+200));
      }
      content = "O sistema esta sendo reiniciado!!";
      Serial.println("Reiniciar");
      server.send(statusCode, "application/json", content);
      delay(1000);
      //ESP.reset();
      ESP.restart();
    }
    if(server.arg("REBOOT")=="REBOOTDEF"){
      content = "O sistema esta sendo restaurado no padrão de fabrica!!";
      Serial.println("Reiniciar padrão de fábrica");
      server.send(statusCode, "application/json", content);
      loadDefault();
      delay(1000);
      ESP.restart();
    }
    
    return;
  }


  content = "<html><body> <title>ESP-Control</title>";
  content+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'><H1>Reinicialização</H1>";
  content+="<div class='reformed-form'>";
  content+="<form method='post' name='cfg' id='cfg' action='/reboot'>";
  content+="<dl><dd><input type='radio' name='REBOOT' value='REBOOT' checked>Reiniciar <br>";  
  content+="<input type='radio' name='REBOOT' value='REBOOTDEF' >Reiniciar no padrão de fábrica </dd></dl>";  
  content+="<div id='submit_buttons'>";    
  content+="<button type='submit'>Reiniciar</button></div></form></div>";  
  
  content += "Usuário logado! <a href=\"/login?DISCONNECT=YES\"><br>Sair</a></body></html>";
  server.send(200, "text/html", content);
}


//root page can be accessed only if authentification is ok
void handleRoot(){
  Serial.println("Enter handleRoot");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  
  String content = "<html><body> <title>ESP-Control</title>";
  content+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'><H1>Menu do sistema</H1><br>";
  content+="1-<a href='/confwifi'>Configurar rede Wifi</a><br>";
  content+="2-<a href='/confipst'>Configurar LAN</a><br>";
  content+="3-<a href='/conflogin'>Configurar login</a><br>";
  content+="4-<a href='/relogio'>Relógio</a><br>";
  content+="5-<a href='/reboot'>Reiniciar o sistema</a><br>";
  
  //if (server.hasHeader("User-Agent")){
  //  content += "the user agent used is : " + server.header("User-Agent") + "<br><br>";
  //}
  content += "Usuário logado! <a href=\"/login?DISCONNECT=YES\"><br>Sair</a></body></html>";
  server.send(200, "text/html", content);
}


void conflogin(){
  Serial.println("Entrou nas configurações");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  if (server.hasArg("USUARIO") && server.hasArg("SENHAATUAL")&& server.hasArg("NOVASENHA")){//enviou configurações de ip
    String content;
    int statusCode=0;
    
    String usuario = server.arg("USUARIO");
    String senha_atual = server.arg("SENHAATUAL");
    String novasenha = server.arg("NOVASENHA");
    String confnovasenha = server.arg("CONFNOVASENHA");
    
    Serial.println("Novo usuario e senha:");
    Serial.println(usuario);
    Serial.println(novasenha);

    if (senha_atual == pwd ){//confere a senha atual
      if (novasenha == confnovasenha ){//confere a nova senha
        if (usuario.length()<=20 ){//confere o tamanho do usuario
          
          for (int i = 100; i < 120; ++i) { EEPROM.write(i, 0); }//apaga o usuario atual da eeprom
          for (int i = 0; i < usuario.length(); ++i){//grava o novo nome de usuario na eeprom
            EEPROM.write(i+100, usuario[i]);
            Serial.println(usuario[i]);
          }
          EEPROM.commit();
          content = "{\"Sucesso\":\"Novo usuário gravado.\"}";  
          for (int i = 120; i < 190; ++i) { EEPROM.write(i, 0); }//apaga a senha atual
          for (int i = 0; i < novasenha.length(); ++i){//grava a nova senha de usuario na eeprom
            EEPROM.write(i+120, novasenha[i]);
            Serial.println(novasenha[i]);
          }
          EEPROM.commit();
          delay(10);

          user=usuario;
          pwd=novasenha;
          
          //loadLoginWeb();//carrega os novos dados do login
          //content += "{\"Sucesso\":\"Nova senha gravada.\"}";  
          //content += "{\"Faça logoff para entrar com a nova senha.\"}"; 
          String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
          server.sendContent(header); 
          return;
        }else{
          content = "{\"Erro\":\"Tamanho maximo para o nome do usuario: 20 caract.\"}";  
        }
      }else{
        content = "{\"Erro\":\"Nova senha difere da confirmação da senha\"}";  
      }
    }else{
        content = "{\"Erro\":\"Senha atual incorreta.\"}";  
    }
    server.send(statusCode, "application/json", content);

    return;
  }

  String ip_local= DisplayAddress(WiFi.localIP());
  
  String content = "<html><body> <title>ESP-Control</title>";
  content+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'><H1>Configurar usuário/senha</H1>";
  content+="<div class='reformed-form'>";
  content+="<form method='post' name='cfguserpass' id='cfg' action='/conflogin'>";
  content+="<dl><dt><label for='user'>Nome do usuário</label>";    
  content+="</dt><dd><input type='text' id='user' name='USUARIO' value='"+user+"' /></dd></dl>";  
  content+="<dl><dt><label for='senha_atual'>Senha atual</label>";    
  content+="</dt><dd><input type='password' id='senha_atual' name='SENHAATUAL' /></dd></dl>";        
  content+="<dl><dt><label for='novasenha'>Nova senha</label></dt>";    
  content+="<dd><input type='password' id='novasenha' name='NOVASENHA' /></dd></dl>";  
  content+="<dl><dt><label for='confsenha'>Conf. nova senha</label></dt>";    
  content+="<dd><input type='password' id='confsenha' name='CONFNOVASENHA' /></dd></dl>";  
  content+="<div id='submit_buttons'>";    
  content+="<button type='submit'>Salvar</button></div></form></div>";  
  
  content += "Usuário logado! <a href=\"/login?DISCONNECT=YES\"><br>Sair</a></body></html>";
  server.send(200, "text/html", content);
}

boolean gravaIpLocal(String _qip){
  IPAddress qip;
  if(qip.fromString(_qip.c_str())){
    for (int i = 200; i < 204; ++i) { EEPROM.write(i, 0); }
    //grava o novo IP
    for (int i = 0; i < 4; ++i){
      EEPROM.write(i+200, qip[i]);
    }
    EEPROM.commit();
    return true;
  }else{
    return false;
  }
}

boolean gravaSubrede(String _qmsk){
  IPAddress qmsk;
  if(qmsk.fromString(_qmsk.c_str())){
    //limpa a eeprom
    for (int i = 208; i < 212; ++i) { EEPROM.write(i, 0); }
    //grava o novo IP
    for (int i = 0; i < 4; ++i){
      EEPROM.write(i+208, qmsk[i]);
    }
    EEPROM.commit();
    return true;
  }else{
    return false;
  }
}

boolean gravaGateway(String _qgtw){
  IPAddress qgtw;
  if(qgtw.fromString(_qgtw.c_str())){
    //limpa a eeprom
    for (int i = 204; i < 208; ++i) { EEPROM.write(i, 0); }
    //grava o novo Gateway
    for (int i = 0; i < 4; ++i){
      EEPROM.write(i+204, qgtw[i]);
    }
    EEPROM.commit();
    return true;
  }else{
    return false;
  }
}


void confipst(){
  Serial.println("Entrou nas configurações");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  if (server.hasArg("IPESTACAO") && server.hasArg("GATEWAY")&& server.hasArg("SUBREDE")){//enviou configurações de ip
    String content="Status:";
    int statusCode=0;

    String _qip = server.arg("IPESTACAO");
    String _qgtw = server.arg("GATEWAY");
    String _qmsk = server.arg("SUBREDE");

    if( gravaIpLocal(_qip)){//se gravou o ip...
      Serial.print("Novo IP:");
      Serial.print(_qip);
      Serial.println("Gravado com sucesso!");
      content+="IP gravado com sucesso.\n";
    }else{
      Serial.print("Erro ao gravar o IP:");
      Serial.print(_qip);
      content+="Erro ao gravao o IP.\n";
    }

    if(gravaSubrede(_qmsk)){//se gravou o ip...
      Serial.print("Nova Sub-rede:");
      Serial.print(_qmsk);
      Serial.println("Gravada com sucesso!");
      content+="Sub-rede gravada com sucesso.\n";
    }else{
      Serial.print("Erro ao gravar a Sub-rede:");
      Serial.print(_qmsk);
      content+="Erro ao gravar a Sub-rede.\n";
    }

    if(gravaGateway(_qgtw)){//se gravou o ip...
      Serial.print("Novo gateway:");
      Serial.print(_qgtw);
      Serial.println("Gravado com sucesso!");
      content+="Gateway gravado com sucesso.\n";
    }else{
      Serial.print("Erro ao gravar o gateway:");
      Serial.print(_qgtw);
      content+="Erro ao gravar o Gateway.\n";
    }

    content+="Para aplicar as configuracoes de rede,\no sistema deve ser reiniciado.\n";
    server.send(statusCode, "application/json", content);
    return;
  }

  String ip_local= DisplayAddress(WiFi.localIP());
  String msk=DisplayAddress(WiFi.subnetMask());
  String gtw=DisplayAddress(WiFi.gatewayIP());
  
  String content = "<html><body> <title>ESP-Control</title>";
  content+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'><H1>Configurar LAN</H1>";
  content+="<div class='reformed-form'>";
  content+="<form method='post' name='cfg' id='cfg' action='/confipst'>";
  content+="<dl><dt><label for='ip'>IP</label>";    
  content+="</dt><dd><input type='text' id='ip' name='IPESTACAO' value='"+ip_local+"' /></dd>";  
  content+="</dl><dl><dt><label for='sub_rede'>Sub-rede</label>";    
  content+="</dt><dd><input type='text' id='sub_rede' name='SUBREDE' value='"+msk+"' /></dd>";        
  content+="</dl><dl><dt><label for='gateway'>Gateway</label></dt>";    
  content+="<dd><input type='text' id='gateway' name='GATEWAY' value='"+gtw+"' /></dd>";  
  content+="</dl><div id='submit_buttons'>";    
  content+="<button type='submit'>Salvar</button></div></form></div>";  
  
  content += "Usuário logado! <a href=\"/login?DISCONNECT=YES\"><br>Sair</a></body></html>";
  server.send(200, "text/html", content);
}

boolean gravaSsid(String qsid, String qpass){
  if (qsid.length() > 0 ){
    Serial.println("Limpando a eeprom");
    for (int i = 0; i < 96; ++i) { EEPROM.write(i, 0); }
    Serial.println("Gravando ssid na eeprom");
    for (int i = 0; i < qsid.length(); ++i){
      EEPROM.write(i, qsid[i]);
    }
    Serial.println("Gravando senha na eeprom"); 
    for (int i = 0; i < qpass.length(); ++i){
      EEPROM.write(32+i, qpass[i]);
    }    
    EEPROM.commit();
    return true;
  }else{
    return false;
  }
}


void relogio(){
  Serial.println("Entrou nas configurações do relógio");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  if (server.hasArg("DIA") && server.hasArg("MES")){//enviou configurações
    String content;
    int statusCode=0;
    
    String _Dia = server.arg("DIA");
    String _Mes = server.arg("MES");
    String _Ano = server.arg("ANO");
    String _Hora = server.arg("HORA");
    String _Min = server.arg("MINUTO");

    int _AnoInt=_Ano.toInt();
    if(_AnoInt <= 99){//digitou apenas 2 casas 
      _AnoInt+=2000;
    }
    p.year  =   _AnoInt;
    p.month =   _Mes.toInt();
    p.day   =   _Dia.toInt();
    p.hour  =   _Hora.toInt();
    p.minute =  _Min.toInt();
    //p.dow =    1;
    p.second = 0;
    
    p.set_time();
    
    Serial.println(_Dia);
    Serial.println(_Mes);
    Serial.println(_Ano);
    Serial.println(_Hora);
    Serial.println(_Min);
    Serial.println("Atualizou o relógio");
    content="Data/hora atualizada.";
    server.send(statusCode, "application/json", content);
    return;
  }
    
 
  String content = "<html><body> <title>ESP-Control</title>";
  content+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'><H1>Data e hora no sistema</H1>";
  content+="<div class='reformed-form'>";
  
  content+="<form method='post' name='cfg' id='cfg' action='/relogio'>";
  content+="<dl><label for='dia'>Dia   </label><input type='text' id='dia' name='DIA' value='"+String(dia)+"' size=1/></dl>";  
  content+="<dl><label for='mes'>Mês  </label><input type='text' id='mes' name='MES' value='"+String(_mes)+"' size=1/></dl>";        
  content+="<dl><label for='ano'>Ano  </label><input type='text' id='ano' name='ANO' value='"+String(ano)+"' size=1/></dl>";  
  content+="<dl><label for='hora'>Hora </label><input type='text' id='hora' name='HORA' value='"+String(hora)+"' size=1/></dl>";  
  content+="<dl><label for='min'>Min. </label><input type='text' id='min' name='MINUTO' value='"+String(minuto)+"' size=1/></dl>";  
    
  content+="<div id='submit_buttons'>";    
  content+="<button type='submit'>Salvar</button></div></form></div>";  
  

  content += "Usuário logado! <a href=\"/login?DISCONNECT=YES\"><br>Sair</a></body></html>";
  server.send(200, "text/html", content);
  
}


void confwifi(){
  Serial.println("Entrou nas configurações");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  if (server.hasArg("SSID") && server.hasArg("SENHA")){//enviou configurações
    String content;
    int statusCode=0;
    String qsid = server.arg("SSID");
    String qpass = server.arg("SENHA");

    if(gravaSsid(qsid, qpass)){
      content="SSID gravada com sucesso.";
    }else{
      content="Erro ao gravar a SSID.";
    }
    
    server.send(statusCode, "application/json", content);
    return;
  }

  String _ssid(ssid);
  
  String content = "<html><body> <title>ESP-Control</title>";
  content+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'><H1>Configurar rede Wifi:</H1>";
  content+="<div class='reformed-form'>";
  content+="<form method='post' name='cfg' id='cfg' action='/confwifi'>";
  content+="<dl><dt><label for='ssid'>SSID</label>";
  content+="</dt><dd><input type='text' id='ssid' name='SSID' value='"+_ssid+"' /></dd>";    
  content+="</dl><dl><dt><label for='senha_ap'>Senha</label>";      
  content+="</dt><dd><input type='password' id='senha_ap' name='SENHA' /></dd>";    
  content+="</dl><div id='submit_buttons'>";    
  content+="<button type='submit'>Salvar</button></div></form></div>";  
  
  content += "Usuário logado! <a href=\"/login?DISCONNECT=YES\"><br>Sair</a></body></html>";
  server.send(200, "text/html", content);
}

void act(){
    if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")&& server.hasArg("rele1")){
      if (server.arg("USERNAME") == user &&  server.arg("PASSWORD") == pwd ){
        if(server.arg("rele1")=="1"){
          digitalWrite(Rele1, HIGH);  
          server.send(200, "text/plain", "Rele 1 ligado!"); // send to someones browser when asked
        }
        if(server.arg("rele1")=="0"){
          digitalWrite(Rele1, LOW);  
          server.send(200, "text/plain", "Rele 1 desligado!"); // send to someones browser when asked
        }
      }else{
        server.send(200, "text/plain", "Login incorreto."); // send to someones browser when asked
      }
    }
}

//no need authentification
void handleNotFound(){
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

bool testWifi(void) {
  int c = 0;
  Serial.println("Waiting for Wifi to connect");  
  while ( c < 20 ) {
    if (WiFi.status() == WL_CONNECTED) { return true; } 
    delay(500);
    Serial.print(WiFi.status());    
    c++;
  }
  //Serial.println("");
  //Serial.println("Connect timed out, opening AP");
  return false;
} 

void drawGraph() {
  String out = "";
  char temp[100];
  out += "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"400\" height=\"150\">\n";
  out += "<rect width=\"400\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"1\" stroke=\"rgb(0, 0, 0)\" />\n";
  out += "<g stroke=\"black\">\n";
  int y = rand() % 130;
  for (int x = 10; x < 390; x+= 10) {
    int y2 = rand() % 130;
    sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"1\" />\n", x, 140 - y, x + 10, 140 - y2);
    out += temp;
    y = y2;
  }
  out += "</g>\n</svg>\n";
  server.send ( 200, "image/svg+xml", out);
}

char *ipExterno(){//função para pegar o ip externo
  HTTPClient http;
  http.begin("http://checkip.dyndns.org/"); //HTTP
  http.GET();
  String payload = http.getString();
  int inicioIp=payload.indexOf(':')+2;
  char strFiltro[18];
  for(int h=0;h<18;h++){
    strFiltro[h]='\0';
  }
  char c;
  int t=0;
  while(t<18 && c!='<'){
    c=payload[inicioIp+t];
    if(c != '<'){
      strFiltro[t]=c;
    }
    t++;
  }
  http.end();
  return strFiltro;
}

void setup() {
  Serial.begin(9600);
  pinMode(Rele1, OUTPUT);      // configura o pino do relé 1 como saida
  pinMode(Rele2, OUTPUT);      // configura o pino do relé 2 como saida
  digitalWrite(Rele1, LOW);
  digitalWrite(Rele2, LOW);
  EEPROM.begin(MEM_ALOC_SIZE);//inicializa a eeprom
  delay(10);
  
  loadLoginWeb();
  
  String esid;
  for (int i = 0; i < 32; ++i)
  {
      esid += char(EEPROM.read(i));
  }
  Serial.print("SSID: ");
  Serial.println(esid);
  Serial.println("Lendo a senha da rede na EEPROM");
  String epass = "";
  for (int i = 32; i < 96; ++i)
  {
      epass += char(EEPROM.read(i));
  }

  
  //lê o ip na eeprom
  for (int i = 0; i < 4; ++i)
  {
    ip[i]= EEPROM.read(i+200);
  }
  //lê o Gateway na eeprom
  for (int i = 0; i < 4; ++i)
  {
    gateway[i]= EEPROM.read(i+204);
  }
  //lê o Sub-rede na eeprom
  for (int i = 0; i < 4; ++i)
  {
    subnet[i]= EEPROM.read(i+208);
  }
  
  WiFi.mode(WIFI_STA);//station
  WiFi.config(ip, gateway, subnet);//configura o ip fixo
  
  boolean AP=false;
  if ( esid.length() > 1 ) {
      WiFi.begin(esid.c_str(), epass.c_str());
      if (!testWifi()) {//se não conectou, inicializa como AP
        AP=true; 
      }
  }
 
  usrInit(); //configuração da interrupção  
  
  server.on("/", handleRoot);
  server.on("/confwifi", confwifi);
  server.on("/confipst", confipst);
  server.on("/login", handleLogin);
  server.on("/conflogin", conflogin);
  server.on("/reboot", reboot);
  server.on("/act", act);
  server.on("/relogio", relogio);
  server.on ("/test.svg", drawGraph );
  server.on("/inline", [](){
    server.send(200, "text/plain", "this works without need of authentification");
  });

  
  server.onNotFound(handleNotFound);
  //here the list of headers to be recorded
  const char * headerkeys[] = {"User-Agent","Cookie"} ;
  size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
  //ask server to track these headers
  server.collectHeaders(headerkeys, headerkeyssize );
  
  server.begin();//inicia o web server

  if(AP){
    Serial.println("Conexao falhou, o sistema entrara em modo Access Point.");
    WiFi.mode(WIFI_AP);//Access Ponit
    IPAddress myIP = WiFi.softAPIP();
    Serial.println("AP IP address: ");
    Serial.println(myIP);
  }else{
    Serial.println("Web Server ativo em: http://");
    Serial.print(WiFi.localIP());
    Serial.print("/");
    
  }
  Serial.println("");
  
}


void loop() {
  if(_timeout)//envia data e hora pela serial a cada segundo
    p.get_time();
    sprintf(dia,"%02d",p.day);
    sprintf(_mes,"%02d",p.month);
    sprintf(ano,"%04d",p.year);
    sprintf(hora,"%02d",p.hour);
    sprintf(minuto,"%02d",p.minute);
    sprintf(segundo,"%02d",p.second);
      
    Serial.print(dia);
    Serial.print(_mes);
    Serial.print(ano);
    Serial.print(hora);
    Serial.print(minuto);
    Serial.print(segundo);
    Serial.println("");
      //char time[50];
      //sprintf(time, "%02d/%02d/%02d %02d:%02d:%02d",
      //p.year, p.month, p.day, p.hour, p.minute, p.second);
      //////Serial.println(time);
      _timeout = false;
  }

  server.handleClient();
 
  
}

 

 

esp.png

  • Curtir 3
Link para o comentário
Compartilhar em outros sites

@aphawk

Valeu Paulo!!

 

É bem humilde, é só o pontapé inicial, devagar vou implementando mais coisas nele. Uma coisa que estou achando muito legal é a memória desses ESPs, se eu estivesse usando um PIC18F (que tem uma memória razoável), esse programaaí tinha lotado ele, mas no ESP agora que está em 50% da capacidade. Sem contar que ainda existe a possibilidade de rodar a 160Mhz, que pelos seus testes aí, funciona muito bem.

Link para o comentário
Compartilhar em outros sites

@ViniciusKruz Achei este seu projeto muito interessante, mas ficaria ainda mais se você colocasse um RTC DS3231, tem alguns que estão vendendo no eBay por menos de 1 USD (uma versão com memória RAM no PCI mantida pela mesma bateria do RTC), que além de ser um RTC muito preciso ainda tem a vantagem de ter memória RAM mantida pela bateria interna (com autonomia de anos se desconectado da energia) em que você pode escrever algumas coisas e não ficar limitado a quantidade de escritas (se não me falha a memória, no flash do ESP são apenas 10 mil) permitidas pelo flash do ESP-01 ou ESP-12 (pelas portas acho que você está usando deve ser o ESP-12). Sei que você quer aproveitar o seu RTC, mas você deveria pensar no assunto.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@Intrudera6

Prometo que o DS3231 será prioridade para o futuro rerere. De imediato, o PCF8583 está resolvendo, eu não ajustei o capacitor do cristal dele ainda, eu só montei e coloquei pra funcionar, nesse momento ele está tremendamente impreciso, mas depois com calma dá pra ajustar com capacitores até ficar razoável, mas depois quero testar o DS3231 com certeza.

 

Quanto à eeprom, realmente esta questão me preocupa, estou usando a eeprom simulada na flash ela é bem limitada no uso, pior é que preciso de 1024 Bytes, é uma quantidade considerável de memória, mas já estou pensando em colocar uma eeprom I2c externa pra deixar a flash de lado.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@ViniciusKruz

 

Existem muitas bibliotecas em C para acessar o DS3231, no Bascon com o Arduino eu não tive a mesma sorte e tive que criar (a partir do datasheet) a minha rotina de comunicação para o DS3231 (não criei uma biblioteca no Bascon só rotinas utilitárias), mas com o C tudo está mastigado demais, mais fácil que pescar com bomba.

 

Eu fiz uma rotina cujo objetivo é permitir um ajuste no capacitor interno do TCXO do DS3231 para melhorar a precisão (em Bascon), os meus DS3231 estão com a precisão melhoradas. Com a minha rotina até é possível ajustar ela sem um frequencímetro de precisão, mas com um é muito mais rápido, dá para calibrar em minutos. Sem um frequencímetro bastante preciso tem que ser por tentativa erro (compensado os erros em segundos por mês, comparando com um relógio acertado por GPS ou servidor SNTP, ajustando a capacitância do TCXO interno), o que pode demorar meses  para conseguir uma precisão decente.

 

O DS3231 tem um registrador com 256 posições (com sinal), mantido pela bateria do RTC, em que você pode aumentar ou diminuir a capacitância do TCXO, a resolução é de 0,2E-6 para cada degrau para mais ou para menos. Com este ajuste é possível uma precisão de +/-0,1E-6 ou +/-0,26 segundos por mês de desvio, pena que o ajuste não se mantêm por muitos meses e também é influenciado pela temperatura ambiente (que não é totalmente compensada pelo TCXO do DS3231), o ajuste acaba sendo dependente da estação do ano (mesmo em Salvador isto faz alguma diferença). Enquanto a bateria de backup não descarregar, o ajuste fino do DS3231 se mantêm, mas indo para o padrão quando perdido.

 

 

O DS3231 que estão vendendo no eBay por 0,75 USD vem com uma memória RAM T24C3 com capacidade de 32K => http://www.ebay.com/itm/Arduino-DS3231-AT24C32-IIC-Module-Precision-RTC-Real-Time-Clock-Quare-Memory-/262123918224?hash=item3d07cd9390:g:FssAAOSwHoFXrTHl

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@Intrudera6

Estou focado em uma outra rotina aqui e estou meio sem tempo pra me preocupar com o RTC agora, mas de imediato, vou ajustar a precisão do PCF de forma básica, já vai resolver por enquanto. 

15 minutos atrás, Intrudera6 disse:

Eu fiz uma rotina cujo objetivo é permitir um ajuste no capacitor interno do RTXO do DS3231 para melhorar a precisão

 

Não seria mais fácil fazer este controle com um capacitor externo (trimmer) usando um osciloscópio? considerando que este seu ajuste fino não permanece fiel. Eu por exemplo, não tenho osciloscópio/frequencímetro, sempre ajusto por tentativa e erro. 

Link para o comentário
Compartilhar em outros sites

@ViniciusKruz

O capacitor do TCXO do DS3231 só pode ser compensado por software, pois ele é controlado por um registrador interno do DS3231. Se eu tivesse paciência, o que eu poderia fazer é uma planilha com o desvio do ajuste fino x data para ver como ele se comporta durante o ano, mas eu nunca fiz isso, e como o meu está com um perna exposta para que eu conecte facilmente um frequencímetro, eu de tempos em tempos corrijo o ajuste. Mas acho que o motivo do desvio pode ser por deriva térmica que talvez não seja perfeitamente compensada pelo TCXO, pois ele, entre outras coisas, tem um erro no sensor de temperatura de +/-3.C, mas não sei se é só isso. O DS3231 tem como padrão o registrador do capacitor do TCXO em 0, um dos meus está com +9 (+/-127) ou seja -4,7segundos mês de correção e outro com +7.

Link para o comentário
Compartilhar em outros sites

11 minutos atrás, Intrudera6 disse:

O capacitor do TCXO do DS3231 só pode ser compensado por software, pois ele é controlado por um registrador interno do DS3231.

 

Então, por isto mesmo, não seria mais fácil fazer este controle via hardware mesmo? somente ajustando um capacitor externo.

Link para o comentário
Compartilhar em outros sites

@ViniciusKruz

Não é acessível externamente, pelo que eu saiba, mas eu não estudei bem a fundo o datasheet, mesmo assim isto teria que ser feito via gambiarra (se for possível, o que eu duvido), pois as plaquinhas disponíveis no eBay não tem as pernas do DS3231 acessíveis. Acho que a capacitância de compensação não deve variar com o envelhecimento, e não vejo muita razão para fazer isso via capacitor variável externo, pois ele já tem isso via software com uma precisão razoável.

Link para o comentário
Compartilhar em outros sites

9 minutos atrás, ViniciusKruz disse:

@Intrudera6

Entendi, ele não deve ter um cristal externo. 

Sim, ele não tem cristal externo, se fosse seria realmente fácil corrigir externamente. Acho que todos os TCXOs tem o cristal internamente ao chip, só assim para ter uma precisão decente.

 

E corrigindo, o AT24C32 é uma EEPROM de 32kbits ou 4096 bytes, que suporta até 1milhão de ciclos de escrita, não é uma RAM, mas em algumas situações é até melhor por não perder a memória nem por falta de energia da bateria.

Link para o comentário
Compartilhar em outros sites

@Intrudera6

Me surgiu uma dúvida e até fui consultar, nas placas mãe de computador, a BIOS usa cristal externo + capacitores para o clock do relógio e tem uma precisão incrível. Não sei se as placas mais recentes ainda são assim, mas creio que ainda são. Ou seja, dá pra extrair coisa boa desses sistemas(cristal+capacitor). 

Link para o comentário
Compartilhar em outros sites

3 minutos atrás, ViniciusKruz disse:

@Intrudera6

Me surgiu uma dúvida e até fui consultar, nas placas mãe de computador, a BIOS usa cristal externo + capacitores para o clock do relógio e tem uma precisão incrível. Não sei se as placas mais recentes ainda são assim, mas creio que ainda são. Ou seja, dá pra extrair coisa boa desses sistemas(cristal+capacitor). 

Mas o RTC das placas mãe não é desse jeito, e a precisão deles deixa um pouco a desejar, às vezes 1 segundo por dia de erro ou até mais.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
1 hora atrás, ViniciusKruz disse:

Nossa!! eu nunca coloquei o relógio do computador à prova, pra mim, eles eram bem precisos, vou passar a observar, vou acertar meu pc com um servidor de horas e vou acompanhar pra ver a real precisão dele.

 

Ele realmente ajusta de tempos em tempos. Eu nunca soube se era atraso dele mesmo ou diferenças do meio. Sempre achei complicadas essas checagens por Internet. Deve ser um algoritmo cheio de "verificações", fiquei pensando por último.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

5 horas atrás, Intrudera6 disse:

@ViniciusKruz

O capacitor do TCXO do DS3231 só pode ser compensado por software, pois ele é controlado por um registrador interno do DS3231. Se eu tivesse paciência, o que eu poderia fazer é uma planilha com o desvio do ajuste fino x data para ver como ele se comporta durante o ano, mas eu nunca fiz isso, e como o meu está com um perna exposta para que eu conecte facilmente um frequencímetro, eu de tempos em tempos corrijo o ajuste. Mas acho que o motivo do desvio pode ser por deriva térmica que talvez não seja perfeitamente compensada pelo TCXO, pois ele, entre outras coisas, tem um erro no sensor de temperatura de +/-3.C, mas não sei se é só isso. O DS3231 tem como padrão o registrador do capacitor do TCXO em 0, um dos meus está com +9 (+/-127) ou seja -4,7segundos mês de correção e outro com +7.

 

Opa valeu pelo link do Ebay! Faz um ano eu comprei duas peças dele  com um módulo um pouco diferente, acho que era lançamento, e paguei uns Us$ 3 em cada um :mad: .... comprei 5 agora prá "fazer a média" !

 

Ainda mais com a memória I2C de brinde, é uma excelente opção !

 

O que podemos ajustar nesse módulo é o Aging Register, que existe para que de tempos em tempos as variações possam ser canceladas novamente. Afinal, esse CI é para uso industrial, não é nem militar e nem científico.

 

No primeiro ano de fabricação ele varia bem pouco, cerca de 1 ppm, mas depois pode chegar a até 5 ppm.

 

Para meus usos, está mais do que suficiente o ajuste de fábrica. E também não tenho um frequencímetro tão  preciso que me permita medir e ajustar.

 

Existem TCXO mais precisos ainda, mas não acompanham o RTC. 

 

Por exemplo, este aqui é 5 vezes mais preciso em todos os sentidos, mas custa 10 X mais e é só o oscilador :

 

http://pages.ebay.com/link/?nav=item.view&alt=web&id=291547954929&globalID=EBAY-US 

 

Paulo

 

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Então imagine o quanto custa um OCXO, que ainda é mais preciso por ser montado numa caixa com temperatura estabilizada, encontrei um no eBay novo pela "bagatela" de 37,28 USD de 10Mhz. Com uma coisa destas acoplada a um GPS você pode conseguir uma precisão de base de tempo de +/-5E-11, uso algo parecido ligado no frequencímetro como base de tempo (é ótimo ter um equipamento que aceita base de tempo externa) para fazer a calibração do meu DS3231 (a precisão do que eu tenho não chega a tanto, pois ele já é um pouco idoso mas é mesmo assim muito alta).

 

http://www.ebay.com/itm/NEW-10MHz-OCXO-DIP-Micro-Crystal-x1pc-5x10E-11-Oven-Oscillator-OCVCXO-GPSDO-/252308905189?hash=item3abec85ce5:g:DFQAAOSwAuNW2Zrb

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!