Recomendaciones para mejorar la obtención de datos de un transmisor de presión y la sincronización de dos sensores

Buenas noches comunidad, estoy haciendo un proyecto para la Universidad (ingeniería mecánica) que trata sobre crear un sistema de adquisición de datos para una máquina de ensayos universal (UTM en ingles) del año 60 aprox, los materiales son:

  1. Arduino UNO
  2. Shield Datalogger (SD y RTC) marca Adafruit
  3. Sensor VL53L0X marca Adafruit
  4. Transductor de presión industrial marca Wika modelo A-10
  5. LCD 16x2 con I2C
  6. Protoboard
  7. Fuente de poder (conector jack) de 12V-3A

Una breve introducción del objetivo del proyecto: la meta es digitalizar las acciones de la maquina, con la ayuda de un transductor de presión incorporado en el sistema hidráulico (Fig 1) crear una relación mediante codigo con el marcador analógico (que marca la fuerza ejecutada en kilogramos) de la maquina (Fig 2).
Fig 1:


Fig 2:

La relación entre lo que indica el marcador analogico y el transductor lo estoy haciendo con una función map, cuando no hay fuerza actuando el transductor siempre indica aprox 200, el problema que tengo es que en la maquina aplico 3 toneladas de fuerza y el sensor apenas marca 227, con un comportamiento terrible en todo el espectro (fig 3), en la Fig4 pueden ver los datos manuales (al ojo, viendo el monitor serie) que anoté. En la columna 1 los valores de la carga real que marca la maquina y en la segunda los valores en brutos leídos por el sensor (no la salida de "map").


Fig 3.


Fig 4

Con ese comportamiento no voy a poder crear una relación, por ejemplo, que cuando en la maquina se indique que hay 2000kg de fuerza aplicados en la salida de la función map me muestre 2000kg.

En la Fig 5 todo conectado, que desastre de cablería jajajaj, pero luego voy a cambiar la protoboard por cables soldados al shield datalogger


Fig5

En resumen, mis preguntas son 2:

1) Que me recomiendan para obtener una BUENA relación entre lo que marca la maquina y el sensor?
2) Como establezco una referencia común para la distancia entregada por el sensor VL53L0X y la presión por el transductor, con un delay de 1000 para cada sensor?

El código de todo el sistema es:

#include <VL53L0X.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include "RTClib.h"

RTC_PCF8523 RTC;
VL53L0X sensor;
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int type = 1;// 1=mm , 2= cm
const int analogInPin=A0;
int sensorValue=0;
int outputValue=0;

// Funcion que simula la lectura de un sensor
const int chipSelect=10; // pin 10 para tarjeta sd
int distance()
{
   return 0;
}

//int SensorPin=A0
String unit;// variable para la unida de medida de VL53L0X [mm]
String ano;
String dia;
String mes;
String horas;
String minutos;
String segundos;
String FECHA;
String HORA;
String Nombredelarchivo;
String Imprimir;

void setup() {
  //pinMode(Salida,OUTPUT);
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  // instrucciones para RTC
  if (! RTC.isrunning())
  {
    Serial.println("RTC no está activada");
    //Para ajustar la fecha y hora, por primera vez, a la del computador que está usando, debe descomentar la siguiente linea:
    //RTC.adjust(DateTime(__DATE__,__TIME__));
  }
 Serial.print("Iniciando tarjeta SD ...");
 
  if (!SD.begin(chipSelect))
  {
    Serial.println("Error al iniciar");
    //while(1);
  }
  else {
  Serial.println(" SD Iniciada correctamente");
  }
  // fin instruccion RTC
  ///////////////////////////////////////
  
  // inicio instrucciones para LCD y VL53L0X
  sensor.init();
  sensor.setTimeout(500);

  // Start continuous back-to-back mode (take readings as
  // fast as possible).  To use continuous timed mode
  // instead, provide a desired inter-measurement period in
  // ms (e.g. sensor.startContinuous(100)).
  sensor.startContinuous(500);
  
  // inicializando LCD, 
  lcd.begin();
  // Enciendiendo luz de fondo e impresión de mensaje
  lcd.backlight(); 
  // fin instrucciones para LCD y VL53L0X
}

