25. Aquisição de dados de um medidor de OD com o Arduino.

Visando automatizar medidas de Respirometria em Lodo Biológico iniciamos o uso da placa Arduino para fazer a conversão Analógico-Digital de um transmissor de Oxigênio Dissolvido (OD) da marca Mettler Toledo (mod. 4050e).

Este não é um medidor adequado para uso em bancada mas para a montagem em um painel de instrumentos. E é um modelo que não é mais fabricado desde 2007.

Figura 177. Visão frontal e lateral do medidor de OD 4050e

Visão frontal e lateral do medidor de OD 4050e

Conforme o manual deste medidor (disponível em Manual_MettlerToledo_4050e.pdf) este instrumento possui duas saídas analógicas, uma para OD e outra para Temperatura, que podem ser configuradas para gerar uma corrente de 0-20mA ou 4-20 mA proporcional à concentração de OD e/ou à Temperatura.

Decidimos utilizar uma placa Arduino (mod. Duemilanove), como interface AD, para converter os sinais analógicos de corrente (do medidor de OD) para sinais digitais (para um PC) e escrever uma interface gráfica em Tcl/Tk (supervisório) para automatizar a aquisição das leituras de OD e Temperatura e consequentemente automatizar medidas de Respirometria em Lodo Biológico.

Utilizamos o Linux Debian 6.0 (Squeeze) como ambiente de desenvolvimento e as informações sobre a instalação dos programas necessários estão disponíveis na seção Instalação da IDE do Arduino no Debian 6.0 (Squeeze).

25.1. Conversão Analógico Digital

O medidor possui, na parte traseira, conexões para o eletrodo e saídas analógicas, dentre outras, conforme a figura abaixo.

Figura 178. Conexões na parte traseira do medidor de OD 4050e com destaque para as conexões 30 e 31 correspondente à saída analógica referentes à concentração de OD.

Conexões na parte traseira do medidor de OD 4050e com destaque para as conexões 30 e 31 correspondente à saída analógica referentes à concentração de OD.

Seguindo o manual do medidor fizemos as configurações necessárias para gerar uma corrente de 4mA para a concentração de 0,00 mg/L de OD e 20mA para a concentração de 9,00 mg/L de OD. Também foi ativado o recurso de gerar uma corrente constante de 22mA (corrente de saturação) para quaisquer concentrações maiores do que 9,00 mg/L de OD.

Figura 179. Gráfico da corrente (mA) gerada pelo medidor 4050e em função da concentração de OD (mg/L).

Gráfico da corrente (mA) gerada pelo medidor 4050e em função da concentração de OD (mg/L).

A corrente mínima de 4mA, para [OD] = 0,00 mg/L, tem uma utilidade prática pois permite identificar uma eventual ruptura do circuito. Ou seja, uma corrente de 0mA indica que o circuito está aberto.

O tutorial http://arduino.cc/en/Tutorial/AnalogReadSerial mostra os comandos básicos para a conversão de um valor de voltagem em um valor numérico adimensional, na faixa de 0 a 1023, e o envio dos dados pela saída serial. Enquanto que o tutorial http://arduino.cc/en/Tutorial/ReadAnalogVoltage além das etapas anteriores mostra também como fazer a conversão das leituras em valores de voltagem (mV).

Nota

Os termos Tensão e Voltagem são usados muitas vezes como sinônimos mas alguns profissionais da área de Eletrônica podem ficar (muito) incomodados com isso!

Peço a compreensão dos profissionais da Eletrônica mas preferi usar o termo Voltagem ao longo do texto.

Gostaria apenas de lembrar que o livro Princípios de Análise Instrumental Skoog, 2002 utiliza o termo Voltagem .

Os pinos analógicos do Arduino (ANALOG IN), usados para leituras analógicas de diversos sensores, suportam uma voltagem de no máximo 5V, por isso colocamos em série com a saída do medidor (pinos 31+ e 30-) um resistor variável (resistência shunt) ajustado para 227 Ohms, para obter uma leitura de no máximo de 5 V (4,994 V) quando o transmissor gerar uma corrente de 22 mA (corrente máxima de saturação). O pino 31(+) do medidor foi conectado ao pino A0 do Arduino e o pino 30(-) do medidor conectado ao Terra(Gnd) da placa Arduino.

