ШИМ. сигналы со сдвигом фазы и их регулировка

eiyawii
Offline
Зарегистрирован: 05.10.2012

 Добрый день!

Необходимо получить на выходе 2х портов PWМ сигнал и сигнал сдвинутый по фазе на 180*, скважность = 2 (то есть 50% заполнение цикла, примерно как управление у инверторов). Ну а потом возможность регулировки скважности этих сигналов от 0,01 до 1. Какими функциями можно управлять ШИМом?

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Мне кажется, средствами IDE Arduino (я имею ввиду Wiring, а не среду) - никак. Нужно напрямую программировать таймеры на с. Что-нибудь в стиле "обнулить второй таймер, когда первый досчитает до половины" - тогда сигналы будут сдвинуты на 180 градусов вне зависимости от скважности, которую уже нужно задавать обычным методом. 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Скорее всего - моя не прав.... Поправьте начинающего :) Но.....

Первый канал - выход PWM - заполнение регулируется от 0,0039 до 0,9961 с шагом 0, 0039.

Второй канал - первый канал пропущенный через инвертор, например, 1533ЛН1.

Кстати, вопрос - не нашёл во "фрице" микросхем базовой логики - НЕ, 2И-НЕ, 2ИЛИ-НЕ и т.д.. Где их мона найти ?

eiyawii
Offline
Зарегистрирован: 05.10.2012

AlexFisher пишет:

Мне кажется, средствами IDE Arduino (я имею ввиду Wiring, а не среду) - никак. 

Жаль, хотел средствами arduino, программно. Но всё-таки подумаю, вдруг можно как-нибудь извернуться.

eiyawii
Offline
Зарегистрирован: 05.10.2012

SU-27-16 пишет:

Первый канал - выход PWM - заполнение регулируется от 0,0039 до 0,9961 с шагом 0, 0039.

Второй канал - первый канал пропущенный через инвертор, например, 1533ЛН1.

