Olá a todos. Tudo bem?
Ontem fui premiado com a quebra do conector usb do esp8266, então, o Celso citou sobre o OTA.
Fui pesquisar, achei bastante interessante.
Como referência, usei este tutorial: https://www.filipeflop.com/blog/programacao-esp8266-ota-wifi/
Instalei o python mais novo e o do citado no link.
Ao rodar o exemplo basicOta, tudo funciona certinho.
Depois de um tempo, tive um problema onde ele emitia um erro: "OTA [ERROR]: No Answer", que foi resolvido adicionando um capacitor eletrolítico (a recomendação era 470uf, mas eu só tinha de 3300uf , que resolveu também) no vin e gnd do módulo (esp).
Então resolvi adaptar meu código ao OTA.
para simplificar o processo, irei chamar de "Sketch OTA" e "Sketch Tiago"
1- #define, #include, variáveis, copiadas de "Sketch OTA" para "Sketch Tiago"
2- Void Setup() de "Sketch OTA" agora é "Void Setup_OTA"
3- Void Loop() de "Sketch OTA" agora é "void loop_OTA"
Agora fica mais interessante.
1) Quando adiciono o setup_OTA no topo do processo do setup(), e o loop_OTA no topo do processo do loop(), tudo funciona perfeitamente, aparecendo no "port" do arduino IDE.
2) Ao criar uma CONDIÇÃO para que o "setup_OTA" inicie (exemplo: apertar um botão, ou passar X segundos, por millis(), com o loop_OTA em outra condição, é exibido a mensagem do ip, dizendo que está pronto, entretanto, ele NÃO aparece no port do Arduino IDE.
Ai você pode perguntar:
"Tiago, então pq não deixa logo ele funcionando desde o inicio?"
R- Não faz sentido ter uma função ativa, consumindo energia, se ela não será usada no momento. O ideal é ativa-la apenas quando for ser usada.
Eu procurei informação sobre o assunto, mas não estou achando nada que me ajude.
Obs- Anexei meu código. Ele não ta bonito, falta organizar algumas coisas e otimizar várias outras coisas, mas o ponto se resume em 2 abas:
- ESP8266_-_TESTADOR_DE_BATERIAS.ino
- OTA.ino
Tags:
Na verdade, a condição que citei ser funcional, eu não tenho mais certeza.
Estou perdido da causa do não funcionamento.
Simplesmente, não aparece no port.
Mas se eu colocar o código limpo, ele aparece.
assim não, né Tiago...
Virgem Santa. O George Boole agora está revirando no túmulo, porque você contrariou tudo que ele criou, e esse "tudo" é simplesmente o que faz toda tecnologia digital existir e funcionar.
Vamos ver por que?
Na figura a seguir, mostro a função "loop" do seu código, e vc pode ver que marquei algumas partes com cores pra ficar mais fácil me referir a estas partes:
(clique na figura para "zoom")
Rapaz, só de olhar o código na figura, já me dá um arrepio daqueles de alma-penada.
Entenda:
1) para que o OTA funcione, obrigatoriamente é preciso que o "setup_OTA()" seja executado para inicializar as funcionalidades do OTA, pois é ele (na verdade o "ArduinoOTA.begin()" ) quem "cria" aquele PORT (associado a um IP) que vc vê na IDE do Arduino, e isso deve ser feito uma única vez, já que é uma inicialização. Então o lugar adequado pra fazer isso é no "setup" do Arduino. Ok?
Mas não se iluda, pois este PORT não é um Port COM "real", ele é virtual. Ou seja, ele é na verdade a conexão a um Server criado no modo AP do ESP8266. Portanto a IDE do Arduino é um cliente desse Server.
2) mas para que o OTA funcione mesmo, também é preciso que o "loop_OTA()", seja rotineiramente executado, pois é ele (na verdade o "ArduinoOTA.handle()" ) quem verifica se em algum momento foi requisitado iniciar uma atualização OTA. Como isso ocorre? quando vc inicia uma atualização OTA na IDE do Arduino, a IDE "cliente" se conecta ao Server do AP do ESP8266, e os dois trocam "figurinhas", de forma que a IDE envie para o Server o código a ser atualizado. Por isso o "loop_OTA()" tem que ser executado rotineiramente, do contrário ele pode não detectar uma requisição para uma atualização OTA. Então, um lugar adequado pra fazer isso é no "loop" do Arduino. Ok?
3) bem, só os itens 1) e 2), já mostram a vc o que precisa ser feito pra que a coisa funcione corretamente como planejado, e quem planejou isso foram os criadores do OTA.
Mas a coisa é um pouco pior: veja o itens seguintes.
4) pra determinar quando vc quer que o OTA funcione (a seu modo), vc criou uma variável tipo "bool" de nome "OTA_ON". Por ser "bool", ela só pode assumir dois valores: ou "0" ou "1". (ou se vc preferir: ou "false" ou "true"). Não há como sua variável "OTA_ON" assumir outro valor que não seja um dos dois listados. Então para testar o "OTA_ON", basta que vc teste verificando um dos dois valores ("0" ou "1"), pois se não for o que vc está verificando, só poderá ser o outro. Não há como existir um terceiro valor possível e uma terceira possibilidade de teste.
Mas no seu código, há três possibilidades, pois há um "if" que testa se "OTA_ON" é igual a "0", onde marquei em roxo na figura anterior (note que a parte do "millis" não muda as coisas, pois no final das contas o resultado será "0" ou "1" de qualquer forma). E se não for "0", então "OTA_ON" só pode ser "1", mas no seu teste vc está verificando isso de forma desnecessária marcado na cor laranja). Mas como se não bastasse essa doidera, vc ainda tem o "else", que seria executado caso "OTA_ON" não fosse nem "0" nem "1". Mas como assim?????? Percebeu porque o George Boole certamente está revirando no túmulo?
Então veja que o que está na parte marcada em amarelo, jamais será executado, pois como "OTA_ON" é tipo "bool", ou será executado a parte na cor verde, ou será executada a parte na cor azul. A parte na cor amarela, sem chance.
5) mas a coisa piora um pouco mais. Como eu disse, para que o OTA funcione, é preciso que o "setup_OTA()" tenha sido executado antes e uma única vez. E depois disso, o "loop_OTA()" deve ser executado rotineiramente. Mas na lógica mostrada na figura anterior, ou será executado a parte verde, ou será executada a parte azul. Jamais as duas partes serão ambas executadas. Então já viu, né? Não tem como o OTA funcionar naquela lógica.
Tá bem doido isso, né?
Nota: sua justificativa pra não deixar o OTA sempre "ativo e consumindo energia", não tem sentido, pois a execução rotineira do OTA é otimizada de forma a não ficar perdendo tempo caso nenhuma atualização seja requisitada (justamente pra ter o menor impacto possível no restante do código, e esse objetivo é alcançado, pois o ESP8266 é um Processador bem rápido).
Que tal vc analisar isso melhor, e talvez decidir fazer as coisas como elas foram planejadas para serem feitas ?
(se vc quiser navegar no mar com a fuselagem de um avião, pode tentar, mas o avião não foi exatamente planejado pra isso, logo algum problema vc vai ter)
Obs.: não fique bravo comigo. O objetivo não é ser duro com vc. Mas que eu imagino o George Boole revirando no túmulo, eu imagino.
Abrçs,
Elcids
HAHAHAA, obrigado pela sua resposta Elcids, como eu disse, o código não está otimizado, entretanto, o "else" funciona sim.
Vamos imaginar a seguinte situação:
OTA_ON = 0
millis() - ota_millis = 1000
o primeiro if possui 2 parâmetros:
1) OTA_ON == 0
2) millis() - ota_millis > 4000
- O primeiro será verdadeiro, pois ota_on será igual a zero.
- O segundo será falso, pois ele pede que seja SUPERIOR a 4000, entretanto, ela possui apenas 1000.
- Entre os dois parâmetros, existe o "&&", que define como sendo obrigatória que os dois parâmetros sejam verdadeiros para que o "if" retorne um "true".
- Como o primeiro é "true", e o segundo é "false", então retornará como "false", passando a bola para o "else if".
Em seguida temos o Else if:
OTA_ON == 1
- EOTA_ON é "0", ele retornará como "false", passando a bola para o "Else".
Em seguida temos o "Else"
- Pelos valores citados, este código será executado.
E, efetivamente, ele é executado.
Com relação ao item 5)
No código atual, o que acontece é o seguinte:
- Primeiro as condições do Else são cumpridas, então as funções que estão nele, são executadas perfeitamente.
- Após 4 segundos (pelo exemplo do código), o primeiro IF é iniciado, fazendo a chamada do Setup_OTA. A tela de LCD fica preta, é mostrada a inicialização (booting, ready, ip atual...). Ao término, ele define o "OTA_ON = 1". Impossibilitando que ele execute uma segunda vez. (perfeito)
Veja que cumpre exatamente o que você citou: "é preciso que o "setup_OTA()" tenha sido executado antes e uma única vez".
- Aqui, o "else if" será verdadeiro (OTA_ON == 1). o loop_OTA() seria executado o tempo todo.
Neste ponto, a única coisa ativa (no loop) seria, justamente, o "ArduinoOTA.handle()".
"Mais nada ficaria rodando" além dele (isso é intencional).
Entretanto, ontem, ao olhar o roteador, não existia o ip citado conectado a ele, mesmo tendo informado um ip. E ai estourou minha mente.
Com relação a sua nota:
Eu não tinha conhecimento sobre isso. Mas gosto da ideia de iniciar este recurso apenas quando for necessário.
Com relação a ficar chateado:
Não tenho motivos. Você ta agregando conhecimento.
Onde exatamente o problema estava? eu não sei.
Mas comecei a organizar o código, e não foi apresentando problema me nenhum momento. Mágica? não, provavelmente algum detalhe que deixei passar. Em todo caso, está funcional.
O problema está resolvido, entretanto, não tenho certeza da solução.
Olá, Tiago!
"Teoria é quando tudo se sabe, mas nada funciona"
"Prática é quando tudo funciona e ninguém sabe porquê"
Aqui em casa eu alio Teoria e Prática: Nada funciona e eu não sei porquê!
D.T. Ribeiro.
Bem-vindo a
Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)
© 2024 Criado por Marcelo Rodrigues. Ativado por