Temp Controlled fans, new build

hi guys,

complete newbie here,
I've been around in circles the last few weeks trying to get my head around a project i need to build.

i'm looking at building a 2x ds18b20 sensor array that will control a fan each and output to a screen to let me know the temps and that the fans are running.

as far as i can tell, using some programs for virtual builds and such my code is good. it might not be perfect but everything seems to function pretty well.

my main concern is the electronics.

ive got...
1x UNO
1x 2ch 5v relay module
2x 12v case fans, 0.72w, 0.06amp each
a lcd
2x ds18b20 thermometers
External power pack, somewhere between 9 and 12v (based on fan noise when i fire em up)

Basics of project.
UNO will be usb powered, running signal pins to the relay module, +5v and ground are shared.
Relay module will switch EXTERNAL source +ve and ground to feed the fans.
LCD and Temp Sensors will feed from the UNO.

now where i start to get confused is everyones different takes on resistors and diodes and such.

can you please all have a look at my image here and see if ive made some horrific blunder with the resistors ive put in place, both in size and location, and suggest to me any corrections that need to be made.

ive mocked this up as best i can so i hope its easy to follow
thanks in advance

R6 & R7 you don't need them.

I don't see a GND connection to ULN2003 pin 8 (E), + what @FantomT said. See page 12 on datasheet.

Keep in mind, your 5V supply will have to supply at least 150 mA for the relay coils, in addition to the rest of your circuit.

hi, thanks for the replies so far

the relay setup is one of these prebuilt modules, it has a GND and VCC terminal built in and that will be fed from the matching points on the UNO.

my understanding is it has everything it needs built in to step up the power to sufficiently run itself that way, it just doesnt show those points on the model i had as it hides the common points as standard.

do i need to place a diode on the signal pins instead of the resistors, i read somewhere about possible power feed back on switch on/off sequences that could damage them?

relay.jpg

If you have the actual relay module pictured, remove the ULN2003 and the base resistors as the board provides everything required to properly control the relays directly from the Arduino I/O pins. The typical relay boards out there use inverted logic, that means to turn the relay on, you write a LOW and a HIGH to turn it off.

Drawing a schematic is very important, but if it doesn’t match EXACTLY what you’ve built, it can be worse than not drawing it all.

PS: Rather than just turning the fans on and off, you can reduce the fan noise by controlling the speed of the fans. To do this, you need a logic level mosfet to turn the fans on and off about a thousand times a second. This method of control is called PWM (pulse width modulation) and is supported by six output pins on the Uno board.

There are tons of examples out on the web, Google “Arduino PWM fan control”.

Modern brushless fans really don't like PWM.

Get a 3-wire or 4-wire computer fan and the Arduino can control the speed command with PWM and no additional components.

OK guys so I've been playing for a week or 2 now...

i got a pretty successful build out of my last design but the relay module was way too noisy for the environment.

I've now built up this design and need you guys to look over it and see if I've missed anything.

I know the unit runs like this( currently built and testing), and as best as i can tell I've copied my model onto the design as it is in the real world, but can u see anything i need to change or any diodes i should fit, or resistors I've missed.

As it has now been refined a little the project is now 2x 1-wire thermostats each in a separate cupboard, each with their own i2c OLED and 12v PWM Fan.

The i2c OLEDs run from the multiplexer so i can get separate unique display feeds.

The Fans are fed a 12v signal and triggered by pins 8 and 11 thru the 2222a transistors.
They are 4 wire fans but i was having major trouble wrapping my head around all the info i was finding on how to run them with the sense wire and such, and ended up stumbling into this method which i understood and it works.
They are very quiet fans and don't seem to been making any electronic noise or anything and all i need them to do is run at 100% when above a temperature or OFF when below a temperature, and this method works for that.

So can i please ask that you look over this design and see if I've missed anything glaringly obvious or dangerous for the hardware, any component i might have missed and let me know.

thanks in advance

Please go back to F**ing and change to "schematic view".

here you go

Fritzing schematic view: the very definition of “from bad to worse”.

I think the best advise anyone could give would be to break out paper and pencil and learn how to draw a schematic. Because what you posted is not a schematic.

I did look at the connection view and would comment that of what I can see looks okay. Other than the missing diodes across the motors. Don’t know if your transistor selection is okay but hey, there is only so much info on a fritzy artwork.

im currently just getting 1 fan and 1 screen going at the moment , so i'm concentrating on the AMP section not the XBOX bit, and this all seems to work how i currently want....

