Capacimetro con Arduino

Aquí os dejo un capacímetro hecho con tan solo una resistencia de 3K ohmios y el arduino.
El siguiente programa está probado en un arduino duemilanove y nos permite saber con un margen de error del 5% la capacidad de un condensador de entre 10.000uF a 0,1uF.

/*
CAPACIMETRO
-----------

DESCRIPCIÓN

- Este programa permite medir la capacidad de condensadores de entre 0,1 uF a más de 10000 uF con un margen de error de 5%.
- Los resultados de las lecturas de los condensadores, se muestran por el puerto serie.
- Los condensadores a medir tienen que ser de al menos 5v.
- Los condensadores a medir tienen que estar completamente descargados o al menos, tienen que estar por debajo de los 5v. De lo contrario, podemos romper el Arduino.

PLATAFORMA

- Este programa a sido probado en un arduino duemilanove.

FUNCIONAMIENTO TEÓRICO DEL PROGRAMA

El siguiente programa mide el tiempo que tarda en cargarse un condensador a través de una resistencia de 3K Ohmios, para determinar la capacidad.
Lo primero que hace el programa es comprobar si el condensador tiene carga eléctrica. Si la tiene, el pin 2 digital se pone en modo 0 lógico y permite que el condensador de descargue completamente.
Cuando el programa detecta que el condensador tiene un voltaje de 0 voltios, pone la salida digital 2 a 1 lógico y alimenta el condensador a través de una resistencia de 3.000 ohmios.
En el mismo momento en el que el programa pone a 1 lógico la salida 2 que permite cargar el condensador, el programa comienza a contar el tiempo.
Cuando la tensión alcanzada en los terminales del condensador alcanza el 63,2% del voltaje de alimentación, el programa para de contar el tiempo y pone la salida 2 a 0 lógico, repitiéndose nuevamente el ciclo de descarga y vuelta a cargar.
El ciclo de carga y descarga se repite cíclicamente y cada vez que se a completado un ciclo, el programa muestra por el puerto serie el resultado de la lectura de capacidad del condensador.

La tensión de alimentación de carga es la de pin digital 2, es decir 5v. 
La tensión de alimentación solo puede llegar al 63,2%, por que hasta esa tensión de la tensión de alimentación, la carga de un condensador es relativamente lineal y es más fácil de calcular la capacidad de un condensador de esta manera.

CONEXIONADO

Se coloca una resistencia de 3000 ohmios en la salida 2 digital al pin 0 analógico y del pin 0 analógico se conectaría el condensador a medir.
El condensador a medir se tendría que conectar del pin 0 analógico a la masa. 
Si se quieren ver los procesos de carga y descarga, solo hay que conectar del pin 2 digital al ánodo de un diodo led y del cátodo del LED a masa, a través de una resistencia de 220 Ohmios.

NOTAS IMPORTANTES
-----------------

- Los condensadores tienen que estar completamente descargados, si están cargados por encima de los 5v, podemos romper el arduino. Sería recomendable poner un diodo zener entre masa y el pin 0 analógico para evitar en lo posible dañar el arduino. La tensión del diodo zener, sería de entre 4 a 5v y de una potencia lo más alta posible.
- El tiempo que tarda en mostrar la lectura dependerá de la capacidad del condensador, es decir que un condensador de 1000 uF tardará unos 10 segundos y un condensador de un 1uF tardará 1000 veces menos.
- Este programa a sido probado y se a comprobado su correcto funcionamiento en la práctica.


<<<< CUIDADO CON LOS CONDENSADORES CARGADOS, UN CONDENSADOR CARGADO CON CIENTOS DE VOLTIOS ES POTENCIALMENTE PELIGROSO, SI VA A MEDIR CONDENSADORES DE VOLTAJES ALTOS, COMPRUEBE CON UN POLÍMETRO QUE ESTÁN DESCARGADOS ANTES DE MANIPULARLOS >>>>
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

AUTOR: Mario R.P - mariorp@terra.es - 13-6-2012


 */

