Voltage monitoring with timer

Hello all,

I am trying to create a voltage monitoring circuit for ultracapacitor charging.
My goal is to monitor the cap voltage and isolate the power to the charger in the event that the caps do not reach a certain level in a given time. This is my first Arduino project, and I have figured out the voltage monitoring and created an if statement to control the relay. My problem is incorporating a timer into the if statement. I would like for my relay to remain high unless 30 volts is not reached in 10 minutes, else do nothing. I would also like to have a secondary timer that starts after my voltage has surpassed 50 volts and drops back down. If the caps do not reach 53 volts in 5 minutes set relay low, else do nothing.
I know this is a tall request, but if I could get some guidance on setting a timer in an if statement based on analog reading I can hopefully figure it out from there.

Voltage_monitor2.ino.ino (1.01 KB)

OP code posted so that everyone can see it. OP, read the how to use this forum sticky to see how to properly post code.

const int analogPin = A0;    // pin that the sensor is attached to
const int relay = 13;       // pin that the LED is attached to
const int threshold = 20;   // an arbitrary threshold level that's in the range of the analog input
const int buttonPin = 2;
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
   // initialize the LED pin as an output:
  pinMode(relay, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
   
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0)*12.5;
  // print out the value you read:
  Serial.println(voltage);
    int analogValue = analogRead(analogPin);
  if (analogValue < threshold)  
    digitalWrite(relay, LOW);
    

   else 
     digitalWrite(relay, HIGH);}

I would also like to have a secondary timer that starts after my voltage has surpassed 50 volts and drops back down. If the caps do not reach 53 volts in 5 minutes set relay low, else do nothing.

Do you mean:

I would also like to have a secondary timer that starts after my voltage has surpassed 53 volts and drops back down. If the caps do not reach 50 volts in 5 minutes set relay low, else do nothing.

?

Jeremywwilks:
I would like for my relay to remain high unless 30 volts is not reached in 10 minutes, else do nothing.

The "else do nothing" is confusing.

The first part seems simple enough

save the value of millis() when you turn on the relay and check the time regularly with something like this pseudo code

if (millis() - relayStartMills >=  10 minutes)
   if (voltage is too low) {
     turn things off
   }
}

...R

A state machine is perfect for this sort of thing:

(compiles, not tested)...

const int analogPin = A0;    // pin that the sensor is attached to
const int relay = 13;       // pin that the LED is attached to
//const int threshold = 20;   // an arbitrary threshold level that's in the range of the analog input
const int buttonPin = 2;

#define CAP_INIT        0
#define CAP_CHARGE      1
#define CAP_RELAX       2
#define CAP_SAFE        3
//
#define HIGH_THRESH_H   (float)53.0
#define HIGH_THRESH_L   (float)50.0
#define CHRG_THRESH_L   (float)29.8
#define CHRG_THRESH_H   (float)30.2
//
#define CAP_CHARGE_MAX_TIME     600000ul        //10-minute "charge time" limit
#define CAP_CHK_TIME            100             //100mS check intervals in "init" state
#define CAP_RELAX_MAX_TIME      300000ul        //5-minute "relaxation" limit

void setup() 
{
    // initialize serial communication at 9600 bits per second:
    Serial.begin(9600);
    // initialize the LED pin as an output:
    pinMode(relay, OUTPUT);    
    digitalWrite(relay, LOW);   //set relay off until SM establishes the cap's state
    
    // initialize the pushbutton pin as an input:
    pinMode(buttonPin, INPUT);
    
}//setup

