/* Fan controller by Neil White - software using the folowing: U8g library: Universal 8bit Graphics Library, https://github.com/olikraus/u8glib/ Copyright (c) 2012, olikraus@gmail.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DHT humidity and temperature library - Written by ladyada, public domain - 3.3volts recommended HCMotor library - HobbyComponents.com - to run a irf520 mos fet unit to switch usb fan on and off This software may not be used directly for the purpose of selling products that directly compete with Hobby Components Ltd's own range of products. THIS SOFTWARE IS PROVIDED "AS IS". HOBBY COMPONENTS MAKES NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ACCURACY OR LACK OF NEGLIGENCE. HOBBY COMPONENTS SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON WHATSOEVER. WARNING! I am NOT a coder, my code is very sloppy and inefficient. There, I've said it. I probably code in a way that would make blood boil, but I look at it this way, if it works, it works. Hardware used: *Arduino UNO clone *4 x 10k pots *0.97" OLED display on I2C bus - 2 pins to analog 4&5 plus 3.3v & Gnd *DHT11 digital humidity and temperature sensor - connected to digital pin 2 plus 3.3v & Gnd - 220kOhm resistor between VCC and Signal *IRF520 MOSFET module - terminal blocks to connect v+ v- to motor, inoput voltage from external supply signal to digital pin 6 plus 5.0v & Gnd *Butchered USB cable to provide power to Uno and MOSFET *Butchered USB socket to provide a handy socket to plug USB fan into without cutting wires While I have included Copywrite details for the libraries I have used, please feel free to use this code as you wish. But I accept no liability for any loss you may suffer as a result of using it. Neil White - Feb 2016 */ #include "U8glib.h" #include "DHT.h" #include "HCMotor.h" #define MOTOR_PIN 6 #define DHTPIN 2 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); HCMotor HCMotor; // pot declarations int potpin = 0; //fan speed int pot2pin = 3; // temperature set point int pot3pin = 1; // amount of time fan is on int pot4pin = 2; // amount of time fan is off // initialise variables int potvalue = 0; int pot2value = 0; int fanspeed = 0; int setpoint = 0; int pot3value = 0; int pot4value = 0; int fanOn = 0; int fanOff = 0; float onTime = 0; float offTime = 0; U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0); // I2C / TWI void setup(void) { HCMotor.Init(); Serial.begin(9600); /* Attach motor 0 to digital pin 6. The first parameter specifies the motor number, the second is the motor type, and the third is the digital pin that will control the motor */ HCMotor.attach(0, DCMOTOR, MOTOR_PIN); /* Set the duty cycle of the PWM signal in 100uS increments. Here 100 x 100uS = 1mS duty cycle. */ HCMotor.DutyCycle(0, 100); // flip screen u8g.setRot180(); // assign default color value if ( u8g.getMode() == U8G_MODE_R3G3B2 ) { u8g.setColorIndex(255); // white } else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) { u8g.setColorIndex(3); // max intensity } else if ( u8g.getMode() == U8G_MODE_BW ) { u8g.setColorIndex(1); // pixel on } else if ( u8g.getMode() == U8G_MODE_HICOLOR ) { u8g.setHiColorByRGB(255,255,255); } } void loop(void) { delay(100); float a = dht.readTemperature(); int Afanspeed = 0; Serial.print("Temperature = "); Serial.println(a); potvalue = analogRead(potpin); pot2value = analogRead(pot2pin); pot3value = analogRead(pot3pin); pot4value = analogRead(pot4pin); //output values to serial monitor - testing and diagnostics only Serial.print("pot 1 value = "); Serial.println(potvalue); Serial.print("pot 2 value = "); Serial.println(pot2value); Serial.print("pot 3 value = "); Serial.println(pot3value); Serial.print("pot 4 value = "); Serial.println(pot4value); // pot is fan speed potvalue = analogRead(potpin); if (potvalue >=0 && potvalue < 120) { Afanspeed = 80; } else if (potvalue >= 120 && potvalue < 180) { Afanspeed = 90; } else if (potvalue >= 180 && potvalue < 270) { Afanspeed = 102; } else if (potvalue >= 270 && potvalue < 360) { Afanspeed = 123; } else if (potvalue >= 360 && potvalue < 450) { Afanspeed = 144; } else if (potvalue >= 450 && potvalue < 540) { Afanspeed = 165; } else if (potvalue >= 540 && potvalue < 640) { Afanspeed = 186; } else if (potvalue >= 640 && potvalue < 695) { Afanspeed = 207; } else if (potvalue >= 695) { Afanspeed = 255; } // pot 2 is temp set point pot2value = analogRead(pot2pin); setpoint = 0; if (pot2value >=0 && pot2value < 70) { setpoint = 15; } else if (pot2value >= 70 && pot2value < 140) { setpoint = 16; } else if (pot2value >= 140 && pot2value < 210) { setpoint = 17; } else if (pot2value >= 210 && pot2value < 280) { setpoint = 18; } else if (pot2value >= 280 && pot2value < 350) { setpoint = 19; } else if (pot2value >= 350 && pot2value < 420) { setpoint = 20; } else if (pot2value >= 420 && pot2value < 490) { setpoint = 21; } else if (pot2value >= 490 && pot2value < 560) { setpoint = 22; } else if (pot2value >= 560 && pot2value < 630) { setpoint = 23; } else if (pot2value >= 630 && pot2value < 700) { setpoint = 24; } else if (pot2value >= 701) { setpoint = 25; } // pot 3 sets the time the fan is ON pot3value = analogRead(pot3pin); fanOn = 0; if (pot3value >=0 && pot3value < 70) { fanOn = 1000; } else if (pot3value >= 70 && pot3value < 140) { fanOn = 1500; } else if (pot3value >= 140 && pot3value < 210) { fanOn = 2000; } else if (pot3value >= 210 && pot3value < 280) { fanOn = 2500; } else if (pot3value >= 280 && pot3value < 350) { fanOn = 3000; } else if (pot3value >= 350 && pot3value < 420) { fanOn = 3500; } else if (pot3value >= 420 && pot3value < 490) { fanOn = 4000; } else if (pot3value >= 490 && pot3value < 560) { fanOn = 4500; } else if (pot3value >= 560 && pot3value < 630) { fanOn = 5000; } else if (pot3value >= 630 && pot3value < 700) { fanOn = 5500; } else if (pot3value >= 701) { fanOn = 6000; } // pot 4 sets the time the fan is OFF pot4value = analogRead(pot4pin); fanOff = 0; if (pot4value >=0 && pot4value < 70) { fanOff = 0; } else if (pot4value >= 70 && pot4value < 140) { fanOff = 1000; } else if (pot4value >= 140 && pot4value < 210) { fanOff = 1500; } else if (pot4value >= 210 && pot4value < 280) { fanOff = 2000; } else if (pot4value >= 280 && pot4value < 350) { fanOff = 2500; } else if (pot4value >= 350 && pot4value < 420) { fanOff = 3000; } else if (pot4value >= 420 && pot4value < 490) { fanOff = 3500; } else if (pot4value >= 490 && pot4value < 560) { fanOff = 4000; } else if (pot4value >= 560 && pot4value < 630) { fanOff = 4500; } else if (pot4value >= 630 && pot4value < 700) { fanOff = 5000; } else if (pot4value >= 701) { fanOff = 6500; } Serial.print("Temperature set-point = "); Serial.println(setpoint); Serial.print("Fan speed = "); Serial.println(Afanspeed); Serial.print("Fan ON time = "); Serial.println(fanOn); Serial.print("Fan OFF time = "); Serial.println(fanOff); Serial.println(" "); delay(100); // if temp is greater than set point (pot 2) turn the fan on if (a > setpoint) { HCMotor.OnTime(0, Afanspeed ); //turn fan on at set speed delay(fanOn); // run fan for time period as set by fanOn if (fanOff > 0) { HCMotor.OnTime(0, 0); //turn fan off delay(fanOff); } } else { HCMotor.OnTime(0, 0); } // picture loop u8g.firstPage(); do { draw(); } while( u8g.nextPage() ); // rebuild the picture after some delay delay(1000); } // Function to write to OLED display - need to get this in the main routine to avoid unnecessary dupes void draw(void) { // graphic commands to redraw the complete screen should be placed here float a = dht.readTemperature(); int b = 0; /* Determine fanspeed from pot position - coverted to % - wanted it in steps from 20% as I don't want the fan to switch off, just slow. I could probably have done this in code using standard arithmatic, but couldn't figure it out to ensure the lowest setting didn't switch OFF the fan */ potvalue = analogRead(potpin); if (potvalue >=0 && potvalue < 90) { fanspeed = 20; } else if (potvalue >= 90 && potvalue < 180) { fanspeed = 30; } else if (potvalue >= 180 && potvalue < 270) { fanspeed = 40; } else if (potvalue >= 270 && potvalue < 360) { fanspeed = 50; } else if (potvalue >= 360 && potvalue < 450) { fanspeed = 60; } else if (potvalue >= 450 && potvalue < 540) { fanspeed = 70; } else if (potvalue >= 540 && potvalue < 640) { fanspeed = 80; } else if (potvalue >= 640 && potvalue < 695) { fanspeed = 90; } else if (potvalue >= 695) { fanspeed = 100; } //Temperature setpoint for OLED display pot2value = analogRead(pot2pin); setpoint = 0; if (pot2value >=0 && pot2value < 70) { setpoint = 15; } else if (pot2value >= 70 && pot2value < 140) { setpoint = 16; } else if (pot2value >= 140 && pot2value < 240) { setpoint = 17; } else if (pot2value >= 240 && pot2value < 280) { setpoint = 18; } else if (pot2value >= 280 && pot2value < 350) { setpoint = 19; } else if (pot2value >= 350 && pot2value < 420) { setpoint = 20; } else if (pot2value >= 420 && pot2value < 490) { setpoint = 21; } else if (pot2value >= 490 && pot2value < 560) { setpoint = 22; } else if (pot2value >= 560 && pot2value < 630) { setpoint = 23; } else if (pot2value >= 630 && pot2value < 700) { setpoint = 24; } else if (pot2value >= 701) { setpoint = 25; } // pot 3 sets the time the fan is ON pot3value = analogRead(pot3pin); fanOn = 0; if (pot3value >=0 && pot3value < 70) { onTime = 1.0; } else if (pot3value >= 70 && pot3value < 140) { onTime = 1.5; } else if (pot3value >= 140 && pot3value < 210) { onTime = 2.0; } else if (pot3value >= 210 && pot3value < 280) { onTime = 2.5; } else if (pot3value >= 280 && pot3value < 350) { onTime = 3.0; } else if (pot3value >= 350 && pot3value < 420) { onTime = 3.5; } else if (pot3value >= 420 && pot3value < 490) { onTime = 4.0; } else if (pot3value >= 490 && pot3value < 560) { onTime = 4.5; } else if (pot3value >= 560 && pot3value < 630) { onTime = 5.0; } else if (pot3value >= 630 && pot3value < 700) { onTime = 5.5; } else if (pot3value >= 701) { onTime = 6.0; } // pot 4 sets the time the fan is OFF pot4value = analogRead(pot4pin); fanOff = 0; if (pot4value >=0 && pot4value < 70) { offTime = 0.0; } else if (pot4value >= 70 && pot4value < 140) { offTime = 1.0; } else if (pot4value >= 140 && pot4value < 210) { offTime = 1.5; } else if (pot4value >= 210 && pot4value < 280) { offTime = 2.0; } else if (pot4value >= 280 && pot4value < 350) { offTime = 2.5; } else if (pot4value >= 350 && pot4value < 420) { offTime = 3.0; } else if (pot4value >= 420 && pot4value < 490) { offTime = 3.5; } else if (pot4value >= 490 && pot4value < 560) { offTime = 4.0; } else if (pot4value >= 560 && pot4value < 630) { offTime = 4.5; } else if (pot4value >= 630 && pot4value < 700) { offTime = 5.0; } else if (pot4value >= 701) { offTime = 5.5; } // print info u8g.setFont(u8g_font_tpssb); // Temperature display u8g.drawStr( 0, 10, "Actual Temp:"); u8g.setPrintPos(90, 10); u8g.print( dht.readTemperature(), 0); u8g.drawStr( 109, 6, "o"); u8g.drawStr( 118, 10, "C"); // Fans speed display u8g.drawStr( 0, 23, "Fan speed:"); u8g.setPrintPos(90, 23); u8g.print(fanspeed); u8g.drawStr(115, 23, "%"); // Length of time fan is on u8g.drawStr( 0, 36, "On Seconds:"); if (offTime == 0) { u8g.drawStr(90,36, "Perm"); } else { u8g.setPrintPos(90,36); u8g.print(onTime); } // Length of time fan is off u8g.drawStr( 0, 49, "Off Seconds:"); if (offTime == 0) { u8g.drawStr(90,49, "NA"); } else { u8g.setPrintPos(90,49); u8g.print(offTime); } // Temperature setting when fan comes on if (setpoint == 15) { u8g.drawStr( 0, 62, "Permanent fan mode!"); } else if (setpoint > 15) { u8g.drawStr( 0, 62, "Temp Setting: >"); u8g.setPrintPos(96, 62); u8g.print(setpoint); u8g.drawStr(113,58, "o"); u8g.drawStr(121,62, "C"); } }