Balanza de peso dinamico

Hola gente comparto este proyecto que hice hace más de dos años, una balanza de peso dinámico para paquetes de 1Kg había tenido problemas con la pantalla, se hablo con el fabricante y ese modelo ya estaba discontinuado y sugirió reemplazar toda la balanza, el costo era de 10 mil USD entonces decidí probar un Arduino Nano con un Hx711 y celda de carga de 5kg el resultado fue que funciono mejor de que pensaba tengo un error de unos 3 gramos y es mas que aceptable al pesar algo en movimiento, el programa es extremadamente sencillo lo que hace es pesar el paquete si esta dentro de un rango establecido lo deja pasar sino un cilindro neumático le pega al paquete y lo descarta. El programa es muy mejorable porque los pesos establecidos son fijos pero como eso nunca se modifica no lo vi necesario use los tan odiados delays, pero en este caso una vez que se peso el paquete no tengo otra cosa que hacer. En principio tenía dudas si andaría porque he leído que arduino no sirve para entornos industriales y hasta un ING me dijo una vez que deje de perder el tiempo con arduino.. en fin haciendo números hasta ahora pasaron aproximadamente 8.060.000 paquetes por la balanza hecha con arduino y sigue funcionando perfectamente, Diseño de PCB no hice porque lo arme en uno de esos PCB que ya vienen perforados.
Esta es la lista de materiales que use:

Arduino Nano
LCD 16X2 I2C
Sesor de proximidad Infrarojo
Hx711
Celda de Carga 5Kg
Modulo LED RGB
Fuente step-down (LM2596)
Lm317
Bc337 x 4
2.2K x 5
470
100nF
100mF
1N4007

Esquema:

Con este codigo se calibra la celda de carga:

#include "HX711.h"
 
// Pin de datos y de reloj
byte pinData = 5;
byte pinClk = 4;
 
HX711 bascula;
 
// Parámetro para calibrar el peso y el sensor

float factor_calibracion = 397900 // Celda Arduino 5Kg 

void setup() {
  Serial.begin(9600);
  Serial.println("HX711 programa de calibracion");
  Serial.println("Quita cualquier peso de la bascula");
  Serial.println("Una vez empiece a mostrar informacion de medidas, coloca un peso conocido encima de la bascula");
  Serial.println("Presiona + para incrementar el factor de calibracion");
  Serial.println("Presiona - para disminuir el factor de calibracion");
 
  // Iniciar sensor
  bascula.begin(pinData, pinClk);
 
  // Aplicar la calibración
  bascula.set_scale();
  // Iniciar la tara
  // No tiene que haber nada sobre el peso
  bascula.tare();
 
  // Obtener una lectura de referencia
  long zero_factor = bascula.read_average();
  // Mostrar la primera desviación
  Serial.print("Zero factor: ");
  Serial.println(zero_factor);
}
 
void loop() {
 
  // Aplicar calibración
  bascula.set_scale(factor_calibracion);
 
  // Mostrar la información para ajustar el factor de calibración
  Serial.print("Leyendo: ");
  Serial.print(bascula.get_units(3), 3);
  Serial.print(" kgs");
  Serial.print(" factor_calibracion: ");
  Serial.print(factor_calibracion);
  Serial.println();
 
  // Obtener información desde el monitor serie
  if (Serial.available())
  {
    char temp = Serial.read();
    if (temp == '+')
      factor_calibracion += 10;
    else if (temp == '-')
      factor_calibracion -= 10;
  }
}

Y este es el programa de la balanza:

#include <Wire.h>      // libreria de comunicacion por I2C
#include <LCD.h>      // libreria para funciones de LCD
#include <LiquidCrystal_I2C.h>    // libreria para LCD por I2C

LiquidCrystal_I2C lcd (0x27, 2, 1, 0, 4, 5, 6, 7); // DIR, E, RW, RS, D4, D5, D6, D7


#include "HX711.h"

#define DEBUG_HX711

// Parámetro para calibrar el peso y el sensor

#define CALIBRACION 397900 // Celda Arduino 5Kg 

// Pin de datos y de reloj
byte pinData = 5;
byte pinClk = 4;
byte pin = 2;
byte sensor = 0;
byte pinLed = 6;
byte pinLed1 = 7;
byte pinLed2 = 8;
byte cilindro = 9;

float peso = 0;


// Objeto HX711
HX711 bascula;

