сигналы со сдвигом

nkp
Offline
Зарегистрирован: 12.03.2014

можно ли сделать подобное 

http://s017.radikal.ru/i430/1503/61/07b29925a44f.png

на одном таймере ардуины??

один "канал" :

(3 и 22 мкс)



//gk1.ino

int flag = 1;
ISR(TIMER1_COMPB_vect) 
{
  if(flag ==0) 
  {
	TCNT1H=0; 
	TCNT1L=0;
	flag = 1;
  }
  else 
  {
	TCNT1H=0x01; //304(22-19=3мкс)
	TCNT1L=0x30; //304(22-19=3мкс)
	flag = 0;
  }
}
void setup() 
{
	TCCR1B=0x05; //CLK/1024
	DDRB|=(1<<6);
	PORTB=0x00;
	TCCR1A=0b00010000; 
	OCR1BH=0x01; 
	OCR1BL=0x60;
    TIMSK1 |= (1 << OCIE1B) ; 
}
void loop() {}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, как связано ваше ТЗ и этот скетч? Достаточно постотреть на TCCR1B что бы было очевидно, что такт таймера будет 64 микросекунды. О каким 3х микросекундах речь? И c назначением порта что-то странное...

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

И c назначением порта что-то странное...

да - что то напутал в расчетах (что то  - это почти всё??)))

тайминги подправлю...

а вот с наначением порта - не подскажите - что не так??

============

связь кода с тз "сакральная"))

так как кодить (с мк еще в большей степени)  желаемых навыков нет - начал с одного "канала"...

выложил код , с надеждой быть ткнутым в ошибки(неизбежные для меня в данном случае))

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, с портами - командой TCCR1A вы назначаете выход OC1B. Он сидит физически на ноге PB2. А что мы видим в сетапе? Вы назначаете выходной ногу PB6 в 22 строке, на ней вообще-то кварц висит. Хорошо, что компилятор не даст этого сделать. А смысл команды PORTB=0 вообще не ясен. На всякий случай опустить все 8 бит порта в 0 ?

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

Хорошо, что компилятор не даст этого сделать. 

значит  - то что я вижу на телевизоре - это не "работа" скетча??

(12-я нога)

http://s019.radikal.ru/i637/1503/9e/974e9aaa6e43.png

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, а какой у вас контроллер?

nkp
Offline
Зарегистрирован: 12.03.2014

2560

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, такие вещи сразу уточнять нужно.  Я то давал нумерацию для atmega328.

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

nkp, такие вещи сразу уточнять нужно.  Я то давал нумерацию для atmega328.

прошу прощения - буду исправляться)))

================

но остается вопрос открытым - можно ли в принципе сделать точный сдвиг сигналов на одном таймере????

если нет  - как оптимальней это решить???

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, я ещё не совсем точно понял тз. Вам нужно на одном таймере что? Два разных импульса из двух выходов, или же всё это с с одного выхода: импульс 3us, потом пауза 122us?

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

nkp, я ещё не совсем точно понял тз. Вам нужно на одном таймере что? Два разных импульса из двух выходов, или же всё это с с одного выхода: импульс 3us, потом пауза 122us?

два разных выхода, числовые значения таймингов не критичны(для того и  хочеться выполнить это в МК , чтоб 

поэкспериментировать как раз с разными значениями длительностей импульсов и пауз),

 

nkp
Offline
Зарегистрирован: 12.03.2014

"на одном таймере" - это конечно тоже не критично - хоть на трех)))

субъективно конечно  - но мне кажется , что на одном  - это было бы максимально точно(я про сдвиг  сигналов)

 

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

Настроить таймер на автогенерацию с интервалом в 1мкс. Два (а можно и больше, по необходимому числу выходов) счетчика числа прерываний которые меняются по срабатыванию таймера. По достижении нужных значений меняется состояние требуемого выхода и его счетчик обнуляется. Для скважности отличной от 0,5 на каждый выход придется использовать 2 порога счетчика.

