Using if statement with conditional timing

I am trying to modify some code in a project. I did read a bunch of topics in the forum, but not sure I implemented it correctly. The other topics are closed, so I created this one.

Quick summary: When the ADC reaches a threshold, I want a message to be displayed on the display saying 'Maximum Input'. What I am noticing, is the threshold is reached with some spikes with the input signal. So I want to add a bit of timing (not delay) to read the signal when it is tripped and only display 'Maximum Input' after that threshold has reached 2 seconds.

Did I implement this correctly? I want this to happen as the threshold is tripped throughout the operation of the code; not just one time.

Thank you.

 if (analogReading > 4000) {                                                                                  

     lastHighVoltageTime = currentMillis;
  }

  if (lastHighVoltageTime != 0 && currentMillis - lastHighVoltageTime >= 2000) {  

  lcd.setCursor(0, 0);                                                         // set cursor for 1st line     
    lcd.print("   Maximum Input!   ");                                           // print Maximum Input!  
    lcd.setCursor(0, 1);                                                         // set cursor for 2nd line
    lcd.print("   Reduce Voltage   ");                                           // print Reduce Voltage
        
    
    lastHighVoltageTime = 0;                                                     // Don't do it again until the voltage goes high again
  }
 if (analogReading > 4000) {                                                                                  

     lastHighVoltageTime = currentMillis;
  }

If this continues to evaluate, what is the value of lastHighVoltageTime ?

Are you asking if it elevates? Meaning the voltage keeps rising?

I had a chance to run my code and something is not correct. The fastest quick spike over the ADC threshold still makes it display 'Maximum Input' but it delays it on the display by 2 seconds.

So do I have something out of place or something not correct in the expression? I want it to wait until the threshold has been exceeded for two seconds before it displays 'Maximum Input'.

You need to detect when the analog reading goes above the threshold and start the timer. When the timer reaches two seconds, do what you want. To modify your snippet it goes something like this.

if (analogReading > 4000 and lastAnalogReading <= 4000) {
  lastHighVoltageTime = millis();
  timing = true;
}

if (timing && currentMillis - lastHighVoltageTime >= 2000) {
  
  if (analogReading > 4000)//check again after 2 seconds
  {

    lcd.setCursor(0, 0);                                                         // set cursor for 1st line
    lcd.print("   Maximum Input!   ");                                           // print Maximum Input!
    lcd.setCursor(0, 1);                                                         // set cursor for 2nd line
    lcd.print("   Reduce Voltage   ");                                           // print Reduce Voltage

    timing = false;
    //lastHighVoltageTime = 0;
  }// Don't do it again until the voltage goes high again
  else timing = false;  
}

Something like this:


if (analogReading > 4000) 
{         
     if( timingFlag == 0)
     {                                                                         
         lastHighVoltageTime = currentMillis;
         timingFlag = 1;
     }
}

else 
{
    timingFlag = 0;
}


if (timingFlag == 1 && currentMillis - lastHighVoltageTime >= 2000) 
{
    lcd.setCursor(0, 0);                                                        
    lcd.print("   Maximum Input!   ");                                           
    lcd.setCursor(0, 1);                                                         
    lcd.print("   Reduce Voltage   ");                                           
        
    timingFlag = 2;                                                
}

1 Like

That is indeed a quick, short summary.

What happens next?

How long will you display the text?

When does the system goes back to “normal”?

I recommend you to familiarize with the concept of Finite State Machines (fsm). There are excellent tutorials in this forum and elsewhere. Once you grasp the concept you’ll see this project and many others from a different, more effective angle.

Also, draw a timing diagram that helps you to determine exactly how you want the system to behave.

Thank you for replies. I am out of time now and will come back to this tomorrow with feedback.

Yes.

The code @LarryD provides is a state machine in mild disguise.

When a flag takes on more than two values, it is more a "state", flags usually have two values corresponding to true/false or is/isn't.

There's a kind of flag that has only one value, but that's for another day.

Once you have states, naming them makes the code easier to read.

This diagram, which looks like I drew it with my finger for a good reason, shows the state machine.

Until a reading greater then 4000 comes along, we are not timing.

Once one does, we start timing, but if the value falls below we go back to not timing.

On the other hand, if the timer runs out, we say so, then wait for the value to go once more below 4000.

Not quite a thousand words, but much clearer when you can read and write a state transition diagram:

If you do look into FSM finite state machines, you will see the switch/case statement used to handle the states and transitions, in this case easily coded directly from inspection of the diagram.

HTH

a7