void setup() {

  lcd.setBacklightPin(3, POSITIVE); // puerto P3 de PCF8574 como positivo
  lcd.setBacklight(HIGH);   // habilita iluminacion posterior de LCD
  lcd.begin(16, 2);
  lcd.setCursor (1 , 1);
  lcd.print ("Esperando peso");


  pinMode (pinLed, OUTPUT);
  pinMode (pinLed1, OUTPUT);
  pinMode (pinLed2, OUTPUT);
  pinMode (cilindro, OUTPUT);
  digitalWrite (pinLed2, HIGH);

#ifdef DEBUG_HX711

#endif

  // Iniciar sensor
  bascula.begin(pinData, pinClk);
  // Aplicar la calibración
  bascula.set_scale(CALIBRACION);
  // Iniciar la tara
  // No tiene que haber nada sobre la balanza
  bascula.tare();
}

void loop() {


  sensor = digitalRead (pin);
  if (sensor == LOW)
  {

#ifdef DEBUG_HX711
    peso = bascula.get_units(8), 3; // cantidad de veces que pesa (), digitos que se muestran 3.  
#endif


    digitalWrite (pinLed2, LOW);
    lcd.setCursor(4, 0);
    lcd.print(peso, 3); // cantidad de caracteres que se muestran del float
    lcd.setCursor(9, 0);
    lcd.print (" Gr");
    lcd.setCursor (0, 1);
    lcd.print ("                ");

    if (peso > 1.031) {
      digitalWrite (pinLed, HIGH);
      delay (650);
      digitalWrite (pinLed, 0);
      digitalWrite (cilindro, HIGH);
      delay (300);
      digitalWrite (cilindro, LOW);

    }
    if (peso < 1.030 && peso > 0.990) {
      digitalWrite (pinLed1, HIGH);
      delay (700);
      digitalWrite (pinLed1, 0);


    }
    if (peso < 0.989) {
      digitalWrite (pinLed, HIGH);
      delay (650); //1130
      digitalWrite (pinLed, 0);
      digitalWrite (cilindro, HIGH);
      delay (300);
      digitalWrite (cilindro, LOW);

    }
  }
}

Algunas fotos:

1 Like

¡Excelente trabajo!

Si me permites una sugerencia, podrías cambiar las comparaciones de este modo

if (peso < 1.030 && peso > 0.990) {
  digitalWrite (pinLed1, HIGH);
  delay (700);
  digitalWrite (pinLed1, 0);
}
else {
  digitalWrite (pinLed, HIGH);
  delay (650); //1130
  digitalWrite (pinLed, 0);
  digitalWrite (cilindro, HIGH);
  delay (300);
  digitalWrite (cilindro, LOW);
}

con el mismo resultado ya que descartas todo paquete que este por fuera del rango aceptable.

Saludos

1 Like

Hola gatul tenes razon !! no me había dado cuenta de poner un else ahora si queda aun mas corto el programa jeje.
Gracias !
Saludos

Cual es el sentido de esto si luego no lo usas?

El año pasado trabajé en algo parecido y llegué a la conclusión que la lectura de peso dinámico arroja errores si no se cuenta con un dosificador que regule el paso del material que se desea medir. Esos 3 gr son maravillosos pero pueden aun mejorarse.
Un tornillo sin fin que se carga con una tolva movida por un motor paso a paso es el dosificador perfecto. Con el llevas el control perfecto de la carga.

El equipo te quedó muy vistoso y como siempre, son consejos para ajustar detalles. Lo realizado es excelente, tu mismo lo has dicho, funciona mejor que el comercial.

Si, magnifico trabajo. Pero a mi me surgen unas dudas en cuanto al codigo ya que no me compila y no tengo una pantalla Lcd i2C para probar.

¿ Porque cargas dos librerias para la pantalla ?

#include <LCD.h>      // libreria para funciones de LCD
#include <LiquidCrystal_I2C.h>    // libreria para LCD por I2C

Si solo usas la segunda, que a mi me da error de compilacion tal como la tienes:

LiquidCrystal_I2C lcd (0x27, 2, 1, 0, 4, 5, 6, 7); // DIR, E, RW, RS, D4, D5, D6, D7

Y si es I2C ¿ Porque le das los pines extra como si no fuera I2C ? .Pines , (4 al 7), pines que ademas usas para otras cosas. ¿No seria mejor llamarla asi:?

LiquidCrystal_I2C lcd (0x27, 16, 2); // DIR, columnas, filas