Как-то так видится.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
// используем "8-bit Timer/Counter2 with PWM"
// выход 1 - OC2A - PB3 - нога 17
// выход 2 - OC2B - PD3 - нога 5
// TCCR2A = COM2A1  COM2A0  COM2B1  COM2B0
//          ------  ------  WGM21   WGM20
// TCCR2B = FOC2A   FOC2B   -----   -----
//          WGM22   CS22    CS21    CS0
// OCR2A и OCR2B - пороги сравнения
// CS22:CS21:CS0 - 0=стоп  1=CLK      2=CLK/8    3=CLK/32  4=CLK/64
//                         5=CLK/128  6=CLK/256  7=CLK/1024
// с кварцем на 16 MHz и CS22:CS21:CS0=110 частота ШИМ будет
// 16000000 / 256 / 2 = 31,250 kHz
// с кварцем на 16 MHz и CS22:CS21:CS0=111 частота ШИМ будет
// 16000000 / 1024 / 2 = 7,812 kHz
int skw; // скважность - от 1 до 127 !!!!!!!!!!!!!!!!!!!!!!
//=================================================================================
void setup()
{                
// настраиваем на 31 kHz
// WGM22:WGM21:WGM20=001 - Mode1 - PWM, Phase Correct
  TCCR2B = TCCR2B | B00000110;
// COM2A1:COM2A0=10 - Clear OC2A on Compare Match when up-counting.
//                    Set OC2A on Compare Match when down-counting.
// COM2B1:COM2B0=11 - Set OC2B on Compare Match when up-counting.
//                    Clear OC2B on Compare Match when down-counting.
// WGM22:WGM21:WGM20=001 - Mode1 - PWM, Phase Correct
  TCCR2A = TCCR2A | B10110001;
// разрешить прерывание по переполнению
  TIMSK2 = TIMSK2 | B00000001;
}
//=================================================================================
// скважность меняем по прерыванию ( когда счётчик в нуле ) !!!!!!!!!!!!!
ISR( TIMER2_OVF_vect )
{
  OCR2A = skw;
  OCR2B = 255 - skw;
}
//=================================================================================
void loop()
{
// это для проверки осциллографом на ногах 5 и 17
  for( int i = 1; i < 128; i++ )
    {
      skw = i;
      delay( 100 );
    }
  for( int i = 127; i < 1; i-- )
    {
      skw = i;
      delay( 100 );
    }
}
//=================================================================================
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

На одном таймере аппаратно не сделать... Так бы коротко выглядел бы скетч если нужно только 1 канал:

void setup() {
pinMode (10,OUTPUT); //(10 порт на выход для меги328)
TCCR1A=(1<<WGM11)|(1<<COM1B1); //mode14 div8
TCCR1B=(1<<CS11)|(1<<WGM12)|(1<<WGM13); //mode14 div8
ICR1=249; //полный цикл 125мкс
OCR1B=5; // упасть в ноль через 3мкс	
}
void loop() {}

Если бы речь не шла о столь высоких частотах (единицы микросекунд) можно было бы выпадать в прерывание, в нём дёргать любыми ногами по любому алгоритму как вам уже написали до меня. Но  вставив в прерывание несколько условий и инкременирующихся счётчиков команды просто не успеют выполнится до начало следущего прерывания, в результате все тайминги развалятся.

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

В прерывании можно делать только инкремент счетчика. А в loop() пустой while по значению счетчика до ближайшего события. Далее то же до следующего события относительно предыдущего. Быстродействия может хватить при 8-битной арифметике и прямом управлении выходами.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Alex_Sk, если бы вы привели действующий скетч,  в котором 100% не сьехали тайминги -было бы хорошо. Пока это только ваше предположение...

Задачку можно решить тупо запустив сначала первый таймер, потом пауза,  и второй таймер.  разницу фаз можно регулировать перезапуском сетапа с новым значением задежки.  Пример для арудины микро:

void setup() {
pinMode (9,OUTPUT); // OC3A arduino micro
pinMode (5,OUTPUT); // OC1A arduino micro
TCCR1A=(1<<WGM11)|(1<<COM1A1); //mode14 div8
TCCR1B=(1<<CS11)|(1<<WGM12)|(1<<WGM13); //mode14 div8
ICR1=249; //полный цикл 125мкс
OCR1A=5; // упасть в ноль через 3мкс	
delayMicroseconds(50); // тут задаётся задержка 
TCCR3A=(1<<WGM31)|(1<<COM3A1); //mode14 div8
TCCR3B=(1<<CS31)|(1<<WGM32)|(1<<WGM33); //mode14 div8
ICR3=249; //полный цикл 125мкс
OCR3A=5; // упасть в ноль через 3мкс	
}
void loop() {}

 

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