Да, после ковыряния подумал что можно просто буфером инвертировать сигнал ко второму каналу. Но всё-таки хотелось бы это реализовать программно. На выходе PWM по сути high сигнал, так вот может быть это значение можно инвертировать внутри программы? Если использовать цифровые выходы, то можно же поочереди мигать диодами, так вот это тоже самое, только вместо просто high используем ШИМ.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Не грузится рисунок... :(

Я понимаю, что недостатки этого варианта :

- частота периодов ШИМ =примерно 490 Hz

- и будет присутствовать "виртуальное" смещение фазы цикла периода ШИМ в инвертированном канале.....

Но ! Если это применить для управления двумя движками, когда заполнение = 50% - оба крутят равномерно, уменьшаем заполнение - 1-ый крутит быстрее, 2-ой - медленнее ( пропорционально ! ) - тогда не имеет значения этот сдвиг фаз !

Пример - гусеничная платформа: 50% - едем прямо, 25% - правая гребёт сильнее, подворачиваем налево, 75% - левая гребёт сильнее, подворачиваем направо.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Синим - цикл ШИМ в обоих каналах. Зелёным  - смещение фазы цикла ШИМ в инвертированном канале.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

eiyawii пишет:

Необходимо получить на выходе 2х портов PWМ сигнал и сигнал сдвинутый по фазе на 180*

А судьба обоих каналов - какая ? Чем они будут управлять ? Нужна ли синфазность обоих каналов ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

1-ая диаграмма - канал ШИМ для значения, типа, 35 ( всё относительно же )

2-ая диаграмма - инверсия 1-ой диаграммы

3-ая диаграмма - канал ШИМ для значения, типа, 60

4-ая диаграмма - инверсия 3-ей диаграммы

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Извините за корявость осциллограм.... Осциллограф такой лажовский :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

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

Суммарная яркость, приблизительно, одинаковая - а яркость в каналах - в противофазе....

Нет ?

Не сочтите за набор баллов !!!!!

leshak
Offline
Зарегистрирован: 29.09.2011

 Попробуйте погуглить что-то типа "Arduino Software PWM library"

Вот что-то типа такой:http://code.google.com/p/rogue-code/wiki/SoftPWMLibraryDocumentation

Если не напрямую ее заюзать, то подзмотреть "как они PWM програмного делают" или "подпилить напильником" ее что-бы шим выдавала сразу на две ноги инверсно - можно.

А можно, кстати, посмотреть еще на библиотеки для Serv (и аппаратные и програмные) они тоже PWM-м в итоге генерят. Только еще и "частосту" подкручивать можно.

Ну и "лобовое решение" (если нам ничего от ардуины кроме этого шима не нужно) никто не отменял.

Читаем http://arduino.ru/forum/programmirovanie/shim-signaly-so-sdvigom-fazy-i-ikh-regulirovka

Считаем какие у нас должны быть тайминги. Предположим частота а нас 500Hz. Значит длины фрейма 2 ms. При скважности 50% 1 ms импульс, 1 ms пауза. Или тысячу микросекунд.

Для Atmer168 получаем инверсный PWM на D8,D9

void setup(){
 pinMode(8,OUTPUT);
 pinMode(9,OUTPUT);
}

void loop(){
  PORTB =B10; // D8=0, D9=1
  delayMicroseconds(1000); // крутим для изменения скважности
  PORTB =B01;  // D8=1, D9=0
  delayMicroseconds(1000); // крутим для изменения скважности
}

Ну и, естественно, держим в уме что delayMicroseconds у нас точнее чем 4 микросекунды в принципе работать не может.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

А так - каналы прямой и инверсный синхронизированы.... Сдвиг фазы - 180, но это не инверсные сигналы.


//-----------------------------------------------------------------
#define PinPWM_1 8                     // прямой канал
#define PinPWM_2 9                     // инверсный канал
int T_PWM ;                            // период PWM, микросекунды, 16383 максимал
byte D_PWM ;                           // заполнение PWM прямого канала ( значения - от 0 до 100 ), проценты
int t_PWM_1 ;                          // длительность положительного импульса в прямом канале, микросекунды, 16383 максимал
unsigned long t_PWM_2 ;                          // длительность положительного импульса в инверсном канале, микросекунды 16383 максимал
//-----------------------------------------------------------------
void setup()
{  
  Serial.begin( 9600 ) ;
  pinMode( PinPWM_1 , OUTPUT ) ;
  pinMode( PinPWM_2 , OUTPUT ) ;
  T_PWM = 100 ;                    // период PWM = 100 сотен микросекунд, частота PWM = 100 Hz
  D_PWM = 0 ;                      // начнём с заполнения прямого канала - 0%, и инверсного, соответственно, - 100%
} 
//-----------------------------------------------------------------
void loop()
{
  t_PWM_1 = T_PWM * D_PWM ;
  t_PWM_2 = T_PWM * ( 100 - D_PWM ) ; 
  
  Serial.print( " D_PWM = " ) ;
  Serial.print( D_PWM ) ; 
  Serial.print( "     " ) ; 
  
  Serial.print( " t_PWM_1 = " ) ;
  Serial.print( t_PWM_1 ) ; 
  Serial.print( "     " ) ; 
  
  Serial.print( " t_PWM_2 = " ) ;
  Serial.print( t_PWM_2 ) ; 
  Serial.print( "     " ) ; 
  
  Serial.print( " T_PWM = " ) ;
  Serial.print( T_PWM * 100 ) ; 
  Serial.print( "     " ) ; 
  
  Serial.print( " T_PWM - t_PWM_1 - t_PWM_2 = " ) ;
  Serial.print( T_PWM * 100 - t_PWM_1 - t_PWM_2 ) ; 
  Serial.println( "" ) ;  

  if ( t_PWM_1 > ( T_PWM * 100 ) )
  {
    Serial.println( " Error t_PWM_1 !" ) ;
  }
  if ( t_PWM_2 > ( T_PWM * 100 ) )
  {
    Serial.println( " Error t_PWM_2 !" ) ;
  }  
  
  Serial.println( "" ) ;
  Serial.println( "" ) ;  
  
  DDRB = B11 ;                   // оба канала стартуют вместе
  if ( t_PWM_1 < t_PWM_2 )       // при заполнении < 50% в прямом канале
  {
    delayMicroseconds( t_PWM_1 ) ;
    DDRB = B10 ;                 // прямой канал - стоп
    delayMicroseconds( t_PWM_2 - t_PWM_1 ) ;
    DDRB = B00 ;                 // инверсный канал - стоп
  }
  if ( t_PWM_1 == t_PWM_2 )      //при заполнении = 50% в прямом канале
  {
    delayMicroseconds( t_PWM_1 ) ;
    DDRB = B00 ;                 // оба канала - стоп
  }
  if ( t_PWM_1 > t_PWM_2 )       // при заполнении > 50% в прямом канале
  {
    delayMicroseconds( t_PWM_2 ) ;
    DDRB = B01 ;                 // инверсный канал - стоп
    delayMicroseconds( t_PWM_1 - t_PWM_2 ) ;
    DDRB = B00 ;                 // прямой канал - стоп
  }
  D_PWM ++ ;                     // увеличиваем заполнение на 1%
  if ( D_PWM > 100 )
  {
    D_PWM = 100 ;
  }
  delay( 1000 ) ;                // для просмотра Serial
}
//-----------------------------------------------------------------

 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

eiyawii пишет:

SU-27-16 пишет:

Первый канал - выход PWM - заполнение регулируется от 0,0039 до 0,9961 с шагом 0, 0039.

Второй канал - первый канал пропущенный через инвертор, например, 1533ЛН1.

Да, после ковыряния подумал что можно просто буфером инвертировать сигнал ко второму каналу. Но всё-таки хотелось бы это реализовать программно. На выходе PWM по сути high сигнал, так вот может быть это значение можно инвертировать внутри программы? Если использовать цифровые выходы, то можно же поочереди мигать диодами, так вот это тоже самое, только вместо просто high используем ШИМ.

Ребятыыыы!!! Сигнал, сдвинутый на 180 градусов и инверсный - это разные вещи!!! Они совпадают только в частном случае при скважности 2 (заполнение 50%)

Если нужно иметь шим, сдвинутый на 180°, то есть "извращенский способ", позволяющий не заглубляться в прерывания таймеров. Как известно, один таймер обеспечивает ШИМ на 2-х ногах. Для получения сдвинутых сигналов берем D5 (управляется таймером 0) и D9 (управляется таймером 1), на D6 (управляется таймером 0) выводим меандр (analogWrite(6, 128);) и соединяем с D2 - здесь есть аппаратное прерывание, которое программируем на срабатывание по заднему фронту, а в прерывании обнуляем счетчик таймера 1. В результате ШИМы от таймеров 0 и 1 сдвинуты на 180°.

leshak
Offline
Зарегистрирован: 29.09.2011

AlexFisher пишет:

Ребятыыыы!!! Сигнал, сдвинутый на 180 градусов и инверсный - это разные вещи!!! Они совпадают только в частном случае при скважности 2 (заполнение 50%)

Упс. А ведь правда.

AlexFisher пишет:

Если нужно иметь шим, сдвинутый на 180°, то есть "извращенский способ", позволяющий не заглубляться в прерывания таймеров. Как известно, один таймер обеспечивает ШИМ на 2-х ногах. Для получения сдвинутых сигналов берем D5 (управляется таймером 0) и D9 (управляется таймером 1), на D6 (управляется таймером 0) выводим меандр (analogWrite(6, 128);) и соединяем с D2 - здесь есть аппаратное прерывание, которое программируем на срабатывание по заднему фронту, а в прерывании обнуляем счетчик таймера 1. В результате ШИМы от таймеров 0 и 1 сдвинуты на 180°.

И это вы назваете "не заглубляться в прерывания таймеров"? ;) ;) 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

