simple timing question that i cant solve

I hate not being able to figure this out and probably is very easy but i cant get this timing setup to work. I have used alot of different searches, websites and tactics but none seem to work. Basic setup is a 24volt battery charger that turns on whenever the battery drops below 24.2 volts. Once activated i want it to stay on for 4 hrs then turn off til the next event. I set it up for 45 sec in the code for testing purposes. I dont want to use the delay function, the code works minus the 45 sec delay. Any help is appreciated

Thank you J

#include<LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int power = 7;
unsigned long start, finished, elapsed;

void setup()
{
  lcd.begin(16, 2);// lcd setup
  pinMode(7, OUTPUT);// actuating relay coil

}

void loop()
{
  start = millis(); // setting up timer for relay
  elapsed = millis() - start;
  int sensorValue = analogRead(A0);//reads battery bank voltage
  float voltage = sensorValue / 18.5;// display correctvoltage on lcd
  lcd.clear();// clears lcd screen
  lcd.setCursor(0, 0);// set cursor
  lcd.print("Voltage= ");
  lcd.print(voltage);



  if (voltage <= 24.2) {
    digitalWrite(power, LOW);// actuate relay to close
  }
  else if (voltage > 24.2) {
    digitalWrite(power,  HIGH);// actuate relay to open
  }
  if (elapsed >= 45000){
    digitalWrite(power, HIGH);// turn off relay after 45 sec
  }








  delay(2000); // 2 sec delay 
}

You want to set start to the time when the thing you want to time actually starts. Not every pass through the loop.

void loop()
{
  start = millis(); // setting up timer for relay
  elapsed = millis() - start;

Think about this for a minute. Can you see why elapsed will always be zero or at best 1. Move that first line inside the if where you turn on the charger.

You probably also want to keep a boolean flag so you only bother to compare the time in the last if statement if the charger is on.

I can see that now, i have been trying all different ways to do this starting to get a little cross eyed. Im new programming in general but is there syntax in arduino for an if statement that " if A happens then B turns on for X min/sec? i don't want it done for me i want to learn the structure. I moved the first line to the charger turn on if statement but still the same issue, leaving the elapsed time where its at would still create the same issue ? I haven't investigated Boolean ill look into it next
thanksJ

#include<LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int power = 7;
unsigned long start, finished, elapsed;

void setup()
{
  lcd.begin(16, 2);
  pinMode(7, OUTPUT);

}

void loop()
{
  
  elapsed = millis() - start;
  int sensorValue = analogRead(A0);//reads battery bank voltage
  float voltage = sensorValue / 18.5;// display correctvoltage on lcd
  lcd.clear();// clears lcd screen
  lcd.setCursor(0, 0);// set cursor
  lcd.print("Voltage= ");
  lcd.print(voltage);



  if (voltage <= 24.2) {
    digitalWrite(power, LOW);
    start = millis();// actuate relay to close
  }
  else if (voltage > 24.2) {
    digitalWrite(power,  HIGH);// actuate relay to open
  }
    if (elapsed >= 45000){
    digitalWrite(power, HIGH);
  }








  delay(2000);
}

You want elapsed to be calculated each time through. You have to know on each pass how much time has elapsed.

When you're saying it doesn't work, what actually does happen? How does that compare with what you expect?

If you mean that the charger turns right off, remember that you've got another condition that would turn it off. If the voltage goes above 24.2 then you won't wait the 45 seconds.

float voltage = sensorValue / 18.5;// display correctvoltage on lcd

Where does the 18.5 come from?

Im using a 0 to 30 volt dc power supply to send various voltages to the voltage divider and arduino. Ive seen the code " float voltage = sensorValue * 5/1024 to display accurately on the lcd on multiforums websites and tutorials. However that didnt work for me i determined through raw voltage what i needed to get the correct voltage to display on the lcd and thats where 18.5 came from and is accurate from 0 to 30

when i power up i start at 25 volts and relay is off when i drop to 24.2 the relay turns on when i go to 24.3 the relay turns off the only delay is the 2 sec between code execution

That was it!! the "else if" statement was causing my issue i see what was going on there.
thank you for your help my brain can rest now J

Im using a 0 to 30 volt dc power supply to send various voltages to the voltage divider and arduino. Ive seen the code " float voltage = sensorValue * 5/1024 to display accurately on the lcd on multiforums websites and tutorials. However that didnt work for me i determined through raw voltage what i needed to get the correct voltage to display on the lcd and thats where 18.5 came from and is accurate from 0 to 30

You need to understand code before you throw it in. That formula calculates the voltage applied to the analog pin with a 5V reference (which is default). If you have a voltage divider or are using a different reference voltage, you need to adjust the calculation to account for that.

jlaughman22:
That was it!! the "else if" statement was causing my issue i see what was going on there.
thank you for your help my brain can rest now J

Without knowing what you did to the else-if clause to fix it, we can't know that you've actually solved the problem.

First, a minor bit:

 if (voltage <= 24.2) {
  ...
  }
  else if (voltage > 24.2) {
    ...
  }

Testing > and <= against the same number is mutually exclusive and covers all cases. Therefore, the conditional on the else-if clause is not needed. Just use else.

Also, literal constants used like this are called magic numbers. This is bad practice. You should declare a constant global variable to represent the battery voltage. That way, if you need to change it while tuning your program, you only need to change it in one place. Something like this:

const float battery_charging_threshold_voltage = 24.2;

Also, the pinMode statement in setup() uses a magic number instead of the power constant you defined.

The more significant potential error hinges on exactly how you want the program to behave. I interpeted your first post's description as saying that, which the voltage hits the charging threshold, it should close the relay for the charging period without caring about the voltage. The way the last sketch you coded is posted, it will turn on the relay when the voltage is 24.2V or below, and turn it off when the charging period expires or the voltage goes above 24.2V.

If you removed the else-if conditional, leaving this:

  if (voltage <= 24.2) {
    digitalWrite(power, LOW);
    start = millis();// actuate relay to close
  }
  if (elapsed >= 45000){
    digitalWrite(power, HIGH);
  }

then the code should work as intended, although depending on the battery type it must be best to have over-current and over-voltage cutoff conditions to turn off the relay if you measure an unsafe condition.