Building Blocks ‐ EN - gajdipajti/fan-control GitHub Wiki

Building Blocks

The documentation, drawings, and circuit diagrams are available under the CC BY-SA-4.0 license.

The building blocks that we will work with, or that may come up during other projects, are collected here. It's hard to draw the line between what to write down and what to reference only. The important thing is that you don't have to read it all the way through, everyone should pick out the unclear elements for themselves, and if you still have questions, you should come back here instead. I will expand this page over time and season it it with figures.

When I start a new project, I often have to look up sources to remind myself of a concept. If these were to be collected in one place, it would make it easier for me to remember.

As buildin blocks I have selected components that are easy to purchase, are well supported, and do not scare novice users away. Electronics is a huge topic and can be approached from several directions. I will typically go the route of describing my own approach and as a different approach videos from GreatScott! or EEVBlog, if available.

The typical problem is that if you take out a catalog, you can get lost in the many choices. On what basis do we choose? How precise the component is, how big is the standard deviation? Is the output BJT or FET? What is the operating voltage range? In many cases, it is sufficient to use only a generic and cheap element, especially for prototypes. I'll try to help with that.

A couple of links (odysee) that migth be of interest for a different project:

Note: The voltage will be marked with the letter 'V' instead of the letter 'U' used in Hungarian terminology. I do this in the code as well. Please keep this in mind.

Basic circuit elements

We will implement the project according to the through-hole technology or THT. This is simpler, faster and offers more possibilities for repairs than surface mounting (SMD).

Resistor

Ohm's law describes the relationship between resistance-voltage-current:

$$ R = {V \over I} $$

Its unit of measurement is the Ohm, or Ω. The typically used value range is from 200 Ω to 10.000 Ω. We can buy the resistors according to series of values [E6, E12, E24]. If we need a custom value, then we can produce the desired value by connecting two or more resistors in series or in parallel. The digits of the value, the range and the standard deviation of the value are marked with coloured bands on the resistors. When marking values on drawings and in text, the symbol Ω is usually omitted and a concise notation is used:

  • 100 Ω -> 100R
  • 200 Ω -> 200R
  • 1000 Ω -> 1k
  • 4700 Ω -> 4k7

Let's think about Ohm's law, that if we have a 5 V voltage source and connect a 330 Ω resistor in series with it, the current flowing through it will be 0.015 A if there is no other load in the circuit. We can use this current value to operate an LED diode connected in series. In this case, less current would flow through the diode, because we have to account for a voltage drop and an internal resistance as well. If we choose the resistors value to be 1k, the current flowing through it will be only 0.005 A, and the same LED will glow dimmer when connected in series.

The deviation of the values can be from 10% down to 0.01%. Choosing a resistor with smaller deviation leads to an increase in the price. Where the exact resistance value is less important (LED light, pull-up resistor, ...) I usually use 5% resistors. Whereas where the value is important (voltage divider, operational amplifier circuit, measurement circuit, ...), I usually use 1%-0.5% resistors. In exceptional cases, I connect 3-5 1% resistors in parallel to reduce the error. It is unnecessary to keep resistors of all kinds of value and accuracy in our stock at home. Do not start the path of a hoarder.

I usually put together the resistance set for a project, usually what I can typically take off the shelf is:

  • 5%: 220R, 470R, 1k, 3k3, 4k7, 10k
  • 1%: 1k, 4k7

Heat development inside the resistor is also imported. Based on the current flowing through, we get the power as follows:

$$ P = I^{2} \cdot R $$

Note that the power depends squarely on the current flowing through the resistor, while it depends linearly on the resistance. In other words, if we connect a 1 Ω resistor to our 5 V voltage source, then the power output will be P = 25 W. Do not fry your resistors.

For this project, we will use 1k 5% and 4k7 1% resistors. The former will be needed for the bipolar transistors, while the latter will be needed for the voltage divider and the DS18B20 sensor. Such a precise resistance would not be essential for the sensor, but we should not increase the number of different components in one project. As a rule of thumb.

Other materials:

Diode

A diode is a non-linear and asymmetric circuit element. Basically, it only conducts current in one direction and only above a certain voltage value. The latter is called the forward voltage.

