Avançar para o conteúdo principal

Capacímetro controlado por uC

Como medir a capacidade de um condensador usando um micro-controlador?

Os micro-controladores são verdadeiros canivetes suíços. São muito versáteis e para o provar decidi mostrar-vos como é fácil construir um capacímetro usando um micro controlador. Neste exemplo usei um Arduíno nano, mas pode ser usado qualquer micro controlador com duas ou mais saídas digitais e um conversor A/D.
O princípio de funcionamento é simples e baseado na constante de tempo de um circuito RC. Essa constante de tempo denomina-se tau, e é igual ao produto da resistência em ohms pela capacidade em Farads. É o tempo que decorre entre o estabelecimento do circuito e o momento em que a tensão aos terminais do condensador atinge 63,2% da tensão aplicada ao circuito. 

Resultado de imagem para tau capacitors
Fig.1 Circuito RC - Carga de um condensador
Ora se um micro-controlador consegue medir tensões através do seus portos analógicos e dos seus conversores A/D, se também consegue medir tempos através dos seus temporizadores, ou timers se preferir, então basta construir um circuito de carga muito simples, com uma resistência de valor conhecido, a carregar um condensador de valor desconhecido. Mede-se então o tempo que demora o condensador a atingir 63,2% da tensão aplicada ao circuito. Esse valor de tempo é a constante de tempo do circuito RC, conhecida como tau. O valor desse condensador pode ser determinado facilmente pela fórmula C=tau/R. Necessitamos de ter a certeza que o condensador está descarregado no início da medição, descarga essa que é conseguida com uma segunda resistência ligada entre o condensador e um pino de saída do micro-controlador como mostra a figura 2

Fig.2 Circuito de carga e descarga do condensador
Quando se coloca esse pino a zero, igual ao potencial de massa, o condensador descarrega-se através dessa resistência de descarga, cujo valor deve ser calculado para que não se ultrapasse a corrente máxima permitida nesse pino do uC. O condensador está descarregado quando a tensão aos seus terminais é zero, o que pode ser verificado com a mesma entrada analógica do uC que é usada para verificar a tensão no processo de carga. Vamos então ver quais os passos necessários:

Algoritmo do programa de medição da capacidade de um condensador:
  1. Descarregar o condensador;
  2. Colocar o pino de descarga em modo de entrada, para garantir alta impedância e não influenciar o processo de carga.
  3. Inicia o processo de carga, pondo o pino usado para a carga do condensador no nível lógico 1;
  4. Inicia contagem de tempo;
  5. Usando uma porta analógica (ADC) ligada ao condensador, verifica se a tensão aos seus terminais atingiu 63.2 % da tensão aplicada ao circuito de carga. Continua a fazer leituras até atingir esse valor de 63,2% da tensão aplicada.
  6. Quando o condensador atingir 63,2 % da carga, paramos a contagem de tempo e calculamos a diferença entre o tempo actual e o tempo de inicio da carga. Ficamos com a constante de tempo, conhecida como tau.
  7. Como a constante de tempo tau é igual a R * C, então C= tau/R . Ao dividir o tempo de carga em segundos, pela resistência em ohms, ficamos com a capacidade em Farads.
  8. Como a unidade Farad é muito grande, convertemos para uF ou nF, o que for mais conveniente.
  9. apresentamos o valor
  10. Descarregamos o condensador novamente.
Na minha implementação deste algoritmo, acrescentei dois LEDs, um verde outro vermelho, que sinalizam as etapas de carga e descarga do condensador. Não são verdadeiramente necessários, mas podem ser úteis para depuração do programa. Se o programa "encravar" podemos ter uma ideia do ponto onde se encontra o problema.

Vamos então falar um pouco sobre esta implementação do algoritmo:
Nas linhas abaixo, começamos por definir os pinos usados, e associamos nomes para nos facilitar o trabalho. Usamos o porto analógico A0 para medir a tensão no condensador, O porto digital 13 para carregar o condensador e o porto digital 11 para o descarregar. Os portos digitais 3 e 4 são usados para comandar os dois LEDs que assinalam a carga e a descarga do condensador.

#define analogPin      A0
#define chargePin      13
#define dischargePin   11
#define chargeLed      3
#define dischargeLed   4
#define resistorValue  10000.0F

