I was looking at a controller for my fan in my bathroom, but found none I liked. ($$$$ :P)
What it should have was
- manual control
- humidity controlled
- autonomous air cycle (run for x mins every x hours)
What I did instead, was to order a 328, the stuff needed to run it, a humidity/temperature sensor, a relay brick, and a 230V>USB power supply.
The code will be updated later, when I got my piezo to beep out what it is doing depending on the button.
Everything is controllable from a button
- 500-2500ms = +30 mins running (up to 4 hours)
- 5000-10000ms = Start/stop without timer
-
10000ms = soft reset
#define relayPin 13 //Relay on pin 8 (pin 14)
#define btnPin 3 //Button on pin 5 (pin 11)
#define maxTime 14400000 //How long the fan max can be on
#define triggerHumidity 40 //Start fan when humitidy is over this percentage
#define DHT11_PIN 0 // ADC0
byte read_dht11_dat()
{
byte i = 0;
byte result=0;
for(i=0; i< 8; i++)
{
while(!(PINC & _BV(DHT11_PIN))); // wait for 50us
delayMicroseconds(30);
if(PINC & _BV(DHT11_PIN))
{
result |=(1<<(7-i));
}
while((PINC & _BV(DHT11_PIN))); // wait '1' finish
}
return result;
}
unsigned long btnTime = 0;
unsigned long startTime = 0;
unsigned long humidityTrigger = 0;
long runTime = 0;
//For humidity smoothing
const int numReadings = 10;
int readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
void setup()
{
for (int thisReading = 0; thisReading < numReadings; thisReading++)
{
readings[thisReading] = 0;
}
DDRC |= _BV(DHT11_PIN);
PORTC |= _BV(DHT11_PIN);
Serial.begin(9600);
pinMode(relayPin, OUTPUT);
pinMode(btnPin, INPUT);
attachInterrupt(1, btnDN, FALLING); //Digital pin 3 (pin 5)
}
void loop()
{
if (millis() >= (4294967295 - maxTime)-60000) software_Reset();
//Check and reset if the fan can run for 4 hours without millis() rolling over
//leave 1 minute to make sure the loop successfully software resetting
int humidity = 0;
byte dht11_dat[5];
byte dht11_in;
byte i;
// start condition
// 1. pull-down i/o pin from 18ms
PORTC &= ~_BV(DHT11_PIN);
delay(18);
PORTC |= _BV(DHT11_PIN);
delayMicroseconds(40);
DDRC &= ~_BV(DHT11_PIN);
delayMicroseconds(40);
dht11_in = PINC & _BV(DHT11_PIN);
if(dht11_in)
{
Serial.println("dht11 start condition 1 not met");
return;
}
delayMicroseconds(80);
dht11_in = PINC & _BV(DHT11_PIN);
if(!dht11_in)
{
Serial.println("dht11 start condition 2 not met");
return;
}
delayMicroseconds(80);
// now ready for data reception
for (i=0; i<5; i++)
{
dht11_dat[i] = read_dht11_dat();
}
DDRC |= _BV(DHT11_PIN);
PORTC |= _BV(DHT11_PIN);
byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
// check check_sum
if(dht11_dat[4]!= dht11_check_sum)
{
Serial.print("Checksum error");
delay(1000);
}
else
{
// subtract the last reading:
total= total - readings[index];
// read from the sensor:
readings[index] = (dht11_dat[0], DEC);
// add the reading to the total:
total= total + readings[index];
// advance to the next position in the array:
index = index + 1;
// if we're at the end of the array...
if (index >= numReadings)
{
index = 0; // ...wrap around to the beginning
}
// calculate the average:
humidity = dht11_dat[0];
if (humidity > triggerHumidity && millis() > 10000)
{
humidityTrigger = millis();
}
Serial.print("Humdity: ");
Serial.print(humidity);
Serial.print(" - Temperature: ");
Serial.println(dht11_dat[2], DEC);
}
long holdtime = 0;
if (btnTime != 0 && digitalRead(btnPin) == HIGH)
{
holdtime = millis() - btnTime;
btnTime = 0;
}
if (holdtime != 0)
{
if (holdtime >= 500 && holdtime <= 2500) //Short press, start fan for 30 mins, or add 30 mins, up to 4 hours
{
if (startTime == 0) startTime = millis();
Serial.println("30 mins added");
runTime += 1800000;
if (runTime > maxTime) runTime = maxTime; //Check and set max time
}
else if (holdtime >= 5000 && holdtime <= 10000) //Long press, manually on/off
{
if (startTime == 0) startTime = millis();
if (runTime == -1 || runTime > 0)
{
runTime = 0;
Serial.println("Switched off");
}
else
{
runTime = -1; //Continuous on
Serial.println("On until manually switched off");
}
}
else if (holdtime >= 10000) //Very long press
{
Serial.println("Very long");
software_Reset();
}
holdtime = 0;
}
//Check if the fan should be on or off
if ((millis() - startTime <= runTime && startTime != 0) || runTime == -1 || (millis() - humidityTrigger <= 300000 && humidityTrigger != 0 ))
{
//Serial.println("on");
digitalWrite(relayPin, HIGH);
}
else
{
//Serial.println("off");
digitalWrite(relayPin, LOW);
}
delay(500); //Delay in for not spamming serial debugging
}
void btnDN()
{
if (btnTime == 0)
{
btnTime = millis();
}
}
void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
To-do is still to get the average stuff implemented, get the piezo stuff in, maybe control for rgb leds, and maybe some blue pulsing leds under the cap, just to make it fancy ![]()