I would highlight two things that make it worth using:

  • We can reduce the voltage by connecting a diode in series with a load. With an forward voltage of 0.7 V in series with the 12 V voltage source, we get 11.3 V on the load. At higher currents, the voltage drop increases and can even be 1 V, so don't think about the exact value when using it.
  • From a protection point of view, I usually put a diode on the 12 V rail so that if I accidentally switch the poles, no current can flow. It can't be used in all cases, but it's worth thinking about. I do not like the smell of burning silicon after midnight.

The most classic diode is the 1N400x family, where 1 is the number of poles minus one, while x refers to the maximum value of the breakdown voltage. In the range of 1 to 7, where 1 represents 50 V, while 7 represents 1000 V.

A separate group of diodes emits light when the voltage between their two poles exceeds the forward voltage. These are the LEDs, and their forward voltage varies inversely with the wavelength of the emitted light. The red LED opens below 2 V, while the blue LED opens above 3.5 V. It is important to remember, that we never use them on their own, as they usually work from a voltage source. Always connect in series with a 220 Ω or 330 Ω resistor to limit the current flowing through.

More information:

Bipolar transistor (BJT)

A bipolar transistor is also a non-linear, asymmetrical circuit element, but with three terminals. These are Collector, Emitter, Base. There are two main types: NPN and PNP. The former allows current to flow from the Collector to the Emitter in the case of current flowing through the Base-Emitter terminals. Whereas the PNP type only allows current flowing from the Emitter to the Collector when current can flow through the Base.

During the project, we will use the NPN type and in the majority of cases the faced problem can be solved with this type. The collector current is given by the following formula:

$$ I_{C} = \beta \cdot I_{B} $$

Here β (or hFE) is the gain, typically in the range of 50 to 250. This means that we can control a hundred or two hundred times larger current with small currents. Similar to diodes, an opening voltage $ (V_{BE}) $ must be reached here to allow current to flow through.

What we will use it for is switching the 12 V voltage generator using 5 V or 3.3 V. Through the Base the Arduino Nano or the Raspberry Pi could permit or stop the Collector-Emitter current.

A classic NPN bipolar transistor is the 2N3904, and the PNP sibling is the 2N3906. The number before N here also refers to the value of pole number - 1, just for the sake of interest. It is important that these are low-power transistors, so they can typically be used for switching. For our project we would prefer the BD139-16, which has a larger Collector-Emitter current rating.

One important thing must be mentioned, similarly with the diode, nothing prevents the Base-Emitter current once the forward voltage has been reached. Therefore, a resistor must be placed between the output of the microcontroller and the Base terminal of the bipolar transistor. The value of this is scaled either for the microcontroller or for the task to be solved with the transistor. Which is a stricter condition for the current. Thoughts:

  • I have a 12 V 0.6 A computer fan in my hands.
  • The gain of BD139-16 is between 150-250, I will use the middle value of this for the estimates and best guesses. 1.5 A is the maximum constant ICE, in case of pulses the maximum value is 3 A. The VBE forward voltage is 1 V, while the VCE voltage in the open state can be taken as 0.5 V, which comes down from the 12 V as a loss.
  • For Arduino Nano, the pin output limit is 5 V and 40 mA. The closest resistor to limit the current would be the 220 Ω value in the E6 kit, so 22.7 mA would flow through it in the event of a short circuit. If we take into account the opening voltage VBE, then the current IBE would be 18 mA. In this case the maximum value of the ICE is 3.636 A, which would be limited by the fan to 0.6 A.
  • If we repeat the same calculation with a 1k resistor, that would mean a 5 mA short circuit current, and 4 mA IBE and 800 mA ICE. In the case of Raspberry Pi, the pin limit is 3.3 V and 16 mA, with the previous 220 Ω resistor, 15 mA could flow through in the event of a short circuit. Taking the voltage drop into account, this would mean 10.5 mA in the IBE direction, which would mean a maximum ICE of 2.09 A.
  • Repeating the calculation with a 1k resistor would result in a 3.3 mA short circuit current, and 2.3 mA IBE and 460 mA ICE. Here, it would be worth thinking about a 680 Ω, 470 Ω, or 500 Ω resistor. The latter could be created by two 1k Ω resistors connected in parallel.

Further materials:

Capacitor

This basic electronic building block behaves like an electrical energy store. I would stick to this property for the project. We will use the capacitor for decoupling, that is, to separate or stabilize a certain element from the noise of the rest of the circuit.