Aunque si sigo este criterio me surge un nuevo error de compilacion en la primera de estas lineas:

  lcd.setBacklightPin(3, POSITIVE); // puerto P3 de PCF8574 como positivo
  lcd.setBacklight(HIGH);   // habilita iluminacion posterior de LCD

Lineas que hacen lo mismo, pero creo que la primera es para una pantalla no I2C. Comentando esa primera linea ya compila sin problemas, creo que debeias probarlo.
Saludos.

Hola Surbyte el primer programa que subi se usa para saber el factor de calibracion de la celda de carga. Una vez que obtengo el valor colocando un peso conocido sobre la celda lo uso para el programa de la balanza de peso dinamico

#define CALIBRACION 397900

En este caso la envasadora tiene un tornillo sin fin vertical que lo hace girar un servo motor y en un teclado con display el operador puede modificar los pulsos por vuelta, por decir un numero 10000 pulsos es 1Kg y variando los pulsos va a ajustando el peso, la maquina saca 28 paquetes por minuto.

Hola gonpezzi esto lo hice hace mas de 2 años y recien estaba empezando con Arduino la verdad ni revise el programa antes de publicarlo, tenes razon lo que decis LCD.h no tiene sentido seguramente eso me quedo porque cuando estaba probando el programa no tenia una display I2C y depues si use uno para el proyecto, pero de todos modos ami me compila sin problemas.

Sigo maravillado de los resultados de algo que parece tan simple.
Insisto, excelente trabajo.

Saludos

Si, asi debe ser. Perfecto!!

Hola consulta con que manejas el tornillo sin fin , tenés algún relé conectado?

Lo lógico sería tener un motor paso a paso o un motor DC controlado por PWM con el que puedas manejar la velocidad. La idea es que a medida que se llena la bolsa tu puedas modificar la dosificación de modo que el ultimo tramo sea lento y solo para llegar al valor deseado dentro de la tolerancia.

Hola joaquin661 el sin fin tiene un servomotor con su controlador y un teclado donde se ingresan la cantidad de pulsos. como di el ejemplo por decir un numero 10000 pulsos es aprox 1 kg de producto luego el paquete pasa por la balanza dinamica y ahi se pesa el paquete si esta fuera del peso establecido descarta lo descarta, en casi de faltarle peso el operario sube los pusos en el teclado que controla el servo en caso de estar por arriba baja los pulsos.

1 Like

No veo para que un operario tenga que hacer manualmente algo, que pudiera ser automático.
Tu vas leyendo el peso y cuando se aproximas bajas la velocidad del stepper. Cambias a modo lento y te aproximas. Eso no debería fallar.
Claro que son enfoques.

Hola surbyte eso que decis esta bien pero seria muy lento imaginate que la envasadora llena 1Kg en 2.1 segundos. Para eso tiene un servomotor de 2hp con su driver, comunicar un Arduino con ese driver esta fuera de mis conocimientos ademas que seria dificil lograr presicion porque desde que lleno el paquete hasta que lo peso hay 20 paquetes antes. fijate que tiene un carrusel la envasadora donde van entrando los paquetes los llena, tambien los vibra para que se asiente el harina y despues pasan por la balanza dinamica.

No entiendo.
Hablo de programar una rampa y tal vez ni eso. Solo frenarse al final y dosificar mas lento.
Eso es rápido en ejecución.
Pero solo era una idea.

Entonces no lo pesas dinámicamente, o al menos yo lo interpreto asi. Tu lo llenas con esa cantidad de pasos que te da bastante bien por no decir casi perfecto, pero no es que lo estas pesando mientras se llena.

El driver de 2HP como si fuera de 50HP da igual. Es un driver y seguramente es un TB6600 aunque habrá cientos, solo que este es muy usasdo. Este driver solo le metes pulsos, quires 10000 pasos pues le envias un high seguido de un low con retardos de 400us minimo.
Imagina que enviaras 9990 pusos y los ultimos 10 le cambias la velocidad simpemente alargando los pulsos y cuando leas 1.000 chau.
A eso me refería.

@Surbyte entiendo tu planteo y también entiendo que el amigo @mvvs35 desarrolló un reemplazo de la etapa de pesaje de la balanza, no hizo un proyecto completo, es lógico entonces que se adaptara al hardware disponible y por lo tanto no interviniera el resto de la máquina.

Saludos

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.