2 Likes
int threshold;

const unsigned long MsecPeriod = 2000;
unsigned long msec0;

void
loop (void)
{
    unsigned long msec = millis ();
    int           anlg = analogRead (A0);

    if (threshold < anlg)  {
        if (msec - msec0 > MsecPeriod)  {
            threshold = anlg;
            Serial.println (threshold);
        }
    }
    else
        msec0 = msec;
}

void
setup (void)
{
    Serial.begin (9600);
}

@gcjr I do not see that your code does what the OP has described or implied nor what I have inferred.

The threshold is 4000. If the threshold is exceeded for 2 seconds, print saying so.

We have assumed but the OP has not clarified what to do next. The previous code and suggestions seem to reset after the read value sinks, however briefly, below the threshold.

a7

i assumed he meant maximum input up to that point

Yeah no.

a7

Thanks for the responses.

I condensed my code into the most basic operation and posted it here so you all can see it. I stripped most stuff out that isn't needed and tested this on my board. It works as shown in the code below.

The background is I built an audio Watt meter to measure voltage and calculate / display Watts and Volts. I'm a hardware guy; terrible with software. But I managed to get this running and it has button modes (press and a few press & hold functions - stripped out of code below for simplicity). My issue is I notice as I max the input, there is some settling time. So the voltage from the source goes up, exceeds my limit for just a moment and then settles. So my display message triggers 'Maximum Input'. But in reality, it just exceeded for a tiny moment. That is why I would like to wait 2 seconds (I may trim that to less time once I get this working). I built an AC to DC converter front end with scaling. I'm not shoving 50 volts into the Arduino. I have relays to scale input dividers too. I could live with the message popping up, but I know this can be smoothed out via code.

I'm terrible with algebra and advanced math. I get really lost in the expressions when they become beyond basic. I understand here we are trying to trigger a timer to start when the threshold exceeds 4000 on the ADC. Then wait until that threshold meets or exceeds 2 seconds. Then display 'Maximum Input'. Else do the regular program of convert input voltage to Watts and Volts because we haven't exceeded the threshold for 2 or more seconds.

const int buttonPin6 = 6;                                                        // the pin that the pushbutton is assigned to D6 Ohm Select
const int buttonPin7 = 7;                                                        // the pin that the pushbutton is assigned to D7 AC Volts
int LED1 = 8;                                                                    // LED1 for press and hold indications is assigned to D8
int RELAY1 = 4;                                                                  // Relay for Channel 1 using D4
int RELAY2 = 5;                                                                  // Relay for Channel 2 using D5
unsigned long timer;                                                             // the timer
unsigned long INTERVAL = 5000;                                                   // the repeat interval
boolean LED1State = false;                                                       // LED1 boolean state
unsigned long analogReading;                                                     // variable used in the math function for A0 reading the ADC level
unsigned long analogReading2;                                                    // variable used in the math function for A1 reading the ADC level
unsigned long currentMillis = millis();


unsigned long buttonTime = 0;                                                    // button time = 0
unsigned long lastButtonTime = 0;                                                // last button time = 0
unsigned long longPressTime = 3000;                                              // press and hold time for button longpresstime in milliseconds [3 seconds]
boolean buttonActive = false;                                                    // boolean for button active state
boolean longPressActive = false;                                                 // boolean for long button press


#include <stdlib.h>                                                              // library for dtostrf and sprintf

#include <eRCaGuy_NewAnalogRead.h>

byte pin = A2;                                                                           // input pin (A0)
byte pin2 = A1;                                                                          // input pin (A1)
byte bitsOfResolution = 12;                                                              // commanded oversampled resolution (10-21). Using 12 so A/D is 4096
unsigned long numSamplesToAvg = 1;                                                       // number of samples AT THE OVERSAMPLED RESOLUTION that you want to take and average

ADC_prescaler_t ADCSpeed = ADC_FAST;
                                                                                          /*Speed options to store into ADCSpeed are as follows:
                                                                                            ADC_PRESCALER_128_CLOCK_125KHZ    
                                                                                            ADC_DEFAULT (same as above)                       
                                                                                            ADC_SLOW (same as above)                          
                                                                                            ADC_PRESCALER_64_CLOCK_250KHZ     
                                                                                            ADC_PRESCALER_32_CLOCK_500KHZ     
                                                                                            ADC_PRESCALER_16_CLOCK_1MHZ       
                                                                                            ADC_FAST (same as above)                          
                                                                                            CAUTION_ADC_PRESCALER_8_CLOCK_2MHZ
                                                                                            CAUTION_ADC_PRESCALER_4_CLOCK_4MHZ
                                                                                            CAUTION_ADC_PRESCALER_2_CLOCK_8MHZ
                                                                                            NB: if you change the ADC clock speed, it doesn't just affect this library, it also affects the 
                                                                                            ADC sample rate when calling the standard core Arduino analogRead() function.
                                                                                           */

