Criando uma Balança com o Arduino

Introdução
Balanças estão presentes em diversas ocasiões em nosso dia, seja para comprar pão com uma regulação fina para medir até mesmo miligramas (mg), ou até mesmo para a pesagem de caminhões que ficam na beira das estradas, com uma variação bem mais robusta para a pesagem de toneladas. Elas nos informam o quanto devemos pagar por produtos, quantos quilos nossos corpos pesam, ou até mesmo para a aplicação da lei, impedindo que caminhões com sobrecarga rodem nas rodovias federais, por exemplo.
Embora uma balança seja muito utilizada, e em alguns casos indispensável, seu custo é elevado por uma série de fatores, seja pela precisão, pela calibragem, ou até mesmo pelo peso máximo suportado. Neste tutorial você vai aprender em poucos passos como fazer uma balança capaz de suportar até 50 kg, além de entender como é feita a calibragem por software.
Lista de Materiais
Conceitos Teóricos
Amplificador Operacional
O módulo HX711 utilizado neste tutorial é um conversor analógico-digital e amplificador operacional de 24 bits. Ele é usado para amplificar o sinal da célula de carga de 50 kg, além de realizar a conversão do sinal analógico para um sinal digital. Isso é necessário, pois o sinal de saída da célula está na escala de milivolts (mV). Portanto para que seja um sinal que possa ser lido pelo microcontrolador, ele precisa ser amplificado para o nível adequado da placa utilizada.
Um amplificador operacional geralmente possui uma entrada variável e uma entrada constante, e então ele retorna como saída a diferença das tensões, de acordo com o ganho do amplificador. Essa matemática pode ser expressa através de Vout = A * [ (V+) - (V-) ]
, onde o ganho "A" costuma ser fornecido como um valor fixo pelo fabricante para o desenvolvimento do circuito.

Fonte: Wikipedia
Os pinos "Vs+" e "Vs-" são responsáveis pela alimentação positiva e negativa, respectivamente, do amplificador.
Funcionamento da Célula de Carga
Células de carga possuem um funcionamento parecido, em relação à variação de resistência, com potenciômetros, pois elas possuem extensômetros que se deformam de acordo com a carga aplicada sobre sua área de contato. Essa deformação faz com que sua resistência aumente. Entretanto existem alguns fatores que podem influenciar na variação ôhmica do extensômetro, como pode ser visto abaixo.

Fonte: Portal Célula de Carga
Em um mundo ideal, o gráfico da diferença de potencial em relação à carga aplicada em uma célula de carga seria uma reta. A linearidade é um erro representado pela diferença entre a curva real de resposta da célula quando aplicado um peso sobre sua área de contato, quando comparado com a curva ideal de expectativa teórica. A histerese também é um fenômeno comum quando testamos relações teóricas na prática. Como é possível ver na imagem acima, a curva desta relação acaba se deslocando para cima ou para baixo durante a aplicação ou a remoção de peso na célula. Ou seja, ao aplicar um peso de um quilo à célula sem carga, por exemplo, teríamos como resposta um valor diferente do que se removermos um quilo da mesma célula já carregada com dois quilos. A repetibilidade é a capacidade da célula de carga em retornar o mesmo valor quando aplicado o exato mesmo peso sobre o sensor, portanto ela deve ser levada em conta na hora de escolha do sensor adequado para realizar uma certa aplicação. A fluência é a perda de característica de transdutor (componente que transforma uma grandeza física, neste caso o peso em um sinal elétrico) do material, causando uma variação inesperada no sinal elétrico de saída. O erro combinado da curva acima é um erro calculado a partir de dois ou mais erros citados anteriormente. Todos esses fatores de distúrbio do componente devem ser levados em conta durante a calibração.
Ponte de Wheatstone
A ponte de Wheatstone é, se não o único, o método mais utilizado para realizar medições sobre a variação da célula de carga. Com ela é possível identificar valores de resistência ôhmica desconhecida. Ela é utilizada para determinar resistências muito pequenas, podendo ser utilizada para medir uma escala de mili-ohms. O circuito da ponte nada mais é do que duas disposições série-paralelo de dois resistores, preferencialmente de mesmo valor. Com o valor igualado em todos os resistores da ponte, a diferença de potencial no centro da ponte quando medido entre as disposições de resistores deve ser igual a zero. A imagem abaixo mostra um exemplo do circuito da ponte de Wheatstone.