void loop() {
  // almacenamientos de valores en variable "distance" para sensor VL53L0X
  int distance = sensor.readRangeContinuousMillimeters();
  // Instrucciones para sensor de temperatura:
  sensorValue=analogRead(analogInPin);
  outputValue=map(sensorValue,198,216,0,2100); 
  //función map: (valor de entrada, inicio rango de entrada, final rango de entrada, inicio rango de salida, final rango de salida)
  // analogWrite(analogOutPin, outputValue);
  //delay(1000);

  
  // configuración de varibles para RTC
  DateTime now=RTC.now();
  ano = now.year();
  mes = now.month();
  dia = now.day();
  horas = now.hour();
  minutos = now.minute();
  segundos = now.second();
  FECHA = dia + "/" + mes + "/" + ano + " " ;
  HORA = horas + ":" + minutos + ":" + segundos;
  //////////////////////////////////////////
  Nombredelarchivo = dia + mes + ano + ".txt";
  /////////////////////////////////////////

 // inicio instrucciones para LCD y VL53L0X
 
  // instrucciones para LCD 16x2
  lcd.clear();
  lcd.print("A10:");
  lcd.print(sensorValue);
  lcd.setCursor (0,1); // go to start of 2nd line
  lcd.print("Dist.: ");
  lcd.setCursor (7,1); // go to start of 2nd line
  if(type ==2){
    float distanceCM = (float) (distance/10.0);
      unit ="cm";
      lcd.print(distanceCM);
      //Serial.print(distanceCM);
      //Serial.print(unit);      
    }else{
    unit ="mm";
      lcd.print(distance);
      //Serial.print(distance); 
      //Serial.print(unit);       
    }  

  lcd.print(unit);    
  
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

  //Serial.println();
  delay(1000);
  // fin instrucciones para LCD y VL53L0X
  ///////////////////////////////////////
  
  // instrucciones para impresión en tarjeta SD
  Imprimir= FECHA + HORA + " " + " " + "Distancia: " + distance + " lectura sensor: " + sensorValue;
  File dataFile= SD.open(Nombredelarchivo,FILE_WRITE);
  //Si el archivo está disponible, escribir en el:
  if (dataFile) {
    dataFile.println(Imprimir);
    dataFile.close();
    Serial.println(Imprimir);
  }
  //Si el archivo no se puede abrir, imprimir mensaje de error:
  else {
    Serial.println("Error al intentar escribir en el archivo");
  }
  delay(500); 
 }

Un video (25s) por si quieren verlo..

Saludos!

Solo te puedo orientar con respecto a este punto, me temo que no vas a poder establecer una relacion, porque entiendo que esa maquina es para determinar la elasticidad de un material y el punto de ruptura, y dependiendo de los materiales unos seran mas elasticos que otros y se estiraran mas o menos con la misma presion.

Un ejemplo, si pones una goma elastica la distancia recorrida sera muy grande con poquisima presion, y sin embargo si colocas una probeta de digamos acero al carbono tendras que aplicar una presion enorme y la distancia recorrida sera a los sumo en el punto de ruptura de unos dos centimetros.

Primeramente este sensor no me parece adecuado pero ya lo analizaremos. He visto muchos hilos donde se pretende usar para medir y los resultados nunca fueron los esperables.
Hay que remitirse a ellos.

Esto se te ha pasado por alto o no lo has visto en su verdadera dimensión.

sensorValue=analogRead(analogInPin);
  outputValue=map(sensorValue,198,216,0,2100); 

Pretendes que un sensor que tiene una variación de 216-198 = 18 pasos del AD de 10 bits te de una variación de 2100 pasos? Dime como puede ser eso posible?

