Project

Hello I'm working on a project for school and I'm having a bit of road block.

I'm got the first part figured out. I'm having a problem with the heatbox aspect of this project. Any advice or direction where I could explain this better would be helpful.
· During initial board start-
o All LEDs flash 3 times within 2 seconds
· Normal Operations
o White LED 1 turns on in light conditions and off in dark conditions
o White LED 2 turns on in dark conditions and off in light conditions
o White LED 3 turns on with first button press and stays on until a second button press. –Tied to heating process described below
o LED 4 turns on and stays on the entire time the board is running except:
§ At 30 second intervals – LED 4 turns of and back on.
o Heating Box Maintains a temperature of 30-40 Celsius
§ When Heating Element is engaged – LED5 is on
§ Heating Box Control Modes –
· Open Loop Control Mode
o After First Button Press
§ LED 6 is on
§ Heating Element turns on for an estimated amount of time to up temp
§ Element Turns off After Duration
§ Fan Vents Chamber for 3 seconds
· Closed Loop Limit Cycle Control
o After Second Button Press
§ LED 6 and LED 7 Is On
§ Temp Sensor Monitors Temp in Hot Box
Heater Turns On/Off when appropriate

What is the problem with the box?

So post the code for the part that you have figured out and include your attempt to get the rest going and details of any problems.

Then if you want help you will also need to provide a lot more information about all the components you are using. Temperature sensor? Heat box? Light sensor? Power? A schematic would also help.

Steve

I recommend a state machine model. Here is an example you can use as a basis. Your sketch will have more states. For example, any part where a timer is running will be a separate state.

// Example Finite State Machine
//
// The pin 13 LED is blinking ON for 0.5s and OFF for 4.5s.
// Until a LOW on D6 triggers it to immediately go ON for 2s, and then return to the 5s cycling.


enum FSMStages {ENTERING, RUNNING, EXITING};
typedef void (FSMStateFunction)(FSMStages stage);


// A function for each state the FSM can be in
void BlinkOn(enum FSMStages stage);
void BlinkOff(enum FSMStages stage);
void ButtonPressed(enum FSMStages stage);


const unsigned long BLINK_ON_INTERVAL = 500;
const unsigned long BLINK_OFF_INTERVAL = 4500;
const unsigned long BUTTON_PRESSED_INTERVAL = 2000;


const byte Button_IPPin = 6;  // INPUT_PULLUP pin for the button


void setup()
{
  Serial.begin(115200);


  pinMode(Button_IPPin, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);


  // Starting in the BlinkOn state
  FSMEnterState(BlinkOn);
}


void loop()
{
  FSMRun();
}


void BlinkOn(enum FSMStages stage)
{
  static unsigned long startTime = 0;
  unsigned long currentTime = millis();
  switch (stage)
  {
    case FSMStages::ENTERING:
      Serial.println("On");
      digitalWrite(LED_BUILTIN, HIGH); // ON
      startTime = currentTime;
      break;


    case FSMStages::RUNNING:
      // Is the interval over?
      if (currentTime - startTime >= BLINK_ON_INTERVAL)
      {
        FSMChangeState(BlinkOff);
      }


      // Has the button been pressed?
      if (digitalRead(Button_IPPin) == LOW)
      {
        FSMChangeState(ButtonPressed);
      }
      break;


    case FSMStages::EXITING:
      break;
  }
}


void BlinkOff(enum FSMStages stage)
{
  static unsigned long startTime = 0;
  unsigned long currentTime = millis();
  switch (stage)
  {
    case FSMStages::ENTERING:
      Serial.println("Off");
      digitalWrite(LED_BUILTIN, LOW); // OFF
      startTime = currentTime;
      break;




    case FSMStages::RUNNING:
      // Is the interval over?
      if (currentTime - startTime >= BLINK_OFF_INTERVAL)
      {
        FSMChangeState(BlinkOn);
      }


      // Has the button been pressed?
      if (digitalRead(Button_IPPin) == LOW)
      {
        FSMChangeState(ButtonPressed);
      }
      break;




    case FSMStages::EXITING:
      break;
  }
}




void ButtonPressed(FSMStages stage)
{
  static unsigned long startTime = 0;
  unsigned long currentTime = millis();


  switch (stage)
  {
    case FSMStages::ENTERING:
      Serial.println("Pressed");
      digitalWrite(LED_BUILTIN, HIGH); // ON
      startTime = currentTime;
      break;


    case FSMStages::RUNNING:
      // Is the interval over?
      if (currentTime - startTime >= BUTTON_PRESSED_INTERVAL)
      {
        FSMChangeState(BlinkOff);
      }
      break;


    case FSMStages::EXITING:
      break;
  }
}


