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.
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.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Half breadboard
- 1 × Temperature sensor, TMP36In Starter Projects Kit.
- 1 × Fan module, L9110
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 pin | Connects to |
|---|---|
| Fan module, L9110 pin INA | Arduino Uno R3 pin 5 |
| Fan module, L9110 pin INB | Arduino Uno R3 pin 4 |
| Temperature sensor, TMP36 pin VS | Arduino Uno R3 pin 5V |
| Fan module, L9110 pin VCC | Arduino Uno R3 pin 5V |
| Temperature sensor, TMP36 pin GND | Arduino Uno R3 pin GND |
| Fan module, L9110 pin GND | Arduino Uno R3 pin GND |
| Temperature sensor, TMP36 pin VOUT | Arduino 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.
// 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. RaiseSTART_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.