Todo lo demás no tiene sentido.
Primero a solucionar esto.
O tu sensor no es el adecuado o no trabaja bien.
Cual es la variación que debe medir ?
de 60 a 3000 kg/cm2? pues busca un sensor que trabaje en ese rango. El tuyo no lo hace.

Revisando las unidades 3000 kg/cm2 son 2.942 bares de modo que tu sensor no sirve porque mide hasta 1000 bares. Extraído de la hoja de datos.
Empieza por ahí.

Entiendo tu punto, pero me refería a que cuando varie "A" unidad en el sensor de presión variará "B" unidad en el sensor de distancia, el tiempo sería lo unico común a ambas mediciones, entonces como lo hago? pongo un delay para que la medida me las muestre por ejemplo cada 2 segundos para cada medida? La idea es construir una curva en donde se represente la variación del sensor y distancia, por ejemplo:

tiempo (s) / distancia (mm) / carga (kg)
.... 1 ...... /.... 50..................../ .....200
.......2....../........50.................../......210
.......3....../........51.................../......300

que ambas medidas estén sincronizadas a una tercera medida, que creo que es el tiempo la obvia, para así después graficarlo.

Espero haberme explicado :slight_smile:

Saludos!

Lo suyo es que las medidas de presion y distancia las tomes consecutivamente ya que simultanemente no se puede hacer, asi habra una correlacion mas directa de ambas medidas, osea tomadas con micro segundos de diferencia, para obtenerlas cada cierto periodo de tiempo es mejor usar la funcion millis() ya que el delay te va a detener el programa en ese punto durante el tiempo que dure dicho delay, no te puedo explicar como implementarlo con millis() porque no he tenido necesidad de usarlo y no estoy muy puesto en ello, pero he visto por el foro un hilo que explica muy bien como implemetar correctamente millis() pero ahora mismo no lo enuentro

¿Donde estas tomando la presión? Alguna vez vi una y había dos circuitos hidráulicos separados, uno de la bomba hidráulica con cilindro principal (el de trabajo ) y otro cilindro separado, el del dial. Los dos cilindros estaban metido uno dentro de otro y a primera vista no se podían diferenciar, salvo por el hecho que salían tres conductos, a diferencia de los esperados dos de un cilindro común ¿Tienes el esquema hidráulico?

Aqui esta lo de millis()

Entender millis y no morir en el intento

Pero al menos los valores que entrega Arduino luego del comando "analogRead" debería ser un poco más lineal pensaba y no con tantas perturbaciones, no te respondí ayer porque quería hacer otra prueba (ver fig 1), hoy el comportamiento fue más estables sin tantas perturbaciones como en el grafico de ayer.
Fig 1:

.

Utilicé el rango "outputValue=map(sensorValue,198,216,0,2100);" en el script porque cuando iba comparando los valores de fuerza entregados por la maquina el sensor indicaba 216 y en la UTM 2100 kg. Pero tienes razón con respecto a la resolución, voy a tener un problema grave ahí.

Puede que esté mal ubicado y no esté midiendo la verdadera presión hidráulica.

Cual es la variación que debe medir?

Esa maquina puede ejercer un máximo de 60 toneladas de tracción, según lo que investigue: su bomba hidráulica puede elevar su presión a un máximo de 350 bar, por eso ese sensor tiene una capacidad máxima de medición de 400 bar. Lo ideal es que la variación pueda hacerlo hasta las 30 toneladas al menos, pero tengo un problema de logística, en este momento no hay probetas (fierros que aguanten más toneladas antes de romperse) y por eso estoy haciendo pruebas con esa cadena que puede romperse con quizás 4 toneladas. Pero aún así, el comportamiento dentro de ese rango es muy errático solo considerando la lectura en bruto del sensor (analogRead) .

Revisando las unidades 3000 kg/cm2 son 2.942 bares de modo que tu sensor no sirve porque mide hasta 1000 bares. Extraído de la hoja de datos.

