Рейтинг@Mail.ru
aave

aave

Дискретное преобразование Фурье на VB.NET

Опубликовано в Программирование

Даётся программный код для прямого и обратного преобразования Фурье. Рассматривается быстрое преобразование Фурье.

Дискретное преобразование Фурье (ДПФ) – это мощный инструмент анализа, который широко используется в области цифровой обработки сигналов (ЦОС). Существуют прямое и обратное преобразования Фурье. Прямое дискретное преобразование Фурье переводит сигнал из временной области в частотную и служит для анализа частотного спектра сигнала. Обратное преобразование делает ровно противоположное: по частотному спектру сигнала восстанавливает сигнал во временной области.

Для расчёта преобразования Фурье обычно используется ускоренная процедура расчёта – т.н. быстрое преобразование Фурье (БПФ). Это позволяет в значительной мере сократить процессорное время на достаточно сложные и ресурсоёмкие математические расчёты.

1Комплексныечисла

Для начала нам потребуется вспомогательный класс, который будет описывать комплексные числа. Комплексные числа – это особый вид чисел в математике. Каждое комплексное число состоит из двух частей – действительной и мнимой. Сейчас нам достаточно знать о комплексных числах применительно к ДПФ то, что действительная часть комплексного числа хранит информацию об амплитуде сигнала, а мнимая – о фазе.

Код класса для описания комплексных чисел (разворачивается)
''' <summary>
''' Комплексное число.
''' </summary>
Public Class ComplexNumber

    ''' <summary>
    ''' Действительная часть комплексного числа.
    ''' </summary>
    Public Real As Double = 0

    ''' <summary>
    ''' Мнимая часть комплексного числа.
    ''' </summary>
    Public Imaginary As Double = 0

    Public Sub New()
        Real = 0
        Imaginary = 0
    End Sub

    ''' <summary>
    ''' Создаёт комплексное число.
    ''' </summary>
    ''' <param name="r">Действительная часть комплексного числа.</param>
    ''' <param name="im">Мнимая часть комплексного числа.</param>
    Public Sub New(ByVal r As Double, Optional ByVal im As Double = 0)
        Real = r
        Imaginary = im
    End Sub

    Private usCult As New Globalization.CultureInfo("EN-us")

    ''' <summary>
    ''' Возвращает строку, состоящую из действительной и мнимой части, разделённых символом табуляции.
    ''' </summary>
    Public Overrides Function ToString() As String
        Return (Real.ToString(usCult) & ControlChars.Tab & Imaginary.ToString(usCult))
    End Function

End Class

2Прямое дискретное быстрое преобразование Фурье

Теперь приведу код функции, которая реализует расчёт прямого дискретного преобразования Фурье. Здесь встречается термин «бабочка». Не пугайтесь, это общепринятое название одной из элементарных операций, которые входят в алгоритм БПФ. Подробнее с термином «бабочка» можно ознакомиться здесь.

На вход функции передаётся массив комплексных чисел. Действительная часть которого представляет произвольный дискретный сигнал, с отсчётами через равные промежутки времени. Мнимая часть содержит нули. Число отсчётов в сигнале должно равняться степени двойки. Если ваш сигнал короче, то дополните его нулями до числа, кратного степени 2: 256, 512, 1024 и т.д. Чем длиннее сигнал, тем у рассчитанного спектра будет выше разрешение по частоте.

Код для расчёта прямого быстрого преобразования Фурье на VB.NET (разворачивается)
''' <summary>
''' Рассчитывает спектр сигнала методом быстрого преобразования Фурье. Использовать только (N/2+1) возвращаемых значений (до половины частоты дискретизации).
''' </summary>
''' <param name="signal">Сигнал, содержащий количество отсчётов, кратное степени двойки, и состоящий из действительной и мнимой частей. Все мнимые части сигнала заполнены нулями.</param>
''' <returns>Возвращает массив комплексных чисел спектра. 
''' Значимы только первые N/2+1, остальные - симметричная часть, соответствующая отрицательным частотам.
''' Первое значение спектра - это постоянная составляющая, последнее - соответствует половине частоты дискретизации (частота Найквиста).
''' Значения выше половины частоты дискретизации - не использовать.
''' </returns>
Public Shared Function FFT(ByVal signal As ComplexNumber()) As ComplexNumber()

    Dim order As Integer = signal.Length 'порядок ДПФ
    CheckFftOrder(order) 'Проверяем, что порядок равен степени двойки

    Dim spectrumLen As Integer = order \ 2
    Dim j As Integer = spectrumLen

    'Бит-реверсная сортировка:
    For i As Integer = 1 To order - 2
        If (i < j) Then
            Dim tmpRe As Double = signal(j).Real
            Dim tmpIm As Double = signal(j).Imaginary
            signal(j).Real = signal(i).Real
            signal(j).Imaginary = signal(i).Imaginary
            signal(i).Real = tmpRe
            signal(i).Imaginary = tmpIm
        End If
        Dim k As Integer = spectrumLen
        Do Until (k > j)
            j -= k
            k \= 2
        Loop
        j += k
    Next

    'Цикл по уровням разложения:
    For level As Integer = 1 To CInt(Math.Log(order) / Math.Log(2))
        Dim lvl As Integer = CInt(2 ^ level)
        Dim lvl2 As Integer = lvl \ 2
        Dim tmp As Double = Math.PI / lvl2
        Dim sr As Double = Math.Cos(tmp)
        Dim si As Double = -Math.Sin(tmp)

        Dim tr As Double = 0
        Dim ur As Double = 1
        Dim ui As Double = 0
        For jj As Integer = 1 To lvl2 'Цикл по спектрам внутри уровня
            For i As Integer = (jj - 1) To (order - 1) Step lvl 'Цикл по отдельным "бабочкам"
                Dim ip As Integer = i + lvl2
                tr = signal(ip).Real * ur - signal(ip).Imaginary * ui 'Операция "бабочка"
                Dim ti As Double = signal(ip).Real * ui + signal(ip).Imaginary * ur
                signal(ip).Real = signal(i).Real - tr
                signal(ip).Imaginary = signal(i).Imaginary - ti
                signal(i).Real = signal(i).Real + tr
                signal(i).Imaginary = signal(i).Imaginary + ti
            Next
            tr = ur
            ur = tr * sr - ui * si
            ui = tr * si + ui * sr
        Next
    Next

    'Заполняем массив комплексных чисел, обработанных БПФ:
    Dim spectrum(order - 1) As ComplexNumber
    For i As Integer = 0 To order - 1 
        With signal(i)
            spectrum(i) = New ComplexNumber(.Real, .Imaginary)
        End With
    Next

    Return spectrum

