lunes, 23 de diciembre de 2013

Monitorizar batería LiPo con Arduino

Trasteando con mi nuevo proyecto me surgió la “problemática” de poder controlar el estado de la batería lipo de 2 celdas que utiliza.

Voy a hacer una pequeña introducción para refrescar conocimientos, para los que los tengáis frescos saltaros esto.
Estas baterías se usan mucho en modelísmo y tienen una fama regular por su inestabilidad si se las trata mal (descargas totales, exposición a altas temperaturas,...). Yo tengo que decir que en todas las pruebas que he realizado y en el tiempo que llevo trasteando con ellas no he tenido ningún problema siempre que se las cuide un poco.

El uso de este tipo de batería es muy atractivo para nuestros proyectos, debido al pequeño tamaño y a la intensidad que pueden llegar a entregar.
Una batería LiPo sencilla entrega 3,7 voltios (un pelin escaso en un proyecto normal con Arduino) por lo tanto tendremos que usar por lo menos una de doble celda o 2S. ¿Que es esto? pues dos baterías sencillas conectadas en serie, por lo tanto una 2S entregara 7,4V.
Esquema 1
 Para su buena conservación la tensión de cada celda no debe de bajar de los 3,3V. Pero como están en serie puede descargarse mas una de las celdas. Para controlar esto traen un terminal intermedio (conector RC desde el que se cargan) que es en donde tenemos que monitorizar el estado de dichas celdas.


Existen soluciones comerciales que nos avisaran de cuando una de las celdas bajo de los 3,3V. Si no te apetece trastear es una buena solución los venden en ebay muy baratos.


Empezando a Trastear:


Antes de empezar tenemos que tener claro que vamos a utilizar voltajes que mal usados podrían llegar a dañar nuestra placa Arduino.  
Para poder medir la tensión de las celdas vamos a usar 2 de las entradas analógicas de nuestro Arduino.
Del conector RC usaremos las conexiones de 3,7v y 7,4v (roja y amarilla del esquema 1), los positivos de las celdas , la masa no la tendremos que conectar a la masa del Arduino ya que es la misma que lo alimenta.
Primer problema!! las entadas analógicas miden de 0 a 5V para la primera celda no hay problema ¿pero para la de 7,4v? Solución, un maravilloso divisor resistivo!!!. Colocaremos 2 resistencias del mismo valor 1k en serie entre la masa y los 7,4v y si medimos entre las dos resistencias tendremos la mitad de la tensión (3,7) la cual si lo podremos medir con la entrada analógica.  
Esquema 2
Ya tenemos el montaje del circuito y ahora toca la programación. Antes de ponernos a entender el código (que tampoco es que sea nada difícil...) hay que saber como nos muestra Arduino las medidas analógicas.
Nos devolverá 1023 cuando tengamos 5 voltios y 0 cuando tengamos 0 voltios por lo tanto si queremos saber que voltios tenemos solo tendremos que hacer una regla de tres (Medida*5)/1023.

Como se puede ver en el esquema 1 el valor que nos da la celda 2 es la suma de la celda 1 y la celda 2. Para calcular la tensión de la segunda celda tendremos que multiplicarla por 2 (debido a que el divisor resistivo divide la tensión a la mitad) y a esto restarle el valor de la primera celda ValorCelda2=(Celda2*2)-Celda1.


Bueno pues aclarado esto analicemos el código:


#define PinCelda1 A0
#define PinCelda2 A1

int Celda1 = 0;
int Celda2 = 0;
float VoltiosCelda1=0;
float VoltiosCelda2=0;

void setup()
{
  Serial.begin(9600);
}


void loop()
{
  // Lee y guarda en las variables
  Celda1 = analogRead(PinCelda1);  
  Celda2 = analogRead(PinCelda2);

  // Calcular el valor de la celda 2
  Celda2=(Celda2*2)-Celda1;

  // Pasa la lectura a voltios
  // si no se pone .0 elimina decimales
  VoltiosCelda1=(Celda1*5)/1023.0;
  VoltiosCelda2=(Celda2*5)/1023.0; 
  
  // Muestra los resultados
  Serial.print("S1 = ");
  Serial.print(VoltiosCelda1);
  Serial.print("V --- S2 = ");
  Serial.print(VoltiosCelda2);
  Serial.print("V ------ ");
  Serial.print(Celda1);
  Serial.print(" - ");
  Serial.println(Celda2);
  
  // Para el flujo durante medio segundo
  delay(500);
}

