Edit Translation
by Transposh - translation plugin for wordpress
IPv6 logo

Vusibino Tachometer

We can see microcontrollers as the cerebellum of a computer, communicating this to those we can feed the CPU with real-world data through sensors, and order him to perform actions on these data or memorize to act autonomously.

In this and the following entries shall see how to build a simple circuit to control computer fans with our VUSiBino. The circuits are connected with wires, we will not make a shield to make it easier to place the plates where we want. We start with a circuit to control two fans with four-pin CPU, These fans are the easiest to control since the PWM we can apply the same voltage of our microcontroller, and carry tachometer built for the speed at which it is spinning.


The following images show circuit designs. To make it more flexible and compatible with other devices I have chosen to make connections to the microcontroller via terminals. to mount, usad reference input VUSiBino. Need:

PCB perfboard 18×11
Resistors 2x10kOhm.

2×68 Ohm.

Connectors 4xClema

2x4Pin strip macho


10k Ohm resistors are “Pullup” of pin collecting the tachometer signal if not in the micro ActiveMOS, those of 68 Ohm serve sump towards the source. The terminals are connected to VUSiBino, as it indicated in the last image of the sequence and connect with the pins of PWM and fan tachometer, that connects to the pin strips (or four-pin connector). The fan power is on the fourth clema, just behind the fan connectors to a source of 12V.

D1 and D4 RPM1 and RPM2 go to, They are connecting with the reader fan speed. This consists of a hall sensor, and two diametrically opposite small magnets, for each revolution two signals will. D3 and D5 provide the PWM signal to each fan connecting terminals PWM1 PWM2 and.

Brief explanation of what the PWM

ATMEGA digital pins can only have two voltages, 0 and + 5V, but if we want to send a lower voltage to slow down a DC motor, lowering the brightness of a LED or change the behavior of other apparatus, we can use a trick that depends on the say “inertia” each apparatus, or the time it takes to react to changing voltage. If we connect a motor we can see that it takes a while to boot, and when you disconnect another little stand, if we turn off and turn on the engine it seems very fast running continuously. If we vary the time between switching on and off it will seem that we are varying the voltage, if we make the time between off is very short and extended the on the apparent result is that the voltage is the maximum, but if we shorten the ignition timing and lengthen the shutdown, it will appear that the voltage has dropped. A more detailed explanation of the PWM can find this link.

Must take into account that not all electrical and electronic equipment support equally rapid cycle off and fired, should learn before trying any expensive or do not have a spare on hand.



We started with statements libraries, constant and global variables.

The bookstore “<avr / io.h>” allows access to pins AVR with constant names and operate them easily, “<avr/interrupt.h>” It enables us to call and handle interruptions, “<avr / wdt.h>” is to use the “watchdog”, “<avr/eeprom.h>” we will use to access the EEPROM, “<util/delay.h>” to use the delay function rather than having to create us our own timer for use which can be cumbersome, “<stdbool.h>” It is a function to use the variables of truth and falsehood, Finally “usbdrv.h” USB is the library where the functions are that we will use to communicate with the port.

Follow the constants that we will use to assess what actions to take when the program “host” call micro, behind them we define the positions of the EEPROM where we store program settings permanently. I will explain in more detail these statements on the part of the program where they are used.

Strings”replyBuf”, “dataReceived” and “adcVal” and we have used in VUSiBino demo, They used to send and receive information to and from the “host”.

We use “sw_auto” for how we move fans, the first two bits correspond to the ehemos taking action on each fan, If this change speed automatically or will we choose a fixed speed in the program “host”. “tach_01” and “tach_02” collect the speed of each fan, I define as the two-byte integer that the number may be greater than 255 If we make the transformation of pulses at RPM. “s” is an intermediate variable that we will use to cambier the type of data we send to the host via USB and USB libraries that accept certain types.

We will use two variables as counters, “lapse_01” and “countA” to control times and cycles while tach “portdhistory” saves the states of ports where the tachometer sends its signals to compare them with new and see if there are changes.

Variables”pwm_01″ and “pwm_02” we will serve to set the fan speed, While “bool_up_01” and “bool_up_02” They serve to control whether we increase or decrease the speed when we automatically.


Management control messages

Case “USB_READ_SENS”. we put in “usbmsgPtr” tachometers values ​​and send them to the “host” the present. As discussed below, We have processed the data and sent revolutions per minute instead of the pulses detected the tachometer when this could be done perfectly in the “host” It is having more memory and speed, but I do this program in the microcontroller to illustrate and test a method of converting data that may be useful in some other circumstance.