#include <Wire.h>                                                                // wire library
#include <LiquidCrystal_I2C.h>                                                   // I2C display library


LiquidCrystal_I2C lcd(0x27,20,4);                                                // set the LCD address to 0x27 for a 20 chars and 4 line display

/*
int bl =0;                                                                       // integer for custom character 'bracketleft'
int c =1;                                                                        // integer for custom character 'letter c'
int br =2;                                                                       // integer for custom character 'brackeright'
*/
int smD =0;                                                                      // integer for custom character 'dot'
int smV =1;                                                                      // integer for custom character 'small V'
int smA =2;                                                                      // integer for custom character 'small A'
int sm1 =3;                                                                      // integer for custom character 'small 1'
int sm2 =4;                                                                      // integer for custom character 'small 2'
int smC =5;                                                                      // integer for custom character 'small C'
int smH =6;                                                                      // integer for custom character 'small H'



byte smallV[8] = {                                                               // small V custom character
  B00000,
  B00000,
  B10001,
  B10001,
  B10001,
  B01010,
  B00100,
  B00000,
};

byte smallA[8] = {                                                               // small A custom character
  B00000,
  B00000,
  B00100,
  B01010,
  B01110,
  B10001,
  B10001,
  B00000,
};


byte small1[8] = {                                                               // small 1 custom character
  B00000,
  B00000,
  B00100,
  B01100,
  B00100,
  B00100,
  B01110,
  B00000,
};

byte small2[8] = {                                                               // small 2 custom character
  B00000,
  B00000,
  B00110,
  B01001,
  B00010,
  B00100,
  B01111,
  B00000
};

byte smallC[8] = {                                                               // small C custom character
  B00000,
  B00000,
  B00111,
  B01000,
  B01000,
  B01000,
  B00111,
  B00000
};

byte smallH[8] = {                                                               // small H custom character
  B00000,
  B00000,
  B01001,
  B01001,
  B01111,
  B01001,
  B01001,
  B00000
};

byte smalldot[8] = {                                                             // dot custom character
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00011,
  B00011,
  B00000
};


int buttonState      = 0;                                                        // current state of the button
int lastButtonState  = 0;                                                        // previous state of the button
int loadState = 1;                                                               // load state 
int ACbutton = 0;                                                                // AC button state
int ledState         = 0;                                                        // remember current led state

int buttonState2      = 0;                                                       // current state2 of the button
int lastButtonState2  = 0;                                                       // previous state2 of the button
int loadState2 = 1;                                                              // load state

int buttonState3      = 0;                                                       // current state3 of the button
int lastButtonState3  = 0;                                                       // previous state3 of the button
int loadState3 = 1;                                                              // load state



void displayVAC10() {                                                              // Function call for displayVAC1() which is volts times 10 for when relay is closed and resitor voltage divider is 50.     
      float voltsAC = (5.0*(analogReading + 8)/adc.getMaxPossibleReading() * 10);  // ADC conversion for volts. Analog reading from ADC / max value (running 12 bit=4096) x 5 (Vref).
                  char VAC[10];                                                    // defines the character called 'VAC' and the buffer size
                  dtostrf(voltsAC, 6, 2, VAC);                                     // decimal to string conversion of the float function called 'voltsAC'. (voltsAC is function, 6 is size of characters[three before the decimal, decimal and two after the decimal], 2 is places after decimal point for display, VAC is the name for the string)
                  lcd.setCursor(1, 3);                                             // set cursor to line 3, character 1   
                  lcd.print(VAC);                                                  // display decimal to string called VAC
           }



void displayWATTS8_10() {                                                                    // Function call for displayWATTS8_10() which is Watts times 10 for when relay is closed and resitor voltage divider is 50.   
      float watts = ((sq(5.0*(analogReading + 8)/adc.getMaxPossibleReading() * 10)) / 8);  // ADC conversion for Watts. Analog reading from ADC / max value (running 12 bit=4096) x 5 (Vref), then squared and divided by 8 for 8 ohms.
               char power[10];                                                   // defines the character called 'power' and the buffer size
               dtostrf(watts, 7, 2, power);                                      // decimal to string conversion of the float function called 'watts'. (Watts is function, 7 is size of characters[four before the decimal, decimal and two after the decimal], 2 is places after decimal point for display, watts is the name for the string)                                                                                
               lcd.setCursor(0, 2);                                              // move the cursor to the third line, character 0
               lcd.print(power);                                                 // display decimal to string called 'power'
           }



  
                    