O coração do programa está no cálculo do tau, a constante de tempo. Na função abaixo está o código que nos permite fazer esse cálculo. 

unsigned long chargetime() {  //Carrega o condensador e mede o tempo de carga
  unsigned long elapsedTime, startTime;
  digitalWrite(chargeLed, HIGH);  // sinaliza a carga do condensador
  digitalWrite(chargePin, HIGH);  // Inicia a carga
  startTime = millis();           // Começa a contar o tempo
  while (analogRead(analogPin) < 647) {  // 647 = 63.2% de 1023 
  }
  elapsedTime = millis() - startTime; //calcula o tempo que passou desde o inicio da carga
  digitalWrite(chargeLed, LOW);    // desliga o LED de Carga
  return (elapsedTime); // devolve valor de tau
}

Apresento seguidamente a listagem completa do programa. É uma adaptação do código original que pode ser consultada aqui:

// Baseado no programa original RCTiming_capacitance_meter de Paul Badger 2008
// Adaptado por Luís Sousa 2020

#define analogPin      A0         // analog pin for measuring capacitor voltage
#define chargePin      13         // pin to charge the capacitor - connected to one end of the charging resistor
#define dischargePin   11         // pin to discharge the capacitor
#define chargeLed      3          // pin conected to charge LED
#define dischargeLed   4          // pin conected to charge LED
#define resistorValue  10000.0F   // change this to whatever resistor value you are using
// F formatter tells compliler it's a floating point value

unsigned long ct;
float uF;                // floating point variable to preserve precision, make calculations
float nF;
float pF;

void testLED(int led) {
  digitalWrite(led, HIGH);//lamp test
  delay(500);
  digitalWrite(led, LOW);
  return (0);
}

unsigned long chargetime() {  //Carrega o condensador e mede o tempo de carga
  unsigned long elapsedTime, startTime;
  digitalWrite(chargeLed, HIGH);  // sinaliza a carga do condensador
  digitalWrite(chargePin, HIGH);  // Inicia a carga
  startTime = millis();           // Começa a contar o tempo
  while (analogRead(analogPin) < 647) {     // 647 is 63.2% of 1023, which corresponds to full-scale voltage
  }
  elapsedTime = millis() - startTime;
  digitalWrite(chargeLed, LOW);    // desliga o Led de Carga
  return (elapsedTime);
}

void discharge() {
  /* dicharge the capacitor  */
  digitalWrite(dischargeLed, HIGH);         // sinaliza a descarga
  digitalWrite(chargePin, LOW);             // desliga o pin de carga do condensador
  pinMode(dischargePin, OUTPUT);            //
  digitalWrite(dischargePin, LOW);          // põe pino de descarga a 0V (descarrega)
  while (analogRead(analogPin) > 0) {       // espera ate o condensador estar descarregado (0V)
  }
  digitalWrite(dischargeLed, LOW);         // desliga LED de Descarga
  pinMode(dischargePin, INPUT);            // Poe pino de descarga em alta impedancia
  return 0;
}

void setup() {
  pinMode(chargePin, OUTPUT);     // set chargePin to output
  pinMode(chargeLed, OUTPUT);     // set chargeLed to output
  pinMode(dischargePin, INPUT);   // Poe pino de descarga em alta impedancia
  pinMode(dischargeLed, OUTPUT);  // set dischargeLed to output
  digitalWrite(chargePin, LOW);
  testLED(chargeLed);
  testLED(dischargeLed);
  //testLED(LED_BUILTIN);
  Serial.begin(9600);             
}

void loop() {
  discharge(); //Começa por descarregar o condensador
  ct = chargetime();
  uF = ((float) ct / resistorValue) * 1000; //carrega e mede o tempo de carga
  Serial.print(ct);       // mostra tempo de carga no serial port
  Serial.print(" mS    ");
  if (uF > 1) {
    Serial.print((long)uF);       // mostra o valor no serial port
    Serial.println(" uF");
  }
  else
  {
    // para valores inferiores a 1 microFarad, convertemos para nF (10^-9 Farad).
    // This is  a workaround because Serial.print will not print floats
    nF = uF * 1000.0;      // multiply by 1000 to convert to nF (10^-9 Farads)
    Serial.print((long)nF);         // print the value to serial port
    Serial.println(" nF");          // print units and carriage return
  }
}

