Regulation of the speed of rotation of a fan

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] Basic connection

In this task we will connect power load to the microcontroller, specifically, it will be a cooling fan from the Pentium 4 processor. Its voltage rating is 12 V, current rating up to 0,45 A.

Three wire electrical connection of the fan, used e.g. for the PC cooling, which allows speed regulation is in the figure below.

In the figure, the wire colours are as follows:

Ucc_FAN: yellow

TACHO_FAN: green

GND_FAN: black


The gate of the transistor IRFZ44N is connected to the control signal (0/5 V from MCU's port).

Soubor:CPU-FAN.png

[editovat] Control of the fan

For the first experiment with the fan is enough to connect +12 V (yellow wire) and GND (black wire) to external voltage source, current limitation of the source set to 300 mA, current limiting mode. With NMOS FET switch IRFZ44N is possible to control the fan by logic value, log. 1=on.

Connection of the transistor IRFZ44N:

Soubor:IRFZ_schematics.png


By the change of duty of the control signal is possible to control mean value of the fan's supply voltage and hence its rotation speed. The TACHO signal and resistors in its circuitry sould not be connected in the first step, however, the TACHO signal musn't be connected to the microcontroller by no means! First experiment implements very simple software PWM. It just switch on the fan, wait a while, than switch it off and wait another short time again. This is just an ilustration of the principle, later we will implement true hardware PWM.


; 
; example fan program for ATmega88
;
; P4 CPU fan Ucc pin is supposed to be connected 
; to +12 V, GND pin is supposed to be connected 
; to FET Drain, Source on GND, Gate on 
; pin 16 (PB2, FAN). Fan runs when FAN output is log. H.
;
; FAN is switched ON with switch between PC2 and PD2


	.EQU DDRB = $04
	.EQU PORTB = $05

	.EQU DDRC = $07
	.EQU PORTC = $08
	.EQU PINC = $06

	.EQU DDRD = $0A
	.EQU PORTD = $0B
	.EQU PIND = $09

;	.INCLUDE "m88def.inc"  ; replaces previous lines of the program

	.EQU FAN = 2


; Pin driving FAN is set as output:

	SBI	DDRB, FAN

; Basic keyboard init:

; One switch of matrix keyboard is connected between PINC 2 a PIND 2
; Zero values of DDRC, 2 and PORTB, 2 are implicit

	SBI DDRD, 2
	SBI PORTC, 2


; Init:
	RCALL   FAN_OFF

GO:	SBIS	PINC, 2
	RCALL	FAN_PWM   ; Simple PWM control of the FAN, if the key is pressed
	RJMP	GO


;;;
;;;
;;; P R O C E D U R E S
;;;
;;;
	
VERYSMALLWAIT:
	LDI R20, 0xFC
	MOV R1, R20
SMALLWAIT:
	INC	R1
	BRNE	SMALLWAIT
	RET

	
FAN_ON:
	SBI	PORTB, FAN
	RET

FAN_OFF:
	CBI	PORTB, FAN
	RET

FAN_PWM:
	RCALL	FAN_ON
	RCALL	VERYSMALLWAIT  ; pulse ratio controlled by number of waits
	RCALL	VERYSMALLWAIT  ; 4:1 in this case
	RCALL	VERYSMALLWAIT
	RCALL	VERYSMALLWAIT
	RCALL	FAN_OFF
	RCALL	VERYSMALLWAIT 

	RET

[editovat] Further steps

Now we improve our software Pulse Width Modulation (PWM) with simple keyboard control of rotation speed of the fan. It will be controlled in the 8 steps according to the pressed key. Full speed corresponds to 8/8 ON time, and 0/0 OFF time; lower speed will be reached by 7/8 ON and 1/8 OFF, 6/8 ON and 2/8 OFF, ..., the fan will be stopped when we reach 0/0 ON time and 8/8 OFF time. The average value of the pulses (an equivalent DC) is 8/8, 7/8, ..., 1/8, 0/8. Even the minimum operating frequency would be just few tents of hertz (when the momentum of the fan integrates the pulses effectively), the minimum recommended frequency is greater than 20 kHz, or we can generally encounter disturbing noise. Higher frequencies we simply cannot hear... The frequency corresponds with the number of clock count of the MCU (number of executed instructions). You can check it with the oscilloscope. For very low speed of rotation, short initial full speed pulse may be required, or the fan needs not to start to rotate.

You can also try to measure speed of rotation via the TACHO signal. In the fan is a transistor with an open collector, which generates 2 pulses per turn on full supply voltage. It is generally 12 V, so it is necessary to decrease it. In our example, we use just a voltage divider, which consists of three resistors of the same resistance. The upper one pulls up the open-collector transistor. Without the divider the microcontroller would be destroyed! The maximum rotation speed is about 3000 turns per minute, so the TACHO signal has most 100 pulses per second. However, the TACHO signal is related to the control signal by NAND logical function (try to explain why), so the speed measurement is a little complicated. We can measure it during the ON phase, and use the XOR logic with the previous state. Použitelné fragmenty programu:

Software PWM (just a fragment of code, you should complete it), the speed of ratation is passed to this function as a number 0-7 stored in the R16 register:


PWM:
	MOV 	R17, R16
	INC		R17
	LDI		R18, 0xF8
	OR		R18, R16
PWM_ON:
	DEC		R17
	BREQ	PWM_OFF
	SBI		PORTB, FAN
	RCALL 	VERYSMALLWAIT
	RJMP	PWM_ON
PWM_OFF:
	INC		R18
	BREQ	PWM_RET
	CBI		PORTB, FAN
	RCALL 	VERYSMALLWAIT
	RJMP	PWM_OFF
PWM_RET:
	RET

A function which handles the keyboard (don't press two or more keys simultaneously, or the MCU may be destroyed! Pressing two or more keys simultaneously has no meaning in this example; however, you can try to write your own function, where outputs are not in logical 1, but in the high-impedance state, as was explained on the seminar):

KEYPRESS:
	CBI 	PORTD, 0	;log. 0 to the row with 1, 2, 3, A
	SBI 	PORTD, 1	;log. 1 on another three
	SBI 	PORTD, 2
	SBI 	PORTD, 3	
KEY1:
	SBIC	PINC, 2
	RJMP	KEY2
	LDI	R16, 1		;pressed key 1
	RJMP	KEYRET
KEY2:
	SBIC	PINC, 3
	RJMP	KEY3
	LDI	R16, 2
	RJMP	KEYRET
KEY3:
	SBIC	PINC, 4
	RJMP	KEY4
	LDI	R16, 3
	RJMP	KEYRET

KEY4:
	SBI 	PORTD, 0
	CBI 	PORTD, 1	;log. 0 to the row with 4, 5, 6, B
	SBI 	PORTD, 2
	SBI 	PORTD, 3	
	SBIC	PINC, 2
;
;
; etc. (you should complete yourselves)
;
;

KEY0:
	SBI 	PORTD, 0
	SBI 	PORTD, 1
	SBI 	PORTD, 2
	CBI 	PORTD, 3	;log. 0 to the row with *, 0, #, D	
	SBIC	PINC, 3
	RJMP	KEYRET
	LDI	R16, 0		;pressed key 0

KEYRET:
	RET

The main program after initialization calls just these two functions.

[editovat] Disadvantages

Even such fun speed regulation is working according to our requirements; it has many disadvantages. The frequencies and delays are given just by the number of executed instructions (and clock speed of the microcontroller), so its accurate setting is very complicated. Any program change is very troublesome. The MCU usage is at the 100%, so it consumes needlessly much energy. It is a problem, specifically if the system is operated on batteries.

[editovat] Interrupt, Sleep

Power saving modes, the sleep, specifically, can reduce power consumption dramatically. The MCU is in the sleep mode with minimum power requirements most of time, and the MCU is waked up just for keybord or PWM handling by interrupts. Here is just a skelet of the program, which will use sleep mode and interrupt.

Take note of the .INCLUDE directive, where is specified the file with definitions related to used processor (RAM size, addresses mapped to the register names, ...). At the beginning of the program are defined two interrupt vectors (Reset and keyboard inputs), and the top of the stack is set. Farther the interrupt mask registers are set, and, finally, the sleep mode is defined.

For handling of keyboard interrupts the Pin Change Interrupt is used. This function applies to all ports of Mega88 MCU. When activated, logical change at port's pin will trigger interrupt request, depending on configuration. Although ATmega88 may handle logic changes at 23 MCU's pins, it may generate just 3 interrupt requests - PCINT0 (PCINT 0 ... 7 pins), PCINT1 (PCINT 8 ... 14 pins) and PCINT2 (PCINT 16 ... 23 pins). The corresponding interrupt is allowed by setting corresponding bit in the Pin change interrupt control register (PCICR) to logical 1. Bit 0 controls PCIE0, bit 1 controls PCIE1 and bit 2 controls PCIE2. The PCICR register resides at address 0x68. It must be accessed by data memory manipulation instructions (ld, st), not i/o instructions (in / out). Which pin may actually trigger the interrupt is controlled by registers PCMSK0 ... PCMSK2. The keyboard columns are connected to the port C, pins 2 ... 5 (2 ... 4 are enough for handling of the fan control requests). These pins are tied to configuration bits PCINT10 .. PCINT13 in the PCMSK1 register (bits 2 ... 5). So these bits must be set to logic 1 to allow interrupt from corresponding pins. Logical change at any of these four pins trigger the same interrupt PCINT1. The PCMSK1 register resides at the address 0x6C. Finally, to allow any maskable interrupts in the MCU, the Global interrupt enable bit (bit 7) of the Status register must be set. This is so special operation, it has dedicated special instruction, sei.

The power saving mode is activated by the sleep instruction. This instruction halts MCU operation, except some peripherals. Which peripherals are active (and corresponding clock sources), depends on the mode selected. ATmega88 MCU supports IDLE, ADC noise reduction, power-down, power-save and standby modes. The desired mode is selected in the Sleep mode control register (SMCR), address 0x33 (I/O), or 0x53 (data space) using bits SM0 ... SM2. The bit 0 (SE - Sleep enable) must be also set to 1. The MCU is wake-up by logic (voltage) change at keybord column pins (PC2 ... PC5).

See lecture slides and ATmega88 datasheet for more details.

; 
; example fan program for ATmega88 with Interrupt&Sleep
;
; To do: *** Rotation speed  is controlled by keyboard, 
; To do: *** keys 0-7 represent the speed between 0 and 100 %
;
; To do: *** Fan starts to rotate with the first valid key press
;
;
; Fan is switched on and off with the valid key press
;
; P4 CPU fan Ucc pin is supposed to be connected 
; to +15 V, GND pin is supposed to be connected 
; to NMOS Drain,, Source on GND, Gate on 
; pin 16 (PB2, FAN). Fan runs when FAN is 1.


.INCLUDE "m88def.inc"

.EQU FAN = 2


.ORG 0x0000 
	jmp Main ; Reset Handler

.ORG 0x0004 
	jmp isr1 ; PCINT1 Handler



; Main program start

Main: 
	ldi r16,high(RAMEND); Main program start
	out SPH,r16 ; Set Stack Pointer to top of RAM
	ldi r16,low(RAMEND)
	out SPL,r16


; Hardware initialization

; Pin driving FAN is output:
	sbi DDRB, FAN

; Initial Fan stop:
	cbi PORTB, FAN
	

; Keyboard init:
	cbi DDRC, 2 ; set inputs for keyboard (COL1-3)
	cbi DDRC, 3
	cbi DDRC, 4

	sbi  PORTC, 2 ; set internal Pull-Ups for keyboard
	sbi PORTC, 3
	sbi PORTC, 4

	sbi DDRD, 0 ; set driving outputs for keyboard
	sbi DDRD, 1 ; (ROW1-ROW4)
	sbi DDRD, 2
	sbi DDRD, 3

	cbi PORTD, 0	; log. 0 on all rows
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3


; Keyboard interrupt  
;
; Activation of pin change interrupt - PROBLEM!!! PCICR and PCIMSK are 
; extended I/O registers (0x68 and 0x6C), and must be handled as 
; a memory location

;	ldi r16,0x02 ; activate PCINT1
;	out PCICR,r16

	ldi r26, PCICR ; load address of PCICR in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00000010 ; activate PCINT1
	st X, r16 ; store new PCINT1


;	ldi r16,0b00011100 ; Mask active inputs
;	out PCMSK1,r16

	ldi r26, PCMSK1 ; load address of PCMSK1 in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00011100 ; allow pin change interrupt on portC bits 2,3,4
	st X, r16 ; store new PCMSK1


	sei ; Enable interrupts


; Set sleep mode of the CPU
; SMCR: 0,0,0,0,SM2,SM1,SM0,SE   SM2..0: Sleep Mode Select Bits, SE: Sleep enabled)
; Select one of two following modes:

;	ldi r16,0b00000001 ; Idle mode 
	ldi r16,0b00000101 ; Power down mode
	out SMCR,r16 ; Sleep mode set


; Sleep loop, wake up by the Interrupt, return with RETI back to sleep loop

loop:
	sleep 
	nop 
	rjmp loop 


; PCINT0 Service Routine - only simple key decoding!:
;
; level change on PC2-4 = Key pressed -> 
; switch the FAN between ON (keys 1, 4, 7, *) and OFF (keys 2, 5, 8, 0) states
;
; To do: *** rpm reading, regulation, etc.
; To do: *** Catching only the key press, not key release, complete key decoding

isr1:
	sbic PINC, 2 ; skip next if KEY = 1,4,7,* 
	rjmp isr11 ; jump if not
	sbi PORTB, FAN ; FAN on
	reti ; return from Interrupt
isr11:
	sbic PINC, 3 ; skip next if KEY = 2,5,8,0 
	reti
	cbi PORTB, FAN ; FAN off
	reti ; return from Interrupt


[editovat] Interrupts

Interrupts may be triggered by most of the peripherals, and other events including the software one (though using port pins). Detailed description is available in the datasheet. Interrups used in our task is descibed above. Note that it is necessary to set up stack poiner properly before we can enable and use interrupts, because the return address is stored there. Because on AVR the stack "grows" down, the most suitable initial address of the stack pointer is the last address in the RAM. It is defined by the RAMEND constant, defined in the include file "m88def.inc", "m168def.inc", or other, depending on the used MCU.

Below is the list of all interrupts (interrupt vector table) on ATmega168. Compare it with interrupts used in our example, since there we use another MCU - ATmega88. ATMega88 has smaller memory, so just RJMP instructions are enoug and so it has interrupt vectors on consequent addresses; ATmega168 has more memory, is requires absolute JMP instructions , which fits into 32 bits or 2 words, so each interrupt vecors occupies two addresses in the memory.

.org 0x0000 
	jmp RESET ; Reset Handler
.org 0x0002 
	jmp EXT_INT0 ; IRQ0 Handler
.org 0x0004 
	jmp EXT_INT1 ; IRQ1 Handler
.org 0x0006 
	jmp PCINT0 ; PCINT0 Handler
.org 0x0008 
	jmp PCINT1 ; PCINT1 Handler
.org 0x000A 
	jmp PCINT2 ; PCINT2 Handler
.org 0x000C 
	jmp WDT ; Watchdog Timer Handler
.org 0x000E 
	jmp TIM2_COMPA ; Timer2 Compare A Handler
.org 0x0010 
	jmp TIM2_COMPB ; Timer2 Compare B Handler
.org 0x0012 
	jmp TIM2_OVF ; Timer2 Overflow Handler
.org 0x0014 
	jmp TIM1_CAPT ; Timer1 Capture Handler
.org 0x0016 
	jmp TIM1_COMPA ; Timer1 Compare A Handler
.org 0x0018 
	jmp TIM1_COMPB ; Timer1 Compare B Handler
.org 0x001A 
	jmp TIM1_OVF ; Timer1 Overflow Handler
.org 0x001C 
	jmp TIM0_COMPA ; Timer0 Compare A Handler
.org 0x001E 
	jmp TIM0_COMPB ; Timer0 Compare B Handler
.org 0x0020 
	jmp TIM0_OVF ; Timer0 Overflow Handler
.org 0x0022 
	jmp SPI_STC ; SPI Transfer Complete Handler
.org 0x0024 
	jmp USART_RXC ; USART, RX Complete Handler
.org 0x0026 
	jmp USART_UDRE ; USART, UDR Empty Handler
.org 0x0028 
	jmp USART_TXC ; USART, TX Complete Handler
.org 0x002A 
	jmp ADCon ; ADC Conversion Complete Handler
.org 0x002C 
	jmp EE_RDY ; EEPROM Ready Handler
.org 0x002E 
	jmp ANA_COMP ; Analog Comparator Handler
.org 0x0030 
	jmp TWI ; 2-wire Serial Interface Handler
.org 0x0032 
	jmp SPM_RDY ; Store Program Memory Ready Handler

[editovat] Mód spánku

V módu spánku lze zastavit nebo omezit činnost jednotlivých částí procesoru, podle toho také klesá spotřeba, která je při normálním provozu v závislosti na napájecím napětí a frekvenci řádu jednotek mA, od cca 0,5 mA při taktu 1 MHz a Ucc=2 V do 12 mA při 8 MHz a 5 V, při nejhlubším uspání do Power down módu je typická spotřeba 500 nA. Podrobněji datasheet, Electrical Characteristics.

Módů je 5, viz datasheet, Power Management and Sleep Modes, přepínají se řídicím registrem SMCR, Sleep Mode Control Register

Idle mode zastaví CPU a nechá běžet SRAM, časovače/čítače, USART, 2-wire Serial Interface, SPI port, a interrupt system.

Power-down mode chrání obsah registrů, ale zastaví oscilátor, to do následujícího interruptu nebo hardwarového resetu zastaví všechny další funkce.

Power-save mode nechá v činnosti asynchronní časovače, zbytek součástky je zastaven.

ADC Noise Reduction mode zastaví CPU a všechny I/O moduly vyjma asynchronního časovače a ADC, aby bylo minimalizováno rušení během A/D převodu.

Ve Standby mode nadále běží oscilátor, zbytek je uspán, to dovoluje rychlé probuzení a přitom nízkou spotřebu.

Osobní nástroje