Start averaging Load Cell value over 1min when threshold value is reached

Hey,
I´d love to hear your advice on this:

Project description:

I want to continuously read a load cell value and display the current weight (in kg) and a max Value (in kg) on an LCD. -> This is already working!

When a threshold Value of (lets say 2kg) is reached I want to start a loop that averages the load cell value over 1 min and displays the average value on the display. After 1 min the loop should stop, leave the average number on the display and wait until I reset the "AveragingLoop". -> This is where I´m stuck

Right now I´m using a Potentiometer instead of a LoadCell for prototyping. And I can calculate an average over 1min, but I can´t get the timer to start at a threshold value and reset the averaging loop after 1min has passed.

Cheers,
Johannes

#include <LiquidCrystal.h>
LiquidCrystal lcd(12,11,5,4,3,2);
int adcValue;  // Sensor Value
float voltage;
float max1 = 0;  // max
int LedPin = 7; // LED Pin lights up after the 1min Interval is over

unsigned long total; // this block is used to calculate the average
float count;         // 
unsigned long whenStarted; //
const unsigned long INTERVAL = 10000;  // 1 min Inteval




void setup() {
lcd.begin(16,2);
lcd.clear();
delay(1000);
whenStarted = millis ();
pinMode(LedPin, OUTPUT); //

}

void loop() {

  int adcValue = analogRead(A0); // read the loadCell Value (right know its not a loadCell, just a Potentiometer for testing
  voltage = adcValue * (5.0/1023.0); // converts the Potentiometer Values to Volts 

lcd.setCursor(0,0);
lcd.print("Volt: "); // this will be Kg later on when I actually use a loadCell
lcd.print(voltage);  




if (voltage > max1){ // Calculate the Maximum Voltage and display a running max on the LCD
  max1 = voltage;
}
lcd.setCursor(0,1);
lcd.print ("MAX:");
lcd.print (max1);
lcd.print(" Av:");  // Place holder for the Average over 1min. 

total += analogRead(0)*5.0/1023.0; // calculate average in Volts
  count++;
  
//while (voltage >= 2){  // this was my approach to start the if loop only if a threshold value is reached. But it´s not working
//total = 0;
//count = 0;
// whenStarted = 0;

if (millis() - whenStarted  >= INTERVAL) {// is a minute up?
   
digitalWrite(LedPin, HIGH); // LED lights up when 1min is over
lcd.print(total/count); // displays the averageValue 
delay(2000);            //bad solution!!! I want to display the value until I press reset or manually reset the if loop
//total = 0;   
//count = 0;
//whenStarted = millis ();
digitalWrite(LedPin, LOW);

while (1);  // executes the if loop just once. Again bad solution!! I don´t want to be stuck in the if loop forever. I want to leave it after the push of a button or automatically.
}

//}


}

I think you want something like this. It only samples the input once per second but that can be adjusted. One way to re-start it is to hit the Reset button on the Arduino but it will also re-start whenever the input goes below threshold.

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const byte LoadCellAIPin = A0;
const byte LedDOPin = 7; // LED Pin lights up after the 1min Interval is over


unsigned long StartOfMeasurementInterval;
const unsigned long MeasurementInterval = 1000;  // one second


unsigned long StartOfAveragingInterval;
const unsigned long AveragingInterval = MeasurementInterval * 60;  // One minute
float MaxVoltage = 0;  // max
unsigned long Total; // Total in 1/100ths of a volt
unsigned SamplesAveraged = 0;


void setup()
{
  lcd.begin(16, 2);
  lcd.clear();


  pinMode(LedDOPin, OUTPUT);
  digitalWrite(LedDOPin, LOW);  // LED Off


  StartOfAveragingInterval = StartOfMeasurementInterval = millis();
}


void loop()
{
  unsigned long currentMillis = millis();


  // Take a sample every second
  if (currentMillis - StartOfMeasurementInterval >= MeasurementInterval)
  {
    StartOfMeasurementInterval += MeasurementInterval;


    float voltage = (analogRead(A0) * 5.0) / 1024.0; // converts the Potentiometer Values to Volts


    if (voltage < 2.0)
    {
      // Below threshold.  Start a new averaging interval
      StartOfAveragingInterval = StartOfMeasurementInterval = millis();
      MaxVoltage = 0;
      Total = 0;
      SamplesAveraged = 0;
      return;  // Nothing more to do until going above threshold
    }


    // Above Threshold
    Total += (unsigned long) (voltage * 100.0);  // Keep two decimal places
    SamplesAveraged++;


    if (voltage > MaxVoltage)  // Calculate the Maximum Voltage and display a running max on the LCD
    {
      MaxVoltage = voltage;
    }


    // Display the current reading
    lcd.setCursor(0, 0);
    lcd.print("Volt: "); // this will be Kg later on when I actually use a loadCell
    lcd.print(voltage);
    lcd.print("   ");  // In case the new value is shorter


    // Only display max and average if the averaging interval is not done
    if (currentMillis - StartOfAveragingInterval < AveragingInterval)
    {
      lcd.setCursor(0, 1);
      lcd.print ("MAX:");
      lcd.print (MaxVoltage);
      lcd.print(" Av:");  // Place holder for the Average over 1min.
      lcd.print((Total / SamplesAveraged) / 100.0);
      lcd.print("   ");  // In case the new value is shorter
    }
  }
}

