Proyecto para automatizar el factor de carga de compresores

Muy buenas, amigos acudo a ustedes de manera urgente,ya que no encuentro la forma de aplicar una fórmula matemática en Arduino y me muestre el resultado en una LCD. Dicha fórmula hace parte de un proyecto para tomar los tiempos de Carga y Vacío para calcular el porcentaje del factor de Carga de unos compresores. Les agradezco de antemano.

Presenta la fórmula y te daremos ayuda.

Pon el código usando etiquetas también asï tendras todo listo para probarlo.

Dicha formula es la la siguiente:

FC: factor de carga
TV: tiempo de vacio
TC: tiempo de carga

FC= TC *100
TC+TV

este es el codigo...

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,9,8,7);
int sensor1=A0;
int sensor2=A1;

int contador1=0;
int contador2=0;
int resultado=0;
void setup()
{
lcd.begin(16,2);
lcd.print("Proyecto");
delay(3000);
pinMode(sensor1,INPUT);
pinMode(sensor2,INPUT);
}

void loop()
{
int val1=digitalRead(sensor1);
delay(100);
int val2=digitalRead(sensor2);
delay(100);

if (val1==HIGH) {contador1++;}
if (val2==HIGH) {contador2++;}

resultado=((contador1+contador2)/contador1*100);
lcd.clear();
lcd.setCursor (0,0);
lcd.print ("FACTOR DE CARGA =" );
lcd.setCursor (0,1);
lcd.print (resultado);
delay (100);
lcd.setCursor(7,1);
lcd.print(contador1);
delay(200);lcd.setCursor(10,1);
lcd.print(contador2);
delay(150);
}

soy algo novato en esto , por tal razón aun no se como usar algunas funciones . le agradezco muchisimo.

Veo que los factores se denominan "tiempo de"; lo que decir que se dan en una unidad de dicha magnitud.
Ahora mi pregunta es: ¿qué unidad es esa? ¿Serán acaso segundos?

Otra pregunta: ¿cómo exactamente se determina cuando está vacío y cuándo bajo carga? Creo que el hecho de leer dos entradas digitales no explica mucho.

PD: para fórmulas como esa, quizá debas usar el tipo float para resultados más exactos.

Comienza dando mayor información sobre los sensores. Son analógicos o digitales? Conectas dos sensores a entradas analógicas que defines correctamente como entradas digitales. Tal vez no tienes mas entradas disponibles. No lo sé pero para eso esta el código y los comentarios. Supongo que no pensaste en hacerlo.

Supongamos que todo eso este bien y de hecho lo está, entonces sondos entradas digitales y tu quieres medir el tiempo ON de cada ciclo.
Si fuera el caso entonces los delay(100) solo permiten que las mediciones sean de 100 mseg en tus contadores.

Bien, vamos a mejorar eso usando millis() y tendras una precisión 100 veces mejor.

Pruebalo a ver si funciona, puede que de algun error

#include <Wire.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,9,8,7);
byte sensor1   = A0;
byte sensor2   = A1;

float resultado = 0.0;
bool val1, val1Ant = false;
bool val2, val2Ant = false;
bool fval1, fval2;
unsigned long TC;
unsigned long TV;

void setup() {
  Serial.begin(9600);
  Serial.println("Proyecto");
  lcd.begin(16,2);
  lcd.print("Proyecto"); 
  delay(3000); 
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
}

void loop() {

  val1 = digitalRead(sensor1);
  if (val1 && !val1Ant) {
      TC = millis();  // inicio
      fval1 = false;  // midiendo TC entonces no puedo calcular resultado
  }
  if (!val1 && val1Ant) { // flanco descendente.
      TC = millis()- TC; // uso la misma variable para medir.
      fval1 = true;   // TC listo para un cálculo
  }
  val1Ant = val1;

  val2 = digitalRead(sensor2);
  if (val2 && !val2Ant) {
      TV = millis();  // inicio
      fval2 = false;  // midiendo TV entonces no puedo calcular resultado
  }
  if (!val2 && val2Ant) { // flanco descendente.
      TV = millis()- TV; // uso la misma variable para medir.
      fval2 = true;   // TV listo para un cálculo
  }
  val2Ant = val2;
  
  if (fval1 && fval2) { // si los dos flags estan 1 entonces calculo
      resultado = 100 * TC / (TC+TV);
      Serial.print("Factor de carga = ");
      Serial.println(resultado);

      lcd.clear();
      lcd.setCursor (0,0);
      lcd.print ("FACTOR DE CARGA =" );
      lcd.setCursor (0,1);
      lcd.print (resultado);
      delay (100);
      lcd.setCursor(6,1);
      lcd.print(TC);
      delay(200);
      lcd.setCursor(10,1);
      lcd.print(TV);
      delay(150);
  }
}

