генерировать два сдвинутых по фазе ШИМ-импульса, запускаемых внешним сигналом с частотным разделением, с помощью Arduino uno?
У меня есть импульс 4 кГц в качестве триггера, и мне нужны два сдвинутых по фазе ШИМ-выхода с разделенной частотой от arduino uno.
Теперь я управлял одним выходом ШИМ, используя следующий код:
int cnt = 0;
void setup() {
pinMode(3, OUTPUT);
pinMode(2, INPUT);
attachInterrupt(digitalPinToInterrupt(2), rising_edge, RISING);
}
void loop() {
}
void rising_edge() {
cnt = cnt + 1;
if (cnt >= 4) { //divide by 8
digitalWrite(3,(digitalRead(3)^1));
cnt = 0;
}
}
Как предложил Majenko♦, я попытался использовать библиотеку Timer1, но фазовый сдвиг всегда составляет 15 мкс, независимо от периода timer1.
#include <TimerOne.h>
int cnt = 0;
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(2, INPUT);
Timer1.initialize(10000);
Timer1.attachInterrupt(ISP_T1);
attachInterrupt(digitalPinToInterrupt(2), ISP_INTx, RISING);
}
void loop() {
}
void ISP_INTx() {
cnt = cnt + 1;
if (cnt >= 4) {
digitalWrite(3,(digitalRead(3)^1));
cnt = 0;
Timer1.start();
}
}
void ISP_T1() {
digitalWrite(4,(digitalRead(4)^1));
Timer1.stop();
}
Сдвиг должен быть произвольным значением от 0 до 1 x период (зависит от делителя)
Регулируемая нагрузка предпочтительна, но не обязательна.
@7E10FC9A, 👍-1
Обсуждение2 ответа
Лучший ответ:
Я думаю, что ваш первый пример очень близок. А как насчет:
int cnt = 0;
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(2, INPUT);
attachInterrupt(digitalPinToInterrupt(2), rising_edge, RISING);
}
void loop() {
}
void rising_edge() {
cnt = cnt + 1;
if (cnt >= 4) { //делим на 8
cnt = 0;
}
switch(cnt){
case 0: digitalWrite(3,HIGH);break;
case 1: digitalWrite(4,HIGH);break;
case 2: digitalWrite(3,LOW);break;
case 3: digitalWrite(4,LOW);break;
}
}
При одинаковой входной частоте контакт 3 будет сдвинут по фазе на 90 градусов по отношению к контакту 4. Вы можете сделать это регулируемым, если не возражаете против большего делителя, расширив переключатель/корпус, например, до 6 или 8 шагов.
Вы можете получить больше шагов, запуская по переднему и заднему фронту (хотя это может не дать однородной фазы, если входящий ШИМ не имеет коэффициент заполнения 50%).
Если я правильно понимаю, он использует timer0 для прерывания и CPU для подсчета.
Нет, это не так. Прерывание есть прерывание. Timer0 - это таймер. На данный момент у вас есть только внешнее прерывание, запускающее ISR, которое добавляет к переменной и переключает выход.
Timer0 используется для управления millis()
и delay()
.
Что вам нужно сделать, так это настроить таймер (не Timer0, так как он уже зарезервирован), который будет отключаться с периодом, равным разнице во времени фазового сдвига. Запустите его в вашем существующем ISR (когда выход переключен), а в ISR таймера остановите таймер и переключите второй выход (или установите его таким же, как выход 0°).
В этом вам может помочь библиотека TimerOne.
Но почему функции timer0 не работают с attachInterrupt?, @7E10FC9A
timer0 не имеет ничего общего с attachInterrupt., @Majenko
[ссылка](https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/) здесь говорится: «Внутри присоединенной функции delay() не будет работать, и значение, возвращаемое millis() не будет увеличиваться»., @7E10FC9A
Это верно. ISR Timer0 не будет работать, пока работает INTx ISR. Но это не имеет никакого отношения к твоему вопросу, так почему ты спрашиваешь?, @Majenko
Я попытался настроить Timer1, но сдвиг всегда 15 мкс., @7E10FC9A
- ATmega328P - проблема с использованием таймера 2 для генерации тона
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Можно ли сгенерировать точный тактовый импульс 15 кГц с помощью ардуино?
- 4-битный счетчик вверх и вниз
- Включить и отключить отдельные прерывания
- Светодиод Arduino PWM с замиранием в сборке
- Измерить количество циклов и время цифрового входа
- Проблема прерывания библиотеки MPU6050 Arduino Jeff Rowberg
На сколько сдвинулась фаза?, @Majenko
0-1 x период, который зависит от делителя (целого числа), @7E10FC9A
Значит, вам нужен переменный фазовый сдвиг? Это усложняет задачу., @Majenko
Для этого вопроса подойдет фиксированный фазовый сдвиг. Я могу прослушивать последовательный порт в цикле и переназначать регистры позже., @7E10FC9A
Если вы можете жить с фиксированным рабочим циклом 50%, то вы можете установить Таймер 1 в режим 4 (CTC с TOP = OCR1A), перевести оба выхода в режим переключения и использовать OCR1B для управления фазовым сдвигом. Никаких прерываний, никакого участия ЦП после установки таймера. Сложная часть будет заключаться в выборе между фазовыми сдвигами φ и φ+π. В этом может помочь TCCR1C., @Edgar Bonet