No, esa máquina muestra en su marcador analógico la fuerza en kilogramos, no en presión, lo que yo deseo hacer es establecer una relación entre la fuerza en kg mostrada por la maquina y el valor que muestre el sensor con ayuda de la función map, y como sé que la presión máximo es de 350 bar dentro del circuito hidráulico compramos un sensor que aguanta máximo 400 bar.

Detalles del producto cuando lo evaluó Wika antes de pasármelo: WIKA Product Pass

Espero haberme explicado bien, es un poco confuso todo esto. Disculpa por el quebrantamiento de las normas que hice (el post en ingles y español), pensé que podía plantear dudas similares en distintos idiomas.

Saludos y gracias por responder!

lguna vez vi una y había dos circuitos hidráulicos separados, uno de la bomba hidráulica con cilindro principal (el de trabajo ) y otro cilindro separado, el del dial. Los dos cilindros estaban metido uno dentro de otro y a primera vista no se podían diferenciar,

Siii esta es parecida, tiene dos cilindros uno dentro del otro!!! Lamentablemente no tengo esquema hidráulico, la maquina es tan antigua que no hay manual por ningún lado, es una maquina marca Riehle modelo KA-120 con una capacidad máxima de tracción/compresión de 60toneladas. Con el operador (por solo su experiencia de años) decidió (decidimos) que ese lugar que indiqué con la foto es el mejor lugar, puede que nos hayamos equivocado y tengo temor que pueda ser eso ya que no es fácil cambiarlo de lugar, hay que fabricar las conexiones y los hilos de unión son difíciles de fabricar a veces. También puede existir la posibilidad que haya quedado aire en la unión, es un lío este proyecto :frowning: .... Además soy estudiante de ingeniería mecánica, a veces siento que me faltan conocimientos más profundos en electrónica para sobrellevar los problemas, fueron 6 años de estudio y en mi carrera vemos sensores, pero no en profundidad como lo hace un electronico o electrico :disappointed_relieved:

SALUDOS!!!!

Gracias! Ya me había leído un post de ese autor y me sirvió harto en su momento. Voy a leer este que me indicas.

Saludos!

Si esta colocado en la linea hidráulica del cilindro de trabajo es de esperar un comportamiento similar a tu figura 3, esos 200 de linea de base se explicarían por la retención de la descarga. Tienes que conectarlo, si o si, dentro de la linea del dial.
saludos

1 Like

No podés usar map() porque no es ni mas ni menos que una regla de 3 simple, por lo tanto es lineal y tu sensor no lo es.

Saludos

1 Like

El problema de map es que opera con enteros largos, enteros al fin. y la regla de 3 no es tal, es la ecuación de una recta con x1, x2, y1 e y2 puntos conocidos. Eso un estudiante de ingeniería sabe resolverlo.
Entiendo que map() luzca cómoda pero no es la solución, porque te pierdes los decimales necesarios. Traducido te hace falta fmap() que es una variante que ya hemos planteado en este foro pero eso cuando el sensor mide adecuadamente y ya te hice ver que no puedes leer una variación de 2100 con un Delta de 18 en el ADC.

Moderador:
Me gustaría que acomodes en tu post inicial todos los temas que tienen que ver con este hilo como referencias para que no queden descolgados.
Voy a cerrarlos a todos y si te quedan dudas las consultas acá.

No, el problema más que una cuestión semántica y de enteros o decimales es que no se puede aplicar una recta a valores que no siguen una recta, no se pierden decimales, se alteran las lecturas.

El sensor permite elegir la alinealidad justamente porque no es lineal, y map() o fmap() (?) son lineales.

Ese es el punto importante no si map() es o no es una regla de 3 simple (que en el fondo lo es igual que lo es la ecuación de la recta).

Saludos

1 Like

