вторник, 22 мая 2012 г.

Пропорциональная модуляция

Недавно задумался над усмирением шумного вентилятора в компьютере.

Ранее у меня было ограничено напряжение на вентиляторе, последовательно подключен стабилитрон.

Схема вполне эффективно работает, вентилятор почти не слышно, но есть один недостаток, стабилитрон греется. Рассеиваемая мощность составляет 1Вт = 3.3В * 0,3А. И еще хотелось бы иметь возможность регулировать скорость, а на материнской плате регулируется только вентилятор процессора.

В регуляторах с высоким КПД применяют широтно-импульсную модуляцию. Регулирующий элемент работает в ключевом режиме, то есть находится в одном из двух состояний: открыт или закрыт. Частота переключений остается постоянной, меняется соотношение времени открытого и закрытого состояний. На выходе импульсное напряжение фильтруется LC цепочкой, на нагрузке остается постоянная составляющая.

Широтно-импульсная модуляция реализована в микроконтроллерах семейства PIC16, но только для одного выхода. Программно сложно сделать достаточно высокочастотную модуляцию сразу для нескольких выходов.

Отладил программку в PIC simulator IDE. 4-х канальный 16-ти уровневый ШИМ модулятор, импульсы на выходах появляются в разное время, при условии что на них установлены разные уровни.


; коэффициент делителя TMR0
TMR0PRESCAL EQU 1 ; значение инициализации регистра OPTION_REG

; Выходы ШИМ
OUTPORT EQU 0x05 ;порт вывода, PORTA в данном случае
OUTPORTMASK EQU 0xF0
OUTPIN1 EQU 0
OUTPIN2 EQU 1
OUTPIN3 EQU 2
OUTPIN4 EQU 3

; Копия порта вывода
TMPOUT EQU 0x21

; Входные параметры функции PWM4
TMPVAL1 EQU 0x22
TMPVAL2 EQU 0x23
TMPVAL3 EQU 0x24
TMPVAL4 EQU 0x25
COUNTER EQU 0x26

; Переменные для хранения контекста во время прерывания
W_TEMP EQU 0x70 ; Для хранения W регистра
STATUS_TEMP EQU 0x20


;----------
 ORG 0
 GOTO MAIN

 ORG 4
INTERRUPT:
 MOVWF W_TEMP
 SWAPF STATUS,W
 BCF STATUS,RP0
 BCF STATUS,RP1
 MOVWF STATUS_TEMP

 ; Тело обработчика прерывания
 BCF INTCON,T0IF ; сбрасываем флаг прерывания

 SWAPF STATUS_TEMP,W
 MOVWF STATUS
 SWAPF W_TEMP,F
 SWAPF w_TEMP,W

 RETFIE

INITTMR0:
 ; переключаем предделитель на вход TMR0
 ; устанавливаем коэффициент деления

 CLRF TMR0
 BSF STATUS,RP0
 MOVLW TMR0PRESCAL
 MOVWF OPTION_REG
 ; Разрешаем прерывания
 CLRF INTCON
 BSF INTCON,T0IE
 BSF INTCON,GIE

 BCF STATUS,RP0

 RETURN

PWM4:
 MOVF TMPOUT,W
 MOVWF OUTPORT ;Отправляем значение в порт
 ANDLW OUTPORTMASK ;Сбрасываем используемые биты
 MOVWF TMPOUT

 INCF TMPVAL1,W
 SUBWF COUNTER,W
 BTFSS STATUS,C
 BSF TMPOUT,OUTPIN1

 INCF TMPVAL2,W
 SUBWF COUNTER,W
 BTFSS STATUS,C
 BSF TMPOUT,OUTPIN2

 INCF TMPVAL3,W
 SUBWF COUNTER,W
 BTFSS STATUS,C
 BSF TMPOUT,OUTPIN3

 INCF TMPVAL4,W
 SUBWF COUNTER,W
 BTFSS STATUS,C
 BSF TMPOUT,OUTPIN4

 RETURN

MAIN:

INIT:
 CLRF STATUS ; По умолчанию выбираем нулевую страницу памяти
 CALL INITTMR0

 ; устанавливаем направление порта
 BSF STATUS,RP0
 CLRF OUTPORT ; TRIS

 BCF STATUS,RP0 ; Переключаем на нулевую страницу памяти

 ; инициализируем переменные BREZEN4
 CLRF TMPOUT
 ; Передаем параметры Функции
 MOVLW 0x00 ; Значение на первом выходе
 MOVWF TMPVAL1
 MOVLW 0x01
 MOVWF TMPVAL2
 MOVLW 0x08
 MOVWF TMPVAL3
 MOVLW 0x0F
 MOVWF TMPVAL4
RESETCOUNTER:
 MOVLW 0x10
 MOVWF COUNTER

MAINLOOP:
 CALL PWM4
 DECFSZ COUNTER,F
 GOTO MAINLOOP 
 GOTO RESETCOUNTER

Генерируемая частота получилась совсем невелика - 11кГц. И это при частоте кварца 20МГц.

