Właśnie ukończyłem regulator obrotów wentylatorów do zasilacza laboratoryjnego
Matrix MPS3005l-3.
Zasilacz w wersji standardowej ma wbudowane 2 wentylatory które są niestety bardzo głośne.
Hałas staje się uciążliwy przy dłuższej pracy zasilacza.
Aby zredukować hałas najprostrzą metodą było obniżenie obrotów wentylatorów i sterowanie nimi w zależności od wartości temperatury zasilacza.
Serce układu stanowi Atmega8 w obudowie SMD tqfp32
Do pomiaru temperatury użyłem trzech termometrów 1-wire DS18B20.
Dwa z trzech czujników temperatury, umieszczone są na tylnim radiatorze który jest podzielony na dwie niezależne części z jednym wspólnym wentylatorem.
Trzeci czujnik mierzy temperature transforamtora.
Ukałd posiada dwa tryby pracy :
Automatyczny – prędkość wentylatorów zależna jest od temperatury zmierzonej przez DS-y
Ręczny –(sterowanie przez rs232) pozwala na ustawienie prędkości wentylatorów przez wpisanie wartości PWM w oknie terminala .
Płytka dwustronna została zaprojektowana w całości w Kicadzie, i wykonana metoda termo transferu w większości użyłem elementów SMD.
Kod napisany w całości w Bascom AVR .
Kod: Zaznacz cały
'$sim
'*******************************************************************************
'------------------------------ATmega8-----------------------------------------
'------------------------------3xDS18b20----------------------------------------
'--------------------------2x PWM controlled FAN--------------------------------
'-------------------------- UART controlled ------------------------------------
'-------------------------Auto and manual mode----------------------------------
'-----------------------------Version: 2.0--------------------------------------
'-------------------------- Flash used 66%--------------------------------------
'------------------------By Pawel L. aka Pikczu---------------------------------
'--------------------------------2010-------------------------------------------
'*******************************************************************************
'DALLAS DS18B20 ROM and scratchpad commands''''''''''''''''''''''''''
'1wwrite....
'&H 33 read rom - single sensor
'&H 55 match rom, followed by 64 bits
'&H CC skip rom
'&H EC alarm search - ongoining alarm >TH <TL
'&H BE read scratchpad
'&H 44 convert T
'*******************************************************************************
'*******************************************************************************
$prog &HFF , &H3F , &HD9 , &H00 ' generated. Take care that the chip supports all fuse bytes.
$regfile = "m8def.DAT" 'uc type
$crystal = 11059200 'crystal frequency
$baud = 9600
Config Serialin = Buffered , Size = 20
'Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Portd.1 = Output 'TX
Config Portd.0 = Input 'RX
Config Portd.6 = Input 'PUSHBUTTON
Portd.6 = 1 'PULL UP
Config 1wire = Portd.2 '1Wire
Config Portd.7 = Output 'BUZZER
Portd.7 = 0 'initial status
Config Portb.0 = Output 'STATUS LED
Portb.0 = 0 'initial status
Config Portb.1 = Output 'oc1a
Config Portb.2 = Output 'oc1b
'*******************************************************************************
'****************************Variables*****************************************
Dim B As Byte 'beep
Dim Index As Byte 'index
Dim Ile As Byte 'How many ds sensor found on 1 wire bus
Dim I1(2) As Byte 'Array for 2 bytes read from DS sensor
Dim I2(2) As Byte 'Array for 2 bytes read from DS sensor
Dim I3(2) As Byte 'Array for 2 bytes read from DS sensor
Dim Dsx(8) As Byte 'Array for 8 bytes read from DS during registration
Dim Ds1(8) As Byte 'Array for 8 bytes from Ds 1
Dim Eds1(8)as Eram Byte At &H10 'Space in eeprom to write 1 ds data
Dim Ds2(8) As Byte 'Array for 8 bytes from Ds 2
Dim Eds2(8) As Eram Byte At &H20 'Space in eeprom to write 2 ds data
Dim Ds3(8) As Byte 'Array for 8 bytes from Ds 3
Dim Eds3(8) As Eram Byte At &H30 'Space in eeprom to write 3 ds data
Dim Ds_y As Byte 'used just for registering ds
Dim Temp1 As Integer 'variable to keep value temp1
Dim Temp_1 As Byte
Dim Temp2 As Integer 'variable to keep value temp2
Dim Temp_2 As Byte
Dim Temp3 As Integer 'variable to keep value temp3
Dim Temp_3 As Byte
Dim T_array(2) As Byte 'master and slave temperature array
Dim T_a_m As Byte 'Temp array max value
Dim Speed1 As Byte 'PWM variable
Dim Speed2 As Byte 'PWM variable
Dim Mod_e As Bit 'variable for auto/manual mode
Dim Czas As Word 'variable for counting time
Dim Czas2 As Byte 'variable counting time for flash and beep
Dim H1 As Byte 'variable
Dim H2 As Byte 'variable
Dim Flag0 As Bit 'Flag for timer 0
Dim Flag1 As Bit 'flag
Dim Flag2 As Bit 'flag temp changed
Dim Serial_flag As Byte 'flag set if char received from serial
Dim Y As Single
Dim Z As Single
'*******************************************************************************
'*******************************************************************************
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
Enable Interrupts
Enable Oc1a
Enable Oc1b
Config Timer0 = Timer , Prescale = 1024
Config Timer2 = Timer , Async = Off , Prescale = 1024
On Timer2 Timer2_isr 'interrupt timer2 for flash and beep
'*******************************************************************************
'*******************************************************************************
Wait 1
Print "Restart"
Wait 1
Debounce Pind.6 , 0 , Zapisz , Sub 'register DS sensors
Wait 1 '
Ile = 1wirecount() 'ile czujnków w ukladzie
Wait 1 'short delay '
Enable Timer2
Flag1 = 0 'flag set to 0 just in case
For B = 1 To Ile 'now depend how many sensors flash and beep
Start Timer2 'now start timer2 just to count delay time
Gosub Flash 'jump to flash
Gosub Beep 'jump to beep
Bitwait Flag1 , Set 'if flag set timer2 counted delay (line 318)
Czas2 = 0 'reset czas2
Next B
Stop Timer2 'now stop timer2
Czas2 = 0 'reset czas2 variable
Disable Timer2
'*************************Read from Eeprom *************************************
'*******************************************************************************
For Index = 1 To 8
Ds1(index) = Eds1(index) 'read numbers from eeprom for ds sensors after power up
Ds2(index) = Eds2(index) 'read numbers from eeprom for ds sensors after power up
Ds3(index) = Eds3(index) 'read numbers from eeprom for ds sensors after power up
Next Index
Index = 0
'*******************************************************************************
'After power Up first reading will be 85 degrees, is necessarily to convert temp
'*************konwersja temp dla wszystkich dsow********************************
1wreset
1wwrite &HCC 'skip all
1wwrite &H44
'*******************************************************************************
'*******************************************************************************
Pwm1a = 255 'set fan speed to max just to test it
Pwm1b = 255 'set fan speed to max just to test it
Wait 2
Pwm1a = 0
Pwm1b = 0
'***************************Ustawienie Timera0**********************************
Load Timer0 , 216
On Ovf0 Timer0_isr
Enable Timer0
'*******************************************************************************
'****************************Poczatek Petli*************************************
Czas = 0
Do
If Czas >= 100 Then
Disable Timer0
1wreset
1wwrite &H55
1wwrite Ds1(1) , 8 'sending address of first ds sensor
1wwrite &HBE
I1(1) = 1wread(2)
1wreset
1wwrite &H55
1wwrite Ds2(1) , 8 'sending address of second ds sensor
1wwrite &HBE
I2(1) = 1wread(2)
1wreset
1wwrite &H55
1wwrite Ds3(1) , 8 'sending address of third ds sensor
1wwrite &HBE
I3(1) = 1wread(2)
Temp1 = I1(2) 'Most significant byte of temp
Shift Temp1 , Left , 8 'shift left
Temp1 = Temp1 + I1(1)
Shift Temp1 , Right , 4
Temp2 = I2(2) 'Most significant byte of temp
Shift Temp2 , Left , 8 'shift left
Temp2 = Temp2 + I2(1)
Shift Temp2 , Right , 4
Temp3 = I3(2) 'Most significant byte of temp
Shift Temp3 , Left , 8 'shift left
Temp3 = Temp3 + I3(1)
Shift Temp3 , Right , 4
' ****konwersja temp dla wszystkich dsow**
1wreset
1wwrite &HCC 'skip all
1wwrite &H44
Czas = 0
Enable Timer0 'all DS do covert T
Gosub Flash
End If 'end if czas>=100 odczyt temperatury z ds
If Temp_1 <> Temp1 Or Temp_2 <> Temp2 Or Temp_3 <> Temp3 Then
Temp_1 = Temp1
T_array(1) = Temp1
Temp_2 = Temp2
T_array(2) = Temp2
Temp_3 = Temp3
Print "Master T= " ; Temp_2 ; "C " ; "Slave T= " ; Temp_1 ; "C " ; "Trafo T= " ; Temp_3 ; "C"
Set Flag2
End If
If Mod_e = 0 Then 'mode = Auto
If Flag2 = 1 Then 'if flag2 =1 new temperature value
T_a_m = Max(t_array(1)) 'pick up from array max value of temp
Y = 8.75 * T_a_m ' do maths
Y = Y - 182.5
' Speed1 = Abs(y)
Speed1 = Y
If T_a_m <= 30 Then 'if temperature array max value smaller than 30 then
Speed1 = 0 'fan speed = 0
End If '
If T_a_m >= 50 Then 'if temperature array max value greater or equal 50 then
Speed1 = 255
End If
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Z = 7 * Temp_3 'same as above but just for small fan and internal temp value
Z = Z - 95
Speed2 = Z
If Temp_3 <= 25 Then
Speed2 = 0
End If
If Temp_3 >= 50 Then
Speed2 = 255
End If
Print "Radiator Fan=" ; Speed1
Print "Case Fan=" ; Speed2
Reset Flag2
Pwm1a = Speed1
Pwm1b = Speed2
End If
'Pwm1a = Speed1
'Pwm1b = Speed2
End If
Serial_flag = Ischarwaiting() 'if some char in buffer then set serialflag
If Serial_flag = 1 Then '
Index = Inkey() 'copy char from buffer to index
If Index = 097 Or Index = 065 Then ' if char = a or A
Print "MODE:"auto "" 'print in terminal window mode was change to auto
Temp_1 = Temp1
Temp_2 = Temp2
Temp_3 = Temp3
Print "Slave T= " ; Temp_1 ; "C " ; "Master T= " ; Temp_2 ; "C " ; "Internal T= " ; Temp_3 ; "C"
Reset Mod_e 'set mode flag to 0
Set Flag2
End If
If Index = 109 Or Index = 077 Then
Print "MODE:"manual ""
Set Mod_e
Temp_1 = Temp1
Temp_2 = Temp2
Temp_3 = Temp3
Print "Slave T= " ; Temp_1 ; "C " ; "Master T= " ; Temp_2 ; "C " ; "Internal T= " ; Temp_3 ; "C"
Input "Input Speed value for radiator Fan=" , Speed1
If Speed1 < 80 Then
Speed1 = 0
End If
If Speed1 > 255 Then
Speed1 = 255
End If
Pwm1a = Speed1
Input "Input Speed Value for Case Fan=" , Speed2
If Speed2 < 80 Then
Speed2 = 0
End If
If Speed2 >= 255 Then
Speed2 = 255
End If
Pwm1b = Speed2
End If
Clear Serialin
End If
Enable Timer0
Loop
End
'*******************************************************************************
'*****************************SUBS**********************************************
'*******************************************************************************
Timer0_isr:
Load Timer0 , 216 'co Xms
Incr Czas
If Czas >= 100 Then
Set Flag0
Else
Reset Flag0
End If
Return
'******************************Timer2_isr:**************************************
'*******************************************************************************
Timer2_isr:
Load Timer2 , 255
Incr Czas2
If Czas2 = 4 Then 'Acive
Reset Portb.0
Reset Portd.7
End If
If Czas2 >= 16 Then 'not active
Flag1 = 1
End If
Return
'**********************************FlashBeep************************************
'*******************************************************************************
Fb: 'Flash beep
Enable Timer2
Flag1 = 0 'reset flag
Toggle Portd.7 'change to opposite level
Toggle Portb.0 'change to opposite level
Bitwait Flag1 , Set 'wait for confirmation bit from timer2
Czas2 = 0 'set to 0 time counted by timer2
Return
'********************************BEEP*******************************************
'*******************************************************************************
Beep:
Flag1 = 0
Toggle Portd.7
Return
'********************************FLASH******************************************
'*******************************************************************************
Flash:
Flag1 = 0
Toggle Portb.0
Return
'********************************ZAPISZ*****************************************
'*******************************************************************************
Zapisz:
Czas = 0 'wyzerownaie licznika czasu od timera0
Gosub Fb 'skocz do flash beep
Print "Rejstracja" ' wyswietla w terminalu
Disable Interrupts 'wylacz przerwania
Ds_y = 0 'wyzeroj zmienna ilosc czojnikow ds
Do 'poczatek petli rejstracyjnej
Dsx(1) = 1wsearchfirst() 'szukaj ds na magistrali
If Err = 0 Then 'jesli znalazl ds-a
Incr Ds_y 'zwieksz ds_y o 1
Select Case Ds_y: 'w zaleznosci ktory to ds
Case 1: 'pierwszy ds
For Index = 1 To 8 'zapisz jego dane do eeprom
Eds1(index) = Dsx(index)
Next Index 'i tak 8 razy
Print "Registered DS1 as Master " 'no i potwierdz
Enable Interrupts 'wlacz przerwania
Gosub Fb 'skocz do flash beep
Disable Timer2 'juz po to wylacz tiemr 2
Enable Timer0 'Wlacz timer0
Bitwait Flag0 , Set 'czekaj na flage od timera 0
Disable Timer0 'wy³acz timer0
Disable Interrupts 'wylacz przerwania
Czas = 0 'wyzerownaie licznika czasu od timera0
Case 2: 'dla ds-a 2
For Index = 1 To 8 'zapisz jego dane do eeprom
Eds2(index) = Dsx(index)
Next Index 'i tak 8 razy
Print "Registered DS2 as Slave "
Enable Interrupts 'wlacz przerwania
Gosub Fb 'skocz do flash beep
Gosub Fb 'skocz do flash beep
Disable Timer2 'juz po to wylacz timer 2
Enable Timer0
Bitwait Flag0 , Set 'czekaj na flage od timera 0
Disable Timer0 'wylacz timer0
Disable Interrupts 'wylacz przerwania
Czas = 0 'wyzerownaie licznika czasu od timera0
Case 3: 'dla ds-a 3
For Index = 1 To 8 'zapisz jego dane do eeprom
Eds3(index) = Dsx(index)
Next Index 'i tak 8 razy
Print "Registered DS3 as internal " 'no i potwierdz
Enable Interrupts 'wlacz przerwania
Gosub Fb 'skocz do flash beep
Gosub Fb 'skocz do flash beep
Gosub Fb 'skocz do flash beep
Disable Timer2
Enable Timer0 'juz po to wylacz timer 2
Bitwait Flag0 , Set 'czaekja na flage od timera 0
Disable Timer0 'wylacz timer0
Disable Interrupts 'wylacz przerwania
Czas = 0 'wyzerownaie licznika czasu od timera0
End Select 'koniec wyboru ds-ow
End If 'koniec warunklu
Loop Until Ds_y = 3 'koniec petli do 3-ech
Enable Interrupts 'wlacz przerwania
Return 'powrot
'*******************************************************************************
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'Y = 8.75 * X -182.5 range from 30 up to 50 degree
'y=predkosc
'x= temp
'Y = 7 * x-95 range from 25 up to 50
'******************************************************************************





Pozdrawiam Pikczu
Ps: Dla zainteresowanych plik bas i bin etc.
------------------------------------Edit--- 8.08.2010-------------------------------------------------
Ps: Poprawiłem błędy w kometarzach.
W samym sofcie nic się nie zmieniło.