Caso USB_WRITE_CONF. We write in the EEPROM pwm values ​​and behavior of micro move when the fans, so if you unplugged, to be fed again it will work with the parameters that we have saved. The EEPROM is a nonvolatile memory, you can write about ten thousand times the space firmware and requires a special access method, in this case we use the macros and functions offered by the avr toolchain through “avr/eeprom.h” to avoid having to use assembler, which it is always cumbersome. Eeprom_write_byte use the function because the data that is going to write that size, We remind the compiler that the constant that we defined above is an unsigned byte and a pointer “(uint8_t *)” and we tell the function which is the variable you want to save, which obviously it has to be an eight-bit data. At the end we in usbMsgPtr information and PWM sensors to pick you up the host, we do in other cases because we want to constantly update this information.

Caso USB_READ_CONF. We read the saved configuration in EEPROM with a function similar to the above, but in this case the information sent to the orderly adcVal chain as we shall see. Again we ship to “host” by usbMsgPtr.

USB_RESET_CONF Case. We write the EEPROM with default variables.

Caso USB_MOD_FAN. Data received from the host on how they will act fans, if they will be in automatic PWM cycle or what you are going to apply. Once received, we passed a usbFunctionWrite to assign the variables to be read routines that control the fans.


Management of incoming information.

Here we will read the information the host sends us on how to operate the fans. It sends three data, but come in packaged words of four bytes as they are produced by Windows controls that work well. As we only need one of those four bytes, first thing we do is extract, We declare the variable “fourth” (fourth byte) obtaining the result of an operation “and” with a filling of one byte and the first character that collects replyBuf, as only fits one byte and have compared the first eight bits of the result will be the first byte.

We assign that byte “sw_auto” and we check if you tell us that the first fan should be automatically seeing if the first bit of the tag is one, in that case we zero lap counter tachometer and continue the routine. Otherwise what we'll do is collect the value should be the first cycle PWM fan extracting second data we can glean from “replyBuf” and we go on.

now we check “sw_auto” and if we indicated in its second bit that we must activate automatic mode for the second fan started the counter, otherwise we put the value of the PWM for the second fan and out of the function.

main routine


The first thing you do is turn the microcontroller to read the EEPROM, and if the byte we defined in “E_INIT” It has a value other than “T” (worth whatever value you want to put), engrave default values, to be; Cycling fans will change automatically and begin to 50% PWM cycle. After working initialize variables with the values ​​read from the EEPROM. The method is the same as previously describe.

After that we initialize the values ​​of ports and timers. In DDRB put one (departure) zero pin, one three, we ensure that PB2 is input. Three pins, five and six of D output port will be, PD1(3) and PD4(6) will be input.

We made sure to activate “pullup” D port assignment “or” “Puerto |= (value<<Pin)”, It is equivalent to a “or” with bits but we use the definitions of pins that gives us “avr / io.h”. This will help the tachometer signal more stable and no rebounds would give us false signals. If for some reason do not want to use this instruction we connect terminals + 5v to the source of VUSiBino to use a pullup signal that stabilizes us.

Now we configure timers records for “timer0” and “Timer2” They can be used to control the PWM and “Timer1” as a timer to measure the pulses gives us the tachometer. I explain in this shipment operations Timer1. If you look at the names of the records timers see that we refer to each according to the number and letter that corresponds to the word top and bottom of the register where we change the timer functions. A) Yes, in TCCR (Timer Counter Control Register) we have two segments, A and B with different bits to indicate their operation, timer 1 we bit WGM12 one segment B to say that it will be counter, and later with the CS12 bit indicate its scale. All these bits have their name and function that are available on the “datasheet” microcontroller. I will just say that to make timers run the PWM on pins corresponding, we must follow the instructions given us such a document, we want a particular PWM mode is great for our purpose, We activate as shown in the code. TCCR_A take bits activated COM_A1, COM_B1, WGM_1 and WGM_0 to go “correct phase” both timers, replacing “_” by the number of timer. A TCCR_B carries information scaling and comparator, slightly varying signal frequency. When fans do tests with three- and two pins see what differences appear, but in a four-pin fan not'll notice that your hardware is perfectly tuned for PWM signals.