Si, estoy de acuerdo @gatul : es un problema de la forma de los datos (la curva que estos describen) más que los decimales de ellos, por eso mostraba las gráficas, porque detectaba que map iba a tener problemas para describir esa forma de la curva, por eso hacía hincapié en el "analogRead" del sensor y quizás ustedes conocían una forma de resolver ese problema, pensé que quizás existe otra función que me pueda ayudar. También tengo el problema que describe @Surbyte , el cual tiene relación con la resolución, la cantidad de unidades que se incrementa en la lectura de la maquina (en kilogramos) es muy alta en comparación a las unidades que aumenta la lectura del sensor, en la siguiente imagen (FIG1 )se puede ver como en el aumento de 4000 unidades (de kilogramos detectados por la UTM) equivalen a 29 unidades en el sensor, una resolución pésima que no sé cómo resolverla.
FIG 1:

En cuanto a la forma de los datos, tengo una idea, que consistiría en caracterizar tramos de datos, y formar rectas con ellas, se puede entender bien esta idea con la siguiente figura:

Es decir, crear una función f=y_1+y_2

Solo tengo que crear un código que sea capaz de hacer eso, Creen que resulte haciendo con map?

Saludos!

Me gustaría que acomodes en tu post inicial todos los temas que tienen que ver con este hilo como referencias para que no queden descolgados.

Te refieres a este post cierto? o te refieres al primer post que hice en este foro?

Voy a cerrarlos a todos y si te quedan dudas las consultas acá.

Ok, en todo caso, en varios marqué la etiqueta "solución", pensé que con eso bastaba para cerrarlos, pero dale nomás, ciérralos, ya obtuve lo que quería de ellos.

Cuando dices, "si te quedan dudas, consúltalas acá" te refieres al tópico "proyectos" o a este post?

Saludos!

Viendo el gráfico "partido" tiene pinta que el cilindro, uno dentro de otro, sea un cilindro telescópico , no el de trabajo y el de carga.
¿Cuando vez el quiebre no se empieza a levantar el cilindro de menor diámetro? Si es así y estas monitorenado la linea de trabajo, ademas debes hacer una corrección por la diferencia de diámetros.
¿Los 200 de linea de base desaparecen al apagar la bomba?

¿Cuando vez el quiebre no se empieza a levantar el cilindro de menor diámetro?

El problema es que cuando estoy haciendo ensayos no se puede ver el cilindro, solo lo puedo ver cuando la maquina está sin nada tracción, entonces no puedo ver si el quiebre se produce cuando uno u otro cilindro se mueve.

¿Los 200 de linea de base desaparecen al apagar la bomba?

Exacto, los 200 no desaparecen nunca, ni cuando la maquina está apagada.

Saludos!

Buenas noches, algunos sabrán que estaba realizando un proyecto que consta de dos sensores, un lcd y un shield datalogger. Tenía todo armado en una protoboard, luego que vi que todo funcionaba correctamente (incluido el código y la actualización de la fecha), procedí a soldar todo en la placa, pueden ver en la siguiente imagen como pasé de prototipo a algo definitivo:

Cuando estaba en la protoboard todo funcionaba bien (bueno, casi todo, el problema del sensor es aparte), se almacenaba correctamente en la sd un archivo txt con la fecha correcta, pero ahora se guarda con una fecha del año 2000 o 2005, y eso que sincronizo con mi pc la hora, pero el error persiste. Pensé que quizás soldé mal algo, pero eso no es, porque todo sigue funcionando bien, el lcd, los sensores, lo unico es que la fecha no se actualiza correctamente. Saqué la pila y la puse de nuevo, pero no sirvió.

El codigo es:

#include <VL53L0X.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include "RTClib.h"

RTC_PCF8523 RTC;
VL53L0X sensor;
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int type = 1;// 1=mm , 2= cm


// Funcion que simula la lectura de un sensor
int distance()
{
   return 0;
}