Figura 180. Diagrama das conexões entre o medidor 4050e e a placa Arduino (Duemilanove) para a conversão analógico digital das medidas de OD.

Diagrama das conexões entre o medidor 4050e e a placa Arduino (Duemilanove) para a conversão analógico digital das medidas de OD.

25.1.1. Sketch

Usamos como ponto de partida o Sketch disponível no tutorial http://arduino.cc/en/Tutorial/ReadAnalogVoltage, e após algumas adaptações utilizamos o seguinte código para os testes iniciais:

/*
ReadAnalogVoltage
Lê a entrada analógica no pino 0, coverte o valor para tensão, e evia o resultado pela porta
serial USB 
 Este código é de Domínio Público
 */

  int i = 0; // variavel de contagem  
  float soma = 0; // variavel que soma os valores obtidos
  float media = 0; // variavel que calcula a media

void setup() {
  // Inicializa a comunicação serial com 9600 bits por segundo
  // O padrão de comunicação serial para a placa Arduino é
  //  8 bits de dados, sem paridade (n) e 1 bit de parada (8,n,1) 
  Serial.begin(9600);
  
}

// A rotina loop é executada indefinidamente
void loop() {

  soma = 0;
  i = 0;
  media = 0;
  
  while(i < 10) {
    
  // ler sinal analogico no pino 0:
  int sensorValue = analogRead(A0);
  
  soma = soma + sensorValue;
  
  i++;
  
  delay(100);
  
  }
  
  media = soma/10;
  
  // Converter leitura analogica (0 - 1023) em voltagem (0 - 5V):
  float voltage = media * (5.0 / 1023.0);
  
  // print exibe sem salto de linha
  //Serial.print("Voltagem  ");
 
 // O número 5 define o número de casas decimais
  // println exibe com salto de linha
  
  Serial.println(voltage, 5);
  delay(50);
}

Nos testes iniciais observamos que as leituras são influenciadas pela presença da resistência externa tornando mais instável as leituras no display do medidor de OD.

Por isso incluímos um loop de amostragem para cálculo da média de 10 leituras no programa de aquisição do Arduino seguindo como exemplo o código disponível em http://labduino.blogspot.com.br/2011/08/calculando-media-com-o-arduino.html.

25.1.2. Cálculo da resolução das leituras de [OD].

O conversor Analógico-Digital (AD) da placa Arduino possui uma resolução[16] de 10 bits, ou seja, consegue converter a escala de 0-5V com uma resolução de:

210 = 1024

Ou seja tem a resolução de uma parte em (1024) e portanto se a faixa medida é de 0-5 V, a resolução será:

resolução = 5 V / (1024) = 0,00488 ou 4,88 mV

Para [OD] = 0,00 mg/L a corrente gerada no medidor é de 4mA e portanto a voltagem através da resistência de 227 Ohms é 0,91 V (227 Ohms x 0,004 A).

E quando [OD] = 9,00 mg/L, a corrente gerada no medidor é de 20mA, gerando uma voltagem através da resistência de 227 Ohms de 4,54 V (227 Ohms x 0,020 A).

Portanto a faixa de leitura de [OD] (0,00 a 9,00 mg/L) corresponde a um intervalo de voltagem de 3,63 V (0,91 V - 4,54 V).

O gráfico [OD] (mg/L) X Voltagem (V) possui uma inclinação de:

(9,00 mg/L - 0,00 mg/L) / (4,54 V - 0,91 V) = 2,48 mg/L*V

Figura 181. Gráfico da voltagem (V) gerada pelo medidor 4050e em função da concentração de OD (mg/L), com inclinação de 2,48 mg/L*V.

Gráfico da voltagem (V) gerada pelo medidor 4050e em função da concentração de OD (mg/L), com inclinação de 2,48 mg/L*V.

Portanto se a resolução das leituras de voltagem da placa Arduino (10 bits) é 4,88 mV podemos estimar a resolução das leituras de [OD], no intervalo considerado, pelo produto:

2,48 (mg/L*V) * 0,00488 (V) = 0,01 mg/L

Atenção

Lembrar que essa resolução de leitura é válida para os intervalos de concentração de OD definidos na configuração do medidor!

25.2. Interface para Aquisição de Dados

Nessa etapa inicial usamos o programa de aquisição (femto600s.tcl) como protótipo para o desenvolvimento de uma interface para aquisição de dados.

25.2.1. Definição das principais variáveis para o algoritmo de cálculo de OD.

Para organizar o algoritmo de cálculo de [OD] a partir das leituras de voltagem realizadas pela placa Arduino foram definidas as seguintes variáveis:

  • LIC - Limite Inferior de Corrente do transmissor (Ex: 0,004 A)

  • LSC - Limite Superior de Corrente do transmissor (Ex: 0,020 A)

  • LSat - Limite de Saturação do transmissor (Ex: 0,022 A)

  • R - Resistência utilizada para converter a corrente do transmissor em voltagem para leitura pela placa Arduino (227 Ohms)

  • LIV - Limite Inferior de Voltagem = R * LIC = 227 Ohms x 0,004 A = 0,91 V

  • LSV - Limite Superior de Voltagem = R * LSC = 227 Ohms x 0,020 A = 4,54 V

  • LV_Arduino - Limite de Voltagem que pode ser aplicada nas entradas analógicas da placa Arduino (5V)

  • OD_LIC - Concentração de Oxigênio Dissolvido associada ao LIC (Ex: 0,00 mg/L)

  • OD_LSC - Concentração de Oxigênio Dissolvido associado ao LSC (Ex: 9,00 mg/L)

  • OD_LIV - Concentração de Oxigênio Dissolvido associada ao LIV = OD_LIC

  • OD_LSV - Concentração de Oxigênio Dissolvido associada ao LSV = OD_LSC

  • Res_V - Resolução das leituras de voltagem pela placa Arduino = 5 V / (1024 -1) = 4,88 mV

  • Res_OD - Resolução das leituras de OD = 0,01 mg/L

Figura 182. Indicação das principais variáveis no gráfico de OD X V.

Indicação das principais variáveis no gráfico de OD X V.

Também podemos formalizar o cálculo da resolução das leituras de OD pela fórmula:

Figura 183. Cálculo da resolução das leituras de OD (Res_OD).

Cálculo da resolução das leituras de OD (Res_OD).

25.2.2. Interface de Aquisição arduino_4050e.tcl

Decidimos dividir as atividades de aquisição em duas etapas:

  1. A placa Arduino faz a aquisição das leituras de voltagem e envia os dados das múltiplas entradas em apenas uma linha pela porta serial USB.

  2. A interface (escrita em Tcl/Tk) faz a leitura dos dados de tensão, extrai os campos referentes aos diferentes padrões e faz a conversão das leituras de voltagem para os parâmetros correspondentes utilizando as respectivas equações de calibração.

Nessa etapa inicial usamos como ponto de partida o programa de aquisição (femto600s.tcl) o qual foi renomeado para arduino_4050e.tcl.

Conforme pode ser verificado na listagem do programa, foram definidas algumas variáveis que são utilizadas para o cálculo dos parâmetros da equação de calibração no procedimento curva_cal pontos(Fonte: Linear regression and correlation coefficient).

Os parâmetros de equação de calibração linear são passados como parâmetros para o procedimento converter x a b.

Listagem parcial do programa arduino_4050e.tcl:

#!/bin/sh
#A próxima linha reinicia usando o wish \
exec wish "$0" "$@"

#11/03/2013
#Programa básico para aquisição de leituras
#de voltagem de uma placa Arduino convertendo
#leituras de OD e Temperatura de um transmissor Mettler Toledo 4050e

#====================================================================================

#Definindo as "constantes" para o cálculo dos parâmetros
#da curva de calibração para conversão das leituras de voltagem (V)
#nas respectivas unidades dos parâmetros monitorados

#As constantes: LIC, LSC, LSat, OD_LIC, OD_LSC, T_LIC e T_LSC
#são configurados manualmente no transmissor 4050e
#LV_Arduino = Limite superior de voltagem  que pode ser aplicada nas 
#entradas analógicas da placa Arduino (5V)