long sensorValue; // Variable que contendrá la tensión medida en el pin analógico 0.
long carga=0; // 0 = descargar 1 = cargando - Esta variable es una variable interna del programa y es la que establece si se empieza a cargar o descargar el condensador.
long tiempocomienzocarga; // Esta variable contiene el tiempo en microsegundos en el que se empezó a cargar el condensador.
float tiempofincarga; // Este variable es la que contiene el tiempo en la que se finalizó la carga del condensador.
void setup() {                
  
  pinMode(2, OUTPUT);  // Se establece el pin 2 digital, como pin de salida de datos
  pinMode(A0, INPUT); // Se establece que el pin 0 analógico es un pin de entrada de datos 
  digitalWrite(2, LOW);   // Se pone el pin digital 2 a 0 lógico
  Serial.begin(9600); // se establece a 9600bps la comunicación por el puerto serie
  Serial.println("CAPACIMETRO"); // Muestra por el puerto serie el mensaje CAPACIMETRO
  Serial.println("-----------");  // Muestra por el puerto serie el mensaje ----------------- en otra linea de texto
  Serial.println(" "); // Muestra un espacio en blanco.
}

void loop() {
  
  sensorValue = analogRead(A0); // Se asigna a la variable "sensorValue" la tensión leída por el puerto serie
  
  if(sensorValue==0 && carga==0) // Si la tensión del condensador es igual a 0v y la variable "carga" = 0, comienza la carga del condensador y se inicia el conteo de tiempo
  {
  digitalWrite(2, HIGH); //La salida digital 2 pasa a 1 lógico y comienza a cargar el condensador
  tiempocomienzocarga=micros(); //Se almacena el tiempo en el que se empezó a cargar el condensador en la variable "tiempocomienzocarga" usando la variable de sistema micros, que es una variable de sistema que devuelve el tiempo en microsegundos que lleva el arduino encendido
  carga=1; // la variable carga pasa a estado 1
  }


  if(sensorValue>=647 && carga==1) // si la tensión en el condensador a llegado al 63,2% y variable carga es igual a 1, se detiene la carga y se calcula en base al tiempo, la capacidad del condensador
  {
  tiempofincarga=micros()-tiempocomienzocarga; // La variable "tiempofincarga" es el resultado de restar el tiempo de inicio de carga, con el de fin
  Serial.println(" "); // Se imprime por el puerto serie el valor calculado de la capacidad del condensador
  Serial.print("Capacidad uF:");
  Serial.print((tiempofincarga/3350)-0.04);  // aquí se hace el cálculo definitivo, en base al tiempo de carga.
  digitalWrite(2, LOW); //La salida lógica 2 se pone a 0 lógico y comienza la descarga del condensador.
  carga=0; // la variable carga se pone a 0 lógico.
  }
  
  
}

