Built-in project · Arduino Uno R3

Temperature-controlled fan on an Arduino Uno

A TMP36 reads the room and an L9110 fan module runs faster as it warms: off under 24 C, 40% at 24 C and full speed by 32 C. The whole build, an Arduino Uno and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Beginner About 20 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $34. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • Reading a TMP36 temperature sensor
  • Converting counts to millivolts to degrees
  • Ramping PWM duty between two temperatures
  • Driving a fan module with PWM
  • Difficulty: Beginner
  • Time: About 20 minutes
  • Board: Arduino Uno R3
  • Parts: 4

How it works

A TMP36 temperature sensor gives 10 mV per degree, with 500 mV at 0 C. The Uno reads it on A0 and does the math in tenths of a degree. An L9110 fan module on pins 5 and 4 runs the fan.

Below 24 C the fan is off. At 24 C it starts at 40 percent duty, and the speed rises to full at 32 C. Pin 5 gets PWM and pin 4 is held LOW.

The L9110 brakes when both inputs are low. PWM on pin 5 with pin 4 low alternates drive and brake, and the duty sets the speed. The sketch prints the temperature and fan percent twice a second.

Parts list

4 parts, plus the jumper wires. They retail for about $34; on Mokxi they're free.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Fan module, L9110 pin INAArduino Uno R3 pin 5
Fan module, L9110 pin INBArduino Uno R3 pin 4
Temperature sensor, TMP36 pin VSArduino Uno R3 pin 5V
Fan module, L9110 pin VCCArduino Uno R3 pin 5V
Temperature sensor, TMP36 pin GNDArduino Uno R3 pin GND
Fan module, L9110 pin GNDArduino Uno R3 pin GND
Temperature sensor, TMP36 pin VOUTArduino Uno R3 pin A0

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Thermostat fan: a TMP36 on A0 and an L9110 fan module on pins 5 and 4.
//
//   A0       the TMP36's VOUT (VS to 5V, GND to GND)
//   pin 5    the fan module's INA, a PWM pin
//   pin 4    the fan module's INB, held low
//   VCC/GND  the fan module's supply, 5 V
//
// The TMP36 gives 10 mV a degree with 500 mV at 0 C, so on a 5 V board a
// reading of n is n x 5000 / 1023 mV and (mV - 500) / 10 degrees. Under 24 C
// the fan is off; from 24 C it starts at 40% (slower and a small motor may not
// turn the propeller at all) and rises to full at 32 C.
//
// The L9110 on the module brakes when both inputs are low, so PWM on INA with
// INB low is drive and brake in turn, and the duty sets the speed.

const int SENSOR = A0;
const int INA = 5;
const int INB = 4;

const int START_C10 = 240;  // tenths of a degree
const int FULL_C10 = 320;
const int START_DUTY = 102; // 40% of 255

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: thermostat fan");
  pinMode(INA, OUTPUT);
  pinMode(INB, OUTPUT);
  digitalWrite(INB, LOW);
}

void loop() {
  long mv = (long)analogRead(SENSOR) * 5000 / 1023;
  int tenths = (int)(mv - 500);
  int duty;
  if (tenths < START_C10) {
    duty = 0;
  } else if (tenths >= FULL_C10) {
    duty = 255;
  } else {
    duty = START_DUTY + (int)((long)(255 - START_DUTY) * (tenths - START_C10) / (FULL_C10 - START_C10));
  }
  analogWrite(INA, duty);

  Serial.print(tenths / 10);
  Serial.print('.');
  Serial.print(tenths % 10);
  Serial.print(" C  fan ");
  Serial.print((long)duty * 100 / 255);
  Serial.println("%");
  delay(500);
}

Code walkthrough

The key functions of the sketch, and what each one does.

setup sketch.ino

Starts serial at 115200 baud and prints a title. It makes INA and INB outputs and holds INB LOW.

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: thermostat fan");
  pinMode(INA, OUTPUT);
  pinMode(INB, OUTPUT);
  digitalWrite(INB, LOW);
}

loop sketch.ino

Reads A0, converts it to millivolts, and subtracts 500 to get tenths of a degree. Below START_C10 the duty is 0. At FULL_C10 or more it is 255. Between them it rises smoothly from START_DUTY. analogWrite sets the fan on INA, and it prints the temperature and fan percent every 500 ms.

void loop() {
  long mv = (long)analogRead(SENSOR) * 5000 / 1023;
  int tenths = (int)(mv - 500);
  int duty;
  if (tenths < START_C10) {
    duty = 0;
  } else if (tenths >= FULL_C10) {
    duty = 255;
  } else {
    duty = START_DUTY + (int)((long)(255 - START_DUTY) * (tenths - START_C10) / (FULL_C10 - START_C10));
  }
  analogWrite(INA, duty);

  Serial.print(tenths / 10);
  Serial.print('.');
  Serial.print(tenths % 10);
  Serial.print(" C  fan ");
  Serial.print((long)duty * 100 / 255);
  Serial.println("%");
  delay(500);
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The fan never starts This project
    Check the TMP36's VOUT goes to A0. Also try a warmer temperature: below 24 C the fan is off by design.
  • The fan hums but does not turn This project
    At 40 percent a small motor may not turn the propeller. Raise START_DUTY.
  • The part gets very hot, and the reading is nonsense. Temperature sensor
    The legs are reversed. With the flat face toward you, the order is +Vs, Vout, GND from left to right. Fix it right away, because a reversed TMP36 heats quickly.
  • The temperature is off by a lot or negative. Temperature sensor
    Output is 0.5 V at 0 degrees C plus 10 mV per degree. So C = (volts minus 0.5) times 100. Compute volts from the ADC using the right reference, 5 V or 3.3 V, not always 5.
  • The fan does not spin or only spins one way. The two inputs need opposite levels to turn, and both high or both low stops it. Fan module
    Set INA high and INB low to spin, and swap them to reverse. Use a PWM pin on INA for speed control. Both low stops it.
  • The fan resets the board, since it draws more than a pin can give or the supply is weak. Fan module
    Power the module VCC from a supply that can give the fan current, and keep the logic pins on the controller. Join the grounds.
  • Upload fails or nothing runs after wiring pins 0 and 1 to a module. Arduino Uno R3
    Pins 0 and 1 are the USB serial port. Move the module to other pins, or unplug it while uploading. Also check the right board is selected.
  • Pins misbehave or the board resets when you power motors or servos from it. Arduino Uno R3
    Each I/O pin gives about 20 mA, 40 mA max. Power motors and servos from their own supply and join its ground to the Uno's GND.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.