End Function

3Обратное дискретное быстрое преобразование Фурье

Обратное дискретное преобразование Фурье (ОДПФ) одним из этапов расчёта включает в себя прямое ДПФ на массиве комплексных чисел, где мнимая часть – это инверсия относительно оси X мнимой части спектра.

Код для расчёта обратного быстрого преобразования Фурье на VB.NET (разворачивается)
''' <summary>
''' Восстанавливает сигнал по его спектру методом обратного быстрого преобразования Фурье.
''' </summary>
''' <param name="spectrum">Спектр сигнала, содержащий количество отсчётов, кратное степени двойки, и состоящий из действительной и мнимой частей.</param>
Public Shared Function InverseFFT(ByVal spectrum As ComplexNumber()) As ComplexNumber()

    Dim order As Integer = spectrum.Length 'Порядок обратного ДПФ.
    CheckFftOrder(order)

    'Изменение арифметического знака элементов мнимой части:
    For i As Integer = 0 To spectrum.Length - 1
        spectrum(i).Imaginary = -spectrum(i).Imaginary
    Next

    'Вычисление прямого БПФ:
    Dim directFFT As ComplexNumber() = FFT(spectrum)

    'Деление на order во временной области со сменой арифметического знака мнимой части:
    Dim signal(directFFT.Length - 1) As ComplexNumber
    For i As Integer = 0 To directFFT.Length - 1
        Dim ReX As Double = directFFT(i).Real / order
        Dim ImX As Double = -directFFT(i).Imaginary / order
        signal(i) = New ComplexNumber(ReX, ImX)
    Next

    Return signal

End Function

Ну и конечно же, опишем использовавшийся метод, который проверяет число элементов переданного массива:

''' <summary>
''' Проверяет, является ли порядок БПФ степенью двойки, и если нет - вызывает исключение.
''' </summary>
''' <param name="order">Порядок БПФ.</param>
Private Shared Sub CheckFftOrder(ByVal order As Integer) 
    Dim chk As Double = Math.Abs(Math.Floor(Math.Log(order, 2)) - Math.Log(order, 2))
    If (chk > 0.0001) Then
        Throw New ArgumentException(String.Format("Длина массива ({0}) не кратна степени двойки.", order))
    End If
End Sub

4Проверка прямого и обратного преобразования Фурье

Теперь давайте проверим, что наши функции работают. Для этого пропустим произвольный сигнал через механизм прямого преобразования Фурье, а затем «соберём» его обратно с помощью обратного преобразования Фурье. Восстановленный сигнал должен практически совпадать с исходным. Ошибки округления, возникающие при работе с числами в компьютере, имеют место быть, поэтому сигналы не будут идентичны полностью, но их отклонение друг от друга должно быть пренебрежимо малым.

Для примера в качестве исходного сигнала возьмём функцию синуса и сформируем данные длиной 128 отсчётов вот таким образом:

Dim cn(127) As ComplexNumber
For i As Integer = 0 To cn.Length - 1
    cn(i) = New ComplexNumber(Math.Sin(i * 3 * Math.PI / 180))
Next

Получим вот такой сигнал:

Исходный сигнал во временной области до преобразования Фурье
Исходный сигнал во временной области до преобразования Фурье

Здесь по оси X – номера отсчётов во временной области, по оси Y – амплитуда. Обратим внимание, что сигнал состоит только из действительных частей, а мнимая часть на всём отрезке равна "0".

Теперь передадим этот сигнал на вход функции FFT(). По полученным в ходе прямого преобразования Фурье массивам комплексных чисел построим два графика – действительной (Re) и мнимой (Im) частей спектра:

Действительная и мнимая части сигнала в частотной области
Действительная и мнимая части сигнала в частотной области

Здесь по оси X – отсчёты в частотной области, по оси Y – амплитуда. Чтобы получить реальные значения частоты, необходимо рассчитать их, учитывая, что "0" оси Y соответствует нулевой частоте, максимум оси Y соответствует частоте дискретизации.

Полученный спектр сигнала передадим функции обратного преобразования Фурье IFFT(). Получим массив комплексных чисел, где действительная часть будет содержать восстановленный сигнал:

Действительная и мнимая части восстановленного с помощью обратного преобразования Фурье сигнала
Действительная и мнимая части восстановленного с помощью обратного преобразования Фурье сигнала

Как видно, восстановленный сигнал полностью повторяет исходный.

Подробнее ...

Кодер и декодер кода Хэмминга на VB.NET

Опубликовано в Программирование

Коды Хемминга позволяют закодировать исходное сообщение таким образом, чтобы после передачи его по зашумлённым каналам связи (например, по радиоканалу) и искажениям в принятой информации, можно было восстановить исходное сообщение.

1Что такое код Хэмминга

Код Хэмминга добавляет к сообщению (информационные разряды) некоторое количество избыточной информации (проверочные разряды), сформированной определённым образом. Сообщение с добавленной проверочной информацией называется «кодовый символ» или «кодовое слово». Параметры кода указываются, например, так: (7, 4). Это означает, что длина кодового слова равна 7 битам, а длина сообщения – 4 бита. В зависимости от количества информационных и проверочных разрядов в кодовых словах существуют коды Хэмминга (7,4), (9,5), (11, 7), (15, 11), (31, 26), (63, 57) и т. д.

Общий вид формулы, по которой определяются виды кодов Хэмминга по соотношению числа информационных символов к проверочным: (2x − 1, 2x − x − 1), где x – натуральное число.

Чтобы восстановить закодированное сообщение, оно подвергается декодированию. При этом есть вероятность, что исходное сообщение нельзя будет восстановить, в случае превышения числом ошибок корректирующей способности кода. Однако помехоустойчивость закодированной информации всё равно выше, чем у незакодированной.

Из-за своей простоты, кодирование кодом Хемминга получило широкое распространение. Оно применяется, например, в беспроводной технологии WiFi, в системах хранения данных (RAID-массивах), в некоторых типах микросхем памяти, в схемотехнике и т.д.

Хорошая статья, описывающая принцип работы кода Хэмминга, есть, например, на Хабре.

2Кодер кода Хэмминга (15, 11), написанный на VB.NET

Напишем кодировщик, который будет получать на вход 11 бит данных, кодировать их и возвращать 15 бит выходной информации. Если на вход пришло больше 11-ти бит данных, генерируется исключение. Если данных меньше 11-ти бит (например, 1 байт – 8 бит), то число дополняется нулями в старших разрядах до 11-ти бит и далее кодируется обычным образом. Возвращает кодер 16 бит (кодовое слово).