BUT if i wanted to add a speed up section for the fan control how would i do that?
currently just sets as below a temp then OFF and above a temp then on,

but if i wanna say like
0-30degrees -off
31-36 - 30%
37-41 - 60%
and over 42 - Max out,

how do i do that????

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
#include <TimerOne.h>

#define ONE_WIRE_BUS 2 
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

#define cFanControlPin0 8
#define cFanControlPin1 11

// Used as a baseline OFF point for fan control
const uint8_t FanOff0 = 35; //**************amp cutoff***********************
const uint8_t FanOff1 = 33; //**************xbox cutoff**********************

// OLED display TWI address
#define OLED_ADDR   0x3C

Adafruit_SSD1306 display(-1);

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif


void setup() {

  Timer1.initialize(40);  // 40 us = 25 kHz
  
//Turn on the Temp Sensors
  sensors.begin();

  // Initialize and clear Display Buffer
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();

  delay(500);

  //set pins for fan control
  pinMode(cFanControlPin0, OUTPUT);
  analogWrite(cFanControlPin0, 0);
  pinMode(cFanControlPin1, OUTPUT);
  analogWrite(cFanControlPin1, 0);

}

void loop()
{
  //GET THE TEMPERATURES FROM ALL SENSORS
  sensors.requestTemperatures();
  //GIVE THEM TIME TO READ
  delay(1000);
  

//*******************************************
//                FAN AMP
//          Controlled by pin #8
//            
//*******************************************

// IF the TEMP on AMP is LESS THAN #FanOff0
// then clear the display and shut the fan off

  
if (sensors.getTempCByIndex(0) < FanOff0)
  {
    display.clearDisplay();
    display.display();
    analogWrite(cFanControlPin0, 0);
  }

  //ELSE is the TEMP on AMP is GREATER OR EQUAL to #FanOff0
  // start the fan and display the temp
  
  
  else if (sensors.getTempCByIndex(0) >= FanOff0)
    {
      analogWrite(cFanControlPin0, 255);

      //Prints the DEG symbol
      printfinish();

      //Sets up the display font and prints the TEMP from Probe#1
      display.setTextSize(4);
      display.setTextColor(WHITE);
      display.setCursor(41,1);
      //    
      display.print(round(sensors.getTempCByIndex(0)),DEC);
      display.display();
      delay(1000);
      //clears display buffer
      display.clearDisplay();
    }



//*******************************************
//                FAN XBOX
//         Controlled by pin #11
//            
//*******************************************

// IF the TEMP on XBOX is LESS THAN #FanOff1
// then clear the display and shut the fan off
  

if (sensors.getTempCByIndex(1) < FanOff1)
  {
//    display.clearDisplay();
//    display.display();
    analogWrite(cFanControlPin1, 0);
  }

  //ELSE is the TEMP on XBOX is GREATER OR EQUAL to #FanOff1
  // start the fan and display the temp
  
  
  else if (sensors.getTempCByIndex(1) >= FanOff1)
    {
      analogWrite(cFanControlPin1, 255);

      //Prints the DEG symbol
   //   printfinish();

      //Sets up the display font and prints the TEMP from Probe#2
  //    display.setTextSize(4);
   //   display.setTextColor(WHITE);
   //   display.setCursor(1,1);
      //
  //    display.print(round(sensors.getTempCByIndex(1)),DEC);
   //   display.display();
  //    delay(1000);
      //clears display buffer
  //    display.clearDisplay();
    }
        
  
}



void printfinish()
{
  
  //Function to build the DEG and FAN marking on the displays
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(90,-3);
  display.print("o");
//  display.setTextSize(3);
//  display.setTextColor(WHITE);
//  display.setCursor(70,8);
//  display.print("FAN");

}

WattsThat:
Other than the missing diodes across the motors. Don’t know if your transistor selection is okay but hey, there is only so much info on a fritzy artwork.

thanks mate, the transistors are 1n2222a equivalents

as for the diodes you mention should they just go straight across the fans +ve and -ve just before the fan connection?

Diode cathode (end with band or stripe) to 12V +, anode (unmarked end) to transistor collector along with motor wire. What is equivalent to a 2N2222a? Pin 8 is NOT a PWM pin, 3,5,6,9,10,11 are, (the ones with the squiggle) (~).
NPNMot-3.png