//
// Finite State Machine utility functions
//


void (*FSMCurrentState)(FSMStages stage);


void FSMRun()
{
  (*FSMCurrentState)(FSMStages::RUNNING);
}


// Enter a new state
void FSMEnterState(FSMStateFunction *SF)
{
  FSMCurrentState = SF;
  (*FSMCurrentState)(FSMStages::ENTERING);
}


// Exit current state
void FSMExitState()
{
  (*FSMCurrentState)(FSMStages::EXITING);
}


void FSMChangeState(FSMStateFunction *SF)
{
  FSMExitState();  // Exit current state
  FSMEnterState(SF);  // Enter a new state
}

Here is the code I have thus far

*/
const int lightSensor= 5; //pin for light source
const int button = 10; //pin for button
int buttonState= 0; //state of the button
int LED1 = 8; //pin 1 for LED1
int LED2 = 2; //pin 2 for LED2 
int LED3 = 3; //pin 2 for LED3
int LED4 = 4; //pin 4 for LED4
int LED5 = 5; //pin 5 for LED5
int LED6 = 6; //pin 6 for LED6
int LED7 = 7; //pin 7 for LED7
unsigned long previoustime=0; //setup time for flashing of LED4
int val =0; //set value for button
int old_val = 0; //set old value for button
int state = LOW; //set button off
int sensValue = 0; //variable to hold sensor readings
int buttonVal = 0; //variable to hold button read 


void setup() {
 // put your setup code here, to run once:
 
 pinMode(LED1, OUTPUT); // Intiates pin as an output
 pinMode(LED2, OUTPUT); // Intiates pin as an output
 pinMode(LED3, OUTPUT); // Intiates pin as an output
 pinMode(LED4, OUTPUT); // Intiates pin as an output
 pinMode(LED5, OUTPUT); // Intiates pin as an output
 Serial.begin(9600); //begin serial communication

 lightsOn();
 delay(300);
 lightsOff();
 delay(300);
 lightsOn();
 delay(300);
 lightsOff();
 delay(300);
 lightsOn();
 delay(300);
 lightsOff();

}

void ledThirty(){
 digitalWrite(LED4, HIGH);  // Turn on LED4
 if (millis()- previoustime >=30000){   //set time to flash at 30 seconds 
   digitalWrite(LED4, LOW);    //turn off LED1          
   delay(300);  //delay for LED4
   digitalWrite(LED4, HIGH); // TURN ON LED
   previoustime = millis(); // used to reset previoustime to match millis     
 }
}



void SerialOutput(){
 Serial.print("Value");
 Serial.print(sensValue); //out sensor value to scren
 Serial.print("\n");

}

void lightsOn() {
 digitalWrite(LED1,HIGH); // Turn on LED1
 digitalWrite(LED2,HIGH); // Turn on LED2
 digitalWrite(LED3,HIGH); // Turn on LED3
 digitalWrite(LED4,HIGH); // Turn on LED4
 digitalWrite(LED5,HIGH); // Turn on LED5
 digitalWrite(LED6,HIGH); // Turn on LED6
 digitalWrite(LED7,HIGH); // Turn on LED7
}

void lightsOff(){
 digitalWrite(LED1,LOW); // Turn on LED1
 digitalWrite(LED2,LOW); // Turn on LED2
 digitalWrite(LED3, LOW); // Turn on LED3
 digitalWrite(LED4,LOW); // Turn on LED4
 digitalWrite(LED5,LOW); // Turn on LED5
 digitalWrite(LED6,LOW); // Turn on LED6
 digitalWrite(LED7,LOW); // Turn on LED7
 
}

void buttonPush(){
 
 val = digitalRead(button); //Read PIN position state

 if ((val ==1) &&(old_val ==0)){ //status of the button
 if(state == LOW){ //button off
   state =HIGH; //state of button is on
   
}

    else{ // else statement for if 

     state = LOW; //button off 

    }

 }

 old_val = val;  //set old_val to val



 if (state == LOW){  // if state is low

   digitalWrite(LED5, HIGH); //turn on LED4

     }

     else {

       digitalWrite(LED5, LOW); //Turn off LED4

     }

}

void lightRead(){ //for light sensor 

 if (sensValue <= 300) { //if sensor value is below 500 switch on LED2 

   digitalWrite(LED2, HIGH);
   digitalWrite(LED3, LOW);                      

 }

 else {  //if sensor value is above 500 turn on LED3

   digitalWrite(LED2, LOW);
   digitalWrite(LED3, HIGH);

}

}