dimax, если посмотреть #13,14 и в #15 изменить режим на 8, OCR1A=244, каналы OCR1A и OCR1B настроить противофазно - то всё должно получиться... ( #13 для другой задачи - но смысл такой же )
ICR1=249 - период, OCR1B=5, OCR1A=249-5 - длительность импульсов в каналах

 нет ?

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

Задачку можно решить тупо запустив сначала первый таймер, потом пауза,  и второй таймер

спасибо! буду проверять все варианты...

но хочется какого то подобия обратной связи:

если фаза (по каким то "немыслимым" причинам ) начнет сползать - "ОС" подкоректировала бы...

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SU-27-16,  Мне нужно смотреть в скетч уже со всеми поправками.. на словах я  плохо понимаю.. :)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, сползать то вроде не счего..  всё синхронно по тактам кварца.  А вот чёткой зависимости между задержкой  в сетапе и задежкой фактической -сложно добиться.

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

 А вот чёткой зависимости между задержкой  в сетапе и задежкой фактической -сложно добиться.

не совсем понял этот тезис...

поясните пож.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, в моём примере между запусками таймеров пауза 50us. В идеале между фронтами фаз сигналов тоже должно быть 50us, но такого не будет. У примеру реально будет 40us. Если увеличить задержку на 1us то не факт что фактическая пауза между сигналами станет 41us, возможно увеличение будет какими-то рывками. Я имел ввиду что сложно подогнать задержку в скетче под желаемую-фактическую.

nkp
Offline
Зарегистрирован: 12.03.2014

в данном случае это недопустимо(((

нет даже времени на "синхронизацию" - в первого такта система должна работать 

в соответствии с алгоритмом - шаг влево,шаг вправо - р....  авария!!

потому и  мыслил о реализации на одном таймере...

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
void setup() {
pinMode (9,OUTPUT);  // OC1A arduino Uno
pinMode (10,OUTPUT); // OC1B arduino Uno
TCCR1A=(1<<WGM13)|(1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0); //mode8
TCCR1B=(1<<CS11); //div8
ICR1=124;   // 124 * 2 тиков - период
OCR1A=3;    // 3 тика - длит. импульса канала А
OCR1B=121;  // 124-121=3 тика - длит. импульса канала В
}
void loop() {}

и рисунок из #14....
полная синхронизация, значения регистров - не пересчитывал....

вы не Н-мост на полевиках делаете ?

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, ну так подгоните задержку сначала на осциллографе, какая проблема-то. На одном таймере видимо никак... по крайней мере на 8-битных контроллерах. Два выхода в таймерах могут давать разную скважность одной частоты, вашу задачу это никак не поможет решить.  А в прерывание не впихнуть всю математику для программного дёрганья ногами. Правда, как вы читали выше некоторые товарищи не согласны, но подтвердить рабочим скечем не торопятся) Я вполне допускаю, что можно какими-то очень оптимизированными ассемблеровскими командами всё уместить, но сам точно не сумею. И в любом случае это идеологически не правильный вариант, т.к. все ресурсы контроллера полностью будут заняты. Ничем другим он заниматься уже не сможет.

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

поделился в #25 - но надо проверять :)
из ресурсов занят только счётчик, МК весь почти свободен

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

nkp, ну так подгоните задержку сначала на осциллографе, 

то есть  , вы имеете в виду  , что единажды подобрав задержку "опытным путем"  , повторяемость будет 

неизменной при перезапусках ...

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SU-27-16, вы что-то всё наперепутали...ваш скетч во первых с этими настройками не выдаст ничего, а если поменять биты портов на 1<<COM1(A,B)0 То выдаст шим 15 гц. на втором выводе то-же, но инверсно...

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nkp, Нет, ну голову на отсеченье не даю :) Но правда не могу представить такой причины, что б таймеры рассинхронизовались..

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

nkp, Нет, ну голову на отсеченье не даю :)

поймите и нас правильно  - после нескольких неудачных стартов,и потери нескольких спутников - у нас нет больше 

права на ошибку)))

все надежды теперь на  ардуино и этот форум

))))

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

dimax пишет:

SU-27-16, вы что-то всё наперепутали...ваш скетч во первых с этими настройками не выдаст ничего, а если поменять биты портов на 1<<COM1(A,B)0 То выдаст шим 15 гц. на втором выводе то-же, но инверсно...

значения регистров сравнения и предделитель ( 3 мксек и 122 мксек ) не проверял и не считал, а в режиме 8 получить картинку #15 - можно ( код заменяет работу микросхемы TL494 )

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