Hey John,

thanks for your advice! This method works really well and I will implement it into my sketch! The only Problem I have is that after the 60sec interval has passed I want to keep the averaging Value displayed on the lcd. Right now the average Value disappears directly after.

My next plan would be to display the current value, max and avg on the screen (Menu I) and by the push of a button the lcd switches to just current value and max (Menu II). Push again and it switches back to currentValue, max and avg screen (Menu I) ...

I tried using different ways of building that simple menu structure. I could somehow get it to work but the values only update when switching from menu I to menu II. When I am in a Menu (either I or II) the values will not update.
How can I read the sensor constantly when I am in a Menu ?

#include <LiquidCrystal.h>
#include <HX711_ADC.h> // https://github.com/olkal/HX711_ADC
LiquidCrystal lcd(12,11,5,4,3,2);
HX711_ADC LoadCell(8, 9);
#include <EEPROM.h>

#define SAMPLES 1
#define IGN_HIGH_SAMPLE 0 
#define IGN_LOW_SAMPLE 0
#define SCK_DISABLE_INTERRUPTS  1 //default value: 0

float max1 = 0;  // max calculation

unsigned long total; // this block is used to calculate the average
float count;         // 
unsigned long whenStarted; //
//const unsigned long INTERVAL = 500;  // not in use right now

int MenuButton = 10; // MENUE Button
boolean ButtonPressed = false; // state of MENU button


void setup() {
  LoadCell.begin(); // start connection to HX711 loadCell amplifier
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(4390.0); // correction factor for LoadCell

lcd.begin(16,2);

whenStarted = millis ();
pinMode(MenuButton, INPUT_PULLUP);

}

void loop() {
LoadCell.update();
float i = LoadCell.getData(); // get output value


if (digitalRead(MenuButton) == LOW) { //MENU 
  delay(10);
if (digitalRead(MenuButton) == LOW) { // MENU I
  reverseLED();
  while (digitalRead(MenuButton) == LOW); // MENU II 
  delay (10);
  
  
}
}
}

void reverseLED() {
  if(ButtonPressed) {  // MENUE 1
  
  LoadCell.update(); 
  float i = LoadCell.getData(); // get output value
    
  lcd.clear();
  lcd.setCursor(0, 0); // set cursor to first row
  lcd.print("Kg:"); // print out to LCD 
  lcd.print(i/10,1); // print out the retrieved value to the second row
  
if (i/10 > max1){ // Calculate the Maximum Voltage and display a running max on the LCD
  max1 = i/10;
}
lcd.setCursor(0,1);
lcd.print ("MAX:");
lcd.print (max1,1);
lcd.print(" Avg:");  // Place holder for the Average  

if(i>1) { // Start Averaging when moren than 1kg is applied to the LoadCell

total += i/10; // // calculation for running average
  count++;
}

lcd.print(total/count,1); // displays the averageValue 

    ButtonPressed = false; // read button state

  }

else { //MENUE II

LoadCell.update();
float i = LoadCell.getData(); // get output value
    
  
    lcd.clear();
if (i/10 > max1){ // Calculate the Maximum Voltage and display a running max on the LCD
  max1 = i/10;
}


lcd.setCursor(0,1);
lcd.print("Kg:"); 
lcd.print(i/10,1);
lcd.print ("MAX:");
lcd.print (max1,1);
    
    
    ButtonPressed = true;
  }

 
}

JCB_Herrmann:
The only Problem I have is that after the 60sec interval has passed I want to keep the averaging Value displayed on the lcd. Right now the average Value disappears directly after.

I think you have added an "lcd.clear();" that I did not have. If you clear the LCD you will have to add code to re-draw the parts of the LCD display that you didn't want erased.

Hey John,

sorry for the confusion! The last code I´ve send was my old version which did not include your alterations, thats why there is a lcd.clear() in it.
I haven´t altered your code yet but want to know how I can keep the average value displayed after the 60sec interval has passed.

Do you have any suggestions regarding my Menu problem?

Cheers,

Johannes

JCB_Herrmann:
I haven´t altered your code yet but want to know how I can keep the average value displayed after the 60sec interval has passed.

Just don't clear the LCD or write over the line that contains the average.