The registers “OCR_A” They correspond to PWM capable pins and also set the upper limit of the signal, this is, the maximum duty cycle will be the record indicating this operation mode we have chosen, This makes the pins that we have chosen “OCR_B” in the circuit will depend on this signal. If we used the four-pin PWM as we have set the timers, the pins “OCR_B” They never go faster than “OCR_A”. Another thing to consider is that the timers 0 and 2 tnenen eight-bit registers, its maximum value will be 255, the timer 1 It is 16 bit can climb to 65535 Steps, or what is the same a larger frequency range. Depending on the device control should take this into account.

There are “ATMEGAS” more timers and PWM as the 32PA, he 644 and the 1284, a little more expensive, with more pins and bulkier, then there are surface mount with many more options but a bit more complex to assemble.

After “initialize” USB activate the interrupt vector input pins which receive the PWM signal, in “PCICR” (Pin Change Interrupt Control Register” activate the bit “PCIE2”, saying the change detection mask two “PCMSK2” (Pin Change Mask 2) will be active, and we say PD4 and PD1 monitor the activating pin PCINT20 bits and PCINT17.

Interruptions activate and adjust the timer to count one for each 62 ticks with the prescaled 62500 Hz.

The main loop

enabled the “Guadián” and routine refresh USB, first thing we do is to see if it has been 100 ticks timer 1, approximately one tenth of a second, This period is arbitrary, We can make this cycle is long or short we want. If so we check if we change the speed of the fan according sw_auto. If indeed so, check if the cycle up or down, we add one if “up_0x” It is true, le one you are left “up_0x” it's false. When “pwm_0x” reaches the upper limit (255) we changed “up_0x” a false loss account, and conversely when “pwm_0x” reaches 0. After that we pass the variable valos “pwm_0x” to its corresponding registry to change the cycle of the PWM. A) Yes “pwm_01” to spend his fences “OCR0B” (Output Compare Register), the pin PD5 (11) and we passed “pwm_02” OCR2B to the pin PD3 (5).

When “lapse_01” reaches one hundred, approximately one tenth of a second, We began to pass the values ​​of the PWM (OCRxB) the chain adcVal, the first byte will go to zero, the second we assign the value of “OCR_xB” at that moment. We turn to calculate the rpm (It can be done in the program “host”), if 0.992 seconds have passed “tach_0x”/2 round (tachometer gives two signals per revolution), in 60, which it is a minute, would “s”, solving we get that “s” It is the product of “tach_0x” by 302. The number given is quite high, as specified, CPU fans reach speeds of several thousand revolutions per minute, so divide it into bytes and then treat the “host”. We started with byte 4 the adcVal, and we say take eight bits counting from eight “s”, a adc[5] we put the underdogs. We repeat the following bytes the value “tach_02”. Now, when the “host” ask us about the status of the fans, and we will have updated.

Having calculated the value of tachometers, restart counter values ​​and.

Interrupt functions

When interrupt conditions occur will be called to these functions. The first one Accel timer has counted 62 “ticks”, which they come to be 0.00992 seconds with a prescaled of 256 about 16Mhz. We add one to the variables “countA” and “lapse_01” discussed in the previous section. It is done, nothing complicated control time.

The second is activated when one of the port pins D, we have activated as input pins (PD1 and PD4). Note that the function takes an additional parameter “ISR_NOBLOCK”, that v-usb recommended not to block other USB functions that can be active at the time and annoy communication. It is a parameter that should not be used too, especially if there is the possibility that using the function variables can be changed during program execution, as a data only we give information “tach_0x” which does not affect the program flow will not pass nothing serious, as much as the tachometer indicates occasionally false data. It should take into account that if the data does influence, and activate a switch that prevents unwanted changes to avoid problems.

XOR do about Pind (registration where D port states are saved) with variable “portdhistory” we store the previous state of PIND, and store the result in “changedbits”. In “changedbits” shall be one, or activated only the bits that have changed according to truth table of XOR. We then saved for the next call to interrupt the current state of Pind in “portdhistory”. And individually compare the D1 and D4 pins with the corresponding bit in “changedbits”. If the result is positive change a led us to connect to PB0 and PB1 or add one lap counter tachometer.

Links of interest

Tutorial de PWM de MaxEmbedded

Tutorial the PWM one avrfreaks

Tutorial input / output for AVR

Datashhet of ATMEGA328P in pñagina of Michocrip

AVRs page with a good list of projects and datasheets.


Download Link planes, sources and executable project.



VUSibino pins and their functions.

VUSiBino Pinout

Leave a Reply