Hay que tener precaución de desconectar las resistencias del conector RC cuando terminemos de usar nuestro proyecto ya que a través del divisor resistivo poco a poco nos puede descargar la batería.


Basado en este código he preparado una librería que facilita su uso en nuestros proyectos:


#include <LiPo.h>

#define PinCelda1 A3
#define PinCelda2 A4
#define PinSalida 13

LiPo Bateria(PinCelda1,PinCelda2,PinSalida);

void setup(){
  Serial.begin(9600);
}

void loop(){
  if(Bateria.Comprueba()){
    Serial.println("Bateria BAJA");
  }
  Serial.print(Bateria.TensionCelda1());
  Serial.print(" - ");
  Serial.println(Bateria.TensionCelda2());
  delay(1000);
}

Cuando ejecutemos Bateria.Comprueba()  nos entregara un false si esta dentro de los parámetros y un true si la batería esta baja y pondrá a HIGH el PinSalida para poder encender un led o controlar un circuito que detenga el funcionamiento del proyecto.
Se puede poner en el PinSalida un circuito con un inversor y un diodo led bicolor para que nos indique el estado, por ejemplo de un color verde y cambiando a rojo cuando la batería este baja.

En otra entrada colgare una librería para ejecutar código cada X tiempo sin detener el flujo del loop().
La ventaja de esto es que nuestro programa continuara un su normal ejecución y por ejemplo cada minuto comprobara el estado de la batería.

Bueno pues a trastear!!!


Temporizar la ejecuciones sin detener el flujo de loop()

En algunos proyectos he necesitado optimizar la lectura de sensores (por consumo de batería u otros motivos) y no medir en cada vuelta de loop(), pero que otros sensores si midieran en cada vuelta de loop.

Por ejemplo que cada 1 minuto leyera "sensor A" pero que cada 2 mida el "sensor B".

Se podría hacer con delay() y contadores de vueltas, pero el código se vuelve difícil de leer.
La solución es crear una variable global cargada con el resultado de millis() y hacer
comparaciones de esta sumándole el tiempo que quiero que tarde en ejecutarse.
Hay que tener en cuenta dos cosas:

  1. Que este resultado no es preciso si hay algún delay que bloque el flujo del loop.
  2. Que millis() devuelve el tiempo en milisegundos transcurridos desde que se arranco la placa Arduino con el programa actual. Este número de desbordará (volverá a cero), después de aproximadamente 50 días.
Bueno pues vamos a ver el código:

unsigned long Crono=0;
// Tiempo de espera para la ejecucion
unsigned int Tiemp=5000; // en milisegundo = 5 segundos

void setup(){
  Serial.begin(9600);
}

void loop(){
  if (( Crono+Tiemp)<millis()) {
    Serial.println("Crono 1");
    Crono=millis();
  }
}

Una vez entendido el funcionamiento os cuelgo la librería y el ejemplo que viene con ella:

#include <Cronos.h>

Cronos M1(1000); // este temporizador se ejecutara cada 1 segundo
Cronos M2(5000);   // este temporizador se ejecutara cada 5 segundos

void setup(){
  Serial.begin(9600);
}

void loop(){
  if(M1.Estado()){Serial.println("Crono 1");}
  if(M2.Estado()){Serial.println("Crono 2");}
}

Pondremos un if() evaluando el resultado de  Estado().  Estado() devuelve un false cuando no se ha cumplido el tiempo y un true cuando se cumplió reiniciando el crono. 

sábado, 21 de diciembre de 2013

Empezando a Trastear

Desde hace muchos años me fascinaban los temas de robótica e hice alguna pequeña incursión. Aunque tengo ciertos conocimientos de electrónica, me resultaba complejo llevar acabo ciertos proyectos... hasta que descubrí Arduino y su filosofía.
Llevo unos meses trasteando con las placas y cada vez estoy mas entusiasmado con las posibilidades que ofrece.
He pasado muchas horas leyendo en Internet y buscando información para hacer realidad mis ideas y poderlas plasmar en los proyectos. Hay muchas cosas que estoy haciendo que no las he encontrado de una manera “sencilla” y a raíz de esto nació la idea de poder compartir esta información de una manera “fácil” para gente como yo que estas empezando.

Bueno pues a TRASTEAR!!!