#A constante R (227 Ohms) corresponde à resistência usada no circuito para conversão
#de corrente em voltagem e é definida em função de LSat (0,022 A) e LV_Arduino (5 V)

#LIC = Limite Inferior de Corrente do transmissor (Ex: 0,004 A)
#LSC = Limite Superior de Corrente do transmissor (Ex: 0,020 A)
#LSat = Limite de Saturação do transmissor (Ex: 0,022 A)
#O LSat especifica qual o valor de corrente que será gerada  para 
#uma concentração de OD maior do que o OD_LSC 

set LIC  0.004
set LSC  0.020
set LSat 0.022

#OD_LIC = Concentração de Oxigênio Dissolvido associada ao LIC (Ex: 0,00 mg/L)
#OD_LSC = Concentração de Oxigênio Dissolvido associado ao LSC (Ex: 9,00 mg/L)

set OD_LIC 0.00
set OD_LSC 9.00

#R = Resistência utilizada para converter a corrente do transmissor 
#em voltagem para leitura pela placa Arduino ( 227 Ohms). 

set R 232

#====================================================================================

#Variáveis calculadas
#LIV = Limite Inferior de Voltagem = R * LIC
#LSV = Limite Superior de Voltagem =  R * LSC

set LIV [expr $R * $LIC]
set LSV [expr $R * $LSC]

#OD_LIV =  Concentração de Oxigênio Dissolvido associada ao LIV = OD_LIC
#OD_LSV =  Concentração de Oxigênio Dissolvido associada ao LSV = OD_LIC

set OD_LIV $OD_LIC
set OD_LSV $OD_LSC


puts "$LIC $LSC $LIV $LSV $LSat $OD_LIV e $OD_LSV"

#====================================================================================

#Dados para o cálculo dos parâmetros de calibração de OD

set pontos_OD [list [list $LIV $OD_LIV] [list $LSV $OD_LSV] ]

#Dados para o cálculo dos parâmetros de calibração de Temperatura

#set pontos_T [list [list $LIV $T_LIV] [list $LSV $T_LSV] ]

#====================================================================================


#Variáveis para cálculo da média


global porta

frame .botoes

pack .botoes -side bottom -fill x

button .botoes.iniciar -text "Iniciar Leitura"  -command { abrir_porta }

button .botoes.parar -text "Parar Leitura" -command { close $porta }

button .botoes.gravar -text "Gravar Arquivo" -command { gravar_arquivo }

button .botoes.sair -text "  Sair  " -command "exit"

pack  .botoes.iniciar .botoes.parar .botoes.gravar .botoes.sair \
    -side left -expand yes -fill both

frame .tela

pack .tela -side top  -fill x

text .tela.dados -relief sunken  -yscrollcommand  {.tela.rolagem set} \
    -background white -width 60
scrollbar .tela.rolagem  -command {.tela.dados yview}

pack .tela.dados -side left -fill y

pack .tela.rolagem -expand yes -fill both

  
 
################################################################
#Procedimento abrir_porta
################################################################

proc abrir_porta { } {
    
    global t0
    global porta

    global media soma cont N

    set media 0.0
    set soma 0.0
    set cont 0
    set N 5.0

    set porta [ open /dev/ttyUSB0 r+ ]
    fconfigure $porta -mode 9600,n,8,1    
    fileevent $porta readable [list ler_porta $porta]
    
    set t0 [clock clicks -milliseconds]
    
    .tela.dados insert end "\nTempo(ms) Leituras\n\n"

}

################################################################
#Procedimento ler_porta
################################################################