void setup() {
 /* Serial.begin(9600);                                                          //open serial port at 9600 baud
 */
  adc.setADCSpeed(ADCSpeed);                                                     // Configure the adc how you want it (ADCSpeed)
  adc.setBitsOfResolution(bitsOfResolution);                                     // (bits of resolution)
  adc.setNumSamplesToAvg(numSamplesToAvg);                                       // (number of samples to average)
  
  
  analogReference (EXTERNAL);                                                    // Using 5V external voltage reference
  
  
  lcd.init();                                                                    // initialize the lcd
  lcd.backlight();                                                               // turn on lcd backlight

  
  pinMode(buttonPin6, INPUT);                                                    // initialize the button pin as an input Ohm Select
  pinMode(buttonPin7, INPUT);                                                    // initialize the button pin as an input AC Volts
  pinMode(LED1, OUTPUT);                                                         // pin 8 external LED output
  pinMode(RELAY1, OUTPUT);                                                       // pin 4 is relay 1 output
  pinMode(RELAY2, OUTPUT);                                                       // pin 5 is relay 2 output
  timer = millis();                                                              // start timer
  
 /*
  lcd.createChar(0, bracketleft);                                                // creates custom character 0 (left bracket)
  lcd.createChar(1, letterc);                                                    // creates custom character 1 (letter c)
  lcd.createChar(2, bracketright);                                               // creates custom character 2 (right bracket)
  */
  lcd.createChar(0, smalldot);                                                   // creates custom character 0 (dot)
  lcd.createChar(1, smallV);                                                     // creates custom character 1 (small V)
  lcd.createChar(2, smallA);                                                     // creates custom character 2 (small A)
  lcd.createChar(3, small1);                                                     // creates custom character 3 (small 1)
  lcd.createChar(4, small2);                                                     // creates custom character 4 (small 2)
  lcd.createChar(5, smallC);                                                     // creates custom character 3 (small C)
  lcd.createChar(6, smallH);                                                     // creates custom character 4 (small H)
  
  lcd.begin(20, 4);                                                              // set up the number of columns and rows on the LCD

                                                                     // clear the LCD display before the loop
}

void loop() {
  
  analogReading = adc.newAnalogRead(pin);                                        // mating the variable to the pin A0
  analogReading2 = adc.newAnalogRead(pin2);                                      // mating the variable to the pin A1
 
  ACbutton = digitalRead(buttonPin7);                                            // AC volts button pin assignment [pin 7]
  buttonState = digitalRead(buttonPin6);                                         // read the pushbutton and buttonstate is digitalread from button pin [pin 6]
  buttonState2 = digitalRead(buttonPin7);                                        // read the pushbutton and buttonstate is digitalread from button pin [pin 7]
  buttonState3 = digitalRead(buttonPin7);                                        // read the pushbutton and buttonstate is digitalread from button pin [pin 7]
  
  


 if (analogReading > 4000 ) {                           // if sensor value (analog input pin 0 or analog input 2 pin 1) is greater than ADC value 4000 (4.88V)

    lcd.setCursor(0, 0);                                                         // set cursor for 1st line     
    lcd.print("   Maximum Input!   ");                                           // print Maximum Input!  
    lcd.setCursor(0, 1);                                                         // set cursor for 2nd line
    lcd.print("   Reduce Voltage   ");                                           // print Reduce Voltage
    lcd.setCursor(0, 2);                                                         // set cursor for 3rd line
    lcd.print("                    ");                                           // print nothing to blank previous characters
    lcd.setCursor(0, 3);                                                         // set cursor for 4th line
    lcd.print("                    ");                                           // print nothing to blank previous characters      
  }
     
  
    else{ 
     
       
              
               lcd.setCursor(0, 0);                                              // set cursor to top display line, position 
               lcd.print("Watts   8 Ohm Load  ");                                // print text 'Watts @ 8 Ohms'      
               lcd.setCursor(3, 1);
               lcd.write(smC);                                                   // print small C
               lcd.setCursor(4, 1);
               lcd.write(smH);                                                   // print small H
               lcd.setCursor(5, 1);                                              
               lcd.write(sm1);                                                   // print small 1
               lcd.setCursor(6, 1);
               lcd.print("      ");                                              // blank this line area
               lcd.setCursor(12, 1);                                              
               lcd.write(smC);                                                   // print small C
               lcd.setCursor(13, 1);                                              
               lcd.write(smH);                                                   // print small H
               lcd.setCursor(14, 1);                                             
               lcd.write(sm2);                                                   // print small 2
               lcd.setCursor(15, 1);
               lcd.print("   ");                                                 // blank this line area
   
             
                  displayWATTS8_10();                                            // else statement is Realy1 is not active. Then do math for Watts at 8 Ohms (times 10x for resistor divider /50) 
                
                              
                  lcd.setCursor(19, 3);
                  lcd.write(smD);                                                 // print small dot                                
                  lcd.setCursor(7, 3);
                  lcd.write(smV);                                                 // print small V
                  lcd.setCursor(8, 3);
                  lcd.write(smA);                                                 // print small A
                  lcd.setCursor(9, 3);
                  lcd.write(smC);                                                 // print small C                                                                         
                  lcd.setCursor(16, 3);
                  lcd.write(smV);                                                 // print small V
                  lcd.setCursor(17, 3);
                  lcd.write(smA);                                                 // print small A
                  lcd.setCursor(18, 3);
                  lcd.write(smC);                                                 // print small C

                  
        
                  displayVAC10();
                  }
                  
                  
                 
     

 
     

    
  delay(250);
 
 
   
}