I would highlight two types, these are the ceramic and the electrolytic capacitors. The former typically have values between 1 uF and 10 pF and are not polarized. The latter are available in values between 1 uF and 100 mF, and their positive and negative sides should not be confused. We also have to pay attention to the maximum rated voltage.

In our case, this external Analog-Digital converter may need to be de-noised, and as a rule of thumb, I would put a 100 nF ceramic capacitor there (but consult the data sheet, because we will have to use a different value in the project). If our voltage source is noisy, I would connect it in parallel with a 22 uF - 100 uF electrolytic capacitor with a maximum voltage of 16 V - 25 V. Using a decoupling capacitor is optional, but elegant.

Further material:

Analog-Digital conversion (ADC)

Analog-to-digital converters (A/D, or ADCs) convert continuous analog signals into digital numbers. However, this conversion cannot be perfect, because at a finite resolution we can only represent the instantaneous value of the signal with an integer within the measurement range. This resolution (N) can be 8, 10, 12, or 16 bits. Or even finer. Care must be taken not to unnecessarily choose a high-resolution A/D converter, because the smallest bits often contain only noise. A low-resolution A/D converter typically calculates faster, while a higher-resolution one takes longer to return the result. The measurement range is usually between 0 V and the reference voltage (VREF). The most common way to digitize signals is based on successive approximation method. Another simple method uses comparators and resistors, sacrificing resolution for speed.

adc-step

Illustration of a poor resolution ADC.

The goal is always to find the right A/D converter for the task along the "speed - price - resolution - error rate" parameters. The typical questions when starting a project are what resolution is needed, how fast to sample, and how much error can be allowed. An ADC in a microcontroller can be considered of average quality, for really accurate sampling, or if the microcontroller does not include an ADC, an external voltage and temperature stabilized A/D converter is required. This could be, for example, the Microchip Microchip MCP3008 (10-bit resolution, 8 channels) or the MCP320x (12-bit resolution) family. They communicate via SPI interface, and have support in Arduino and Raspberry Pi. For Arduino, several libraries are available from the Library Manager, and for Raspberry Pi, we can rely on the device tree overlay or the implementation of gpizero.

Note: Before choosing another external ADC, it's worth looking up what kind of support it has and whether we need to write the code snippet for it. Turning the question around, does the project pay to start from scratch?

For this project, a resolution of 0.5 °C, 15 seconds sampling, and an error of +/-2% are sufficient for us. A worse specification would do, because we want to track a slowly changing continuous value. Of course, we will do more than that.

We are not dealing with the sampling frequency now, it is interesting for rapidly changing signals. In such a case, the Shanon-Nyquist sampling theorem must be taken into account: the sampling frequency must be at least twice the frequency of the signal to be restored.

In the case of an A/D converter, the resolution is described by the following formula:

$$ V_{LSB} = {V_{REF} \over 2^{N}} $$

In case of the Arduino Nano the internal A/D converters accuracy és 10 bites resolution is enough. In case of the Raspberry Pi because of the device tree and gpizero supoort, the MCP3202 is choosen. It is more than enough for this project.

As suggested by the datasheet the MCP3202 needs a 1 uF decoupling capacitor.

More materials:

Voltage reference

The simplest voltage reference would be a voltage divider consisting of two resistors connected in series. In this case, R1 represents a resistance closer to the reference voltage. The voltage Vout can then be measured on the resistor R2:

$$ V_{out} = {R_{1} \over (R_{2} + R_{1}) } \cdot V_{ref} $$

The problem with this method is that it cannot draw current from the middle point, because then the voltage value changes. A much more accurate result is obtained if a voltage stabilizer is used, or even more accurate if a voltage reference is used.

Voltage stabilizers can usually be loaded in the range of 100 mA - 3 A typically, and the classic of this category is the L7805, which produces a stable 5 V from the range of 7.5 V - 35 V. The difference is the waste heat (must be cooled) according to the current flowing through it and the voltage dropped. Also, to achieve a more stable voltage, a 330 nF capacitor must be used at the input and a 100 nF capacitor at the output terminals, according to the data sheet. Arduino Nano also has one built in for VIN power supply, the LM1117MPX-5.0, which has a typical maximum current of 800 mA and produces a stable 5 V from the 6.5 V - 15 V input range.