Решил реализовать на основе метода Брезенхема. Сигнал на выходе появляется во время переполнения счетчика-сумматора.

Например:
Нам нужно значение 5 из 16 уровней.

Значение счетчикаДействиеВыход
00+5Переполнения не возникло, на выходе 0
55+5Переполнения не возникло, на выходе 0
1010+5Переполнения не возникло, на выходе 0
1515+5Переполнение, на выходе 1

Импульсы в выходном потоке появляются достаточно равномерно.

Программная реализация 4-х канального регулятора для микроконтроллера PIC.

; коэффициент делителя TMR0
TMR0PRESCAL EQU 1 ; значение инициализации регистра OPTION_REG

; Выходы ШИМ
START_SHIFT EQU 128 ;начальное смещение последовательности
OUTPORT EQU 0x05
OUTPORTMASK EQU 0xF0
OUTPIN1 EQU 0
OUTPIN2 EQU 1
OUTPIN3 EQU 2
OUTPIN4 EQU 3

; Входные параметры функции BREZEN4
TMPOUT EQU 0x21
TMPVAL1 EQU 0x22
TMPVAL2 EQU 0x23
TMPVAL3 EQU 0x24
TMPVAL4 EQU 0x25

; Промежуточные значения для алгоритма
OLDVAL1 EQU 0x26
OLDVAL2 EQU 0x27
OLDVAL3 EQU 0x28
OLDVAL4 EQU 0x29

; Переменные для хранения контекста во время прерывания
W_TEMP EQU 0x70 ; Для хранения W регистра
STATUS_TEMP EQU 0x20


;----------
 ORG 0
 GOTO MAIN

 ORG 4
INTERRUPT:
 MOVWF W_TEMP
 SWAPF STATUS,W
 BCF STATUS,RP0
 BCF STATUS,RP1
 MOVWF STATUS_TEMP

 ; Тело обработчика прерывания
 BCF INTCON,T0IF ; сбрасываем флаг прерывания

 SWAPF STATUS_TEMP,W
 MOVWF STATUS
 SWAPF W_TEMP,F
 SWAPF w_TEMP,W

 RETFIE

INITTMR0:
 ; переключаем предделитель на вход TMR0
 ; устанавливаем коэффициент деления

 CLRF TMR0
 BSF STATUS,RP0
 MOVLW TMR0PRESCAL
 MOVWF OPTION_REG
 ; Разрешаем прерывания
 CLRF INTCON
 BSF INTCON,T0IE
 BSF INTCON,GIE

 BCF STATUS,RP0

 RETURN

BREZEN4:
 MOVF TMPOUT,W
 MOVWF OUTPORT ;Отправляем значение в порт
 ANDLW OUTPORTMASK
 MOVWF TMPOUT

 MOVF TMPVAL1,W
 ADDWF OLDVAL1,F
 BTFSC STATUS,C
 BSF TMPOUT,OUTPIN1

 MOVF TMPVAL2,W
 ADDWF OLDVAL2,F
 BTFSC STATUS,C
 BSF TMPOUT,OUTPIN2

 MOVF TMPVAL3,W
 ADDWF OLDVAL3,F
 BTFSC STATUS,C
 BSF TMPOUT,OUTPIN3

 MOVF TMPVAL4,W
 ADDWF OLDVAL4,F
 BTFSC STATUS,C
 BSF TMPOUT,OUTPIN4

 RETURN

MAIN:

INIT:
 CLRF STATUS ; По умолчанию выбираем нулевую страницу памяти
 CALL INITTMR0

 ; устанавливаем направление порта
 BSF STATUS,RP0
 CLRF OUTPORT ; TRIS

 BCF STATUS,RP0 ; Переключаем на нулевую страницу памяти

 ; инициализируем переменные BREZEN4
 CLRF TMPOUT
 MOVLW START_SHIFT
 MOVWF OLDVAL1
 MOVWF OLDVAL2
 MOVWF OLDVAL3
 MOVWF OLDVAL4

 ; Передаем параметры Функции
 MOVLW 0x30 ; Значение на первом выходе
 MOVWF TMPVAL1
 MOVLW 0x80
 MOVWF TMPVAL2
 MOVLW 0xFF
 MOVWF TMPVAL3
 MOVLW 0x01
 MOVWF TMPVAL4

MAINLOOP:
 CALL BREZEN4
 GOTO MAINLOOP

Такие осциллограммы получаем на выходах

Основная частота получилась выше, примерно 96кГц при уровне 128/256.
Частота следования импульсов изменяется от уровня к уровню, для уровня 1 в выходной последовательности появляется 1 положительный импульс, для 20 - 20.
Если генерировать последовательности по таймеру, то частота понизится, а её стабильность повысится. А неизрасходованные такты процессора можно выделить для коммутации с другими устройствами.

Есть идея передавать нужные уровни через последовательный порт с компьютера или по параллельному интерфейсу с другого микроконтроллера с LCD дисплеем и клавиатурой.

Комментариев нет:

Отправить комментарий