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.