Fonte: Electronics Tutorials
Para a ponte de Wheatstone, a fórmula matemática para calcular as resistências necessárias para o valor Vout ser igual a zero é Vout = Vc - Vd = [ R2 / ( R1 + R2 ) ] * Vin - [ R4 / ( R3 + R4 ) ] * Vin
. Nessa condição, pode-se usar a relação entre os resistores R1 / R2 = R3 / R4
. Assim é possível calibrar manualmente a tensão de saída da ponte, já que ao variar uma das resistências, o valor será alterado. Para realizar uma calibragem de hardware através das resistência, é necessário substituir um dos resistores de cada lado da ponte, por exemplo R1 e R3, então alimentar a ponte com 5 V e GND nos pontos "A" e "B", respectivamente, como pode ser visto na imagem acima. Então, com um multímetro, variar os potenciômetros para que o valor lido entre os pontos "C" e "D" seja igual a zero.
Calibração Via Software
Circuito
O circuito a seguir utiliza o módulo HX711 para realizar a comparação entre as tensões de entrada do circuito (excitações), com os pinos "E+" e "E-", e a tensão de entrada do amplificador operacional, com os pinos "A-" e "A+". Observe a montagem na imagem abaixo.

A calibração será feita por um fator que será calculado com o valor retornado pelo módulo HX711, para converter o valor lido para uma unidade de peso (neste caso, utilizaremos a medida em quilogramas).
Código
Para esse tutorial, você precisa instalar a biblioteca criada por "bogde" para o módulo HX711. Para instalar uma biblioteca, siga o tutorial Adicionando Bibliotecas na IDE Arduino. Com o circuito acima montado, carregue o código a seguir para a sua placa para realizar a calibração via software.
/*******************************************************************************
* Calibracao do Peso em kg (v1.0)
*
* Codigo para realizar a calibracao do peso medido pela celula de carga. Para
* a calibraca serao utilizados os caracteres "n"(-1), "m"(+1), "v"(-10), "b"(+10),
* "x"(-100), "c"(+100), para ajuste fino do fator de
* calibracao da escala. Utilize uma peca com um peso conhecido para calibrar
* corretamente a escala.
*
* Copyright 2019 RoboCore.
* Escrito por Giovanni de Castro (10/04/2019).
* Creditos - Nathan Seidle - Sparkfun Electronics (2014)
* - Bogde - GitHub library
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version (<https://www.gnu.org/licenses/>).
*******************************************************************************/
#include <HX711.h> //adiciona a biblioteca ao codigo
//configuracao dos pinos para o modulo HX711
const int PINO_DT = 3;
const int PINO_SCK = 2;
const int TEMPO_ESPERA = 1000; //declaracao da variavel de espera
HX711 escala; //declaracao do objeto escala na classe HX711 da biblioteca
float fator_calibracao = -45000; //pre-definicao da variavel de calibracao
char comando; //declaracao da variavel que ira receber os comandos para alterar o fator de calibracao
void setup ()
{
//mensagens do monitor serial
Serial.begin(9600);
Serial.println("Celula de carga - Calibracao de Peso");
Serial.println("Posicione um peso conhecido sobre a celula ao comecar as leituras");
escala.begin (PINO_DT, PINO_SCK); //inicializacao e definicao dos pinos DT e SCK dentro do objeto ESCALA
//realiza uma media entre leituras com a celula sem carga
float media_leitura = escala.read_average();
Serial.print("Media de leituras com Celula sem carga: ");
Serial.print(media_leitura);
Serial.println();
escala.tare(); //zera a escala
}
void loop ()
{
escala.set_scale(fator_calibracao); //ajusta a escala para o fator de calibracao
//verifica se o modulo esta pronto para realizar leituras
if (escala.is_ready())
{
//mensagens de leitura no monitor serial
Serial.print("Leitura: ");
Serial.print(escala.get_units(), 1); //retorna a leitura da variavel escala com a unidade quilogramas
Serial.print(" kg");
Serial.print(" \t Fator de Calibracao = ");
Serial.print(fator_calibracao);
Serial.println();
//alteracao do fator de calibracao
if(Serial.available())
{
comando = Serial.read();
switch (comando)
{
case 'x':
fator_calibracao = fator_calibracao - 100;
break;
case 'c':
fator_calibracao = fator_calibracao + 100;
break;
case 'v':
fator_calibracao = fator_calibracao - 10;
break;
case 'b':
fator_calibracao = fator_calibracao + 10;
break;
case 'n':
fator_calibracao = fator_calibracao - 1;
break;
case 'm':
fator_calibracao = fator_calibracao + 1;
break;
}
}
}
else
{
Serial.print("HX-711 ocupado");
}
delay(TEMPO_ESPERA);
}
Este código foi desenvolvido para que, durante as leituras de peso do circuito, o fator de calibração possa ser alterado para obter um ajuste fino sobre um peso já conhecido. Ou seja, é recomendado utilizar uma balança digital já funcionando para obter o peso do objeto a ser pesado, para que, com os comandos, o fator seja alterado de modo a obter com perfeição o peso através da calibração. Infelizmente a resolução desta célula de carga é de 100 g, portanto o valor variável dessa célula será informado de 100 em 100 g, tendo esse valor como leitura mínima.
Entendendo o Código
O código é criado a partir da biblioteca disponibilizada pelo usuário do GitHub "bogde", portanto os comandos que serão explicados são os comandos específicos da biblioteca. O comando escala.begin(PINO_DT, PINO_SCK)
inicia a definição dos pinos PINO_DT e PINO_SCK como portas que serão utilizadas pelo objeto escala, definida em função da biblioteca HX711 no comando HX711 escala
.
A função escala.read_average()
realiza uma média em função de dez leituras, e utilizamos esse comando para imprimir no monitor serial uma média de leituras em valores brutos, sem a conversão para a unidade de quilogramas. Na linha em que a função está sendo usada, o valor retornado equivale à tensão para a célula sem carga, ou seja, no zero de uma balança. escala.tare()
zera a escala utilizada pela biblioteca para leitura de peso em função de dez leituras, da mesma maneira que restaurantes por quilo zeram a balança com um prato em cima para não influenciar no peso da comida, que é proporcional ao quanto será pago.
O fator de calibração é relacionado ao código com o comando escala.set_scale(fator_calibracao)
. Com ele, a escala é regulada de acordo com o fator de calibração que poderá ser alterado com o bloco de comandos switch - case
. Neste código estamos utilizando oito casos com oito ações diferentes para a alteração do valor do fator de calibração. Para realizar essa alteração, basta, com o monitor serial aberto, enviar um dos seguintes comandos: "x","c", "v", "b","n" e "m". Eles representam, respectivamente, uma alteração de "-100", "+100", "-10", "+10", "-1" e "+1" ao fator de calibração. Outro método de alterar o fator de calibração é digitando um valor conhecido para fator_calibracao
antes de carregar o programa para a placa. Esse valor de calibração será utilizado para o projeto final, portanto é importante guardar o valor desse fator para não ter que repetir o processo de calibração via software novamente.
Da mesma maneira que a calibração manual é díficil de se acertar com precisão, a calibração via software também tende a ser bem complicada e pode levar um certo tempo para chegar ao resultado desejado. Porém não é impossível, então não desista e continue tentando.
Projeto Balança Digital
Circuito
Aproveitando o circuito utilizado para a calibração via software, iremos acrescentar um display LCD, com um módulo I2C para facilitar a prototipagem e diminuir o número de portas utilizadas, para mostrar o peso que está sendo aplicado na área de contato da célula de carga. O circuito completo pode ser visto na imagem abaixo.