leshak пишет:

И это вы назваете "не заглубляться в прерывания таймеров"? ;) ;) 

Да :) Мы не трогаем прерывания таймеров. Мы берем внешнее. Из "углубления" - только обнуление счетчмка таймера.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 в сообщении #12 - всё просто и понятно.....

а моё из #13 - работоспособно ? там же и отметил я, что 180 и ннверсия - не одно и тоже.....

А вот дальше лешак и алекс - такое начали обсуждать, что нам с автором ветки, ещё долго изучать придётся :(

А Вы не правы, алекс..... При заполнении 50% осциллограммы обоих каналов будут одинаковы, если синхронизироваться по началу цикла ШИМ....

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Осциллограммы будут одинаковы, если для каждой из них синхронизироваться по фронту. При этом фаза не учитывается. А если вывести сразу 2 канала, а синхронизироваться по одному из них, то будут взаимоинверсные сигналы - 1-й начнется, скажем, с 1, тогда 2-й - с 0 (это для скважности 2).

Вы же поставили задачу получения 2-х сигналов ШИМа, сдвинутых на 180°

При заполнении 25% (скважность 4) они должны выглядеть так:

 

в #13 Вы получаете просто меандр (взаимоинверсный) - тот самый, частный случай, когда инверсия и сдвиг на 180 дают одинаковый результат.

kpmic
Offline
Зарегистрирован: 01.12.2019
  TCCR1B = TCCR1B & 0b11111000 | 0x01;
  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10) | _BV(COM1B0);
  TCCR1B = _BV(CS10);
Этот код дает сдвиг 180 градусов между двумя сигналами как на фото.
Но есть проблема, здесь ШИМ 8-бит 256 разрядов а надо ШИМ 10-12-бит на 1024-4096 разрядов
Кто может помочь по данной проблеме?