Interaccionar con FireBase desde Arduino


Como  podemos ver en este blog en numerosas  entradas que hablamos de dispositivos de IoT, es  relativamente sencillo construir nuestros  propios dispositivos de IoT con algunos sensores y microcontroladores  como Arduino, NodeMCU, Raspberry  Pi, etcétera , lo cual le permitirán automatizar su hogar apoyándose en estos dispositivos como por ejemplo usando el servicio de Cayenne .

De hecho ,como ejemplo de lo  sencillo  y económico  que puede ser  la construcción de dispositivos   IoT desde un punto de vista más empírico , lo ideal es usar un o NodeMCU ESP-12E para   acceder a Firebase  

 

 NodeMCU ESP-12E  es muy barato (unos 6€)   ,  y al tener  wifi incorporado para conectarse a internet,  ya tenemos los elementos suficientes  para conectarnos a  bases de datos avanzada  en l anube como puede ser Firevase y   gracias a un hardware tan eficiente  (y por supuesto los servicios cloud de Firebase).

Precisamente  FirebaseArduino (abstracción completa de la API REST de Firebase expuesta a través de las llamadas de C ++ de una manera amigable con el cableado.)   es una biblioteca muy útil usada   para simplificar la conexión a la base de datos Firebase desde cualquier cliente Arduino .Esta biblioteca  como podemos imaginar  se encarga de todo el análisis de Json y puede realizar transacciones en tipos C / Arduino puros.

En un post anterior «Primeros pasos con NodeMCU y Firebase»  ya vimos un sencillo ejemplo de como ambos componentes pueden funcionar, Veamos a  a continuación  que podemos hacer c muchas mas cosas con esta famosa librería

 

class FirebaseArduino

Esta es la clase principal para que los clientes de Arduino interactúen con Firebase. Como es habitual con arduino  para referenciarla  y poderla usar necesitamos  introducir  esta libreria con un include  al principio del programa , como por ejemplo

 #include <FirebaseArduino.h>»

Esta implementación está diseñada para seguir las mejores prácticas de Arduino y favorecer la simplicidad sobre todo lo demás. Para casos de uso más complicados y más control, podemos usar la clase Firebase en Firebase.h.

Esta libreria debe ser llamada primero con void begin ( const String y host , const String y auth = «» )  , lo cual inicializa el cliente con el host y las credenciales de base de fuego dados.

Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);  //intentamos conectarnos a la base de datos Firebase con nuestras credenciales

Los parámetros son :

  • host : es decir el  host de base de datos de base de datos de Fierbase , normalmente X.firebaseio.com.
  • auth : credenciales  para la db  que pueden ser  una palabra  secreta o token.

 

Lo más sencillo  precisamente para pasar las credenciales de Firebase   a esta clase es usando  variables que  definiremos al principio del programa:

  • FIREBASE_HOST “xxxxxxxxxxxxxxx.firebaseio.com”
  • FIREBASE_AUTH “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”

 

Veamos algunas funciones que podemos usar con esta clase:  pushInt,pushFloat, pushBool,pushString,push,setInt, setFloat,setBool,setString,set ,getInt, getFloat,getBool,getString,get,   las relacionadas con Firebaseobject(get,readevent)  .   asi como remove,stream, available,read ,success, failed,error

 

 

String pushInt ( const String & path , int value )

Anexa el valor entero al nodo en la ruta.Equivalente al POST de la API REST. Debe comprobar  success()  después de llamar. Devuelve la clave única del nuevo nodo hijo.

Los parámetros que usa:

  • path : La ruta del nodo padre.
  • value : valor entero que desea agregar al nodo.

 

String pushFloat(const String &path, float value)

Esta función anexa el valor flotante al nodo en la ruta.  Es equivalente al POST de la API REST. Debe comprobar   success()   después de llamar. Devuelve la clave única del nuevo nodo hijo.

Los parámetros que usa:

  • path : La ruta del nodo padre.
  • value : valor flotante que desea agregar al nodo.

String pushBool(const String &path, bool value)

Esta función anexa el valor booleano al nodo en la ruta.  Es equivalente al POST de la API REST. Debe comprobar el resultado de salida con  success()  después de llamar a a funcion . Devuelve la clave única del nuevo nodo hijo.

Los parámetros que usa:

  • path : La ruta del nodo padre.
  • value : valor Booleano que desea agregar al nodo.

String pushString(const String &pathconst String &value)

Esta función anexa el valor de cadena al nodo en la ruta.Es equivalente al POST de la API REST. Debe comprobar el resultado de salida con  success()  después de llamar a a funcion. Devuelve la clave única del nuevo nodo hijo.

Los parámetros que usa:

  • path : La ruta del nodo padre.
  • value : valor de la  cadena que desea agregar al nodo.

 