Код кодера Хэмминга (15, 11) на VB.NET (разворачивается)
''' <summary>
''' Кодирует 11 бит информации кодом Хэмминга (15, 11). 
''' Входные данные – 11 бит, выходные – 16 бит.
''' </summary>
''' <param name="dataIn">Входные данные, не более 11-ти бит.</param>
''' <remarks>
''' Размещение проверочных и информационных бит в кодовом слове:
''' 
'''          |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
''' in_data  |  |  |  |  |  | L| K| I| H| G| F| E| D| C| B| A|
''' code_word| L| K| I| H| G| F| E| P| D| C| B| P| A| P| P| X|
''' 
''' A,B,C,D,E,F,G,H,I,K,L – биты данных информационного слова;
'''                     P – проверочный бит;
'''                     X – бит, равный 0 (не используется).
''' Кодовое слово дополняется одним битом, чтобы длина была равна степени двойки. Сейчас этот бит никак не используется.
''' Можно его использовать как бит чётности и получить так называемый дополненный код Хэмминга. Здесь этого не сделано.
''' </remarks>
Public Shared Function Encode_15_11(ByVal b As BitArray) As BitArray
 
            'Можно также добавить проверку на длину передаваемой битовой последовательности:
            'If (b.Count > 11) Then
            '    Throw New ArgumentException("Входная последовательность длиннее 11-ти битов.")
            'End If

            Dim preDataIn As New BitArray(11)
            For i As Integer = 0 To 10
                If (b.Count > i) Then
                    preDataIn(i) = b(i)
                Else
                    Exit For
                End If
            Next

            Dim dataIn As New BitArray(preDataIn)

            'Весь процесс кодирования – это сложение по модулю два бит информационного слова.
            Dim codeWord As New BitArray(16)

            'Младший разряд не используется. Можно добавить в него проверку на чётность.
            codeWord(0) = False

            'Вычисление первого проверочного символа:
            codeWord(1) = dataIn(0) Xor dataIn(1) Xor dataIn(3) Xor dataIn(4) Xor dataIn(6) Xor dataIn(8) Xor dataIn(10)

            'Вычисление второго проверочного символа:
            codeWord(2) = dataIn(0) Xor dataIn(2) Xor dataIn(3) Xor dataIn(5) Xor dataIn(6) Xor dataIn(9) Xor dataIn(10)

            'Вычисление третьего проверочного символа:
            codeWord(4) = dataIn(1) Xor dataIn(2) Xor dataIn(3) Xor dataIn(7) Xor dataIn(8) Xor dataIn(9) Xor dataIn(10)

            'Вычисление четвертого проверочного символа:
            codeWord(8) = dataIn(4) Xor dataIn(5) Xor dataIn(6) Xor dataIn(7) Xor dataIn(8) Xor dataIn(9) Xor dataIn(10)

            'Информационные символы:
            codeWord(3) = dataIn(0)
            codeWord(5) = dataIn(1)
            codeWord(6) = dataIn(2)
            codeWord(7) = dataIn(3)
            codeWord(9) = dataIn(4)
            codeWord(10) = dataIn(5)
            codeWord(11) = dataIn(6)
            codeWord(12) = dataIn(7)
            codeWord(13) = dataIn(8)
            codeWord(14) = dataIn(9)
            codeWord(15) = dataIn(10)

            Return codeWord

        End Function

Данный кодер легко переписать таким образом, чтобы он работал не с битовыми массивами типа BitArray(), а с байтами: на вход получал 11-разрядное число (от 0 до 0x7FF) и выдавал 2 закодированных байта:

Public Shared Function Encode_15_11(ByVal numberToEncode As Integer) As Byte()
    Dim enc As BitArray = Hamming.Encode_15_11(New BitArray({numberToEncode}))
    Dim encBytes(1) As Byte
    enc.CopyTo(encBytes, 0)
    Return encBytes
End Function

3Декодер кода Хэмминга (15, 11), написанный на VB.NET

Теперь пора поговорить о декодере. Декодер плучает на вход 2 байта закодированных данных и возвращает 11 бит декодированных данных, которые распределены по двум байтам. Если в кодер были переданы 8 бит данных, то нас будет интересовать только первый байт, полученный с декодера.