Fig. 4 - Apresentação de resultados

As ligações elétricas são muito simples:
  • Liga-se o condensador em teste, entre o Pino A0(+) e a massa(-) ;
  • Liga-se a resistência de carga (10K) entre o pino D13 e A0;
  • Liga-se a resistência de descarga entre o pino D11 e A0;
  • Liga-se o pino D3 ao ânodo do LED Verde;
  • Liga-se o pino D4 ao ânodo do LED Vermelho;
  • Os cátodos dos LEDs ligam à massa através de resistência de 330 ohm
Fig. 3 Circuito montado numa pequena breadboard
Gama de utilização: Com uma resistência de carga de 10K ohm, não devemos confiar nas leituras abaixo de 1uF. Como o tempo mínimo que conseguimos medir com a instrução millis() é 1ms, para medir condensadores mais pequenos, deverá ser usada uma resistência de carga de valor superior (não esquecer de alterar no programa o valor de R). Podemos ainda se for necessário, alterar o programa para fazer as contas em microsegundos usando a instrução micros() e ajustando os cálculos. 
A partir daqui é convosco. Divirtam-se

Comentários

Mensagens populares deste blogue

Apresentação da Placa Freedom FRDM-KL25Z

Olá a todos! O artigo de hoje é dedicado aos adeptos dos micro-controladores e suas plataformas de avaliação e desenvolvimento. Estas placas são úteis para prototipagem rápida de aplicações baseadas em micro-controladores.  Vamos hoje falar da placa Freedom FRDM-KL25Z. Com um custo na ordem dos 20€, esta placa usa um micro-controlador Kinetics da série L, de 32 bits, mais propriamente o KL25Z128VLK, baseado no ARM® Cortex™-M0+. Com uma frequência de relógio que chega aos 48MHz, 128K de flash e muitos portos analógicos, digitais, e PWM. é sem duvida promissora a nível de possibilidades e desempenho.     Fig. 1 - ARM® Cortex®-M0+ MCU 32-Bit Embedded Evaluation Board A forma da placa e do seu pinout, permite usar placas de expansão desenhadas para o Arduino R3, tendo no entanto em atenção que esta placa FRDM-KL25Z trabalha com 3.3V. Devemo-nos portanto assegurar da compatibilidade dos "shields" Arduino com os 3.3V. ...

Guia de utilização da placa KL25Z

Olá a todos, Fig. 1 KL25Z Vista Superior Num artigo anterior sobre esta mesma placa, a KL25Z, fiz uma pequena apresentação que permite ter uma ideia das suas capacidades. Como vejo muito potencial nesta placa, tendo em conta o seu baixo preço, decidi escrever este segundo artigo. Vou desta vez detalhar um pouco mais, indo mais ao pormenor, permitindo a sua utilização a quem porventura não esteja muito familiarizado com estas placas nem com os seus ambientes de desenvolvimento, os chamados IDE (Integrated Development Environment). Introdução A grande vantagem dos microcontroladores sobre a lógica programada, é a sua flexibilidade. Uma máquina comandada por microprocessadores ou microcontroladores pode ser adaptada a um novo trabalho, a uma nova tarefa, bastando para isso alterar o programa, que não são mais que instruções sequenciais que o microprocessador reconhece e executa.  Uma máquina desenhada com lógica fixa, (portas lógicas discretas) não será capaz de efetuar ...

Projecto: PWM - o que é e como funciona

Olá! Todos já ouviram falar de PWM, mas nem todos sabem o que é e como funciona. O principal objectivo deste projecto é ajudar as pessoas a entender melhor os conceitos por detrás do PWM e perceber como funciona. Decidi portanto construir uma placa de encaixe no Arduino (Arduino shield) que usando as saídas  PWM do Arduino, e algum código simples, consegue demonstrar com ajuda de um osciloscópio, como funciona o PWM. Todo o projeto está descrito neste link : https://create.arduino.cc/projecthub/lmsousa/pwm-demonstration-board-using-arduino-a17d0f?ref=user&ref_id=391612&offset=1   Para uma introdução ao PWM, não deixe de visitar esta página .