Control a heat pad and fan independently

Hi Folks,

Currently I'm working with a heating element and a sharp IR sensor. Essentially the heating element is heating a page with thermochromic ink. Once the sensor is interacted with the heating element turns on. When I take away my hand from the sensor the heating element turns off. This is working fine for me. Essentially I'm now looking to integrate a fan into the circuit. I've purchased a 2 pin 5v fan online and I'm now looking to turn the heating element on for 30 seconds, once the heating element turns off I'm looking to turn on the fan for thirty seconds. The heating element is being powered by a 12v power supply via a tip122 transistor as a switch. I was thinking of using a similar circuit for the 5v fan and power it with a 3 AA batteries in series, which would be 4.5 volts. Although it's not 5 in theory it should still power it enough.

I suppose I'm wondering how to set up the code to turn on the fan once the heating element turns off after 30 seconds.

Here is the current state of the code for the heating element only, all help would be greatly appreciated on this, thanks folks

#include <SharpIR.h>
#define ir A5
#define model 1080
const int heatPin1 =  7;      // the number of the LED pin
SharpIR sensor(GP2YA41SK0F, A5);
int SharpIR =  A5;
boolean sharpIR = true;

void setup() {
// initialize the LED pin as an output:
pinMode(heatPin1, OUTPUT); 
digitalWrite( heatPin1, LOW );     
Serial.begin(9600);    
}


void loop(){
delay(500);
 

 unsigned long pepe1 = millis(); // takes the time before the loop on the library begins

  int distance = sensor.getDistance(); // this returns the distance to the object you're measuring




  Serial.print(" distance: ");  // returns it to the serial monitor
  Serial.println(distance);

  unsigned long pepe2 = millis() - pepe1; // the following gives you the time taken to get the measurement
  Serial.print("Time taken (ms): ");
  Serial.println(pepe2);

  if ((distance < 7) && ( distance > 1)) {
    digitalWrite(heatPin1, HIGH);
  }
  else
    //delay(5000);// leave on for 5 seconds
    {digitalWrite(heatPin1, LOW); // Turn Relay OFF
    //delay(000);
    }


  }