outsider:
Diode cathode (end with band or stripe) to 12V +, anode (unmarked end) to transistor collector along with motor wire. What is equivalent to a 2N2222a? Pin 8 is NOT a PWM pin, 3,5,6,9,10,11 are, (the ones with the squiggle) (~).
NPNMot-3.png

my apologies,
it IS a 2N2222a and i have now attached those diodes as per your feedback and corrected the pin assignment to pins 9 an 10.

thanks for that help

now...

i came across this little guy which works great....

#include <TimerOne.h>


#define motorPin 10

void setup() {
  Timer1.initialize(40);  // 40 us = 25 kHz
  pinMode(motorPin, OUTPUT);
  analogWrite(motorPin, 0);
  Serial.begin(9600);
  Serial.println("Enter number between 0 and 9:");
}

void loop() {
if(Serial.available()){
  char ch = Serial.read();
  if (ch >= '0' && ch <= '9'){
    int speed = ch - '0';
    analogWrite(motorPin, map(speed, 0, 9, 0, 255));
  }
}
}

but i can't seem to get it to translate into my code to control the fan based on my temp readings,

i tried adding in

else if (sensors.getTempCByIndex(0) >= FanOff0)
{
  int tp = (round(sensors.getTempCByIndex(0)),DEC);
  if (tp >= 0 && tp <= 100)
     {
      int speed = tp;
      analogWrite(cFanControlPin0, map(speed, 0, 100, 0, 255));
     }
}

but i don't seem to get any fan throttling, it does turn on a point and off at the same point, but no throttling????

any ideas where i'm going wrong, as i said I'd like to have something similar to....

0-30degrees -off
31-36 - 30%
37-41 - 60%
and over 42 - Max out

dumvamp:
thanks mate, the transistors are 1n2222a equivalents

as for the diodes you mention should they just go straight across the fans +ve and -ve just before the fan connection?

2N2222A. Any device beginning '1N' is a two-terminal device (diode). Add one to the first digit to get the number of electrodes, so transistors/FETs are 2Nxxxx, 4-terminal devices will be 3Nxxxx, etc.

Many optocouplers are 4Nxxx because they have 5 active leads (although in a 6 pin package)

They are 4 wire fans

Your schematic shows 2-wire motors. Which one is it?

Brushless fans hate PWM. They will usually do what you just described: run at full speed until the PWM goes below some threshold, then they stop.

If you truly have 4-wire fans then give them power and use the tone() function to apply different frequencies to the speed input. But tone() won't control 4 fans independently.

Aside: once you switch to schematic view, place the components so there is a logical flow left-to-right and power goes top to bottom. Rearrange until you have the minimum number of lines crossing each other. Use ground symbols to replace all ground wires. Depending on complexity, you may need to use named symbols for other wires.

they are 4 wire, but i'm only using 2,

i've had great trouble wrapping my head around the whole PWM thing and using the sense lines and messing with the signal hz/khz stuff and all the "do it this way/ do it that way" and all the half information that i can find around.....

but in the end I managed to get it to run this way....

i'm using pin 9 and 10 now as mentioned previously (1 per fan) to trigger the transistors which allows me to control the fan via opening and closing the ground(if i understand that correctly), the 12 +ve is connected constantly and it only completes the ground when told to.,...

after adding in the diodes as suggested by WattsThat and outsider, and going back to my code and reworking the same few little bits and banging my head a few more times.......

i am now able to complete the circuit to the fan, then it allows me to control the fan the same way you would for a sense wire, but i'm guessing by pulsing the negative feed, which may not be the best for the fan long term but as it is a fancy Noctua PMW fan i figure it'll handle it for a while...

i can guarantee its not the cleanest way to do it, but its a way i can understand and for now....

I am very happy to say IT WORKS!

i can also say my code probably isn't the "best practice" but again, it works and i can always clean it up as i continue to learn better ways.

its not 100% finished, as i'm waiting for a multiplexer to arrive so i can run my second screen (i got i2c non-addressable) but as far and doing what i need... it does.

heres the current version (still to be cleaned) but maybe it'll help someone someday.

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
#include <TimerOne.h>

#define ONE_WIRE_BUS 2 
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

#define cFanControlPin0 10
#define cFanControlPin1 9

// Used as a baseline OFF point for fan control
const uint8_t FanOff0 = 35; //**************amp cutoff***********************
const uint8_t FanOff1 = 33; //**************xbox cutoff**********************