proc ler_porta { canal } {
    
    global t0  OD_cal_incl  OD_cal_int
    global cont soma media N

#Comando para calcular o tempo atual em milisegundos
    set tn [clock clicks -milliseconds]
    
#Comando para calcular o tempo decorrido desde t0 em segundos
    set tn [expr ($tn - $t0)/1000.0]
    
    if { [eof $canal ] } {
	    puts stderr "Fechando $canal"
	    catch { close $canal }
	    return }
    set dados [gets $canal]
	
#Comando regsub usado para substituir as ocorrências de . por , 
#É possível usar \\. e \\, ou {\.} e {,} ou {,}
    set tn [regsub {\.} $tn \, ]

    set OD [converter $dados $OD_cal_incl $OD_cal_int]

if {$cont < $N} {

set soma [expr $soma  + $OD]

incr cont
puts "soma: $soma cont: $cont"

} else {


set media [expr $soma / $N]

puts "media: $media"

.tela.dados insert end "Média de OD: $media\n"

set cont 0
set soma 0.0

}

 set dados [regsub {\.} $dados {,} ]
    
    set OD [regsub {\.} $OD {,} ]

    .tela.dados insert end " $tn $dados $OD\n"

    .tela.dados see end
}


################################################################
#Procedimento gravar_arquivo
################################################################

proc gravar_arquivo { } {

    set dados [.tela.dados get 1.0 {end -1c}]

    set tipo_arquivo {
	{"Arquivos Texto" { .txt .TXT } }
	{"Todos os arquivos" * }
    }

    set nome_arquivo [tk_getSaveFile -filetypes $tipo_arquivo  \
-initialdir pwd  -defaultextension .txt]

    if {[catch {set id_arquivo [open $nome_arquivo w]} result] != 0} {
	    return
	}
    
    puts -nonewline $id_arquivo $dados
    
    close $id_arquivo
}


################################################################
#Procedimento para o cálculo dos parâmetros de uma regressão 
#linear retornando a(coef. angular), b(interseção) e
#r(coef. correlação
#Fonte: Linear regression and correlation coefficient 
#http://wiki.tcl.tk/819
################################################################

proc curva_cal pontos {
    # linear regression y=ax+b for {{x0 y0} {x1 y1}...}
    # returns {a b r}, where r: correlation coefficient
    set N 0

    foreach i {Sx Sy Sxy Sx2 Sy2} {
	set $i 0.0
    }
    foreach ponto $pontos {
        foreach {x y} $ponto break
        set Sx  [expr {$Sx  + $x}]
        set Sy  [expr {$Sy  + $y}]
        set Sx2 [expr {$Sx2 + $x*$x}]
        set Sy2 [expr {$Sy2 + $y*$y}]
        set Sxy [expr {$Sxy + $x*$y}]
        incr N
    }
    set t1 [expr {$N*$Sxy - $Sx*$Sy}]
    set t2 [expr {$N*$Sx2 - $Sx*$Sx}]
    set a [expr {double($t1)/$t2}]
    set b [expr {double($Sy-$a*$Sx)/$N}]
    set r [expr {$t1/(sqrt($t2)*sqrt($N*$Sy2-$Sy*$Sy))}]
#    puts "$a $b $r"
#Retorna o coeficiente angular "a" e o coeficiente linear "b"
#da regressão linear
    return [list $a $b]
} ;#RS

#Lista contendo os parâmetros de calibração para OD
set OD_par_cal [curva_cal $pontos_OD]

#Coeficiente angular para calibração de OD
set OD_cal_incl [lindex $OD_par_cal 0]

#Coeficiente linear para calibração de OD
set OD_cal_int  [lindex $OD_par_cal 1]


#Procedimento para conversão das leituras de voltagem 
#para o parâmetro de interesse
proc converter { x a b } {

return [expr $a * $x + $b]

}

Fizemos os testes iniciais com R = 227 Ohms mas observamos uma diferença entre as leituras feitas pelo Arduino e o display do medidor. Alteramos o valor de R no código do programa para reduzir a diferença e após várias tentativas chegamos experimentalmente no valor de 232 Ohms.

25.3. Circuito Seguidor de Voltagem

Nos testes iniciais observamos que as leituras do medidor tornam-se mais instáveis quando iniciamos a aquisição de dados com a placa Arduino.

Por exemplo, as leituras do transmissor, com a placa Arduino desligada, oscila entre 7,55 e 7,57 mg/L (variação na segunda casa decimal) mas ao iniciar a aquisição as leituras passam a oscilar entre 7,00 e 7,40 mg/L (variação na segunda casa decimal).