Here is a link to a post I had last week about functions. I included a photo of the project.

Of all the responses, this from @LarryD is the easiest for me to follow. But I would like to break it down here and have some help.
if (analogReading > 4000) then do the next statement.
if( timingFlag == 0) This means if timingFlag equals state zero, then do the following:
lastHighVoltageTime = currentMillis; timingFlag = 1 So I get a big confused, but I think this means lastHighVoltageTime is now the current time. Set the timingFlag to state 1.
else the analogReading is not >4000 so the timingFlag state is 0.
if (timingFlag == 1 && currentMillis - lastHighVoltageTime >= 2000) if the timingFlag state equals 1 and current time minus lastHighVoltageTime is greater than or equal to 2000 then display 'Maximum Input....'
timingFlag = 2 set timingFlag to state 2.

I copied this code into my program and removed the other expression for analogRead > 4000. But the code is not working. I never get a message of Maximum input when I reach >4000.

I put the following at the top of the sketch (very top before VOID Setup). Did I code this correctly?

unsigned long currentMillis = millis();
unsigned long timingFlag;
unsigned long lastHighVoltageTime;

More correctly, if (analogReading > 4000) then execute the code in the dependant code block. There may be one line or many lines of code in that block which is delimited with a pair of curly braces

if (analogReading > 4000) 
{         
     if( timingFlag == 0)
     {                                                                         
         lastHighVoltageTime = currentMillis;
         timingFlag = 1;
     }
}
  • When analogReading > 4000 is true, we check the timingFlag (which should be type byte).
    When timingFlag is == 0, we capture the current controller time.
    To prevent continual current time capturing, we make timingFlag = 1. i.e. lastHighVoltageTime = currentMillis; will no longer be executed.

  • If our analogReading ever goes to analogReading <= 4000, we disable our timingFlag i.e. we execute:

else 
{
    timingFlag = 0;
}
  • Assume timingFlag == 1, therefore we check our 2 second TIMER.
    When the TIMER expires, we do the printing then make timingFlag = 2.
    Making timingFlag = 2 prevents any further printing.

  • When we have analogReading <= 4000 we disable timingFlag i.e. we execute:

else 
{
    timingFlag = 0;
}
  • When we get to timingFlag == 0 again, we start another cycle.

  • You should now see timingFlag can be 0 or 1 or 2, depending on where we are in our timing sequence.

1 Like

So much can go wrong if we all out here try to do what you did over there with your editing.

So we can see where you went wrong please post a complete sketch that compiles but does not yet do what you want.

Explain what it does that it should not or does not do what it should.

a7

@LarryD - Thank you for the additional breakdown and explanation.

@alto777 - Here is my same code from post 14, with the addition of @LarryD code. I placed /* */ around my original code that recognizes the analogReading > 4000 and used his code. I added variables at the top of the code for: currentMillis, timingFlag and lastHighVoltage. But I don't know if I did it correctly.

Post 14 explains how things work. The code modified with @LarryD suggestions compiles, but doesn't ever display Maximum Input.