Код декодера Хэмминга (15, 11) на VB.NET (разворачивается)
''' <summary>
''' Декодер кода (15, 11). 
''' </summary>
''' <param name="b">Входные данные, 16 бит (2 байта).</param>
''' <returns>Выходные данные – 10 бит.</returns>
''' <remarks>
''' Размещение проверочных и информационных бит в кодовом слове:
''' 
'''          |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
''' code_word| L| K| I| H| G| F| E| P| D| C| B| P| A| P| P| X|
''' out_data |  |  |  |  |  | L| K| I| H| G| F| E| D| C| B| A|
''' 
''' A,B,C,D,E,F,G,H,I,K,L – биты данных информационного слова;
'''                     P – проверочный бит;
'''                     X – бит, равный 0 (не используется).
''' 
''' Кодовое слово дополняется одним битом, чтобы длина была равна степени двойки. Сейчас этот бит никак не используется.
''' Можно его использовать как бит четности и получить так называемый дополненный код Хэмминга. Здесь этого не сделано.
''' </remarks>
Public Shared Function Decode_15_11(ByVal b As Byte()) As Integer

    Dim codeWord As New BitArray(b) '16 бит входных данных

    'Весь процесс декодирования – это сложение по модулю два бит информационного слова, по весу полученных единиц в результате – получение позиции ошибки.
    Dim syndrome As New BitArray(4) 

    'Вычисление первого проверочного символа из полученного кодового слова и далее сравнение его с полученным.
    syndrome(0) = codeWord(3) Xor codeWord(5) Xor codeWord(7) Xor codeWord(9) Xor codeWord(11) Xor codeWord(13) Xor codeWord(15) Xor codeWord(1)

    'Вычисление второго проверочного символа из полученного кодового слова и далее сравнение его с полученным.
    syndrome(1) = codeWord(3) Xor codeWord(6) Xor codeWord(7) Xor codeWord(10) Xor codeWord(11) Xor codeWord(14) Xor codeWord(15) Xor codeWord(2)

    'Вычисление третьего проверочного символа из полученного кодового слова и далее сравнение его с полученным.
    syndrome(2) = codeWord(5) Xor codeWord(6) Xor codeWord(7) Xor codeWord(12) Xor codeWord(13) Xor codeWord(14) Xor codeWord(15) Xor codeWord(4)

    'Вычисление четвёртого проверочного символа из полученного кодового слова и далее сравнение его с полученным.
    syndrome(3) = codeWord(9) Xor codeWord(10) Xor codeWord(11) Xor codeWord(12) Xor codeWord(13) Xor codeWord(14) Xor codeWord(15) Xor codeWord(8)

    'Вычисление по синдрому позиции ошибки. Это просто ПЗУ или дешифратор.
    'Если смотреть на синдром как на число - то это и есть номер позиции ошибки.
    'Синдром равен 0 - ошибки нет.
    'Поскольку на выход модуля передаются только биты данных - не все варианты перечислены, нет смысла исправлять проверочные биты.
    Dim syn As Integer = (Convert.ToInt32(syndrome(3)) << 3) Or (Convert.ToInt32(syndrome(2)) << 2) Or (Convert.ToInt32(syndrome(1)) << 1) Or Convert.ToInt32(syndrome(0))

    '         |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
    'code_word| L| K| I| H| G| F| E| P| D| C| B| P| A| P| P| X|
    'Синдромы ошибок в информационных битах, позиции в кодовом слове 3,5,6,7,9,10,11,12,13,14,15:
    Dim correction As New BitArray(11) 
    Select Case syn
        Case 3 'позиция 3
            correction = New BitArray({True, False, False, False, False, False, False, False, False, False, False}) 
        Case 5 'позиция 5
            correction = New BitArray({False, True, False, False, False, False, False, False, False, False, False}) 
        Case 6 'позиция 6
            correction = New BitArray({False, False, True, False, False, False, False, False, False, False, False}) 
        Case 7 'позиция 7
            correction = New BitArray({False, False, False, True, False, False, False, False, False, False, False}) 
        Case 9 'позиция 9
            correction = New BitArray({False, False, False, False, True, False, False, False, False, False, False}) 
        Case 10 'позиция 10
            correction = New BitArray({False, False, False, False, False, True, False, False, False, False, False})  
        Case 11 'позиция 11
            correction = New BitArray({False, False, False, False, False, False, True, False, False, False, False})  
        Case 12 'позиция 12
            correction = New BitArray({False, False, False, False, False, False, False, True, False, False, False})  
        Case 13 'позиция 13
            correction = New BitArray({False, False, False, False, False, False, False, False, True, False, False})  
        Case 14 'позиция 14
            correction = New BitArray({False, False, False, False, False, False, False, False, False, True, False})  
        Case 15 'позиция 15
            correction = New BitArray({False, False, False, False, False, False, False, False, False, False, True})  
        Case Else
            'Если синдром равен 0 или указывает на ошибку в проверочном символе "P" - коррекция информационных символов не требуется.
            'Мы инициализировали correction() нулями (correction = New BitArray(11)), поэтому ничего делать не нужно.
        End Select

        'Результат декодирования с учетом коррекции (11 бит выходных данных):
        Dim outData As New BitArray(11)
        outData(0) = codeWord(3) Xor correction(0)    
        outData(1) = codeWord(5) Xor correction(1)     
        outData(2) = codeWord(6) Xor correction(2)     
        outData(3) = codeWord(7) Xor correction(3)     
        outData(4) = codeWord(9) Xor correction(4)     
        outData(5) = codeWord(10) Xor correction(5)   
        outData(6) = codeWord(11) Xor correction(6)  
        outData(7) = codeWord(12) Xor correction(7) 
        outData(8) = codeWord(13) Xor correction(8) 
        outData(9) = codeWord(14) Xor correction(9) 
        outData(10) = codeWord(15) Xor correction(10) 

        Dim masks(31) As Integer
        masks(0) = BitVector32.CreateMask()
        For i As Integer = 1 To 31
            masks(i) = BitVector32.CreateMask(masks(i - 1))
        Next

        Dim v As New BitVector32
        For i As Integer = 0 To 10
            v(masks(i)) = outData(i)
        Next
        Dim decoded As Integer = v.Data

        Return decoded

End Function

4Консольная программа, кодирующая и декодирующая код Хемминга (15, 11)

Для быстрой проверки кодировщика и декодировщика кода Хэмминга (15, 11), используя вышеописанные классы, я написал две программы. Первая – кодер Хэмминга. Вводите 11-разрядное число (от 0 до 0x7FF или 2047), и на выходе получаем 16-разрядное число, представленное в виде двух байтов.

Внешний вид программы кодера кода Хэмминга (15, 11)
Внешний вид программы кодера кода Хэмминга (15, 11)

Вторая программа – декодер кода Хмминга (15, 11).

Внешний вид программы декодера кода Хэмминга (15, 11)
Внешний вид программы декодера кода Хэмминга (15, 11)

Легко убедиться, что если мы внесём битовую ошибку при декодировании, то декодер восстановит исходное закодированное число.

Обе программы работают под ОС Windows и требуют .NET версии 3.5. Выкладываю описанные программы.

Скачать кодер и декодер кода Хэмминга (15, 11)

Подробнее ...

Как автоматизировать обновление антивирусных баз Dr.Web по локальной сети

Опубликовано в Компьютеры и программы

Допустим, у вас на рабочем месте нет подключения к интернету, а локальная сеть есть. И на каком-то из компьютеров в локальной сети периодически обновляются антивирусные базы. Можно, конечно, каждый день копировать базы к себе на компьютер и вручную обновлять их. А можно один раз потратить 15 минут, чтобы настроить автоматизацию этого процесса, и надолго забыть об этом.

Рассмотрим задачу на примере антивируса Dr.Web. Хотя это решение подойдёт для любого антивируса, который позволяет качать антивирусные базы отдельно от программы и не умеет обновлять базы по локальной сети.

Весь алгоритм сводится к четырём простым шагам:

  • создать папку на локальном компьютере, где будет храниться антивирусная база;
  • создать скрипт для автоматического копирования свежих баз с удалённого компьютера на локальный;
  • создать в планировщике заданий задачу и настроить её периодическое выполнение;
  • указать антивирусу, где брать обновления.

1Создание директории для антивирусных баз

Создадим на своём компьютере папку, в которую будут копироваться базы с условного сервера. Пусть это будет, например: C:\DRWEB\DRWEBBASE9

2Создание скрипта для автоматизированного копирования баз антивируса

Теперь создадим скрипт (программу), который будет выполнять копирование антивирусных баз с удалённого компьютера в локальной сети на локальный компьютер. В любом текстовом редакторе создадим файл с расширением *.BAT (например, “copy_bases.bat”) вот с таким содержимым:

@echo off
echo Dr.Web bases copying is in progress...
:: xcopy /s \\server\DRWEBBASE9 C:\DRWEB\DRWEBBASE9/H /E /G /Q /R /Y
:: Может потребовать права Администратора:
robocopy \\server\DRWEBBASE9 C:\DRWEB\DRWEBBASE9 /COPYALL /E
echo Done!

Здесь “server” – это имя в сети удалённого компьютера, на котором хранятся антивирусные базы, а далее сетевой путь к ним. Строки, начинающиеся с двойного двоеточия (“::”) – комментарии. Они не читаются компьютером, но подсказывают пользователю назначение тех или иных строк кода.

В скрипте приведены два разных варианта копирования файлов – с помощью утилиты xcopy и robocopy. Один из вариантов закомментирован.

УтилитаОписание
xcopyУстаревшая утилита для копирования файлов, но всё ещё достаточно популярная и мощная. Впервые появилась в MS DOS 3.2. Описание XCOPY на сайте Microsoft.
robocopyОбновлённая версия утилиты xcopy. Поддерживается в Windows, начиная с Windows 7. Описание ROBOCOPY на сайте Microsoft.

Попробуйте оба варианта и выберете тот, который будет работать у вас. Для проверки нужно дважды щёлкнуть мышью на созданном файле. Должно появиться окно консоли, в котором будут отображаться сведения о процессе копирования баз.

Процесс копирования файлов, запущенный с помощью встроенной утилиты Windows
Процесс копирования файлов, запущенный с помощью встроенной утилиты Windows

По завершению копирования консольное окно закроется.

3Настройка планировщика заданий Windows

После того как когда скрипт создан и проверен, нужно создать в планировщике заданий ОС Windows задание, которое будет периодически запускать наш скрипт. Откроем панель управления и перейдём в раздел «Администрирование». Выберем «Планировщик заданий». В левой части планировщика перейдём в «Библиотеку планировщика заданий». В разделе «Действия» выберем «Создать простую задачу…».

Или кликнем правой кнопкой мыши на свободном месте в центральной части окна и выберем аналогичный пункт.

Откроется мастер создания задач. Введём название задачи, например «Копирование антивирусных баз Dr.Web». Жмём «Далее».

Создание простой задачи в планировщике Windows
Создание простой задачи в планировщике Windows

Теперь зададим периодичность запуска задачи. Укажем подходящий вариант и нажмём «Далее».

Заполнение названия задачи в мастере создания задач
Заполнение названия задачи в мастере создания задач

Настроим время запуска задачи и перейдём далее.

Настройка периодичности запуска задачи
Настройка периодичности запуска задачи

Зададим для задачи действие – «Запустить программу».

Настройка действия, выполняемого задачей
Настройка действия, выполняемого задачей

И на следующем шаге мастера укажем путь к нашему скрипту “copy_bases.bat”.

Указание пути к запускаемому файлу/скрипту
Указание пути к запускаемому файлу/скрипту

Ещё раз убедимся, что все настройки задачи выставлены правильно, и нажмём «Готово». Задание должно появиться в конце списка заданий.

Сводка параметров созданной задачи
Сводка параметров созданной задачи

4Настройка антивирусной программы

Последнее, что осталось сделать – это сконфигурировать антивирусную программу так, чтобы она обновляла свои базы из правильной директории. Идём в настройки антивируса, в раздел, касающийся обновлений, и указываем путь к папке, в которой у нас будут лежать свеженькие антивирусные базы.

Настройка источника обновления антивирусных баз Dr.Web
Настройка источника обновления антивирусных баз Dr.Web

По скриншоту видно, что Dr.Web позволяет обновляться из сетевой папки. Однако работает эта функция, почему-то, плохо. В моей локальной сети, например, антивирус категорически не желает обновляться из директории на удалённом компьютере.

Но после проделанных операций можно быть уверенным, что антивирусные базы всегда будут в актуальном состоянии, как только они будут обновлены на сервере.

Подробнее ...

Как подключить регулятор громкости M62429 к Arduino

Опубликовано в Arduino

Микросхема M62429 предназначена для снижения громкости звука в электрических схемах. Микросхема позволяет управлять одновременно и независимо двумя звуковыми каналами. Диапазон регулировки звука – от 0 до -83 дБ, т.е. микросхема способна ослаблять уровень громкости примерно в 100000 раз.

1Описание регулятора громкостиM62429

Микросхема M62429 выполняется в двух типах корпусов – DIP-8 (8P4) и SOP-8 (8P2S-A). Назначение выводов для обоих типов корпусов приведена на рисунке. Как видно, тут имеется два входа (VIN1, VIN2) и два выхода (VOUT1, VOUT2) для звуковых каналов, питание и земля (VCC и GND), а также две управляющие ножки (DATA и CLOCK).

Питание микросхемы осуществляется напряжением от 4,5 до 5,5 В (абсолютный максимум – 6 вольт).

Расположение выводов на микросхеме M62429
Расположение выводов на микросхеме M62429

Вот так выглядит микросхема в выводном корпусе:

Микросхеме M62429 в DIP-корпусе
Микросхеме M62429 в DIP-корпусе

У меня микросхема в корпусе для поверхностного монтажа. К такой микросхеме сложно подключиться без пайки, поэтому для тестирования я буду использовать вот такой переходник с корпуса SOP-8 на соединители типа PLS:

Микросхема M62429 на плате-переходнике
Микросхема M62429 на плате-переходнике

2Схема подключения микросхемы M62429 к Arduino

Подключим микросхему к Arduino и к микрофону вот по такой схеме:

Схема подключения M62429 к Arduino
Схема подключения M62429 к Arduino

Производитель рекомендует стабилизировать вход питания VCC с помощью развязывающего конденсатора (соединить вход питания с землёй через ёмкость 0,1…0,33 мкФ).

Также производитель рекомендует поставить на вход электролитический конденсатор ёмкостью 2,2 мкФ (схему см. на последней странице технического описания).

Микрофон и динамик на схеме изображены условно просто чтобы показать, что на вход VIN1 микросхемы M62429 подаётся выход с микрофона или иного источника аудиосигнала, а выход – далее в электрическую цепь и на устройство воспроизведения звука.

3Описание последовательного сигнала управления регулятором громкости M62429

Для управления микросхемой M62429 используется последовательный интерфейс с пакетной передачей данных. Длина одного пакета данных – 11 бит. Структура пакета приведена на рисунке.

Структура пакета управления микросхемой M62429
Структура пакета управления микросхемой M62429

Первым битом передаётся номер канала, вторым – использовать ли независимое управление каналами или одновременное, далее 7 бит отведены под код громкости, и завершают пакет два бита, равные "1".

Важно знать параметры импульсов частоты и данных. Микросхема управляется меандром (скважность равна 2), минимальная длительность импульса tWHC (как и tWLC) – 1,6 мкс, а период tcr – 4 мкс. Остальные характеристики импульсов приводятся в техническом описании (datasheet), которое можно скачать по ссылкам ниже.

Временная диаграмма сигнала информационного обмена с микросхемой M62429
Временная диаграмма сигнала информационного обмена с микросхемой M62429

4Скетч для управления микросхемой M62429 с помощью Arduino

Зная всё это, напишем скетч, который будет изменять громкость регулятора от максимума до минимума со скоростью 1 децибел в секунду. Сердце программы – процедура setVolume() и два массива кодов громкости, которые составлены из двух таблиц кодов громкости в техническом описании (таблицы "Volume Code").

Скетч управления регулятором громкости M62429 (разворачивается)
const int CLK = 4;
const int DATA = 2;
const int twhc  = 2;
const int twlc  = 2;

// Коды громкости аттенюатора 1.
// Значения кодов - из таблицы кодов громкости из технического описания.
int att1[21][5] = {
  {1, 0, 1, 0, 1}, //-0db
  {0, 0, 1, 0, 1}, //-4db
  {1, 1, 0, 0, 1}, //-8db
  {0, 1, 0, 0, 1}, //-12db
  {1, 0, 0, 0, 1}, //-16db
  {0, 0, 0, 0, 1}, //-20db
  {1, 1, 1, 1, 0}, //-24db
  {0, 1, 1, 1, 0}, //-28db
  {1, 0, 1, 1, 0}, //-32db
  {0, 0, 1, 1, 0}, //-36db
  {1, 1, 0, 1, 0}, //-40db
  {0, 1, 0, 1, 0}, //-44db
  {1, 0, 0, 1, 0}, //-48db
  {0, 0, 0, 1, 0}, //-52db
  {1, 1, 1, 0, 0}, //-56db
  {0, 1, 1, 0, 0}, //-60db
  {1, 0, 1, 0, 0}, //-64db
  {0, 0, 1, 0, 0}, //-68db
  {1, 1, 0, 0, 0}, //-72db
  {0, 1, 0, 0, 0}, //-76db
  {1, 0, 0, 0, 0}  //-80db
};

// Коды громкости аттенюатора 2
int att2[4][2] = {
  {1, 1}, //-0db
  {0, 1}, //-1db
  {1, 0}, //-2db
  {0 ,0}  //-3db
};

void setup() {
  pinMode(DATA, OUTPUT);
  pinMode(CLK, OUTPUT);
  digitalWrite(DATA, HIGH);
  digitalWrite(CLK, LOW);
  delay(1000);
}

void loop() {
  // Ежесекундно уменьшаем громкость на 1 дБ,
  // по достижении -83 дБ начинаем с начала:
  for (int db=0; db>=-83; db-=1){
    setVolume(0, true, db);
    delay(1000);
  }
  delay(2000);
}

// Задаёт уровень громкости в заданном канале.
// channel – канал, 0 или 1;
// independent – управление одним каналом (true) или обоими сразу (false);
// decibels – ослабление громкости в децибелах, от 0 до -83.
void setVolume(int channel, bool independent, int decibels) {

  // Определяем значения аттенюаторов:
  int att1index = floor(abs(decibels) / 4);
  int att2index = abs(decibels) % 4;
  
  // Задаём в пакете канал:
  digitalWrite(DATA, (bool)channel);
  digitalWrite(CLK, HIGH);
  digitalWrite(DATA, LOW);
  digitalWrite(CLK, LOW);

  // Задаём одновременное или независимое управление каналами:
  digitalWrite(DATA, independent);
  digitalWrite(CLK, HIGH);
  digitalWrite(DATA, LOW);
  digitalWrite(CLK, LOW);

  // Задаём значение 1-го аттенюатора D2..D6:
  for (int i=0; i<5; i++) {
    digitalWrite(DATA, (bool)att1[att1index][i]);
    digitalWrite(CLK, HIGH);
    digitalWrite(DATA, LOW);
    digitalWrite(CLK, LOW);
  }
  
  // Задаём значение 2-го аттенюатора D7..D8:
  for (int i=0; i<2; i++) {
    digitalWrite(DATA, (bool)att2[att2index][i]);
    digitalWrite(CLK, HIGH);
    digitalWrite(DATA, LOW);
    digitalWrite(CLK, LOW);
  }

  // Два последних бита пакета – две единицы:
  digitalWrite(DATA, HIGH);
  digitalWrite(CLK, HIGH);
  delayMicroseconds(twhc);
  digitalWrite(DATA, LOW);
  digitalWrite(CLK, LOW);
  delayMicroseconds(twlc);

  digitalWrite(DATA, HIGH);
  digitalWrite(CLK, HIGH);
  delayMicroseconds(twhc);
  digitalWrite(CLK, LOW);
  digitalWrite(DATA, LOW);
  delayMicroseconds(twlc);
}

Замечу, что в децибелах задавать ослабление громкости не всегда удобно. Можно сделать процедуру, принимающую, допустим, уровень громкости. Типа такого: setVolumeInPercent(0, true, 35), где 0 – второй канал, true говорит о независимом управлении каналами, а 35 – уровень громкости в процентах от максимального (или же наоборот – уровень ослабления аттенюатора).

Загрузим скетч в память Arduino и посмотрим на результат. Я подключил осциллограф к каналам CLOCK и DATA для демонстрации.

Осциллограмма информационного обмена Arduino с микросхемой M62429
Осциллограмма информационного обмена Arduino с микросхемой M62429

Фиолетовый сигнал – CLOCK, зелёный – DATA.

Осциллограмма информационного обмена Arduino с микросхемой M62429
Осциллограмма информационного обмена Arduino с микросхемой M62429

А вот как выглядит осциллограмма напряжения на выходе VOUT1 микросхемы M62429.

Изменение напряжения на выходе микросхемы M62429
Изменение напряжения на выходе микросхемы M62429

Скачать техническое описание на микросхему M62429

Подробнее ...
Подписаться на этот канал RSS