при значениях OCR1A и OCR1B равноудалённых от мин и макс ICR1 и COM1A=10 и COM1B=11 в режиме 8 - будет что надо...
....считать значения для предделителя и уровни сравнения - неохота :(

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SU-27-16 поправил ваш скетч, так работает:

void setup() {
pinMode (9,OUTPUT);  // OC1A arduino Uno
pinMode (10,OUTPUT); // OC1B arduino Uno
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0); //mode8
TCCR1B=(1<<CS11)|(1<<WGM13); //div8
ICR1=124;   // 124 * 2 тиков - период
OCR1A=3;    // 3 тика - длит. импульса канала А
OCR1B=121;  // 124-121=3 тика - длит. импульса канала В
}
void loop() {}

Между фазами 60us. А регулировать как?

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

спасибо за ремонт :) , WGM13 не в том регистре записал :(

что регулировать ? в комментах в строках #6,7,8 - всё указано :)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SU-27-16 пишет:

что регулировать ? в комментах в строках #6,7,8 - всё указано :)

Как что, сдвиг фаз. Правда ТС не уточнял сколько нужно, но как я понял такая возможность нужна. ICR мы не можем менять, он задаёт частоту. И изменение OCR приведёт к изменению скважности, и нарушения условия (длительность импульса=3us) Получается этот вариант только для жёстко фиксированной дельты между каналами.

nkp
Offline
Зарегистрирован: 12.03.2014

dimax пишет:

SU-27-16 пишет:

что регулировать ? в комментах в строках #6,7,8 - всё указано :)

Как что, сдвиг фаз. Правда ТС не уточнял сколько нужно, но как я понял такая возможность нужна.

да ,именно возможность нужна...

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

 

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

это тоже можно обойти, только придётся в одном периоде жонглировать уровнями сравнения и принудительным изменением состояния пина - FOC1A,B , плюс прерывания прописать по сравнению и переполнению

подождём ТСа - может пропишет задачу поконкретнее-поточнее :)

на картинке у него в сообщении не указан сдвиг, по картинке - 180 градусов

nkp
Offline
Зарегистрирован: 12.03.2014


//dimax.ino

void setup() {
pinMode (5,OUTPUT); // OC3A arduino 2560
pinMode (11,OUTPUT); // OC1A arduino 2560

TCCR1A=(1<<WGM11)|(1<<COM1A1); //mode14 div8
TCCR1B=(1<<CS11)|(1<<WGM12)|(1<<WGM13); //mode14 div8
ICR1=249; //полный цикл 125мкс
OCR1A=5; // упасть в ноль через 3мкс	
delayMicroseconds(75); // тут задаётся задержка 
TCCR3A=(1<<WGM31)|(1<<COM3A1); //mode14 div8
TCCR3B=(1<<CS31)|(1<<WGM32)|(1<<WGM33); //mode14 div8
ICR3=249; //полный цикл 125мкс
OCR3A=5; // упасть в ноль через 3мкс	
}
void loop() {}

http://s006.radikal.ru/i213/1503/63/6e4da87bf7ad.png

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
// пока только задумка
// сдвиг фазы от 1 до 179 градусов
// сдвиг больше 180 градусов - посложнее будет
void setup()
{
pinMode (9,OUTPUT); // OC3A arduino micro
pinMode (5,OUTPUT); // OC1A arduino micro
TCCR1A=(1<<WGM13)|(1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0); //mode8
TCCR1B=(1<<CS11); //div8
ICR1=124;   // 124 * 2 тиков - период
OCR1A=3;    // 3 тика - длит. импульса канала А
OCR1B=97;   // 97 тиков - задержка запуска счётчика 3   // тут задаётся задержка 
// delayMicroseconds(50); // удалить
TCCR3A=(1<<WGM31)|(1<<COM3A1); //mode14 div8
TCCR3B=(1<<CS31)|(1<<WGM32)|(1<<WGM33); //mode14 div8
ICR3=249; //полный цикл 125мкс
OCR3A=5; // упасть в ноль через 3мкс
}

// обработчик прерывания ??????????????? потом
//ISR......................
{
  // разрешить прерывание по сравнению в канале В счётчика 1
}

// обработчик прерывания по сравнению в канале В счётчика 1
//ISR......................
{
  TCNT3=0; // запуск с нуля всегда через OCR1B=97; тиков счётчика 1 - для синхронизации
  // запретить прерывание по сравнению в канале В счётчика 1
}

void loop() {}