Acreditamos que essa oscilação se deve à drenagem de corrente do medidor para o Arduino durante a leitura.

Por isso decidimos usar o Amplificador Operacional TL084CN como seguidor de voltagem isolar o medidor do circuito de aquisição (evitando drenagem de corrente) para reduzir as oscilações nas leituras de OD.

O TL084 é um circuito integrado com quatro Amplificadores Operacionais conforme mostra a figura seguinte.

Figura 184. Pinagem do Amplificador Operacional TL084CN (VCC+ e VCE-).

Pinagem do Amplificador Operacional TL084CN (VCC+ e VCE-).

Para conhecer mais detalhes desse modelo consulte o datasheet no link: http://www.st.com/web/en/resource/technical/document/datasheet/CD00000493.pdf

Dica

Para entender melhor o funcionamento dos amplificadores operacionais (e outros componentes) visite o site de simulações eletrônicas: http://www.falstad.com/circuit/e-index.html e conheça os tutoriais do site www.centelhas.com.br/biblioteca

A figura seguinte mostra um Amplificador Operacional como um Seguidor de Voltagem, no qual o sinal de entrada é conectado na entrada não-inversora e a saída é conectada na entrada inversora.

Figura 185. Um amplificador operacional como seguidor de voltagem onde Vi = Vo.

Um amplificador operacional como seguidor de voltagem onde Vi = Vo.

O seguidor de voltagem (ou tensão) tem a vantagem de não exigir (drenar) corrente do sinal de entrada, é o circuito interno do amplificador operacional e a fonte de alimentação que fornecem a corrente na saída do amplificador operacional, e por isso Vi = Vo Skoog, 2002

Figura 186. Diagrama das conexões entre o medidor 4050e, o amplificador operacional (como seguidor de voltagem) e a placa Arduino para a conversão analógico digital das medidas de OD.

Diagrama das conexões entre o medidor 4050e, o amplificador operacional (como seguidor de voltagem) e a placa Arduino para a conversão analógico digital das medidas de OD.

Nota

A alimentação do amplificador operacional foi feito com duas fontes de alimentação de 12 V, nas quais foram cortados os pinos terra e interligadas conforme a figura seguinte:

Figura 187. Diagrama das conexões de duas fontes de 12V para alimentação do amplificador operacional.

Diagrama das conexões de duas fontes de 12V para alimentação do amplificador operacional.

Nota

Lembrar que a resistência deve estar antes do AO para que o medidor de OD gere uma corrente, já que o parâmetro de saída do medidor é corrente. Para diferentes resistências o medidor gera uma corrente correspondente à [OD]. Se as saídas do medidor estiverem abertas (resistência infinita) o medidor vai manter aplicar a voltagem máxima considerando que o sistema está com alta resistência!

Figura 188. Montagem para testes do amplificador operacional na protoboard.

Montagem para testes do amplificador operacional na protoboard.

O uso do amplificador operacional reduziu significativamente a oscilação das leituras como mostra a figura seguinte.

Figura 189. O gráfico da esquerda mostra uma sequência de leituras de OD sem o uso do amplificador operacional como seguidor de voltagem, e o gráfico da direita mostra a redução significativa das oscilações com o uso do amplificador operacional.

O gráfico da esquerda mostra uma sequência de leituras de OD sem o uso do amplificador operacional como seguidor de voltagem, e o gráfico da direita mostra a redução significativa das oscilações com o uso do amplificador operacional.

Mais tarde encontramos uma outra sugestão para minimizar a interferência do circuito de aquisição (Arduino) nas leituras do medidor, conforme figura seguinte.

Figura 190. Circuito alternativo para minimizar a interferência do circuito de aquisição (Arduino) nas leituras de um medidor (Fonte: http://forum.arduino.cc/index.php/topic,19613.0.html

Circuito alternativo para minimizar a interferência do circuito de aquisição (Arduino) nas leituras de um medidor (Fonte: http://forum.arduino.cc/index.php/topic,19613.0.html



[16] Para entender o conceito de resolução na conversão AD consulte o tutorial http://emc5710.lago.prof.ufsc.br/arquivos/5conversao AD 122.pdf