void loop() {
 // put your main code here, to run repeatedly:

 sensValue = analogRead(lightSensor); //read data from sensor
 ledThirty();
 lightRead();
 SerialOutput();
 


delay(1000);
}

I haven't even started on temp sensor stuff yet.

Please edit your post to add code tags. See the "How to get the best out of the forum" post.

My apologies

I think it would be best to, as per #3, convert your operations to a state machine or, if using an ESP32 convert your code to using freeRTOS.

You still have not described the actual problems you have.

What is supposed to happen, and what happens instead?

My actual problem is writing the closed loop for the final step. I know I need an if statement that says if the temperature drops below the 40 Celsius that I have to turn on the heater and to turn on the fan if it goes over 60 celsius

If temp < 40 turn on heater

if temp > 60 turn on fan.

Here's a simple (i.e. non PID) concept for a "closed loop" heater control:

.
.
.
//change pin assignments as needed
const uint8_t LED6 = 8;
const uint8_t LED7 = 9;
const uint8_t pinBlower = 10;
const uint8_t pinHeaterRelay = 11;

enum statesHeater
{
    HEATER_INIT = 0,
    HEATER_OFF,
    HEATER_ON,
    HEATER_OVERHEAT
    
};

#define HEATER_CTL_INTERVAL     50ul        //mS    heater control interval

const float TARGET_TEMP = 35.0;             //oC    desired temperature
const float LOW_HYSTERESIS = 1.0;           //oC    low-side hysteresis (temp must fall below desired - low for heater on condition)
const float HIGH_HYSTERESIS = 1.0;          //oC    high-side hysteresis (temp must rise above desired + high for heater off condition)
const float OVERHEAT_THRESHOLD = 60.0;      //oC    overheat temperature at which fans come on and heater turned off
const float OVERHEAT_RECOVERY = 25.0;

void Heater_SM( void )
{
    static uint8_t
        stateHeater = statesHeater::HEATER_INIT;
    static uint32_t
        timeHeater;
    uint32_t
        timeNow = millis();

    if( (timeNow - timeHeater) < HEATER_CTL_INTERVAL )
        return;

    timeHeater = timeNow;
    float TempoC = GetHeaterTemperature();          //<--- return temp in oC            
                                                    //could add filtering if temperature reading is noisy
    
    switch( stateHeater )
    { 
        case    statesHeater::HEATER_INIT:
            digitalWrite( LED7, HIGH );                         //init closed-loop indicator on
            digitalWrite( LED6, LOW );                          //init heater-on indicator off
            digitalWrite( pinHeaterRelay, LOW );                //init heater off
            //
            //...add other inits as required
            //
            
            stateHeater = statesHeater::HEATER_OFF;             //move to off state
        
        break;

        case    statesHeater::HEATER_OFF:
            //normal operation:
            //heater is off now; is temp cool enough to turn heater on?
            if( TempoC <= (TARGET_TEMP - LOW_HYSTERESIS) )
            {
                digitalWrite( pinHeaterRelay, HIGH );           //turn heater on
                digitalWrite( LED6, HIGH );                     //heater-on indicator illuminated
                stateHeater = statesHeater::HEATER_ON;          //move to on state
                
            }//if
        
        break;

        case    statesHeater::HEATER_ON:
            //are we overheating?
            if( TempoC >= OVERHEAT_THRESHOLD )
            {
                digitalWrite( pinHeaterRelay, LOW );            //turn off heater
                digitalWrite( LED6, LOW );                      //heater-on indicator off
                digitalWrite( pinBlower, HIGH );                //blower on           
                stateHeater = statesHeater::HEATER_OVERHEAT;    //move to overheat state
                
            }//if
            else if( TempoC >= (TARGET_TEMP + HIGH_HYSTERESIS) )
            {
                //normal operation:
                //heater is on now; is temp high enough to turn heater off?
                digitalWrite( pinHeaterRelay, LOW );            //turn off heater
                digitalWrite( LED6, LOW );                      //heater-on indicator off
                stateHeater = statesHeater::HEATER_OFF;         //move to off state
                
            }//if
        
        break;

        case    statesHeater::HEATER_OVERHEAT:
            //overheat state
            //temperature must fall below OVERHEAT_RECOVERY temperature to re-enabled loop
            if( TempoC <= OVERHEAT_RECOVERY )
            {
                //temperature is safe:
                digitalWrite( pinBlower, LOW );                 //blower off
                stateHeater = statesHeater::HEATER_OFF;         //go back to off state
                
            }//if
        
        break;
        
    }//switch
    
}//Heater_SM