String push(const String &pathconst JsonVariant &value)

Esta función anexa los datos JSON al nodo en la ruta.Equivalente al POST de la API REST.   Devuelve la clave única del nuevo nodo hijo.

Parámetros

  • path : La ruta del nodo padre.
  • value : los datos JSON que desea agregar al nodo.

 

void setInt(const String &path, int value)

Escribe el valor entero en el nodo ubicado en la ruta equivalente al PUT de la API REST. Debe comprobar el resultado de salida con  success()  después de llamar a a función

Parámetros que usa

  • path : la ruta dentro de su base de datos al nodo que desea actualizar.
  • value : valor entero que desea escribir.

void setFloat(const String &path, float value

Escribe un  valor en coma flotante en el nodo ubicado en la ruta equivalente al PUT de la API REST.Debe comprobar el resultado de salida con  success()  después de llamar a a función

Parámetros necesarios:

  • path : la ruta dentro de su base de datos al nodo que desea actualizar.
  • value : el valor flotante que desea escribir.

void setBool(const String &path, bool value)

Escribe el valor booleano  en el nodo ubicado en la ruta equivalente al PUT de la API REST.  Debe comprobar el resultado de salida con  success()  después de llamar a a función  

Parámetros que usa

  • path : la ruta dentro de su base de datos al nodo que desea actualizar.
  • value :  valor booleano  que desea escribir.

void setString(const String &pathconst String &value)

Escribe el valor de la cadena en el nodo ubicado en la ruta equivalente a la PUT de la API REST. Debe comprobar el resultado de salida con  success()  después de llamar a a función

Parámetros que requiere:

  • path : la ruta dentro de su base de datos al nodo que desea actualizar.
  • value : valor de la cadena que desea escribir.

 

void set(const String &pathconst JsonVariant &value)

Escribe los datos JSON en el nodo ubicado en la ruta.  Equivalente al PUT de la API REST.  Debe comprobar el resultado de salida con  success()  después de llamar a a función

Parámetros necesarios:

  • path : la ruta dentro de su base de datos al nodo que desea actualizar.
  • value : datos JSON que desea escribir.

 

int getInt(const String &path)

Obtiene el valor entero ubicado en la ruta. Debe comprobar el resultado de salida con  success()  después de llamar a a función   Devuelve el valor entero ubicado en esa ruta. Solo será poblado si  success()   es verdadero. Requiere un único  parámetro path : la ruta al nodo que desea recuperar.

 

float getFloat(const String &path)

Obtiene el valor flotante ubicado en la ruta. Debe comprobar el resultado de salida con  success()  después de llamar a a función. Devuelve  un valor flotante ubicado en ese camino. Solo será poblado si un success()  ) es verdadero.

Requiere un único  parámetropath : la ruta al nodo que desea recuperar.

 

String getString(const String &path)

Obtiene el valor de cadena ubicado en la ruta.Debe comprobar el resultado de salida con  success()  después de llamar a a función.   Devuelve el valor de cadena ubicado en esa ruta. Solo será poblado si el   success()   es verdadero.

Requiere un único  parámetropath : la ruta al nodo que desea recuperar.

 

bool getBool(const String &path)

Obtiene el valor booleano ubicado en la ruta.Debe comprobar el resultado de salida con  success()  después de llamar a a función. Devuelve el  valor booleano ubicado en esa ruta. Solo será poblado si el éxito () es verdadero. Requiere un único  parámetro  path : la ruta al nodo que desea recuperar.

Es muy usado para  activar o desactivar un  nivel  lógico  en los pines binarios  en la placa ,por ejemplo para activar una salida a nivel alto  o bajo 

Ejemplo

      bool isLedOn = Firebase.getBool(“led”); // recuperamos el valor del objeto led de la sesión firebase

 

 

FirebaseObjectget(const String &path)

Obtiene el valor del objeto json ubicado en la ruta.Debe comprobar el resultado de salida con  success()  después de llamar a a función. Devuelve el valor FirebaseObject ubicado en esa ruta. Solo será poblado si el éxito () es verdadero.Requiere un único  parámetro path : la ruta al nodo que desea recuperar.

FirebaseObjectreadEvent()

Lee el siguiente evento en una stream ( secuencia).Esto solo tiene sentido una vez que se ha llamado a  stream() 

A la salida FirebaseObject tendrá [«type»] que describe el tipo de evento, [«path»] que describe la ruta efectuada y [«data»] que se actualizaron.

 

 

 

void remove(const String &path)

Elimina el nodo, y posiblemente el árbol completo, ubicado en la ruta.Debe comprobar el resultado de salida con  success()  después de llamar a a funcion.Requiere un único  parámetro path : la ruta al nodo que desea eliminar, incluidos todos sus hijos.