//}
void loop(){
delay(500);

Why are you stuffing your head in the sand for 1/2 a second on EVERY pass through loop()?

  if ((distance < 7) && ( distance > 1)) {
    digitalWrite(heatPin1, HIGH);
  }

I will never understand why people write code this way. That is not how I think of the comparisons needed to determine if a value is in a range. I think in terms of being above the low end of the range first.

You KNOW where you turn the relay (that is NOT a relay) off. Add a delay(), turn the fan on, add another delay, then turn the fan off.

Or, look at the blink without delay example to see how to do things without using delay. A boolean variable, fanNeedsToRun, can be set to true when the fan needs to come on later. If the variable is true, and the appropriate amount of time has passed, turn the fan on. If the variable is true, and the appropriate amount of time has passed, turned the fan off AND set the variable to false.

Thank for you reply Paul, At the moment I'm just trying to get the heat pad to turn on for ten seconds and cut off. I need to get this working first before I go near the fan. I did what you asked with regards to adding the delay but it seems as if the heat pad stays on, even though I have set the delay for 10 seconds. Here is the current code

#include <SharpIR.h>
#define ir A5
#define model 1080
const int heatPin1 =  7;      // the number of the LED pin
SharpIR sensor(GP2YA41SK0F, A5);
int SharpIR =  A5;
boolean sharpIR = true;

void setup() {
// initialize the LED pin as an output:
pinMode(heatPin1, OUTPUT); 
digitalWrite( heatPin1, LOW );     
Serial.begin(9600);    
}


void loop(){
//delay(500);
 

 unsigned long pepe1 = millis(); // takes the time before the loop on the library begins

  int distance = sensor.getDistance(); // this returns the distance to the object you're measuring




  Serial.print(" distance: ");  // returns it to the serial monitor
  Serial.println(distance);

  unsigned long pepe2 = millis() - pepe1; // the following gives you the time taken to get the measurement
  Serial.print("Time taken (ms): ");
  Serial.println(pepe2);

  if ((distance < 7) && ( distance > 1)) {
    digitalWrite(heatPin1, HIGH);
  }
  else
    
    {digitalWrite(heatPin1, LOW); // Turn Relay OFF
    delay(10000);
    }


  }


//}

Does this help?

#include <SharpIR.h>

const byte pinIR = A5;
#define modelIR     1080

#define HEAT_OFF    LOW     //change to suit your setup
#define HEAT_ON     HIGH
//
#define FAN_OFF     LOW     //change to suit your setup
#define FAN_ON      HIGH

//state machine state names
#define INIT        0
#define HEATER_ON   1
#define FAN_ON      2
#define WAIT_CLEAR  3

const unsigned long HEAT_CYCLE_TIME = 30000ul;
const unsigned long FAN_CYCLE_TIME = 30000ul;

const byte pinHeat =  7;
const byte pinFan = 8;      //change to suit your setup

SharpIR sensor( pinIR, modelIR );   //verify parm order: github SharpIR indicates (pin,model)

void setup() 
{
    // initialize the LED pin as an output:
    pinMode( pinHeat, OUTPUT ); 
    digitalWrite( pinHeat, HEAT_OFF );
    pinMode( pinFan, OUTPUT );
    digitalWrite( pinFan, FAN_OFF );
    Serial.begin(9600);    
    
}//setup

void loop()
{
    int
        dist;
    static byte
        stateCycle = INIT;
    static unsigned long
        timeCycle = 0;
    unsigned long
        timeNow;

    timeNow = millis();
    
    switch( stateCycle )
    {
        case    INIT:
            dist = sensor.getDistance();
            if( dist > 1 && dist < 7 )
            {
                digitalWrite( pinHeat, HEAT_ON );
                timeCycle = timeNow;
                stateCycle = HEATER_ON;
                
            }//if
            
        break;

        case    HEATER_ON:
            if( timeNow - timeCycle > HEAT_CYCLE_TIME )
            {
                digitalWrite( pinHeat, HEAT_OFF );
                digitalWrite( pinFan, FAN_ON );
                
                timeCycle = timeNow;
                stateCycle = FAN_ON;
                
            }//if
        break;

        case    FAN_ON:
            if( timeNow - timeCycle > FAN_CYCLE_TIME )
            {
                digitalWrite( pinFan, FAN_OFF );                
                stateCycle = WAIT_CLEAR;
                
            }//if

        break;

        case    WAIT_CLEAR:
            //wait for the sensor to read > 8 before returning to start of state machine
            dist = sensor.getDistance();
            if( dist > 8 )
                stateCycle = INIT;
            
    }//switch

}//loop

I know this a thread about software but your hardware choice for the fan will be problematic. The TIP122 is an ancient, 50 year old design part that will result in your fan only receiving about 3.3-3.4 volts. This is due to the high voltage drop of 1.2 volts across the C-E junction that occurs with a silicon Darlington transistor.

You can avoid the problem by using a modern logic level n channel mosfet like the FQP30N06L or RFP30N06LE (and there are hundreds more devices that are suitable). The mosfet voltage drop will be virtually zero with a fan load, the result being full battery voltage reaching the fan.

Your code still looks terrible. Use Tools + Auto Format BEFORE posting code.

If you want to turn the heater on for 10 seconds, why are you delaying for 10 seconds after turning it off?

Turn it on, if appropriate, wait 10 seconds, then turn it off.

Get rid of code that has nothing to do with the problem, like timing how long it takes to get a distance reading.

Hi Paul,

Thanks for getting back to me. I've made the changes to the code but it seems that the the heat pad isin't turning off after ten seconds. The longer I leave my hand in front of the sensor the hotter the pad becomes. Here's the code currently.

#include <SharpIR.h>
#define ir A5
#define model 1080
const int heatPin1 =  7;      // the number of the LED pin
SharpIR sensor(GP2YA41SK0F, A5);
int SharpIR =  A5;
boolean sharpIR = false;




void setup() {
  // initialize the LED pin as an output:
  pinMode(heatPin1, OUTPUT);
  digitalWrite( heatPin1, LOW );
  Serial.begin(9600);
}





void loop() {

  unsigned long pepe1 = millis(); // takes the time before the loop on the library begins
  int distance = sensor.getDistance(); // this returns the distance to the object you're measuring




  Serial.print(" distance: ");  // returns it to the serial monitor
  Serial.println(distance);

  //unsigned long pepe2 = millis() - pepe1; // the following gives you the time taken to get the measurement
  //Serial.print("Time taken (ms): ");
  //Serial.println(pepe2);

  if ((distance < 7) && ( distance > 1)) {
    digitalWrite(heatPin1, HIGH);
    delay(10000);
  }
  else

  { digitalWrite(heatPin1, LOW); // Turn heat pad OFF

  }


}


//}

You STILL have useless code.
You have excessive white space. I hate having to scroll so much to find code that should be right there.

You are STILL not turning the heater off at the end of the 10 seconds.

I really do NOT understand what you are trying to do. Specifically, why do you want to turn the heater on for 10 second blasts as long as the distance that the sensor sees is between 1 and 7 somethings?

Hi Paul,

I'm looking to turn the pad on for ten seconds to reveal an image underneath the thermo ink. Then I want the heat pad to cool down as quick as possible and return the thermo ink back to its original state.

This is why I was going to integrate the fan into the circuit to cool it quicker.

I feel at the moment as long as my hand is in font of the sensor the heat pad stay on. Essentially I'm looking to switch the circuit once my hand interacts with the sensor, even if I keep my hand in front of the sensor I want the circuit to turn on for 10 seconds only.

I hope this makes sense

Thanks

I feel at the moment as long as my hand is in font of the sensor the heat pad stay on.

It does. If that is not what you want, you need to change the code.

If you want the CHANGE to the distance being in the range 1 to 7 to control the heater, rather than when the distance IS between 1 and 7, something like this:

bool needToHeat = true;

void loop()
{
     int distance = sensor.getDistance(); // No useless comments needed

     if(distance > 1 && distance < 7)
     {
        if(needToHeat)
        {
           digitalWrite(heatPin1, HIGH); // Turn the heater on
           delay(10000);
           digitalWrite(heatPin1, LOW); // Turn the heater off
           needToHeat = false;
        }
     }
     else
     {
         needToHeat = true;
     }
}

Notice that there is no unneeded code and no excessive white space and that there is NOTHING else on any line with a { or a }.

Hi,
Is this the sequence you are trying to get.

  • With everything at rest, heater OFF, fan OFF, no image on heat paper.
  • When hand is bought in front of sensor its output turns ON, heater turns ON for 10 or 30seconds, long enough for image to appear on paper.
  • No matter if and when the hand is removed, the heater runs for 10 or 30seconds then stops, the fan is turned ON for 30seconds to erase the image.
  • Return to step 1.

Each time you will be looking for a change in the sensor output from OFF to ON, not for the sensor to stay in the ON condition.

Tom... :slight_smile:

Yes, Tom that is exactly what I'm trying to achieve but I have integrated the 5v fan as yet. I'm a little unsure as to how to do this. I would presume you would switch the fan with a smiliar circuit in parallel via a tip122 running off 5v as it's a 5v fan?