const int buttonPin6 = 6;                                                        // the pin that the pushbutton is assigned to D6 Ohm Select
const int buttonPin7 = 7;                                                        // the pin that the pushbutton is assigned to D7 AC Volts
int LED1 = 8;                                                                    // LED1 for press and hold indications is assigned to D8
int RELAY1 = 4;                                                                  // Relay for Channel 1 using D4
int RELAY2 = 5;                                                                  // Relay for Channel 2 using D5
unsigned long timer;                                                             // the timer
unsigned long INTERVAL = 5000;                                                   // the repeat interval
boolean LED1State = false;                                                       // LED1 boolean state
unsigned long analogReading;                                                     // variable used in the math function for A0 reading the ADC level
unsigned long analogReading2;                                                    // variable used in the math function for A1 reading the ADC level
unsigned long currentMillis = millis();
unsigned long timingFlag;
unsigned long lastHighVoltageTime;

unsigned long buttonTime = 0;                                                    // button time = 0
unsigned long lastButtonTime = 0;                                                // last button time = 0
unsigned long longPressTime = 3000;                                              // press and hold time for button longpresstime in milliseconds [3 seconds]
boolean buttonActive = false;                                                    // boolean for button active state
boolean longPressActive = false;                                                 // boolean for long button press


#include <stdlib.h>                                                              // library for dtostrf and sprintf

#include <eRCaGuy_NewAnalogRead.h>

byte pin = A2;                                                                           // input pin (A0)
byte pin2 = A1;                                                                          // input pin (A1)
byte bitsOfResolution = 12;                                                              // commanded oversampled resolution (10-21). Using 12 so A/D is 4096
unsigned long numSamplesToAvg = 1;                                                       // number of samples AT THE OVERSAMPLED RESOLUTION that you want to take and average

ADC_prescaler_t ADCSpeed = ADC_FAST;
                                                                                          /*Speed options to store into ADCSpeed are as follows:
                                                                                            ADC_PRESCALER_128_CLOCK_125KHZ    
                                                                                            ADC_DEFAULT (same as above)                       
                                                                                            ADC_SLOW (same as above)                          
                                                                                            ADC_PRESCALER_64_CLOCK_250KHZ     
                                                                                            ADC_PRESCALER_32_CLOCK_500KHZ     
                                                                                            ADC_PRESCALER_16_CLOCK_1MHZ       
                                                                                            ADC_FAST (same as above)                          
                                                                                            CAUTION_ADC_PRESCALER_8_CLOCK_2MHZ
                                                                                            CAUTION_ADC_PRESCALER_4_CLOCK_4MHZ
                                                                                            CAUTION_ADC_PRESCALER_2_CLOCK_8MHZ
                                                                                            NB: if you change the ADC clock speed, it doesn't just affect this library, it also affects the 
                                                                                            ADC sample rate when calling the standard core Arduino analogRead() function.
                                                                                           */

#include <Wire.h>                                                                // wire library
#include <LiquidCrystal_I2C.h>                                                   // I2C display library


LiquidCrystal_I2C lcd(0x27,20,4);                                                // set the LCD address to 0x27 for a 20 chars and 4 line display

/*
int bl =0;                                                                       // integer for custom character 'bracketleft'
int c =1;                                                                        // integer for custom character 'letter c'
int br =2;                                                                       // integer for custom character 'brackeright'
*/
int smD =0;                                                                      // integer for custom character 'dot'
int smV =1;                                                                      // integer for custom character 'small V'
int smA =2;                                                                      // integer for custom character 'small A'
int sm1 =3;                                                                      // integer for custom character 'small 1'
int sm2 =4;                                                                      // integer for custom character 'small 2'
int smC =5;                                                                      // integer for custom character 'small C'
int smH =6;                                                                      // integer for custom character 'small H'



byte smallV[8] = {                                                               // small V custom character
  B00000,
  B00000,
  B10001,
  B10001,
  B10001,
  B01010,
  B00100,
  B00000,
};

byte smallA[8] = {                                                               // small A custom character
  B00000,
  B00000,
  B00100,
  B01010,
  B01110,
  B10001,
  B10001,
  B00000,
};


byte small1[8] = {                                                               // small 1 custom character
  B00000,
  B00000,
  B00100,
  B01100,
  B00100,
  B00100,
  B01110,
  B00000,
};

byte small2[8] = {                                                               // small 2 custom character
  B00000,
  B00000,
  B00110,
  B01001,
  B00010,
  B00100,
  B01111,
  B00000
};

