Introduction: Digital Scale With ESP32
Have you ever thought about mounting a digital scale using an ESP32 and a sensor (known as a load cell)? Today, I'll show you how to do this through a process that also allows for other laboratory tests, such as identifying the force that an engine performs on a point, among other examples.
I will then demonstrate some concepts related to the use of load cells, capture cell data to build an example scale, and point out other possible applications of load cells.
Step 1: Resources Used
• Heltec Lora 32 WiFi ESP
• Load cell (0 to 50 newtons, using a scale)
• 1 potentiometer of 100k (better if you use a multivolt trimpot for fine adjustment)
• 1 Amp Op LM358
• 2 1M5 resistors
• 2 10k resistors
• 1 4k7 resistor
• Wires
• A Protoboard
• A USB cable for ESP
• A scale, container with graduated volume, or any other method of calibration.
Step 2: Demonstration
Step 3: Load Cells
• They are force transducers.
• They can use various methods to translate the applied force into a proportional magnitude that can be used as a measure. Among the most common are those using sheet extensometers, THE piezoelectric effect, hydraulics, vibrating strings, etc...
• They can also be classified by the measurement form (tension or compression)
Step 4: Load Cells and Strain Gauges
• Sheet extensometers are films (usually plastic) with a printed wire that have a resistance that can vary with their size change.
• Its construction mainly aims to convert a mechanical deformation into a variation of an electrical magnitude (resistance). This occurs preferably in a single direction, so that component evaluation can be performed. For this, the combination of several extensometers is common
• When properly attached to a body, its deformation equals that of the body. Thus, its resistance varies with the deformation of the body, which in turn is related to the deforming force.
• They are also known as strain gauges.
• When stretched by a tensile force, the strands elongate and narrow, increasing resistance.
• When compressed by a compressive force, the wires shorten and widen, reducing the resistance.
Step 5: Wheatstone Bridge
• For a more accurate measurement and to allow for more efficient detection of resistance variation in a load cell, the strain gauge is assembled into a Wheatstone bridge.
• In this configuration, we can determine the variation of the resistance through the bridge imbalance.
• If R1 = Rx and R2 = R3, the voltage dividers will be equal, and the voltages Vc and Vb will also be equal, with the bridge in equilibrium. That is, Vbc = 0V;
• If Rx is other than R1, the bridge will be unbalanced and the voltage Vbc will be nonzero.
• It is possible to show how this variation should occur, but here, we will make a direct calibration, relating the value read in the ADC to a mass applied to the load cell.
Step 6: Amplification
• Even using the Wheatstone bridge to make the reading more efficient, the micro deformations in the metal of the load cell produce small voltage variations between Vbc.
• To solve this situation, we will use two stages of amplification. One to determine the difference and another to match the value obtained to the ADC of the ESP.
Step 7: Amplification (scheme)
• The gain of the subtraction step is given by R6 / R5 and is the same as R7 / R8.
• The gain of the non-inverting final step is given by Pot / R10
Step 8: Collection of Data for Calibration
• Once assembled, we set the final gain so that the value of the largest measured mass is close to the maximum value of the ADC. In thIS case, for 2kg applied in the cell, the output voltage was around 3V3.
• Next, we vary the applied mass (known through a balance and for each value), and we associate a LEITUR of the ADC, obtaining the next table.
Step 9: Obtaining Function Relation Between Measured Mass and the Value of the ADC Obtained
We use the PolySolve software to obtain a polynomial that represents the relationship between the mass and the value of the ADC.
Step 10: Source Code
Source Code - #Includes
Now that we have how to get the measurements and know the relationship between the ADC and the applied mass, we can move on to actually writing the software.
//Bibliotecas para utilização do display oLED
#include <Wire.h> // Necessário apenas para o Arduino 1.6.5 e anterior #include "SSD1306.h" // o mesmo que #include "SSD1306Wire.h"
Source code - #Defines
//Os pinos do OLED estão conectados ao ESP32 pelos seguintes GPIO's:
//OLED_SDA -- GPIO4 //OLED_SCL -- GPIO15 //OLED_RST -- GPIO16 #define SDA 4 #define SCL 15 #define RST 16 //RST deve ser ajustado por software
Source - Global Variables and Constants
SSD1306 display(0x3c, SDA, SCL, RST); //Instanciando e ajustando os pinos do objeto "display"
const int amostras = 10000; //número de amostras coletadas para a média const int pin = 13; //pino de leitura
Source Code - Setup ()
void setup()
{ pinMode(pin, INPUT); //pino de leitura analógica Serial.begin(115200); //iniciando a serial // Inicia o display display.init(); display.flipScreenVertically(); //Vira a tela verticalmente }
Source Code - Loop ()
void loop()
{ float medidas = 0.0;//variável para manipular as medidas float massa = 0.0; //variável para armazenar o valor da massa //inicia a coleta de amostras do ADC for (int i = 0; i < amostras; i++) { medidas = medidas + float(analogRead(pin)); } medidas = (medidas / float(amostras));//Tira a média das amostras massa = calculaMassa(medidas); //Calcula a massa em gramas //Ao iniciar, exibirá uma mensagem por 5 segundos //para só depois mostrar as medidas realizadas if (millis() > (5000)) //se está ligado a mais que 5 segundos { //Envia um CSV contendo o instante, a medida média do ADC e o valor em gramas //para a Serial. Serial.print (millis() / 1000.0, 0); //instante em segundos Serial.print( " , "); Serial.print(medidas, 3);//valor médio obtido no ADC Serial.print( " , "); Serial.println((massa), 1); //massa em gramas //Escreve no buffer do display display.clear(); //Limpa o buffer do display //ajusta o alinhamento para a esquerda display.setTextAlignment(TEXT_ALIGN_LEFT); //ajusta a fonte para Arial 16 display.setFont(ArialMT_Plain_16); //Escreve no buffer do display a massa display.drawString(0, 0, "Massa: " + String(int(massa)) + "g"); //escreve no buffer o valor do ADC display.drawString(0, 30, "ADC: " + String(int(medidas))); } else //se está ligado a menos de 5 segundos { display.clear(); //limpa o buffer do display display.setTextAlignment(TEXT_ALIGN_LEFT); //Ajusta o alinhamento para a esquerda display.setFont(ArialMT_Plain_24); //ajusta a fonte para Arial 24 display.drawString(0, 0, "Balança"); //escreve no buffer display.setFont(ArialMT_Plain_16);//Ajusta a fonte para Arial 16 display.drawString(0, 26, "ESP-WiFi-Lora"); //escreve no buffer } display.display();//transfere o buffer para o display delay(50); }
Source Code - Function calculaMassa ()
//função para cálculo da massa obtida pela regressão
//usando oPolySolve float calculaMassa (float medida) { return -6.798357840659e+01 + 3.885671618930e-01 * medida + 3.684944764970e-04 * medida * medida + -3.748108838320e-07 * medida * medida * medida + 1.796252359323e-10 * medida * medida * medida * medida + -3.995722708150e-14 * medida * medida * medida * medida * medida + 3.284692453344e-18 * medida * medida * medida * medida * medida * medida; }