void stream(const String &path)

Inicia la transmisión de los cambios realizados en el nodo ubicado en la ruta, incluido cualquiera de sus elementos secundarios.

Debe comprobar el resultado de salida con  success()  después de llamar a a funcion Esto cambia el estado de este objeto. Una vez que se llama a esto, puede comenzar a monitorear available () y llamar a readEvent () para obtener nuevos eventos.

Requiere un único  parámetro path : la ruta dentro de su db al nodo que desea monitorear.

bool available()

Comprueba si hay nuevos eventos disponibles.Esto solo tiene sentido una vez que se ha llamado a  stream()  .Devuelve si un nuevo evento está listo.

bool success ( ) 

Devuelve   si el último comando fue exitoso.

bool failed ( ) 

Devuelve si el último comando falló.

 

const String &error()

 Devuelve el  mensaje de error del último comando si  failed() es verdadero.

 

 

 

 

 

class FirebaseObject

 

Representa el valor almacenado en Firebase , puede ser un valor singular (nodo de tipo leaf) o una estructura de árbol.

Las  funciones publicas  definidas para esa clase son las siguientes:

 

FirebaseObject ( const char * data ) 

Construir a partir de json.  Requiere un único  parámetro data : cadena formateada JSON.

 

bool getBool ( const String & path = «» ) const

Devuelve el valor como un booleano. .Requiere un único  parámetro optional : ruta en el objeto JSON.

 

int getInt ( const String & path = «» ) const

 Devuelve el  resultado como un entero.Requiere un único  parámetro optional : ruta en el objeto JSON.

 

float getFloat ( const String & path = «» ) const

Devuelve el valor como un flotador..Requiere un único  parámetro optional : ruta en el objeto JSON.

 

String getString ( const String & path = «» ) const

Devuelve el valor como una cadena.Requiere un único  parámetro optional : ruta en el objeto JSON.

 

JsonVariant getJsonVariant ( const String & path = «» ) const

Devuelve el valor como JsonVariant.Requiere un único  parámetro optional : ruta en el objeto JSON.

bool success ( ) const

Devuelve si hubo un error en la descodificación o el acceso al objeto JSON.bool 

 

failed ( ) const

Devuelve si  hubo un error en la descodificación o el acceso al objeto JSON.const 

 

String & error ( ) const

 Devuelve un mensaje de error si  failed()  es verdadero.

 

 

Mas informacion en  https://firebase-arduino.readthedocs.io/en/latest/

Como eliminar la luz residual de las luminarias con leds


Puede  que al realizar una pequeña instalación en la que hacemos uso de luminaria basada en diodos  LED nos hayamos  topado con un curioso fenómeno  que al pagar esta   queda una levísima  iluminación que solo se  advierte claramente si nos quedamos a oscuras.

Este fenómeno que no ocurre no existe con las luminarias incandescentes se explica  porque los leds llegan a lucir (aunque muy débilmente) con corrientes del orden de pocos microAmp , lo cual ya es suficiente  de hecho para que a  podemos observar una débil luz( similar al efecto de ver carteles fluorescentes  que con la luz que destellan)

Con esta anomalía  podemos tener la sensación molesta de que estamos ante un relativamente molesto  gasto de suministro eléctrico ,si bien es mínimo   dado la mínima corriente que los atraviesa  y que por tanto consumimos

Es cierto que hay personas que no les molesta en absoluto este efecto pues por la noche gracias a «ese defecto» podemos ver lo justo para ir a cualquier parte de la casa sin encender la luz en plena oscuridad..¿pero y si deseamos   que no se encienda en absoluto? Pues veamos como solucionarlo

 

Cables y derivaciones en lamparas de sobremesa o de pie

Antes de conectar o desconectar elementos , en caso de lamparas de  sobremesa, de pie, de mesa ,flexo,etc si tiene conectadas luminarias de leds , podemos probar los siguientes recursos:

  • Invertir la forma de conectar el enchufe a la toma de corriente ( es decir invertir la fase por el neutro y viceversa)
  • Probar con otra luminaria de otra marca o modelo ( podría se defecto de la propia bombilla de led sobre todo si es de origen asiático de bajo coste)
  • Revisar el cableado  interior  pues si toca uno de los cables con el apantallado metálico ademas de ser peligroso podria hacer suficiente masa para que se encienda la luminaria levemente
  • Reemplazar el interruptor monopolar por bipolar , es decir que corte no solo uno de los cables ( fase o neutro ) sino ambos a la vez.

Interruptores con testigos de neón

Esta particular característica de los leds está creando un nuevo problema cuando estos se usan para iluminación porque las instalaciones eléctricas, muchas veces tienen diferencias de potencial a tierra que generan pequeñas fugas de corriente y que no dejan que las lámparas de leds se apaguen completamente.