byte smallC[8] = {                                                               // small C custom character
  B00000,
  B00000,
  B00111,
  B01000,
  B01000,
  B01000,
  B00111,
  B00000
};

byte smallH[8] = {                                                               // small H custom character
  B00000,
  B00000,
  B01001,
  B01001,
  B01111,
  B01001,
  B01001,
  B00000
};

byte smalldot[8] = {                                                             // dot custom character
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00011,
  B00011,
  B00000
};


int buttonState      = 0;                                                        // current state of the button
int lastButtonState  = 0;                                                        // previous state of the button
int loadState = 1;                                                               // load state 
int ACbutton = 0;                                                                // AC button state
int ledState         = 0;                                                        // remember current led state

int buttonState2      = 0;                                                       // current state2 of the button
int lastButtonState2  = 0;                                                       // previous state2 of the button
int loadState2 = 1;                                                              // load state

int buttonState3      = 0;                                                       // current state3 of the button
int lastButtonState3  = 0;                                                       // previous state3 of the button
int loadState3 = 1;                                                              // load state



void displayVAC10() {                                                              // Function call for displayVAC1() which is volts times 10 for when relay is closed and resitor voltage divider is 50.     
      float voltsAC = (5.0*(analogReading + 8)/adc.getMaxPossibleReading() * 10);  // ADC conversion for volts. Analog reading from ADC / max value (running 12 bit=4096) x 5 (Vref).
                  char VAC[10];                                                    // defines the character called 'VAC' and the buffer size
                  dtostrf(voltsAC, 6, 2, VAC);                                     // decimal to string conversion of the float function called 'voltsAC'. (voltsAC is function, 6 is size of characters[three before the decimal, decimal and two after the decimal], 2 is places after decimal point for display, VAC is the name for the string)
                  lcd.setCursor(1, 3);                                             // set cursor to line 3, character 1   
                  lcd.print(VAC);                                                  // display decimal to string called VAC
           }



void displayWATTS8_10() {                                                                    // Function call for displayWATTS8_10() which is Watts times 10 for when relay is closed and resitor voltage divider is 50.   
      float watts = ((sq(5.0*(analogReading + 8)/adc.getMaxPossibleReading() * 10)) / 8);  // ADC conversion for Watts. Analog reading from ADC / max value (running 12 bit=4096) x 5 (Vref), then squared and divided by 8 for 8 ohms.
               char power[10];                                                   // defines the character called 'power' and the buffer size
               dtostrf(watts, 7, 2, power);                                      // decimal to string conversion of the float function called 'watts'. (Watts is function, 7 is size of characters[four before the decimal, decimal and two after the decimal], 2 is places after decimal point for display, watts is the name for the string)                                                                                
               lcd.setCursor(0, 2);                                              // move the cursor to the third line, character 0
               lcd.print(power);                                                 // display decimal to string called 'power'
           }



  
                    
void setup() {
 /* Serial.begin(9600);                                                          //open serial port at 9600 baud
 */
  adc.setADCSpeed(ADCSpeed);                                                     // Configure the adc how you want it (ADCSpeed)
  adc.setBitsOfResolution(bitsOfResolution);                                     // (bits of resolution)
  adc.setNumSamplesToAvg(numSamplesToAvg);                                       // (number of samples to average)
  
  
  analogReference (EXTERNAL);                                                    // Using 5V external voltage reference
  
  
  lcd.init();                                                                    // initialize the lcd
  lcd.backlight();                                                               // turn on lcd backlight

  
  pinMode(buttonPin6, INPUT);                                                    // initialize the button pin as an input Ohm Select
  pinMode(buttonPin7, INPUT);                                                    // initialize the button pin as an input AC Volts
  pinMode(LED1, OUTPUT);                                                         // pin 8 external LED output
  pinMode(RELAY1, OUTPUT);                                                       // pin 4 is relay 1 output
  pinMode(RELAY2, OUTPUT);                                                       // pin 5 is relay 2 output
  timer = millis();                                                              // start timer
  

 /*
  lcd.createChar(0, bracketleft);                                                // creates custom character 0 (left bracket)
  lcd.createChar(1, letterc);                                                    // creates custom character 1 (letter c)
  lcd.createChar(2, bracketright);                                               // creates custom character 2 (right bracket)
  */
  lcd.createChar(0, smalldot);                                                   // creates custom character 0 (dot)
  lcd.createChar(1, smallV);                                                     // creates custom character 1 (small V)
  lcd.createChar(2, smallA);                                                     // creates custom character 2 (small A)
  lcd.createChar(3, small1);                                                     // creates custom character 3 (small 1)
  lcd.createChar(4, small2);                                                     // creates custom character 4 (small 2)
  lcd.createChar(5, smallC);                                                     // creates custom character 3 (small C)
  lcd.createChar(6, smallH);                                                     // creates custom character 4 (small H)
  
  lcd.begin(20, 4);                                                              // set up the number of columns and rows on the LCD

                                                                     // clear the LCD display before the loop
}