If only a small amount of load capacity is required, but a more precise and accurate value, then we use a voltage reference.

A/D converters and microcontrollers usually contain an internal voltage reference, or the reference is connected to their power supply. Their data sheet can provide information about this. But we can also choose the reference if we want the more precise one or the one better suited to the task to be performed.

For Arduino Uno and Nano, the internal voltage reference can be 5.0 V and 1.1 V. Of course, the former 5.0 V is valid and accurate if the Arduino is not powered via USB. For other values, we can use an external reference that must be connected to the AREF pin (don't forget to change it in the code), and then we can choose the measurement range of the ADC. Raspberry Pi does not have its own ADC, but if we choose an external ADC, we can use the Pi's 3.3 V output.

Without mentioning every, I would like to mention a couple of external voltage references: in the case of the LM285Z-1.2G, the reference voltage is 1.2 V, in the case of the LM385Z-2.5 it is 2.5 V, while in the case of the LM336Z-5 it is 5.0 V. The external voltage references keep their values accurately in a large temperature range (-50 °C – 150 °C), which reduces our measurement error. Just for the sake of interest, we can also choose a voltage source matching our A/D converter, say the Texas Instruments LM4040-N-4.1 using , which produces a voltage of 4.096V. A 12-bit ADC then has a resolution of 0.001 V and resulting in an easier calculation.

In the table below, we can see with what resolution we can digitize the voltage in different measurement ranges. You can also save on the number of bits with a well-chosen reference voltage.

N 2N VLSB (VREF = 5 V) VLSB (VREF = 2,5 V) VLSB (VREF = 1,1 V)
8 256 0.0195 V 0.00977 V 0.0043 V
10 1024 0.00488 V 0.00244 V 0.001074 V
12 4096 0.00122 V 0.00061 V 0.000268 V
16 65536 0.00000763 V 0.0000381 V 0.0000168 V

If we know that the voltage to be measured will be between 0-1 V, then by choosing the reference voltage to 1.1 V, we can achieve a better resolution with an 8-bit ADC than if we used a 10-bit one with a 5 V reference.

The 5 V or 1.1 V reference for Arduino is sufficient for this project. The exact value will be determined by our choice of temperature sensor. However, the 5.0 V value is only stable if the board is powered from the VIN pin. In the case of Raspberry Pi, if we choose a temperature measurement that requires an external A/D converter, we can use the 3.3 V reference voltage. Or we choose an external voltage reference with a smaller value.

Temperature measurement

I would like to show several solutions for measuring external temperature, any of which may be suitable for measuring the temperature of the air or a surface. From our point of view, either would be sufficient. We are only interested in the range of 10 °C - 85 °C, there is no need to pay attention to corrosive substances, there are no special requirements for dust or condensing water. But let's see how we can choose from the options. I will use three concepts: precision, accuracy and linearity. I explain them in the summary.

Voltage output sensor type

When building on a microcontroller with an A/D converter or an external A/D converter, it is easiest to use a sensor that already has a voltage output. Examples include the Analog Devices AD22100 sensor or the Texas Instruments LM35 sensor. In this case, the value read by the ADC must be converted into a voltage, and then the temperature can be calculated based on the formula in the datasheet. In the case of Arduino Nano, the range 0 V - VREF is digitized in 10 bits, i.e. we get a value between 0-1023. I will use this range as a basis from now on. In the case of the external MCP3202, the measured value is digitized at 12 bits. If this ADC is used, replace 1024 with 4096 in the equations.

According to the AD22100 datasheet, the sensor can be used in the -50 °C and 150 °C range, can be powered from +5 V with the tolerance range of +4 V and +6.5 V. Linearity +/- 1%, accuracy +/- 2% over the entire measurement range. From the sensor's formula we can calculate that at a temperature of -50 °C we would measure 0.25 V, while at 150 °C we would measure 4.75 V:

$$ V_{out} = \left( {V_{+} \over 5V} \right) \cdot (1.375 V + 0.0225 V/°C \cdot T) $$

Assuming that $ V_{+} = 5 V $ expressing the temperature from the equation:

$$ T = {V_{out} – 1.375V \over 0.0225 V/°C} $$

And for Arduino:

$$ T = {{ADC \cdot (V_{ref}/1024) – 1.375 V} \over 0.0225 V/°C} $$

Now lets look at a different option. According to the LM35 datasheet, the sensor can be used in the -55 °C and 150 °C range. It can be powered from +5 V with a tolerance range of +4 V and +20 V. The accuracy is listed as +/- 0.75 °C for the entire temperature range. From the sensor's formula, it can be calculated that at -55 °C we would measure -0.55 V, while at 150 °C we would measure 1.5 V:

$$ V_{out} = 0.01 V/°C \cdot T $$

In a simple case, we can only measure a positive ranges with it, which suits us. The data sheet contains the solution to be able to measure in the negative range as well (the 0 °C value must be shifted with a diode). For Arduino, the temperature is:

$$ T = {{ADC \cdot (V_{ref}/1024) } \over {0.01 V/°C}} $$

Note: we can increase the resolution by decreasing the $ V_{ref} $ value.

Resistance output sensor type

The resistance of materials is temperature dependent. If we look at the periodic table, it can generally be said that in the case of metals the resistance increases with increasing temperature, while in the case of semiconductors and insulators the resistance decreases. This change is usually small and cannot be used for measurement. However, in the case of certain materials, alloys, and compounds, a good thermometer can be made.

I would mention two types of resistance based temperature solutions. In case of the Pt100 and the Pt1000 thermometers the resistance of platinum changes, and are commonly used in industrial applications. The number in the name represents the resistance measured at 0 °C expressed in Ohms (Ω). Their temperature dependence can be described quite well with a linear relationship. In electronics, thermistors are widely used in NTK (NTC) and PTK (PTC) designs with a wide variety of values. N and P letters mean that as the temperature increases, the resistance of the thermistor decreases (N) or increases (P). In addition to temperature measurement, they can also be used for regulation, the former for protection against high current inrushes occurring during a cold start, while the latter can be used for protection against overheating.

The resistance of the thermistor strongly depends on the temperature and can be described by an exponential function. For this we need two parameters that typically describe the thermistor:

  • R25 – the resistance value corresponding to 25 °C. Usually 1k Ω, 4k7 Ω, 10k Ω, or 100k Ω.
  • K or β – temperature coefficient of the material. Typically a value around 4000 1/Kelvin, in absolute terms.

The resistance can be calculated using the following formula: $$ R_{T} = R_{25} \cdot e^{(K \cdot (1/T – 1/T_{25}))} $$

ntc

What is important to remember is that the temperatures in the formula are in Kelvin, that is $ T_{25} = 298.16 K $. I used the Celsius scale in the figure.

From this we can express the reciprocal of the temperature: $$ {1 \over T} = {1 \over T_{25}} + {1 \over K} \cdot \ln {\left( {R_{T} \over R_{25}} \right) } $$ With a microcontroller or an external A/D converter, we cannot measure resistance directly. With a voltage divider arrangement, however, it can be traced back to an already solved method, that is, to measure voltage. The accuracy will be influenced by the value and accuracy of the resistor (Rs) chosen for the voltage divider. It is therefore worth choosing a resistor equal to R25 and from the 1% tolerance resistor series. In case of more demanding circuits, an external voltage reference can also be used here (for example LM336Z-5 for 5V), or we connect our voltage divider to the value of ADC VREF.

In the case of Arduino, this is how the resistance of the thermistor is calculated from the ADC value: $$ V_{out} = {R_{T} \over (R_{s} + R_{T}) } \cdot V_{ref} $$ $$ ADC = {V_{out} \over V_{ref}} \cdot 1024 $$ $$ ADC = {R_{T} \over (R_{s} + R_{T})} \cdot 1024 $$ $$ {ADC \over 1024} = {1 \over (R_{s}/R_{T}) + 1} $$ $$ R_{T} = {R_{s} \over (1024/ADC) -1)} $$