Este  fenómeno es especialmente persistente  cuando se usan interruptores de encendido con luz de señalización con neón como podemos observar en el  esquema de abajo  donde el testigo de neón con la correspondiente resistencia va en paralelo con el propio interruptor:

.

 

Es evidente en el esquema  anterior que si abrimos el interruptor  , la lampara de neon  y la resistencia de 330k quedará en serie  con la luminaria de leds, lo cual en muchos caso sera suficiente para que este conjunto resistencia-neón  deje pasar la suficiente corriente  para que se ilumine levemente la luminaria.

Por  tanto si deseamos eliminar este efecto residual bastará eliminar el testigo de neón del interruptor ( suelen ir separados del interruptor  y enchufables para sustituirlo fácilmente en caso de que se fundan) 

Pero ¿Y si no desea eliminar el testigo del interruptor?  pues para eliminar la luminosidad residual en las lámparas a leds podemos aprovechar dos factores:

  • Que  la corriente que atraviesa el circuito es muy baja.
  • Que es necesario superar un umbral de tensión para que los leds se enciendan , umbral  que dependerá de como esten conectados en la luminaria (  más alto si los leds están conectados en serie).

¿Y como lo logramos ? pues  lo que tenemos que hacer es conectar en paralelo con   la luminaria una resistencia de  1Mohmio  para lograr que la caída de tensión sobre la lámpara, cuando esta se encuentra apagada, sea más baja de la tensión de umbral citada.

Naturalmente, debido a que existen numerosos tipos de lámparas, será necesario probar experimentalmente el valor justo.

Podemos empezar con un valor muy alto, por ejemplo 1Mohms , lo cual dará una corriente de I=V/R =220/1.000.000 =0,00022 ( es decir 2.2mA  ) ,   que en  potencia disipada seria =I^2 x R = 0,00022*0,00022*100000= 0.0484W , lo cual es asumible con una simple resistencia de 1/4W)

Si no logramos que los leds se apaguen puede ir bajando de forma  muy conservadora este valor pues a medida  que disminuya este valor la corriente y la potencia disipada por esta resistencia serán mayores

Como referencia , como tope de valores podemos estar en 1/4 de Watt con valores por encima de 330K con 220V y 100K con 110V. 

 

Por cierto,  hay personas  que precisamente buscan potenciar   el fenómeno de la luz residual de los leds   por ejemplo, conectando una resistencia de algunos K en paralelo con los interruptores de alimentación de 12V en modo tal que quede una débil luz en el ambiente para permitir de ver cuando todas las luces están apagadas. Es un sistema realmente cómodo. 

Solución con rele 

Tal y como hemos hablado con las lamparas de sobremesa , muchas veces el problema se debe a que los interruptores no cortan por completo los dos hilos ( fase  y neutro ) de la instalación ya que suelen ser monopolares . Ademas  para empeorar al situación en algunas y instalaciones esta conectado el neutro en lugar de la fase al interruptor (o incluso hay instalaciones con fase y fase en lugar de fase o neutro como debería  ser )

 

En este caso no podemos hacer casi nada sino buscar un sistema que haga que ese resto de corriente no llegue a la luminaria provocando ese resplandor residual, para lo cual podemos optar por «un cortador de luz.» , es decir un «relé»o contacto que actúe cortando eléctricamente los dos hilos que llegan a la lámpara   y de esta manera impidiendo la llegada de tensión por ambos hilos simultáneamente.

El proceso consiste en separar ligeramente la luminaria del techo y colocar el «relé» entre los cables que llegan a la luminaria . De esta forma y una vez colocado de nuevo, cuando accionamos el pulsador de la luz sólo oiremos un muy ligero chasquido (es imperceptible) que nos indica que la corriente ha sido totalmente cortada y por lo tanto no llega residuo alguno que provoque el pequeño resplandor.

 

 

 

 

Solución  dudosa con condensador

Por último hay personas que optan   por conectar  un condensador  de .47uf en paralelo con lo podriamos llamarlo polos de la lampara, asi este absorbe la corriente residual y antes de completar su carga se descarga por el cambio de ciclo,

Es  una solución interesante aunque podría  tener un problema: la reactancia del capacitor es Xc = 1 / (2 * Pi * f * C ) = 1 / (2 * 3,14 * 50 * 0,00000047) = 6772 ohms. Por lo tanto, la potencia disipada por el capacitor será P = V * V / R = 7,15 Watts. Es decir, tendríamos un consumo extra de 7 Watts que se pierde en el condensador

 

 

Por cierto este efecto  al igual que no les afecta a todas las instalaciones   tampoco les afecta por igual  a todos las luminarias  dependiendo muchas veces del fabricante y  modelo para manifestarse o no este efecto cuanto menos indeseado