// OLED display TWI address
#define OLED_ADDR   0x3C

Adafruit_SSD1306 display(-1);

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif


void setup() {
//  Serial.begin(9600);
  Timer1.initialize(40);  // 40 us = 25 kHz
  
//Turn on the Temp Sensors
  sensors.begin();

  // Initialize and clear Display Buffer
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();
  delay(500);

  //set pins for fan control
  pinMode(cFanControlPin0, OUTPUT);
  analogWrite(cFanControlPin0, 0);
  pinMode(cFanControlPin1, OUTPUT);
  analogWrite(cFanControlPin1, 0);

}

void loop()
{
  //GET THE TEMPERATURES FROM ALL SENSORS
  sensors.requestTemperatures();
  //GIVE THEM TIME TO READ
  delay(1000);


//********************;***********************
//                FAN AMP
//          Controlled by pin #10
//            
//*******************************************

// IF the TEMP on AMP is LESS THAN #FanOff0
// then clear the display and shut the fan off

float temp0 = round(sensors.getTempCByIndex(0)); 

if (temp0 < FanOff0)
  {
    display.clearDisplay();
    display.display();
    analogWrite(cFanControlPin0, 0);
  }

  //ELSE is the TEMP on AMP in a range
  // set the speed accordingly and display the temp
  
    else if (temp0 >= 36 && temp0 <= 40)
    {
      analogWrite(cFanControlPin0, 40);
      
      printfinish();

      display.setTextSize(4);
      display.setTextColor(WHITE);
      display.setCursor(41,1);
         
      display.print(round(sensors.getTempCByIndex(0)),DEC);
      delay(1000);
      display.setTextSize(1);
      display.setCursor(110,22);
      display.print("F");
      display.display();
    }
    else if (temp0 >= 41 && temp0 <= 46)
    {
          
      analogWrite(cFanControlPin0, 120);
      
      printfinish();

      display.setTextSize(4);
      display.setTextColor(WHITE);
      display.setCursor(41,1);
          
      display.print(round(sensors.getTempCByIndex(0)),DEC);

      delay(1000);
      display.setTextSize(1);
      display.setCursor(110,12);
      display.print("A");
      display.setCursor(110,22);
      display.print("F");
      display.display();
    }
    else if (temp0 >= 47)
    {

      analogWrite(cFanControlPin0, 255);
      
      printfinish();

      display.setTextSize(4);
      display.setTextColor(WHITE);
      display.setCursor(41,1);
          
      display.print(round(sensors.getTempCByIndex(0)),DEC);
 
      delay(1000);
      display.setTextSize(1);
      display.setCursor(110,2);
      display.print("N");
      display.setCursor(110,12);
      display.print("A");
      display.setCursor(110,22);
      display.print("F");
      display.display();
    }


    

//*******************************************
//                FAN XBOX
//         Controlled by pin #9
//            
//*******************************************

// IF the TEMP on XBOX is LESS THAN #FanOff1
// then clear the display and shut the fan off

float temp1 = round(sensors.getTempCByIndex(1));

//Serial.print(temp1); 
if (temp1 < 32)
  {
  //  display.clearDisplay();
   // display.display();
    analogWrite(cFanControlPin1, 0);
  }  

  // start the fan and display the temp
  
  
  else if (temp1 >= 33 && temp1 <= 36)
    {
      analogWrite(cFanControlPin1, 40);
    }
  else if (temp1 >= 37 && temp1 <= 40)
    {
      analogWrite(cFanControlPin1, 120);
    }
  else if (temp1 >= 41)
    {
      analogWrite(cFanControlPin1, 255);
    }
      
      //Prints the DEG symbol
   //   printfinish();

      //Sets up the display font and prints the TEMP from Probe#2
  //    display.setTextSize(4);
   //   display.setTextColor(WHITE);
   //   display.setCursor(1,1);
      //
  //    display.print(round(sensors.getTempCByIndex(1)),DEC);
   //   display.display();
  //    delay(1000);
      //clears display buffer
  //    display.clearDisplay();
    }
        
  




void printfinish()
{
  
  //Function to build the DEG and FAN marking on the displays
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(90,-3);
  display.print("o");
}

thanks everyone for the feedback and the suggestions, and now i only have to tidy up all the loose ends, finish the code, test it with 2 screens, get it off the breadboard, build the thing properly, make a housing,
fit it all up and complete the task...

crap, that sounds like more work than i thought, lol.