I decided to keep this project as simple as possible but without giving up functionality. Having a surplus of ATtiny13’s (in a DIP8 package), I tend to go to this MCU for smaller controller projects. It has 1KB of FLASH program memory 64 bytes of RAM and 64 bytes of EEPROM.
I’ll admit right up front that I’m not big on using “C” for my microcontroller projects. I’ve been programming AVR’s for many years using assembly language, so this project, like most others I’ve designed, is written in assembly language for the 8-bit AVR series from ATMEL (now owned by MICROCHIP).
For this project, all I really needed to do is repeatedly read the ATtiny13’s ADC, compare it to a value and set the PWM register to set the proper fan speed. Even though this project is “line powered”, I still see no need to waste power if I don’t have to. My hardware and software experience is embedded low-power (battery operated) devices, so when I can, I use the AVR’s sleep instruction and the watchdog timer in interrupt mode to periodically wake the MCU. The program flow is as follows:
- Initialize registers, I/O ports, variables and (UART)buffer.
- Initialize the ADC, PWM mode and UART.
- Initialize the watchdog timer for 1 second timeout.
- Fetch the reading from the ADC (4 samples are taken and averaged).
- Look up the ADC reading in the temperature-to-PWM table.
- Set the PWM register to set the fan speed.
- if UART enabled: send the ADC reading and PWM value.
- Reset the watchdog timer then enter sleep mode.
- Watchdog interrupt wakes AVR, goto step #4.
The lookup table being implemented is a simple window-comparator type stored in the AVR’s FLASH program memory. At the moment, there are a total of 7 steps, including “off” and “full on”. The table data is below:
.dw 420,0 ;Speed level 0 (below 34 deg C - off) .dw 338,$60 ;Speed level 1 (35-44 deg C) .dw 267,$80 ;Speed level 2 (45-54 deg C) .dw 210,$A0 ;Speed level 3 (55-64 deg C) .dw 165,$C0 ;Speed level 4 (65-74 deg C) .dw 130,$DF ;Speed level 5 (75-84 deg C) .dw 102,$FF ;Speed level 6 (85+ deg C)
The 1st column contains the ADC reading (i.e “420”) and the 2nd column contains the desired PWM register value, which is the fan speed. The averaged ADC reading is successively compared to the 1st column value. If the reading is lower than the 1st column’s value then the PWM register is loaded with the prior row’s 2nd column value. One can see that this a “windowed” function. Using this method, any number of “levels” can be implemented. Furthermore, this same technique can be modified for use with other “real-world” input and output devices that use the ADC for an analog input and a PWM signal as the “analog output”.
I chose 7 levels but after testing, which I will discuss in a future post, 5 levels or even 3 or 4 would be fine for this project.
WORDPRESS does not allow ZIP or 7Z files in posts (unless you pay for it) and I’m not storing my project files on any external Internet accessible repositories. However, I am using ZOHO for email and I can store the ZIP file there. The project’s ZIP file can be downloaded here.
In the next post, I’ll discuss the testing phase.