Thought I'd share my code, I've messed with this over the past couple of days. I wanted to have a threshold which would prevent the program from turning on the fan immediately.
Basic program:
Check temp;
-----> if higher than setpoint + threshold, then turn fan on
-----> if between setpoint and setpoint + threshold, check previous fan state,
----------> if was on, stay on
----------> if was off, stay off
-----> if lower than setpoint, then turn fan off
Right now its setup to print a lot of info, but you can remove it as you see fit.
#include <OneWire.h>
OneWire ds(10); // on pin 10
int PinLED = 13; //LED Pin
float temp_setpoint = 75.00; //Temperature Set Point
float temp_thresh = 2.50; //Temperature threshold
void setup(void) {
Serial.begin(9600);
pinMode(PinLED,OUTPUT);
}
void loop(void) {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if ( !ds.search(addr)) {
ds.reset_search();
delay(250);
return;
}
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(750); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
// convert the data to actual temperature
unsigned int raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// count remain gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
}
fahrenheit = (float)raw / 16.0 * 1.8 + 32.0;
float temp_current = fahrenheit;
Serial.print(", Fan Relay: ");
if (temp_current >= temp_setpoint + temp_thresh) {
Serial.print("ON ");
digitalWrite(PinLED, 1);
}
else if (temp_current >= temp_setpoint && temp_current <= temp_setpoint + temp_thresh) {
int fan1state = digitalRead(PinLED);
if (fan1state == 1){
Serial.print("ON ");
digitalWrite(PinLED, 1);
}
else {
Serial.print("OFF");
digitalWrite(PinLED, 0);
}
}
else if (temp_current <= temp_setpoint) {
Serial.print("OFF");
digitalWrite(PinLED, LOW);
}
Serial.print(", Current Temp / Threshold: ");
Serial.print(fahrenheit);
Serial.print(" / ");
Serial.print(temp_setpoint + temp_thresh);
Serial.print(" (");
Serial.print(temp_current >= temp_setpoint + temp_thresh);
Serial.println(")");
}
So I have messed around with this and have found out that if I put a load on pin 13, reading its state no longer returns the expected result. I want it to tell me that it was previously on but it defaults to 0 state. Connecting an NPN transistor to drive a relay as load.
robtillaart:
Split your program up in several functions that do one task to simplify the loop() to something like this
void loop()
{
float t = readTemperature();
if (t > setpoint+threshold)
{
state = ON;
}
if (t < setpoint)
{
state = OFF;
}
setFan(state);
}
the part below makes no difference in state...
> -----> if between setpoint and setpoint + threshold, check previous fan state,
> ----------> if was on, stay on
> ----------> if was off, stay off
Thanks for your help.
But I have to disagree with you, that part does make a difference. Or at least I want it to make a difference, I may just not be programming it correctly. The threshold is designed to prevent excessive cycling of the fan. I want the fan to only turn on when the temp > setpoint + threshold AND it needs to stay on until temp < setpoint.
I could rewrite the program to be an if then based on output pin state, but based on the trouble with the pin beg read low when it should be high that I've been seeing, I'll hold off on this.
Here is a more complete code, take a pen and paper and iterate over loop and let the temperature go from 15 - 30 and back to 15 and write dowwn state for every temp. This will help to understand how the code works. I learned a lot of programming with paper and pencil and being "the interpreter" myself
#define FANPIN 5
int state = LOW; // note this is a global variable IMPORTANT
int setpoint = 20;
int threshold = 5;
void setup()
{
Serial.begin(115200);
Serial.println("Start...");
pinMode(FANPIN, OUTPUT);
}
void loop()
{
float t = readTemperature();
if (t > setpoint+threshold)
{
state = ON;
}
if (t < setpoint)
{
state = OFF;
}
Serial.print("temp: ");
Serial.print(t, 2); // 2 decimals
Serial.print("\t\tstate: ");
Serial.print(state);
setFan(state);
}
void setFan(int state)
{
digitalWrite(FANPIN, state);
}
float readTemperature()
{
float t = analogRead(A0); // assuming an analog LM35 sensor , other code
t = t * 5000 / 1023; // make millivolts of it
t = -25 + t/10; // 1C per 10 mv (dont know exact formula)
}
poldim:
So I have messed around with this and have found out that if I put a load on pin 13, reading its state no longer returns the expected result. I want it to tell me that it was previously on but it defaults to 0 state. Connecting an NPN transistor to drive a relay as load.
Any advice appreciated.
Erm, you connected the NPN how exactly? If the pin is set to HIGH and you are reading LOW that means you're grossly overloading it (which can fry the chip) - or that its configured as an INPUT...
I'm going to to the same thing with my code which uses DS18B20.h to show the temperature and control the heat-sink fan.
Since the temperature rises very slowly, it reaches many times to the "set point" and comes down and
this makes the microcontroller to turn on and off the fan when temperature gets close to "setpoint" and plays around 49-50.
In result fan starts and stops tens of times until temperature stays on 50 or goes above; then it stays on.
Setpoint is set to 50 degrees in this line in DS18B20.h file.
if(((temp_whole/10)%10) >= 5) PORTD.F1=1; // Aici setez temp de pornire cooler [5=50 grade] (maximum setpoint temperature to turn on fan 5=50 degrees)
So i'm asking the same question like "Poldim".
I want the fan to only turn on when the temp > setpoint + threshold AND it needs to stay on until temp < setpoint.