// if cap has not reached 30V after 10 minutes open the relay and fault out
// when cap has reached 50V it has 5 minutes to 
void SuperCapStateMachine( void )
{
    float
        volts;
    static byte
        stateCap = 0;
    static unsigned long
        timeCapCheck = 0,
        timeCap = 0,
        timeDelay;
    unsigned long
        timeNow;

    switch( stateCap )
    {
        case    CAP_INIT:
            //while in INIT state check every CAP_CHK_TIME mS
            timeNow = millis();
            if( (timeNow - timeCapCheck) < CAP_CHK_TIME )
                return;
            timeCapCheck = timeNow;

            //get the cap voltage
            volts = ReadCapVoltage();
            //and determine the what state we need to be in
            if( volts >= HIGH_THRESH_H )
            {
                Serial.println( "Timing relaxation..." );
                timeDelay = CAP_RELAX_MAX_TIME;
                stateCap = CAP_RELAX;
                
            }//if
            else if( volts <= CHRG_THRESH_L )
            {
                Serial.println( "Timing charge phase..." );
                timeCap = millis();
                timeDelay = CAP_CHARGE_MAX_TIME;
                stateCap = CAP_CHARGE;
                
            }//else

            Serial.println( volts );

            //cap is somewhere in the happy-zone; turn on the relay
            //and stay in this state monitoring things
            digitalWrite(relay, HIGH);            
            
        break;
                
        case    CAP_CHARGE:
            //waiting for cap to go above CHRG_THRESH_H volts
            //or timeout to occur
            timeNow = millis();
            //if time expired, go to safe state
            if( (timeNow - timeCap) > timeDelay )
                stateCap = CAP_SAFE;
            else
            {
                if( ReadCapVoltage() > CHRG_THRESH_H )
                {
                    Serial.println( "Charge timing complete..." ); 
                    timeCapCheck = millis();               
                    stateCap = CAP_INIT; 
                    
                }//if
                    
            }//if
        
        break;

        case    CAP_RELAX:
            //waiting for cap to go above CHRG_THRESH_H volts
            //or timeout to occur
            timeNow = millis();
            //if time expired, go to safe state
            if( (timeNow - timeCap) > timeDelay )
                stateCap = CAP_SAFE;
            else
            {
                if( ReadCapVoltage() <= HIGH_THRESH_L )
                {
                    Serial.println( "Relaxation timing complete..." );
                    timeCapCheck = millis();                
                    stateCap = CAP_INIT; 
                    
                }//if
                    
            }//if
            
        break;

        case    CAP_SAFE:
            //open the relay and "do nothing"
            digitalWrite(relay, LOW);
            Serial.println( "Relay opened." );
            while(1);
            
        break;

    }//switch
        
}//SuperCapStateMachine

float ReadCapVoltage( void )
{
    int 
        sensorValue = analogRead(A0);
    
    return( (float)sensorValue * (5.0 / 1023.0)*12.5 );
    
}//ReadCapVoltage

// the loop routine runs over and over again forever:
void loop() 
{   
    SuperCapStateMachine();
            
}//loop

Thank you all for your help and advise.

I'm probably more confused now than I was when I started.

What I am trying to achieve is as follows.

First step

const int analogPin = A0; // pin that the voltage sensor is attached to
const int relay = 13; // pin that the relay is attached to. The relay is controlling the 230v input voltage to the charger.

When the board powers up digitalWrite(relay, HIGH)
Monitor dc input on analog pin.
If dc voltage does not reach 30 volts in 10 minutes digitalwrite(relay, LOW)
If it did not reach the 30 volts in 10 minutes and the relay is low wait 30 minutes and try again.
If it did reach 30 volts the relay will stay high.

Second step

If the voltage does not reach 53 volts in 30 minutes digitalwrite(relay, LOW)
If it did not reach the 53 volts in 30 minutes and the relay is low wait 30 minutes and try again.
If it did reach 53 volts in 30 minutes the relay will stay high.

Third step

If the voltage drops below 50 volts start a timer for 10 minutes.
If in 10 minutes the voltage has not returned back to 53 digitalwrite(relay, LOW) wait 30 minutes and digitalwrite(relay, HIGH)
If in 10 minutes the voltage has returned to 53 the relay will remain HIGH.

const int analogPin = A0;    // pin that the sensor is attached to
const int relay = 13;       // pin that the LED is attached to
const int threshold_L = 30;   // an arbitrary threshold level that's in the range of the analog input
const int threshold_M = 50;
const int threshold_H = 53;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // initialize the LED pin as an output:
  pinMode(relay, OUTPUT);

}

// the loop routine runs over and over again forever:
void loop() {

  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0) * 12.5;
  // print out the value you read:
  Serial.println(voltage);
  int analogValue = analogRead(analogPin);
  if (analogValue < threshold_L)
    digitalWrite(relay, LOW);


  else
    digitalWrite(relay, HIGH);
}

I think the example that @Blackfin has proposed in Reply #4 should be close to what you need.

In it he envisages 4 states (don't mind the numbers, they are just for use by the compiler)

#define CAP_INIT        0
#define CAP_CHARGE      1
#define CAP_RELAX       2
#define CAP_SAFE        3

and the system moves from state to the next appropriate one as the measurements or the time direct.

I think if I had been writing the demo I would have used more wordy names for the states to make them more obviously reflect the language the user is familiar with, but that would not affect the performance and Blackfin cannot be expected to be familiar with your use of language.

You need to consider your need as a series of states to see if the 4 that have been proposed fully capture the requirement - maybe there is a need for one or two more. When you have that figured out post your list here Once you have the list the program almost falls into place.

...R