{"id":7759,"date":"2018-05-05T21:20:06","date_gmt":"2018-05-05T20:20:06","guid":{"rendered":"http:\/\/blog.whatsbee.net\/?p=7759"},"modified":"2019-06-05T12:00:59","modified_gmt":"2019-06-05T11:00:59","slug":"cuarto-paso-poniendo-el-esp8266-en-deep-sleep","status":"publish","type":"post","link":"https:\/\/blog.whatsbee.net\/?p=7759","title":{"rendered":"Cuarto paso: Poniendo el ESP8266 en deep sleep"},"content":{"rendered":"<p>En este momento ya tenemos el ESP8266 soldado en la placa y pinchado en la protoboard, es el momento de probar el modo deep-sleep.<\/p>\n<h3>\u00bfC\u00f3mo funciona?<\/h3>\n<p>El micro arranca normalmente conect\u00e1ndolo a la alimentaci\u00f3n o pulsando el bot\u00f3n de reset, ejecuta la funci\u00f3n setup() y cuando la acaba ejecuta la funci\u00f3n loop(), \u00bfque tenemos que hacer?, sencillo. En el momento en el que queramos podremos utilizar la funci\u00f3n\u00a0 <code>ESP.deepSleep(x)<\/code>, d\u00f3nde x es el tiempo en microsegundos que va a estar dormido y el micro se pondr\u00e1 autom\u00e1ticamente en ese modo. La funci\u00f3n\u00a0 deepsleep admite un segundo par\u00e1metro que es el modo en el que va a despertar la radio, nosotros, como no utilizaremos la Wifi ponemos el modo <code>WAKE_RF_DISABLED<\/code>. Eso implica que en el siguiente reinicio la WiFi no va a estar disponible y no va a haber forma de habilitarla. En el caso en el que necesitemos la Wifi simplemente haremos un ciclo de deep sleep corto en el que cambiaremos el par\u00e1metro (ya lo veremos).<\/p>\n<p>Por lo que he visto con esta funci\u00f3n hay alg\u00fan l\u00edo, por lo que utilizaremos realmente:<\/p>\n<p><code>system_deep_sleep_set_option(WAKE_RF_DISABLED);<br \/>\nsystem_deep_sleep(segundos*1000*1000);<\/code><\/p>\n<p>Funcionalmente es lo mismo, primero seleccionamos el modo para que se inicie sin WiFi y despu\u00e9s activamos el modo de deep sleep. Desde ese momento el ESP empezar\u00e1 a consumir unos 20 uA y, una vez transcurrido el tiempo pondr\u00e1 el GPIO16 a nivel bajo. \u00bfQue es lo que pasar\u00e1?, NADA.<\/p>\n<p>Para que pase algo tenemos que conectar el GPIO16 con el reset, cuando eso ocurra sencillamente el ESP recibir\u00e1 un nivel bajo en el pin de reset y se reiniciar\u00e1 el programa de nuevo. Ojo!!!! es exactamente lo mismo que pulsar el bot\u00f3n de reset, de hecho si mientras el ESP est\u00e1 en deep sleep pulsamos f\u00edsicamente el bot\u00f3n de reset ocurrir\u00e1 lo mismo.<\/p>\n<p>(Como en posts anteriores no quiero reinventar la rueda y hacer un tratado sobre los modos de sleep, est\u00e1n muy bien documentados <a href=\"https:\/\/www.losant.com\/blog\/making-the-esp8266-low-powered-with-deep-sleep\">aqui<\/a>)<\/p>\n<h3>Pero \u00bfc\u00f3mo me acuerdo en que punto estaba del programa?<\/h3>\n<p>La primera tentaci\u00f3n siempre es utilizar la memoria EEPROM, que en el ESP est\u00e1 emulada sobre la nvRAM mediante una librer\u00eda. Pero hay que tener mucho cuidado, el n\u00famero m\u00e1ximo de escrituras antes de que deje de funcionar es de unas 10.000 (hay diversas opiniones al respecto) por lo que si hacemos un ciclo de 2 segundos en el cual escribimos la informaci\u00f3n que queremos transmitir al siguiente ciclo solo tendremos 20.000 segundos hasta que la memoria del ESP se aver\u00ede, eso le dar\u00e1 una vida \u00fatil a nuestro circuito de unas 6 horas.<\/p>\n<p>Afortunadamente el ESP8266 cuenta con 512 bytes de memoria RTC que se guarda incluso aunque el micro est\u00e9 en modo deep sleep, es en esta memoria en la que almacenaremos los datos que tengan que sobrevivir a un deep sleep.<\/p>\n<p>\u00bfcomo lo hacemos?, sencillo, los guardamos en una variable que guardamos siempre antes del deep sleep en la memoria RTC, lo primero que hace nuestro programa es copiarlos de la memoria RTC a la variable, con lo que los tendremos disponibles.<\/p>\n<p>\u00bfC\u00f3mo lo hacemos? lo hacemos <a href=\"https:\/\/github.com\/esp8266\/Arduino\/blob\/master\/libraries\/esp8266\/examples\/RTCUserMemory\/RTCUserMemory.ino\">as\u00ed<\/a>.<\/p>\n<h3>S\u00ed, pero \u00bfque pasa en el primer arranque o en un reinicio?<\/h3>\n<p>Si vamos a cargar una variable desde la memoria RTC la primera vez que arranquemos el ESP o si se le desconecta la alimentaci\u00f3n no sabremos lo que carga, como esa variable es la que determina que vamos a hacer es muy recomendable saber si el ESP viene de un seep sleep o se ha iniciado porque se ha alimentado de nuevo. He hecho esta funci\u00f3n:<\/p>\n<p><code>boolean bootFromDeepSleep (){<br \/>\nif (ESP.getResetReason()==\"Deep-Sleep Wake\"){returntrue;}<br \/>\nreturnfalse;<br \/>\n}<\/code><\/p>\n<p>Sencillamente, al principio del setup valoraremos el resultado de la funci\u00f3n, si devuelve true podemos cargar de la memoria RTC con seguridad y continuar con la ejecuci\u00f3n, en cualquier otro caso vamos a hacer otra cosa.<\/p>\n<p>Y la cosa que haremos es cargar los mismos valores de la EEPROM (nvRam en el ESP),\u00a0para evitar tener que cargar unos valores por defecto para el primer arranque lo que haremos es que en la variable guardada los primeros valores sean conocidos, si los valores que se cargan no son los que esperamos la EEPROM se inicializar\u00e1 con unos valores por defecto, lo cual resolver\u00e1 el problema. Tambi\u00e9n tendremos que guardar la configuraci\u00f3n de la memoria RTC en la EEPROM cada cierto tiempo, de esta forma tendremos los contadores menos actualizados, pero no desactualizados del todo. hay que tener la precauci\u00f3n de que el numero de ciclos de escritura en la EEPROM no supere la vida \u00fatil del equipo.<\/p>\n<h3>\u00bfEn que punto estamos?<\/h3>\n<p>Ahora mismo tenemos un ESP8266 en una placa de prototipos durmiendo la mayor parte del tiempo y despertando con unas variables definidas en el ciclo anterior.\u00a0 El ESP despierta sin WiFi para tener el m\u00ednimo consumo.<\/p>\n<p>Si el dispositivo se ha desconectado de la alimentaci\u00f3n, Lo detecta y recoge unos valores de la EEPROM en lugar de iniciarse con valores desconocidos.<\/p>\n<p>Peri\u00f3dicamente guardamos en la EEPROM los valores\u00a0 actualizados, asumiendo que si guardamos cada x ciclos nos podemos encontrar una desactualizaci\u00f3n de los valores.<\/p>\n<p>Adem\u00e1s antes de cargar esos valores de la EEPROM comprobamos si son consistente, si no lo son reiniciamos a los valores por defecto y empezamos de cero (mejor eso que nada).<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>En este momento ya tenemos el ESP8266 soldado en la placa y pinchado en la protoboard, es el momento de probar el modo deep-sleep. \u00bfC\u00f3mo funciona? El micro arranca normalmente conect\u00e1ndolo a la alimentaci\u00f3n o pulsando el bot\u00f3n de reset,&hellip; <br \/><a class=\"read-more-button\" href=\"https:\/\/blog.whatsbee.net\/?p=7759\">Leer m\u00e1s<\/a><\/p>\n","protected":false},"author":1,"featured_media":7761,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0},"categories":[208],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=\/wp\/v2\/posts\/7759"}],"collection":[{"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7759"}],"version-history":[{"count":1,"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=\/wp\/v2\/posts\/7759\/revisions"}],"predecessor-version":[{"id":7760,"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=\/wp\/v2\/posts\/7759\/revisions\/7760"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=\/wp\/v2\/media\/7761"}],"wp:attachment":[{"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7759"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7759"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.whatsbee.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7759"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}