Yo hace tiempo probé otro código ( http://arduino.cc/en/Tutorial/CapacitanceMeter ), muy parecido al tuyo, y me daba un margen de error mucho más grande del 5%, sobre todo contra más pequeño era el condensador :relaxed:

La otra parte que no me gusto es que se haga la descarga por un pin del arduino, ya que con un transistor o un MOSFET se podría descargar sin poner en peligro el micro.

Un saludo!

La carga y descarga del condensador se hace a través de una resistencia de 3000 ohmios. Si aplicamos la ley de ohm, la intensidad que circula por el pin no supera nunca los 1,7 mA. No creo que sea peligrosa una intensidad tan baja para el pin que hace las funciones de carga y descarga.

Con respecto al enlace que has puesto, no lo había visto, le echaré un ojo a ver que tal.

Si quieres mejorar la precision, lo que se puede hacer es medir varios ciclos de carga y descarga. Es decir, mides el tiempo que tarda en cargar, inviertes y mides el tiempo que tarda en descargar y lo repites varias iteraciones.

El error se da por que se trata el tiempo de carga de un condensador, como si fuese algo lineal y no lo es. La carga de un condensador se corresponde a una curva poco pronunciada, pero aunque no sea pronunciada, sigue siendo una curva y por eso da errores de lectura. En mi programa la lectura se repite continuamente y los valores son siempre similares. El error no es tanto por una cuestión de tomar barias muestras, si no por una cuestión matemática.

La descarga no es peligrosa, pero como tu adviertes si pruebas un condensador que tenga una carga superior a 5V y empieza la descarga por un pin de arduino no creo que sobreviva el micro.

Yo simplemente hacia un critica constructiva :slight_smile:

Sí, en el supuesto de que el condensador esté cargado a más de 5v podría ser peligroso para el arduino, por eso recomiendo poner entre masa y el pin 0 analógico un diodo zener de algo menos de 5v, para que en caso sobre tensión se cortocircuite por el zener. Pero de todos modos, la mayoría de capacímetros tiene ese problema, que si se miden cargados corren peligro de romperse, aunque se ponga un zener, sobre todo si hablamos de condensadores cargados a cientos de voltios, el Zener no va a aguantar un chispazo como dios manda.

Y por supuesto se que tú comentario es constructivo, no me lo he tomado de otra manera. XD

A ver, a ver si me aclaro. ¿Como es posible tener una tensión mayor en el condensador si la carga se hace con un pin del AVR y el circuito RC no es un charge pump?

@fm si el condensador por cualquier cosa esta cargado antes de probarlo por ejemplo a 12V no podría quemar el micro al hacer la descarga internamente por un pin.

Si podría pero es muy improbable que se ponga uno a desenchufar condensadores cargados y conectarlos para medirlos.

¿Que sucederia si pusiesemos un condensador sin polaridad cargado? Pues si lo conectas al revés, saldrian chispas hacia la masa del controlador.

lm386:
El error se da por que se trata el tiempo de carga de un condensador, como si fuese algo lineal y no lo es. La carga de un condensador se corresponde a una curva poco pronunciada, pero aunque no sea pronunciada, sigue siendo una curva y por eso da errores de lectura.

No entiendo esto muy bien. La ecuación matemática sale totalmente lineal. Has elegido un 63,2% de la tensión final de modo que operando sobre la ecuación de carga el ln es 1 y por tanto queda que C = t / R. Es totalmente lineal aunque la carga del condensador no lo sea. Si existe un error del 5% tiene que ser debido a otros factores.

Bueno pues nada, se me a ocurrido probar una serie de condensadores electrolíticos del mismo fabricante y estos son los resultados que he conseguido con el programa que hice, que es el que está al principio del hilo.

Valor Medido %Error

0.1uF .................= 0.1uF................. 0%
1uF ...................= 1,02uF................ 2%
4,7uF .................= 4,83uF............... 3%
10uF ..................= 10,56uF.............. 5,6%
22uF ..................= 21,5uF...............-2,3%
47uF ..................= 48,7uF............... 3,6%
100uF .................= 113,4uF............. 13,4% <<<< Una burrada <<<
220uF .................= 223,2uF............. 1,5%
470uF .................= 500uF................ 6,4%
1000uF ...............= 1009uF............... 0.9%

Valor = Es el valor marcado en el condensador.
Medido = Es el valor medido por el programa del arduino.
%Error = Es el porcentaje de error, entre la capacidad medida y la que figura escrita en el condensador.

Con estos resultados no se que pensar. Los condensadores son nuevos, son del mismo fabricante (uno chino) y probando condensadores de misma capacidad me dan los mismos resultados, así que no es que unos tengan algo más o menos de capacidad. El error debe de estar en el programa, pero en los condensadores de 100uF me da un error del 13%, que es una salvajada, sin embargo, el resto de mediciones más o menos tiene errores relativamente tolerables.

No veo una linealidad en los errores, así que esto debe de ser algo más complejo de lo que parece.

Lo que estas viendo es la tolerancia que tienen los condensadores, algunos son hasta del 20%!

fm:
Lo que estas viendo es la tolerancia que tienen los condensadores, algunos son hasta del 20%!

Pues tienes razón, he mirado por Internet y sí, las tolerancias típicas suelen llegar al 20%.

Muchas gracias por la info, pensaba que las tolerancias de los condensadores serían de menos del 5%, pero no, es mucho más.

Un saludo.

Un par de cosas. La ecuación para calcular la capacidad del condensador pones

(tiempofincarga/3350)-0.04

pero matemáticamente debería ser el tiempo de carga dividido por la resistencia. ¿Por qué has puesto esa otra? ¿Cómo has llegado a esa ecuación? ¿Es algo que has hecho de forma empírica?

Y una última cosa. El programa es sencillo pero a la vez lo veo muy práctico. Tanto es así que podías ampliarlo para calcular valores de condensadores más pequeños. En el programa que puedas seleccionar entre la resistencia de 3K u otra de por ejemplo 100K (no sé si la impedancia de las entradas de Arduino permitiría valores más altos para la resistencia).

Cheyenne:
Un par de cosas. La ecuación para calcular la capacidad del condensador pones

(tiempofincarga/3350)-0.04

pero matemáticamente debería ser el tiempo de carga dividido por la resistencia. ¿Por qué has puesto esa otra? ¿Cómo has llegado a esa ecuación? ¿Es algo que has hecho de forma empírica?

Y una última cosa. El programa es sencillo pero a la vez lo veo muy práctico. Tanto es así que podías ampliarlo para calcular valores de condensadores más pequeños. En el programa que puedas seleccionar entre la resistencia de 3K u otra de por ejemplo 100K (no sé si la impedancia de las entradas de Arduino permitiría valores más altos para la resistencia).

3350 fue a base de probar. En realidad tendría que ser 3000, que es la resistencia de carga del condensador, pero como los resultados que me daba no coincidían por el tema de las tolerancias tan altas de los condensadores, lo ajusté hasta que cuadrasen las medidas leídas. -0.04 es una lectura que me daba el programa en vacío, es decir, sin conectar ningún condensador, así que se me ocurrió rectar ese valor de 0,04uF. No se si será que los 40 nanofaradios es por algún error en el programa, es por que las pistas de la protoboard hacen de condensador o es por algún tema interno del arduino.

Con respecto a poner resistencias mucho más altas no hay problema teóricamente, pero lo tengo que probar. El programa en principio lo hice únicamente con fines educativos.

La verdad que con el arduino se puede hacer un polímetro bastante práctico y barato. Por supuesto con limitaciones.

Ni que decir tiene que se admiten mejoras al programa que hice. Si alguien ve como mejorarlo, aumentando el rango de lecturas o implementándole otras funciones, pues por supuesto bien venido sea. Eso sí, ruego que se prueba antes de colgar el código aquí y que se comente de la forma más exhaustiva posible, el código incluido o modificado.

Es diferencia entre el valor teórico y el valor que has medido viene determinado por:

  • el tiempo que tarda el AVR en invocar a la rutina para leer el tiempo.
  • el tiempo que tarda el código digitalWrite hasta que realmente se pone el pin a 1 o a 0.
  • error de cuantización del contador de micros. Es decir, tu mejor resolución es 1 micro segundo.
    Por otro lado, las rutinas digitalWrite y microseconds son deterministas, e.d. constantes. Por eso puedes añadir ese offset, que realmente debería ser un offset en vez de una constante por la que multiplicas.

Resumiendo:

  1. cuando la constante RC sea inferior a 1us o de unos poco microsegundos, el error será mayúsculo.
  2. tendrías que calibrar cuanto tiempo se tarda, desde que invocas a microseconds y se pone el pin a 1 y restar este valor al tiempo que estás midiendo a modo de offset.

@lm386, ese sistema de ajuste de valores es muy bueno para ti pero puede ser muy malo para cualquier otro que vaya a utilizar el código ya que has fijado unos ajustes para tu resistencia y tu Arduino. Lo importante es conseguir precisión independientemente del usuario y los elementos que utilice, bien porque se consigue con el código reducir los errores o bien porque se establece una subrrutina de calibración que cada usuario puede hacer. No lo he pensado mucho así que no sé si para este caso hay alguna forma.

Cheyenne:
@lm386, ese sistema de ajuste de valores es muy bueno para ti pero puede ser muy malo para cualquier otro que vaya a utilizar el código ya que has fijado unos ajustes para tu resistencia y tu Arduino. Lo importante es conseguir precisión independientemente del usuario y los elementos que utilice, bien porque se consigue con el código reducir los errores o bien porque se establece una subrrutina de calibración que cada usuario puede hacer. No lo he pensado mucho así que no sé si para este caso hay alguna forma.

La única forma que se me ocurre, es modificar el programa para que pueda auto calibrarse usando la capacidad de un condensador conocido, pero eso supone hacer más complejo el código y más difícil de entender para el que quiera entender como funciona el programa. Aunque es una idea totalmente razonable la que propones, creo que con que cada uno modifique la cifra hasta conseguir una lectura correcta, de un condensador de capacidad conocida, es suficiente por el momento.

Este programa posiblemente lo termine ampliando y mejorando, pero como lo hago como simple hobbye, no se para cuando estará. Hice pruebas con condensadores de mucha menos capacidad y en condensadores de cientos de pico faradios las lecturas son correctas. Pero bajando de los 100 picofaradios se producen errores monumentales, posiblemente por que las entradas del arduino tengan algún tipo de condensador entre sus patillas o a nivel interno dentro del propio chip o yo que se, lo mismo las pitas también hacen de condensador.

De todas formas si los condensadores los fa rican con un 20% de precisión de su capacidad y teniendo en cuenta que en la gran mayoría de sus usos no se necesitan valores más exactos creo que tu programa cumple muy bien su finalidad.