This RT resistance value just has to be substituted back into the previous 1/T equation. If you use an external A/D converter, don't forget to change the number of steps according to the resolution.

Digital sensors

The really convenient solution is to use sensors that include both the temperature-dependent component and the A/D converter. The temperature value can be read via SPI (Serial Peripheral Interface, or 3-Wire Interface), I2C (Inter-Integrated Circuit, or 2-Wire Interface), or 1-Wire communication protocol. If you want to choose from these sensors, look for support, for example, we already have almost everything for the sensors belonging to the Bosch BME and BMP families. This is also true for Maxim (formerly Dallas) DS18B20 1-Wire temperature sensors, but also for the cheap DHT22 an unknown standard 1-Wire-like temperature-humidity sensor. Most of my experience is with the DS18B20 sensor, so I will continue with that.

ds Pinout for the Raspberry Pi connection.

The DS18B20 sensor can be powered from +3.3 V and +5 V rail, and for the 1-Wire network a digital I/O pin and a 4k7 Ω a pull-up resistor must be used for Arduino or Raspberry Pi. The resolution of the sensor can be adjusted between 9 and 12 bits, and its measurement range is -55 °C to 125 °C. Its accuracy is +/- 0.5 °C.

Another advantage is that we can communicate with several sensors in a half-duplex manner on a 1-Wire network (that is, using a only a single digital I/O pin), and each can be addressed separately. Although we could also write the 1-Wire communication by hand (we did it during university), we will use the pre-made libraries for our project and communicate only with one sensor. For Arduino this will mean using OneWire and DallasTemperature, while for Raspberry Pi it will be the w1-gpio overlay, and the w1_gpio and w1_therm Linux kernel modules.