void loop() {
  
  analogReading = adc.newAnalogRead(pin);                                        // mating the variable to the pin A0
  analogReading2 = adc.newAnalogRead(pin2);                                      // mating the variable to the pin A1
 
  ACbutton = digitalRead(buttonPin7);                                            // AC volts button pin assignment [pin 7]
  buttonState = digitalRead(buttonPin6);                                         // read the pushbutton and buttonstate is digitalread from button pin [pin 6]
  buttonState2 = digitalRead(buttonPin7);                                        // read the pushbutton and buttonstate is digitalread from button pin [pin 7]
  buttonState3 = digitalRead(buttonPin7);                                        // read the pushbutton and buttonstate is digitalread from button pin [pin 7]
  
  

if (analogReading > 4000) 
{         
     if( timingFlag == 0)
     {                                                                         
         lastHighVoltageTime = currentMillis;
         timingFlag = 1;
     }
}

else 
{
    timingFlag = 0;
}


if (timingFlag == 1 && currentMillis - lastHighVoltageTime >= 2000)
{
    lcd.setCursor(0, 0);                                                        
    lcd.print("   Maximum Input!   ");                                           
    lcd.setCursor(0, 1);                                                         
    lcd.print("   Reduce Voltage   ");                                           
        
  timingFlag = 2;                                          
}

/*
 if (analogReading > 4000 ) {                           // if sensor value (analog input pin 0 or analog input 2 pin 1) is greater than ADC value 4000 (4.88V)

    lcd.setCursor(0, 0);                                                         // set cursor for 1st line     
    lcd.print("   Maximum Input!   ");                                           // print Maximum Input!  
    lcd.setCursor(0, 1);                                                         // set cursor for 2nd line
    lcd.print("   Reduce Voltage   ");                                           // print Reduce Voltage
    lcd.setCursor(0, 2);                                                         // set cursor for 3rd line
    lcd.print("                    ");                                           // print nothing to blank previous characters
    lcd.setCursor(0, 3);                                                         // set cursor for 4th line
    lcd.print("                    ");                                           // print nothing to blank previous characters      
  }
     
 */ 
    else{ 
     
       
              
               lcd.setCursor(0, 0);                                              // set cursor to top display line, position 
               lcd.print("Watts   8 Ohm Load  ");                                // print text 'Watts @ 8 Ohms'      
               lcd.setCursor(3, 1);
               lcd.write(smC);                                                   // print small C
               lcd.setCursor(4, 1);
               lcd.write(smH);                                                   // print small H
               lcd.setCursor(5, 1);                                              
               lcd.write(sm1);                                                   // print small 1
               lcd.setCursor(6, 1);
               lcd.print("      ");                                              // blank this line area
               lcd.setCursor(12, 1);                                              
               lcd.write(smC);                                                   // print small C
               lcd.setCursor(13, 1);                                              
               lcd.write(smH);                                                   // print small H
               lcd.setCursor(14, 1);                                             
               lcd.write(sm2);                                                   // print small 2
               lcd.setCursor(15, 1);
               lcd.print("   ");                                                 // blank this line area
   
             
                  displayWATTS8_10();                                            // else statement is Realy1 is not active. Then do math for Watts at 8 Ohms (times 10x for resistor divider /50) 
                
                              
                  lcd.setCursor(19, 3);
                  lcd.write(smD);                                                 // print small dot                                
                  lcd.setCursor(7, 3);
                  lcd.write(smV);                                                 // print small V
                  lcd.setCursor(8, 3);
                  lcd.write(smA);                                                 // print small A
                  lcd.setCursor(9, 3);
                  lcd.write(smC);                                                 // print small C                                                                         
                  lcd.setCursor(16, 3);
                  lcd.write(smV);                                                 // print small V
                  lcd.setCursor(17, 3);
                  lcd.write(smA);                                                 // print small A
                  lcd.setCursor(18, 3);
                  lcd.write(smC);                                                 // print small C

                  
        
                  displayVAC10();
                  }
                  
                  
                 
     

 
     

    
  delay(250);
 
 
   
}