He probado el código con mi simulador y funciona correctamente.

No muestra bien los datos en el LCD (use un I2C asi que debí iniciarlizarlo mal) pero eso te lo dejo a ti.

Muy buenas Amigo,tiene mucha razon en algunas cosas, no estoy usando sensores solo estoy usando la señal de 5vdc de un presostato que esta en la valvula de alivio del compresor.

La formula ya la conoce.. y se nececita tomar el tiempo en segundos de cada entrada.
cabe resaltar que las 2 entradas no pueden estar activas simultaneamente.

En el codigo que me mostro anteriormente funciona ,hace un calculo pero los resultados son algo erroneos ya que contabilice el Tiempo de carga (TC) 135seg. y el tiempo de vacio (TV) 43 seg aplicando la formula , elfactor de carga deberia dar como resultado un 75% aunque esa programacion esta mucho mas cerca de lo que yo estaba , tambien me di cuenta de que se visualizan los 2 contadores pero creo que esta dando los valores en milisegundos, he intentado pasarlos a segundos pero todo lo que hago es dañar el codigo.A lo mejor no estoy usando la funcion correcta para cambiar de unidad.

Muchisimas gracias.

Me sorprende tu comentario.
Si algo lo lees en milisegundos y lo quieres en segundos, solo divide por 1000 y listo!!

Solo modifica esto porque el resto no se alterará poniendo las cosas en segundos

lcd.setCursor(6,1);
      lcd.print(TC/1000);
      delay(200);
      lcd.setCursor(10,1);
      lcd.print(TV/1000);

Al ser de una sola entrada, supongo que algo así debería funcionar:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,9,8,7);

volatile unsigned long TC; // Acumulador en milisegundos
volatile unsigned long TV; // Acumulador en milisegundos
volatile unsigned long tAnterior; // Momento desde el último cambio de estado
volatile bool cargado; // "Bandera" para indicar si es está contando tiempo cargado o vacío

void setup() {
  lcd.begin(16,2);
  lcd.print("Proyecto"); 
  delay(3000);
  cargado = digitalRead(2); // Señal al pin 2
  attachInterrupt(0, cambio, CHANGE);

}

void loop() {
  unsigned long TCA = TC / 1000;
  unsigned long TVA = TV / 1000;
  if (cargado) TCA += (millis() - tAnterior) / 1000;
  else TVA += (millis() - tAnterior) / 1000;
 
  float resultado = 100.0 * (TCA / (TCA+TVA));
  lcd.home();
  lcd.print("FACTOR DE CARGA:");
  lcd.setCursor(0,1);
  lcd.print(resultado);
  lcd.print('%');
  delay(1000);
}

void cambio() {
  unsigned long tActual = millis();
  cargado = !cargado; // Si esta interrupción se dispara, se supone que es porque se cambió el estado

  // Guardar el tiempo transcurrido en el acumuador correspondiente
  if (cargado) TV += tActual - tAnterior;
  else TC += tActual - tAnterior;
 
  tAnterior = tActual;
}

El cambio de estado se maneja por interrupción externa. Se puede hacer sin esta, lo que pasa es que en este momento no estoy para quebrarme la cabeza con tanta variable e if :sweat_smile:

Me funciono perfecto con esto, muchísimas gracias a todos.

lcd.setCursor(6,1);
      lcd.print(TC/1000);
      delay(200);
      lcd.setCursor(10,1);
      lcd.print(TV/1000);