More resources:

Summary

Since I want to build a reference circuit and create reference code for it, I will add one of each of the three sensor types. Everyone should choose for themselves which one they like, and which one is comfortable for them.

Measurement theory

If a physical quantity (distance, temperature, voltage, ...) is measured several times, the values obtained may differ. If I am being strict, I would say that we cannot get the same value twice if our measuring device has infinite resolution. The difference between two measurements can be so small that our measuring device cannot even indicate it. If we want to estimate the measured values from the values displayed by our measuring device, we calculate an average. We can also get precision from the standard deviation of the displayed values. More measurements and averaging can increase precision, but don't make the mistake of measuring too much and average unnecessarily.

The measured value obtained from averaging may not be the same as the real value. The values displayed by our instrument could have a constant offset in a positive or negative direction. The result obtained during averaging will also have this offset, and we can specify how much it is with the accuracy. If we know the accuracy of our measurement method, we can correct for it by adding an offset.

We speak of a linear relationship if the relationship between two physical quantities can be reduced to a linear equation $ f(x) = Ax + B $. In reality, this is usually only true in a small measurement range, linearity is not fulfilled in a larger measurement range. If, for example, we are interested in the relationship between the voltage and the current flowing through a resistor, we must also take into account the self-heating of the resistor. The resistance of metal layer resistors will increase, while the resistance of carbon layer resistors will decrease with increasing temperature.

Pulse-Width Modulation (PWM) and Timers

Pulse width modulation is a method for changing the time-averaged power or time-averaged value of the analog signal outputted by the microcontroller based on a digital value. The goal is not to restore the exact signal shape, a Digital-Analog converter (DAC) can be used to achieve this task. We restore the time average, without averaging. For Arduino Nano, the PWMs and timers are well known. For Raspberry Pi, we can use gpiozero PWMOutputDevice.

There are two important values to pay attention to:

  • Repetition frequency - how many times the microcontroller outputs the pulse, this is usually a fixed value, we do not change it while the code is running.
  • Duty cycle - in the time window of the pulse, how long the pulse was in HIGH (or on) compared to the entire time window.

$$ \tau = {T_{on} \over {T_{on} + T_{off}}} \cdot 100 % $$

If the HIGH state means 5 V and the LOW state means 0 V, then a the temporal average of a PWM signal with a τ = 20% duty cycle is 1 V. In the case of Arduino Nano, the duty cycle can be specified in 8 bits, so it can take a value of 0-255. In the figure below, we can see the different filling factors and the Arduino command.

PWM

Reference: Basics of PWM

For simple loads (LED, resistor, motor, bulb), PWM power control is not a problem. If we want to add time averaging to PWM, a low-pass filter consisting of a resistor and a capacitor should be connected to it. And the really demanding ones relieve the low-pass filter with a follow-up operational amplifier and load the output of the operational amplifier... (but I digress).

The repetition frequency is given by the internal Timer's frequency, of which there are 3 in the Arduino Nano. By default, the repetition frequencies are 976 Hz (Timer0) and 488 Hz (Timer1-2). The following options are available for setting them, assuming a 16 MHz base clock signal:

Value Div. Timer0 [Hz] Timer1 [Hz] Value Div. Timer2 [Hz]
0x01 1 62500,0000 31250,0000 0x01 1 31250,0000
0x02 8 7812,5000 3906,2500 0x02 8 3906,2500
0x03 64 976,5625 488,2812 0x03 32 976,5625
0x04 256 244,1406 122,0703 0x04 64 488,2812
0x05 1024 61,0351 30,5176 0x05 128 244,1406
0x06 256 122,0703
0x07 1024 30,5176

Changing the timer frequencies can be done with the following lines:

TCCR0B = TCCR0B & 0b11111000 | 0x01;    // Timer0   f=~62,5 kHz
TCCR1B = TCCR1B & 0b11111000 | 0x01;    // Timer1   f=~31kHz
TCCR2B = TCCR2B & 0b11111000 | 0x01;    // Timer1   f=~31kHz

Two pins are connected to each timer on the Arduino Nano platform:

  • 3, 11 - Timer2
  • 5, 6 - Timer0 - a delay(), millis(), micros() functions are connected to this timer.
  • 9, 10 - Timer1

The fastest frequency will be needed in the project, because at least a 21 kHz signal is required for PWM control of the 4-wire fan, and in the case of a bipolar transistor solution, we can avoid smoothing the signal in this way.

Reference:

Computer fans

Computer fans can be divided into three categories according to operating voltages: +5 V, +12 V, and +24 V. The most common are fans operating from +12 V, desktop computers are equipped with them, and they are also cheap. They are available with three connector types, with wire colors according to Intel specification:

Wire Function Colour 2-wire 3-wire 4-wire
1 GND black yes yes yes
2 +12 V yellow yes yes yes
3 RPM green yes yes
4 PWM blue yes

Don't be surprised if the colors of the wires are different, the functions will be in the correct order. Fortunately, GND is always black.

In the case of 2- and 3-wire fans, pulse length modulation is used to control the speed. The correct duty cycle is produced by pulse length modulation. We connect a transistor in series with the fan on the collector side of the transistor. Connect the +12 V wire of the fan and the emitter of the transistor to the power supply. This is how we transfer the PWM signal to the fan. For low revolutions we use pulses with a small duty cycle, while for high revolutions we use pulses with a high duty cycle. There are three problems with this solution:

  1. It makes the tachometer speed feedback unreadable in the case of three-wire fans. The solution for this is to use a low-pass filter, a follow-up op-amp and a transistor. However, his would further complicate the project.
  2. Because of the coil in the motor, negative currents are generated during interrupts. The solution here is a diode, which is connected in parallel with the fan to dissipate such impulses.
  3. PWM noise, that is, if we use low frequency pulses, we will hear a chirping sound. The solution to this is to increase the PWM frequency (as I mentioned in the previous subsection), or to choose the low-pass filter, operational amplifier circuit.

With 4-wire fans, we have a simpler task. Here, the speed is controlled by the PWM wire. The +12 V and GND wires must be connected to the power supply, we only deal with the PWM wire. According to the intel specification, we must meet the following specifications:

  • Target frequency: 25kHz, acceptable range 21kHz to 28kHz. - Timer1 and Timer2 can be used to achieve this, even if we are above it.
  • Maximum voltage for logic low: 0.8 V.
  • Absolute maximum current sourced: 5 mA. - Arduino Nano and Raspberry Pi can also output this current.
  • Absolute maximum voltage level: 5.25 V. - Arduino Nano and Raspberry Pi also fit into this range. In the case of the latter, another transistor might be needed.
  • Allowed duty-cycle range 0% to 100%. - This is actually 20% - 100%, the fan has a minimum speed.

In the case of Arduino Nano and Raspberry Pi, we can control a maximum of four 4-wire fans. The Arduino Nano can manage six channels from 3 and 2-wire fans, and the Raspberry Pi only four. Here we also have the option of putting more transistors on one channel and connecting more fans to them.

RPM measurement

The 3rd line of the fans is the tachometer output. We have to supply it with a voltage of 3.3 V or 5 V, which the fan brings to zero twice per revolution. The simple solution is to count how many pulses there were in one minute, the more advanced solution is to measure the time elapsed between two pulses. We will do the latter.

References:

⚠️ **GitHub.com Fallback** ⚠️