float GetHeaterTemperature( void )
{
    float
        fTemp = 0.0;
        
    //whatever you do to read temperature

    return( fTemp );
    
}//GetHeaterTemperature

This is the code I'm coded in my Arduino sketch, I won't be able to test it till I get home. Not getting any errors when I check it, but I'm sure there will be some tweaking I need to do to it.

/*
 * Final Lab 
 */
const int lightSensor= 5; //pin for light source
const int tempSensor = 4; //pin for temp sensor
int button = 10; //pin for button
int buttonState= 0; //state of the button
const int Relay1 = 11; // pin for relay 1
const int Relay2 = 12; // pin for relay 2
const int LED1 = 8; //pin 1 for LED1
const int LED2 = 2; //pin 2 for LED2 
const int LED3 = 3; //pin 2 for LED3
const int LED4 = 4; //pin 4 for LED4
const int LED5 = 5; //pin 5 for LED5
const int LED6 = 6; //pin 6 for LED6
const int LED7 = 7; //pin 7 for LED7
int buttonval=0; //value of button 
int timer=0;  //timer value 
unsigned long previoustime=0; //setup time for flashing of LED4
int val =0; //set value for button
int old_val = 0; //set old value for button
const int state = LOW; //set button off
int sensValue = 0; //variable to hold sensor readings
int buttonVal = 0; //variable to hold button read 
int countdownState=0; //count down state
float tval = 0; //Temp value 
float tempcel = 0; // Tempature for celsuis
float diff = 24.03; // differencial
float tempsensValue = 0; // temp sensor reading
 
 
 void setup() {
  // put your setup code here, to run once:
  
  pinMode(LED1, OUTPUT); // Intiates pin as an output
  pinMode(LED2, OUTPUT); // Intiates pin as an output
  pinMode(LED3, OUTPUT); // Intiates pin as an output
  pinMode(LED4, OUTPUT); // Intiates pin as an output
  pinMode(LED5, OUTPUT); // Intiates pin as an output
  pinMode(Relay1, OUTPUT); //relay 1 pin output
  pinMode(Relay2, OUTPUT); // relay 2 pin output
  Serial.begin(9600); //begin serial communication

  lightsOn();
  delay(300);
  lightsOff();
  delay(300);
  lightsOn();
  delay(300);
  lightsOff();
  delay(300);
  lightsOn();
  delay(300);
  lightsOff();

}

void ledThirty(){
  digitalWrite(LED4, HIGH);  // Turn on LED4
  if (millis()- previoustime >=30000){   //set time to flash at 30 seconds 
    digitalWrite(LED4, LOW);    //turn off LED1          
    delay(300);  //delay for LED4
    digitalWrite(LED4, HIGH); // TURN ON LED
    previoustime = millis(); // used to reset previoustime to match millis     
  }
}

 

void SerialOutput(){
  Serial.print("Timer="); //provide text to explain output
  Serial.print(timer); //output variable x value
  Serial.print("\n"); // drop down a line
  Serial.print("buttonState="); //provide text to explain output
  Serial.print(buttonState); //output variable x value
  Serial.print("\n"); // drop down a line
  Serial.print("countdownState="); //provide text to explain output
  Serial.print(countdownState); //output variable x value
  Serial.print("\n"); // drop down a lineSerial.print("Value");
  Serial.print(sensValue); //out sensor value to scren
  Serial.print("\n");
  Serial.print("Temp Value");
  Serial.print(tempsensValue); //out sensor value to scren
  Serial.print("\n");
  Serial.print("Tval");
  Serial.print(tval); //out sensor value to scren
  Serial.print("\n");
  Serial.print("temcel=l");
  Serial.print(tempcel); //out sensor value to scren
  Serial.print("\n");
}

void lightsOn() {
  digitalWrite(LED1,HIGH); // Turn on LED1
  digitalWrite(LED2,HIGH); // Turn on LED2
  digitalWrite(LED3,HIGH); // Turn on LED3
  digitalWrite(LED4,HIGH); // Turn on LED4
  digitalWrite(LED5,HIGH); // Turn on LED5
  digitalWrite(LED6,HIGH); // Turn on LED6
  digitalWrite(LED7,HIGH); // Turn on LED7
}

 void lightsOff(){
  digitalWrite(LED1,LOW); // Turn on LED1
  digitalWrite(LED2,LOW); // Turn on LED2
  digitalWrite(LED3, LOW); // Turn on LED3
  digitalWrite(LED4,LOW); // Turn on LED4
  digitalWrite(LED5,LOW); // Turn on LED5
  digitalWrite(LED6,LOW); // Turn on LED6
  digitalWrite(LED7,LOW); // Turn on LED7
  
}



