Сдвиг фазы квадратной волны Arduino на 270 градусов

Я использую этот код для генерации прямоугольной волны с помощью Arduino и сдвига ее на 90 и 180 градусов. Однако этот код не способен сдвинуть его на 270 градусов. Не могли бы вы предложить, как я могу изменить код, чтобы он поддерживал операцию фазового сдвига прямоугольной волны на 270 градусов.

void setup() {
  pinMode( 9 , OUTPUT );    // Arduino Pin 9 = OCR1A
  pinMode( 10 , OUTPUT );   // Arduino Pin 10 = OCR1B
  // Оба выхода в режиме переключения
  TCCR1A = _BV( COM1A0 ) |_BV( COM1B0 );
  // Режим генерации сигнала CTC
  // ВЕРХ=ICR1
  // Обратите внимание, часы пока отключены
  TCCR1B = _BV( WGM13) | _BV( WGM12);
  OCR1A = 0;    // Первый вывод является базовым, он всегда переключается на 0
}
// прескалер 1 даст нам 8МГц - 488Гц
// Используйте более высокий прескалер для более низких частот

#define PRESCALER 1
#define PRESCALER_BITS 0x01
#define CLK 16000000UL    // Тактовая частота по умолчанию 16 МГц на Arduino Uno


// Выходные формы волны со сдвигом по фазе на выводах 9 и amp; 10
// freq = частота в герцах ( 122 < freq <8000000 )
// сдвиг = фазовый сдвиг в градусах ( 0 <= сдвиг < 180 )
// Делайте сдвиги на 180-360 градусов, вы можете инвертировать OCR1B, выполнив дополнительное переключение с помощью FOC
/// Обратите внимание, фазовые сдвиги будут округлены в меньшую сторону до ближайшего возможного значения, поэтому чем выше частота, тем меньше разрешение фазового сдвига вы получите. На частоте 8 МГц у вас может быть только 0 или 180 градусов, потому что за цикл приходится только 2 тактовых импульса.
int setWaveforms( unsigned long freq , int shift ) {
  // Предполагается, что предварительный делитель = 1. Для более низких частот используйте больший предварительный делитель.
  unsigned long clocks_per_toggle = (CLK / freq) / 2;    // /2, потому что для создания полной волны требуется 2 переключателя
  ICR1 = clocks_per_toggle;
  unsigned long offset_clocks = (clocks_per_toggle * shift) / 180UL; // Сначала делаем mult, чтобы сохранить точность
  OCR1B= offset_clocks;
  // Включаем таймер сейчас, если он еще не был включен
  // Источник часов = clkio/1 (без предварительного масштабирования)
  // Примечание: здесь можно использовать предварительный делитель для более низких частот
  TCCR1B |= _BV( CS10 ); 
}
// Демонстрация циклическим изменением некоторых фазовых сдвигов на частоте 50 кГц
void loop() {
  setWaveforms( 40000 , 0 );
  delay(1000); 
  setWaveforms( 40000 , 90 );
  delay(1000); 
  setWaveforms( 40000 , 180 );
  delay(1000); 
}

, 👍1

Обсуждение

Ответ находится в коде, который вы разместили, в комментарии: «Чтобы выполнять сдвиги на 180-360 градусов, вы можете инвертировать OCR1B, выполнив дополнительный переключатель с помощью FOC»., @Edgar Bonet

Я пытался понять это утверждение, и оно не имеет для меня особого смысла. Не могли бы вы помочь мне изменить код или понять утверждение? @ЭдгарБонет, @Bogdan Raspopin

Не ваш собственный код?, @AJD

Нет, я взял отсюда: https://electronics.stackexchange.com/questions/174656/avr-arduino-output-2-pwm-waveforms-with-90-grade-phase-shift?utm_medium=organic&utm_source=google_rich_qa&utm_campaign= google_rich_qa, @Bogdan Raspopin

Звучит так, как будто это означает «Инвертируйте форму волны и сделайте сдвиг на 90 градусов»., @Majenko

установка бита FOC вызывает однократное сравнение выходных данных независимо от значения OCR, фактически вызывая «преждевременное» переключение. Это инвертирует форму волны в долгосрочной перспективе. FOC — последние 2 бита (6, 7) в регистре TCCRB, FOCxA/B по макросу, @mystery

@mystery, не могли бы вы посоветовать, как мне изменить код, чтобы выполнить операцию. Извините, я действительно новичок в этом пространстве, @Bogdan Raspopin


1 ответ


1

Arduino может переключаться только в диапазоне 180 градусов в режиме CTC, используя 16-битный таймер. Если вы сдвинете один канал на 90 градусов (другой OCR установлен на 1, а не на ноль), а затем добавите логический инвертор, вы получите эквивалент 270 градусов, как упоминал Эдгар Боне.

Что касается использования FOC (принудительного сравнения вывода), Эдгар Б. снова прав. Канал можно предварительно настроить как инвертированный, а затем выполнить сдвиг, установив OCR на 90 градусов — вам не понадобится дополнительный логический инвертор. Но этот метод не для кого-то новым. Вам понадобится O-Scope, чтобы заставить его работать (и некоторое время, чтобы изучить FOC и режим CTC-12).

Я думаю, что проще использовать одну секцию шестнадцатеричного инвертора 7404, чтобы преобразовать сдвинутую на 90 градусов форму сигнала на 270 градусов.

Поиск "Прямоугольные волны с фазовым сдвигом" и вы найдете ВИДЕО (по состоянию на 2022 год) для примера проекта, в котором используется тактика FOC для создания фазовых сдвигов, регулируемых во время выполнения, на Arduino. Возможно, вы найдете способ легко изменить код для нужной вам перевернутой фазы...

FWIW стокву

,