Como é possível observar na imagem acima, mantivemos o circuito utilizado anteriormente para realizar a calibração via software, porém incluímos o display LCD com módulo I2C para simular uma balança digital. Neste exemplo será possível apresentar pelo display o peso medido pela célula em quilogramas.
Código
Com o circuito acima montado, copie e cole o código abaixo para a Arduino IDE e carregue ele para a placa. Vale lembrar que o valor do fator de calibração encontrado durante a calibração via software deve ser alterado.
xxxxxxxxxx
/*******************************************************************************
* Balanca Digital (v1.0)
*
* Este codigo utiliza uma celula de carga com o modulo HX711 para realizar a
* leitura do peso aplicado para, no diplay LCD, apresentar o valor em kg medido
* pelo sistema.
*
* Copyright 2019 RoboCore.
* Escrito por Giovanni de Castro (11/04/2019).
* Creditos - Bogde - GitHub library
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version (<https://www.gnu.org/licenses/>).
*******************************************************************************/
//adiciona as bibliotecas ao codigo
#include <HX711.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x20,16,2); //endereçamento do LCD
//configuracao dos pinos para o modulo HX711
const int PINO_DT = 3;
const int PINO_SCK = 2;
//declaracao do intervalo de espera
const int TEMPO_ESPERA = 500;
HX711 escala; //declaracao do objeto ESCALA na classe HX711 da biblioteca
const int FATOR_CALIBRACAO = -45000; //esse valor deve ser alterado para o valor de calibracao obtido com o outro codigo
void setup ()
{
//mensagens do LCD
lcd.begin(); //inicializacao do display
lcd.backlight(); // ligacao do backlight do LCD
lcd.print(" ");
lcd.print("RoboCore");
delay(TEMPO_ESPERA);
lcd.clear();
escala.begin (PINO_DT, PINO_SCK); //inicializacao e definicao dos pinos DT e SCK dentro do objeto ESCALA
escala.tare(); //zera a escala
escala.set_scale(FATOR_CALIBRACAO); //ajusta a escala para o fator de calibracao
}
void loop ()
{
//verifica se o modulo esta pronto para realizar leituras
if (escala.is_ready())
{
//mensagens de leitura no monitor serial
lcd.print(" Peso: ");
lcd.print(escala.get_units(), 1); //retorna a leitura da variavel escala com a unidade quilogramas
lcd.print(" kg");
}
else
{
lcd.print(" Aguarde . . . ");
}
delay(TEMPO_ESPERA); //intervalo de espera para leitura
lcd.clear();
}
Diferentemente do código de calibração, este código possui menos comandos relacionados à biblioteca "HX711", porém utiliza comandos da biblioteca LiquidCrystal I2C. Este código utiliza as leituras da célula de carga para mostrar o peso lido no display LCD.
Indo Além
A maioria das balanças não utiliza apenas uma célula de carga para realizar medição de peso, e sim duas a mais células, podendo chegar a até quatro células de carga. Já pensou como seria o circuito da ponte de Wheatstone para esse projeto? Parece ser difícil, não é mesmo? Por incrível que pareça, utilizar mais de uma célula de carga não só facilita a montagem do circuito, como facilita a calibração, já que se trata da mesma variação em todas os componentes, não tendo uma resistência fixa em um dos lados do circuito como utilizamos neste tutorial. Caso você queira dar uma olhada sobre como fazer essa projeto com o mesmo módulo HX-711, você pode acessar esse tutorial criado por um usuário do Instructables.
Além disso, já pensou como é realizada a calibração manual de circuitos de células de cargas? É possível entender o conceito de uma calibração utilizando leituras das porta analógicas de uma BlackBoard UNO. Embora, devido à resolução de leituras analógicas da plataforma Arduino, não seja um método eficiente para realizar a calibração manual do circuito, é o suficiente para se entender o conceito.