Невозможно получить последовательность импульсов на частоте 32 Гц с шириной импульса 20 мкс с помощью Uno
Я пытался получить последовательность импульсов 32 Гц (между 30 Гц и 35 Гц тоже подойдет) с шириной импульса около 20 мкс с помощью Arduino Uno, но не смог. Проблема в следующем:
Если я сделаю следующее:
void setup() {
TCCR1B = TCCR1B & B11111000 | B00000101;
pinMode(pwmPin9, OUTPUT); // устанавливает вывод как выход
}
void loop() {
analogWrite(pwmPin9, 1)
}
Я могу установить частоту примерно на 30 Гц, но analogWrite(pwmPin9, 1) даст минимум 100 мкс и не сможет снизиться до 20 мкс.
С другой стороны, метод digitalWrite с задержкой не позволяет получить частоты ниже 60 Гц.
Как получить выходной сигнал последовательности импульсов с частотой от 30 Гц до 35 Гц и шириной импульса около 20 мкс?
@user16307, 👍0
2 ответа
Лучший ответ:
Для решения такого рода задач первое, что нужно сделать, это преобразовать два
соответствующие моменты времени (период сигнала и длительность состояния HIGH
)
в несколько циклов ЦП. С тактовой частотой 16 МГц, что дает:
- Время HIGH: 20 мкс = 320 циклов ЦП
- период: 31,25 мс = 500000 циклов (±7%)
Затем разделите эти числа на доступные значения предварительного делителя, чтобы получить соответствующее количество предварительно масштабированных тактовых циклов:
prescaler 1 8 64 256 ...
HIGH time 320 40 5 1.25 ...
period 500000 62500 7812.5 1953.125 ...
В идеале вам нужен предделитель, который выдает целые числа в порядке чтобы избежать ошибок округления. И поскольку вы используете 16-битный таймер, вы хотите, чтобы эти числа были не больше 216. Или вдвое больше, если вы используете режим фазовой коррекции ШИМ, но я предпочитаю этого избегать усложнение, если возможно.
Из таблицы выше следует, что идеальным является предделитель 8. 64 будет практически таким же хорошим, с погрешностью частоты всего лишь 64 ppm, что меньше допуска частоты керамики резонатор тактирует ваш Uno.
Затем вы используете либо OCR1A
, либо OCR1B
для установки высокого времени, в зависимости от
от того, выводите ли вы сигнал на вывод OC1A (цифровой 9) или OC1B (цифровой
10). Вы используете либо OCR1A
, либо ICR1
для установки периода. Поскольку вы
выводятся на вывод 9, регистр OCR1A
будет использоваться для установки
время, поэтому вам нужно использовать ICR1
для установки периода. Затем вы
найдите в таблице режимов в техническом описании тот, который соответствует
этот режим работы - режим 14: быстрая ШИМ с ВЕРХНИМ значением
определяется ICR1. Это дает следующую конфигурацию:
void configure_timer_1()
{
DDRB |= _BV(PB1); // установить вывод 9 = PB1 = OC1A как выход
TCCR1A = 0; // сброс таймера
TCCR1B = 0; // то же самое
OCR1A = 40 - 1; // HIGH для 40 * 8 циклов ЦП
ICR1 = 62500 - 1; // период = 62500 * 8 циклов ЦП
TCCR1A = _BV(COM1A1) // неинвертирующий ШИМ на выводе OC1A
| _BV(WGM11); // режим 14: быстрый ШИМ, TOP = ICR1
TCCR1B = _BV(WGM12) // то же самое
| _BV(WGM13) // то же самое
| _BV(CS11); // тактовая частота F_CPU/8
}
Обратите внимание, что OCR1A
и OCR1B
должны быть установлены на желаемое количество циклов.
минус один.
analogWrite
— 8-битный.
Обратная величина 30 Гц (время за полный период) составляет 0,0313.
0,0313 деленное на 256 (28) равно 0,000122 или 122uS.
8 бит — это наименьшее время, на которое можно разрезать сигнал частотой 30 Гц.
Чтобы получить меньшие срезы, вам нужен ШИМ-сигнал с более высоким разрешением. Этот вопрос и ответ показывают, как это можно сделать, но он ограничен тем, какие выводы можно использовать, поскольку вам нужны каналы ШИМ, подключенные к 16-битному таймеру.
- Можно ли сгенерировать точный тактовый импульс 15 кГц с помощью ардуино?
- Генерация сигнала частотой 38 кГц без таймеров
- Светодиод Arduino PWM с замиранием в сборке
- Отрегулируйте расчет времени после изменения частоты Timer0
- Как измерить ультразвуковой датчик без импульсного метода?
- Teensy 4.1 / 4.0 Когда использовать контакты FlexPWM и QuadTimer для стробирования светодиодов
- Seeeduino СЯО запись и чтение ШИМ продолжительность (период) с помощью таймеров
- Генерация импульса 200 кГц на Arduino Uno в обычном режиме