void lightRead(){ //for light sensor 

  if (sensValue <= 300) { //if sensor value is below 500 switch on LED2 

    digitalWrite(LED2, HIGH);
    digitalWrite(LED3, LOW);                      

  }

  else {  //if sensor value is above 300 turn on LED3

    digitalWrite(LED2, LOW);
    digitalWrite(LED3, HIGH);

}

}

void heater()

{
 if (tempcel >= 30) { //if tempcel is below 30 celsius turn on heater 

    digitalWrite(Relay1,LOW);
    digitalWrite(Relay2,HIGH);
   
                          

  }

  else if(tempcel <=40) {  

    digitalWrite(Relay1, HIGH);
    digitalWrite(Relay2,LOW);
    

}
}

void buttonCheck(){
  buttonval = digitalRead(button);  //check for button press
  if ((buttonval == 1) && (buttonState == 0))
  {
    //if the button is pushed for the first time startup timer etc.
    digitalWrite(LED6, HIGH);
    digitalWrite(Relay1, LOW); //Turn on Heater
    delay(10000);
    digitalWrite(Relay1,HIGH);
    delay(1000);
    digitalWrite(Relay2,LOW);
    delay(3000);
    digitalWrite(Relay2,HIGH);
    Serial.print("button pushed and state should change");
    Serial.print("\n");
    countdownState=1; //set variable to 1 to run countdown used in countdownCheck function
    buttonState=1; //increment buttonState by 1  

  }
  else if ((buttonval == 1) && (buttonState == 1)){
    // if the button is  pushed for the second time - reset everything and shutdown the counting function through countdownState=0
     digitalWrite(LED6, HIGH); //turn on
     digitalWrite(LED7,HIGH); //turn on

    countdownState = 0; //set variable to 1 to run countdown
    buttonState--; //decrement buttonState by 1
    timer=0; //reset the timer
    digitalWrite(LED3, LOW); //turn off LED
    digitalWrite(Relay1, HIGH); //turn on Relay1
  
}
   else if (tempcel >= 30) { //if tempcel is below 30 celsius turn on heater 

    digitalWrite(Relay1,LOW);
    digitalWrite(Relay2,HIGH);
    digitalWrite(LED5, HIGH);
                       

  }
 
   else if (tempcel <=40) {  

    digitalWrite(Relay1, HIGH);
    digitalWrite(Relay2,LOW);
    digitalWrite(LED5, LOW);
 }
}

void countdownCheck(){
  if ((countdownState == 1) && (timer != 30)) { 
    //if the countdown is set to run (countdownState==1) and max time not met, turn on relay, led and increment the timer counter
    timer++; // increment timer
    digitalWrite(Relay1, LOW); //turn on relay
    digitalWrite(LED3, HIGH); //turn on LED
  }
  if ((countdownState ==1) && (timer == 30)){
    //if we hit the maximum timer counter value of 5, reset countdownState to turn off counting and reset buttonState and timer
    countdownState = 0;//reset countdownState to off
    timer = 0; //reset the timer to 0
    buttonState = 0; //reset the buttonState for next cycle
    digitalWrite(Relay1, HIGH); //turn off relay
    digitalWrite(LED3, LOW); //turn off LED
  }

}
       
void tempRead(){
  tempsensValue = analogRead(tempSensor); //read sensor data
    tval = ((tempsensValue*3.3)/1024);
  
  tempcel= (tval * 100) - diff;sensValue = analogRead(lightSensor); //read data from sensor
  
  }
void loop() {
  // put your main code here, to run repeatedly:

  tempRead();
  buttonCheck();
  countdownCheck();ledThirty();
  lightRead();
  heater();
  SerialOutput();
  


delay(1000);
}
 else if (tempcel >= 30)   //if tempcel is below 30 celsius turn on heater

The code does the opposite of what the comment says.

    digitalWrite(Relay1, LOW); //Turn on Heater
    digitalWrite(Relay1, HIGH); //turn on Relay1

These two comments conflict.

The code would be easier to read if you use names like "HeaterRelay" and "FanRelay" rather than "Relay1" and "Relay2". For relay modules that use LOW to turn a relay ON and HIGH to turn a relay OFF it would be less confusing to the reader to define two constants to use with digitslWrite():

const int RelayOn = LOW;
const int RelayOff = HIGH;

Then you could use statements like:

    digitalWrite(HeaterRelay, RelayOn);

instead of:

    digitalWrite(Relay1, LOW); //Turn on Heater

John,

Thank you for catching that and thank you for the suggestions for the Relayon and off. I did change that to my code as it is much easier to read.