Программный ШИМ без загромождения процессора? - PullRequest
1 голос
/ 14 марта 2012

Это академический вопрос (я не обязательно планирую это делать), но мне любопытно, как это будет работать.Я думаю о программном решении для пользователя (а не в аппаратном обеспечении).

Я хочу производить ШИМ-сигналы (скажем, для небольшого числа цифровых выводов GPIO, но более 1).Я, вероятно, написал бы программу, которая создавала бы Pthread и затем бесконечно зацикливалась по рабочему циклу с соответствующими sleep() s и т. Д. В этом потоке, чтобы получить правильные пропорции.

Не будет ли это ужасно загромождать процессор?Я предполагаю, что частота будет где-то около отметки 100 Гц.Я не делал ничего подобного раньше, но могу представить, что постоянное зацикливание, переключение контекста и т. Д. Не подходит для многозадачности или использования ЦП.

Какой-нибудь совет по использованию ЦП в этом случае и многозадачности?Я думаю о одноядерном процессоре.Я чувствую, что ответы могут варьироваться от ', что сделает вашу систему непригодной для использования' до ', число участвующих на несколько порядков меньше, чем окажет влияние на современный процессор' !

Предположим, C, потому что это кажется наиболее подходящим.

РЕДАКТИРОВАТЬ: Предположим, что Linux или другая операционная система общего назначения POSIX на компьютере с доступом к аппаратным выводам GPIO.

РЕДАКТИРОВАТЬ: я предполагал, что будет очевидно, как я буду реализовывать ШИМ в спящем режиме,Во избежание сомнений, что-то вроде этого:

while (TRUE)
{
    // Set all channels high
    for (int c = 0; x < NUM_CHANNELS)
    {
        set_gpio_pin(c, 1);
    }

    // Loop over units within duty cycle
    for (int x = 0; x < DUTY_CYCLE_UNITS; x++)
    {   
        // Set channels low when their number is up
        for (int c = 0; x < NUM_CHANNELS)
        {
            if (x > CHANNELS[c])
            {
                set_gpio_pin(c, 0);
            }
        }

        sleep(DUTY_CYCLE_UNIT);
    }
}

Ответы [ 7 ]

2 голосов
/ 14 марта 2012

Используйте драйвер, если можете.Если ваше встроенное устройство имеет ШИМ-контроллер, тогда хорошо, иначе выделите аппаратный таймер для генерации интервалов ШИМ и управления выводами GPIO.

Если вам нужно сделать это на уровне пользователя, поднимите процесс / поток довысокий приоритет и использование вызовов sleep () обязательно вызовут много дрожания и плохой диапазон ширины импульса.

2 голосов
/ 14 марта 2012

Вы не очень четко указываете конечную цель этого, но так как вы пометили этот встроенный и pthreads, я буду считать, что у вас есть выделенный чип с работающим вариантом linux.

В этом случае я бы предложил лучший способ создания вывода ШИМ - через основной цикл программы, поскольку я предполагаю, что ШИМ является частью большего управляющего приложения.Большинство простых встроенных приложений (без пользовательского интерфейса) могут выполняться в одном потоке с периодическими обновлениями GPIO в вашем основном потоке.

Например:

InitIOs();

while(1)
{
   // Do stuff
   UpdatePWM();
}  

При этом проверьте свой чипСогласно спецификации, в большинстве встроенных устройств есть выделенные выходные штырьковые выводы (которые также могут выступать в качестве GPIO), и их можно просто настроить в аппаратном обеспечении, установив рабочий цикл и обновив этот рабочий цикл по мере необходимости.В этом случае аппаратное обеспечение сделает всю работу за вас.

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

1 голос
/ 15 марта 2012

Если у вас есть таймер, вы можете установить его так, чтобы он прерывал прерывание каждый раз, когда требуется новый фронт ШИМ. С помощью некоторого умного кодирования вы можете поставить их в очередь, чтобы обработчик прерываний знал, какой из многих каналов ШИМ и нужен ли высокий или низкий фронт, и затем планировал сам для следующего требуемого фронта.

Если у вас достаточно этих таймеров, то это еще проще, поскольку вы можете выделить один на канал ШИМ.

На встроенном контроллере с откликом на прерывание с малой задержкой это может дать удивительно хорошие результаты.

1 голос
/ 14 марта 2012

Использование потока и спящего режима в ОС, которая не является ОСРВ, не даст очень точных или согласованных результатов.

Лучший способ - использовать прерывание по таймеру и переключать GPIO в ISR. В отличие от использования аппаратного ШИМ-выхода на аппаратном таймере, этот подход позволяет использовать один таймер для нескольких сигналов и для других целей. Вы все еще, вероятно, увидите больше дрожания, чем аппаратный ШИМ, а также практический частотный диапазон и разрешение импульсов, которые будут намного ниже аппаратных, но будет гораздо ниже, чем аппаратный, но, по крайней мере, дрожание будет порядка микросекунд, а не миллисекунд.

1 голос
/ 14 марта 2012

100 Гц кажется выполнимым из пространства пользователя. Типичные временные интервалы планировщика задач ОС тоже составляют около 10 мс, поэтому ваш ЦП будет уже многозадачным примерно через этот интервал. Вы, вероятно, захотите использовать высокий приоритет процесса (низкую точность), чтобы убедиться, что периоды сна не будут превышать (сильно), и отслеживать фактическое время перерыва и потенциально корректировать значения времени ожидания на основе этой обратной связи, чтобы избежать дрейфа. Вам также нужно убедиться, что таймер, который ядро ​​использует для этого на вашем оборудовании, имеет достаточно высокое разрешение!

Если у вас очень мало оперативной памяти и вы сильно меняетесь, вы можете столкнуться с проблемами при переносе вашей программы на диск. Кроме того, если ядро ​​выполняет другие ресурсоемкие процессы, это также приведет к недопустимым задержкам. (другие задачи с пользовательским пространством с более низким приоритетом должны быть в порядке) Если поддержание постоянной частоты является критическим, лучше решить эту проблему в ядре (или даже запустить ядро ​​реального времени).

1 голос
/ 14 марта 2012

Возможно, лучше использовать некий подход, основанный на прерываниях. Я полагаю, это зависит от вашей системы, но IIRC Arduino использует прерывания для ШИМ.

0 голосов
/ 14 марта 2012

Я не понимаю, почему вы захотите использовать ШИМ в программном обеспечении со всем присущим джиттером синхронизации, который будет вводить обработка прерываний и программные взаимодействия (например, попадания прерываний ШИМ, когда прерывания отключены, процессор обслуживает длинную непрерывную инструкцию или активна другая сервисная процедура). Большинство современных микроконтроллеров (ARM-7, ARM Cortex-M, AVR32, MSP, ...) имеют таймеры, которые могут быть либо сконфигурированы для производства, либо выделены как генераторы ШИМ. Они будут генерировать несколько устойчивых сигналов ШИМ, которые после настройки требуют нулевого входа процессора для продолжения работы. Эти выходы ШИМ могут быть настроены так, чтобы два сигнала не перекрывались или имели одновременные фронты, как того требует приложение.

Если вы используете функцию ожидания ОС для установки времени между фронтами ШИМ, то это будет работать медленно. Функция сна устанавливает минимальное время между активациями задачи, а время между ними будет задерживаться переключателями задач, наличием потока с более высоким приоритетом или другой выполняющейся функцией ядра.

...