//int SensorPin=A0
String unit;// variable para la unida de medida de VL53L0X [mm]
String ano;
String dia;
String mes;
String horas;
String minutos;
String segundos;
String FECHA;
String HORA;
String Nombredelarchivo;
String Imprimir;

const int chipSelect=10;

void setup() {
  //pinMode(Salida,OUTPUT);
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  // instrucciones para RTC
  if (! RTC.isrunning())
  {
    Serial.println("RTC no está activada");
    //Para ajustar la fecha y hora, por primera vez, a la del computador que está usando, debe descomentar la siguiente linea:
    //RTC.adjust(DateTime(__DATE__,__TIME__));
  }
 Serial.print("Iniciando tarjeta SD ...");
 
  if (!SD.begin(chipSelect))
  {
    Serial.println("Error al iniciar");
    //while(1);
  }
  else {
  Serial.println(" SD Iniciada correctamente");
  }
  // fin instruccion RTC
  ///////////////////////////////////////
  
  // inicio instrucciones para LCD y VL53L0X
  sensor.init();
  sensor.setTimeout(500);

  // Start continuous back-to-back mode (take readings as
  // fast as possible).  To use continuous timed mode
  // instead, provide a desired inter-measurement period in
  // ms (e.g. sensor.startContinuous(100)).
  sensor.startContinuous(500);
  
  // inicializando LCD, 
  lcd.begin();
  // Enciendiendo luz de fondo e impresión de mensaje
  lcd.backlight(); 
  // fin instrucciones para LCD y VL53L0X
}

void loop() {
  // almacenamientos de valores en variable "distance" para sensor VL53L0X
  int distance = sensor.readRangeContinuousMillimeters();
  // configuración de varibles para RTC
  DateTime now=RTC.now();
  ano = now.year();
  mes = now.month();
  dia = now.day();
  horas = now.hour();
  minutos = now.minute()+9;
  segundos = now.second();
  FECHA = dia + "/" + mes + "/" + ano + " " ;
  HORA = horas + ":" + minutos + ":" + segundos;
  //////////////////////////////////////////
  Nombredelarchivo = dia + "-" + mes + "-" + ano + ".txt";
  /////////////////////////////////////////

 // inicio instrucciones para LCD y VL53L0X
  
 //int distance =sensor.startContinuous(100);
  
  Serial.print("distancia: ");

  // instrucciones para LCD 16x2
  lcd.clear();
  lcd.print("Sensor VL53L0X");
  lcd.setCursor (0,1); // go to start of 2nd line
  lcd.print("Dist.: ");
  lcd.setCursor (7,1); // go to start of 2nd line
  if(type ==2){
    float distanceCM = (float) (distance/10.0);
      unit ="cm";
      lcd.print(distanceCM);
      Serial.print(distanceCM);
      Serial.print(unit);      
    }else{
    unit ="mm";
      lcd.print(distance);
      Serial.print(distance); 
      Serial.print(unit);       
    }  

  lcd.print(unit);    
  
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

  Serial.println();
  delay(100);
  // fin instrucciones para LCD y VL53L0X
  ///////////////////////////////////////
  
  // instrucciones para impresión en tarjeta SD
  Imprimir= FECHA + HORA + " " + " " + "Distancia: " + distance;
  File dataFile= SD.open(Nombredelarchivo,FILE_WRITE);
  //Si el archivo está disponible, escribir en el:
  if (dataFile) {
    dataFile.println(Imprimir);
    dataFile.close();
    Serial.println(Imprimir);
  }
  //Si el archivo no se puede abrir, imprimir mensaje de error:
  else {
    Serial.println("Error al intentar escribir en el archivo");
  }
  delay(500); 
 }
   

Cuál puede ser la cauda del error?

Saludos!

Recompila agregando el seteo que pone fecha del momento de la compilación. Dudo que este en fecha.
O prueba con algun ejemplo que te muestre que fecha tiene.

Moderador:
Deja de crear mas hilos relacionados.