сигналы со сдвигом
- Войдите на сайт для отправки комментариев
Втр, 17/03/2015 - 07:35
можно ли сделать подобное
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() {}
nkp, как связано ваше ТЗ и этот скетч? Достаточно постотреть на TCCR1B что бы было очевидно, что такт таймера будет 64 микросекунды. О каким 3х микросекундах речь? И c назначением порта что-то странное...
И c назначением порта что-то странное...
да - что то напутал в расчетах (что то - это почти всё??)))
тайминги подправлю...
а вот с наначением порта - не подскажите - что не так??
============
связь кода с тз "сакральная"))
так как кодить (с мк еще в большей степени) желаемых навыков нет - начал с одного "канала"...
выложил код , с надеждой быть ткнутым в ошибки(неизбежные для меня в данном случае))
nkp, с портами - командой TCCR1A вы назначаете выход OC1B. Он сидит физически на ноге PB2. А что мы видим в сетапе? Вы назначаете выходной ногу PB6 в 22 строке, на ней вообще-то кварц висит. Хорошо, что компилятор не даст этого сделать. А смысл команды PORTB=0 вообще не ясен. На всякий случай опустить все 8 бит порта в 0 ?
Хорошо, что компилятор не даст этого сделать.
значит - то что я вижу на телевизоре - это не "работа" скетча??
(12-я нога)
http://s019.radikal.ru/i637/1503/9e/974e9aaa6e43.png
nkp, а какой у вас контроллер?
2560
nkp, такие вещи сразу уточнять нужно. Я то давал нумерацию для atmega328.
nkp, такие вещи сразу уточнять нужно. Я то давал нумерацию для atmega328.
прошу прощения - буду исправляться)))
================
но остается вопрос открытым - можно ли в принципе сделать точный сдвиг сигналов на одном таймере????
если нет - как оптимальней это решить???
nkp, я ещё не совсем точно понял тз. Вам нужно на одном таймере что? Два разных импульса из двух выходов, или же всё это с с одного выхода: импульс 3us, потом пауза 122us?
nkp, я ещё не совсем точно понял тз. Вам нужно на одном таймере что? Два разных импульса из двух выходов, или же всё это с с одного выхода: импульс 3us, потом пауза 122us?
два разных выхода, числовые значения таймингов не критичны(для того и хочеться выполнить это в МК , чтоб
поэкспериментировать как раз с разными значениями длительностей импульсов и пауз),
"на одном таймере" - это конечно тоже не критично - хоть на трех)))
субъективно конечно - но мне кажется , что на одном - это было бы максимально точно(я про сдвиг сигналов)
Настроить таймер на автогенерацию с интервалом в 1мкс. Два (а можно и больше, по необходимому числу выходов) счетчика числа прерываний которые меняются по срабатыванию таймера. По достижении нужных значений меняется состояние требуемого выхода и его счетчик обнуляется. Для скважности отличной от 0,5 на каждый выход придется использовать 2 порога счетчика.
Как-то так видится.
// используем "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 ); } } //=================================================================================На одном таймере аппаратно не сделать... Так бы коротко выглядел бы скетч если нужно только 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() {}Если бы речь не шла о столь высоких частотах (единицы микросекунд) можно было бы выпадать в прерывание, в нём дёргать любыми ногами по любому алгоритму как вам уже написали до меня. Но вставив в прерывание несколько условий и инкременирующихся счётчиков команды просто не успеют выполнится до начало следущего прерывания, в результате все тайминги развалятся.
В прерывании можно делать только инкремент счетчика. А в loop() пустой while по значению счетчика до ближайшего события. Далее то же до следующего события относительно предыдущего. Быстродействия может хватить при 8-битной арифметике и прямом управлении выходами.
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() {}dimax, если посмотреть #13,14 и в #15 изменить режим на 8, OCR1A=244, каналы OCR1A и OCR1B настроить противофазно - то всё должно получиться... ( #13 для другой задачи - но смысл такой же )
ICR1=249 - период, OCR1B=5, OCR1A=249-5 - длительность импульсов в каналах
нет ?
Задачку можно решить тупо запустив сначала первый таймер, потом пауза, и второй таймер
спасибо! буду проверять все варианты...
но хочется какого то подобия обратной связи:
если фаза (по каким то "немыслимым" причинам ) начнет сползать - "ОС" подкоректировала бы...
SU-27-16, Мне нужно смотреть в скетч уже со всеми поправками.. на словах я плохо понимаю.. :)
nkp, сползать то вроде не счего.. всё синхронно по тактам кварца. А вот чёткой зависимости между задержкой в сетапе и задежкой фактической -сложно добиться.
А вот чёткой зависимости между задержкой в сетапе и задежкой фактической -сложно добиться.
не совсем понял этот тезис...
поясните пож.
nkp, в моём примере между запусками таймеров пауза 50us. В идеале между фронтами фаз сигналов тоже должно быть 50us, но такого не будет. У примеру реально будет 40us. Если увеличить задержку на 1us то не факт что фактическая пауза между сигналами станет 41us, возможно увеличение будет какими-то рывками. Я имел ввиду что сложно подогнать задержку в скетче под желаемую-фактическую.
в данном случае это недопустимо(((
нет даже времени на "синхронизацию" - в первого такта система должна работать
в соответствии с алгоритмом - шаг влево,шаг вправо - р.... авария!!
потому и мыслил о реализации на одном таймере...
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.... полная синхронизация, значения регистров - не пересчитывал.... вы не Н-мост на полевиках делаете ?nkp, ну так подгоните задержку сначала на осциллографе, какая проблема-то. На одном таймере видимо никак... по крайней мере на 8-битных контроллерах. Два выхода в таймерах могут давать разную скважность одной частоты, вашу задачу это никак не поможет решить. А в прерывание не впихнуть всю математику для программного дёрганья ногами. Правда, как вы читали выше некоторые товарищи не согласны, но подтвердить рабочим скечем не торопятся) Я вполне допускаю, что можно какими-то очень оптимизированными ассемблеровскими командами всё уместить, но сам точно не сумею. И в любом случае это идеологически не правильный вариант, т.к. все ресурсы контроллера полностью будут заняты. Ничем другим он заниматься уже не сможет.
поделился в #25 - но надо проверять :)
из ресурсов занят только счётчик, МК весь почти свободен
nkp, ну так подгоните задержку сначала на осциллографе,
то есть , вы имеете в виду , что единажды подобрав задержку "опытным путем" , повторяемость будет
неизменной при перезапусках ...
SU-27-16, вы что-то всё наперепутали...ваш скетч во первых с этими настройками не выдаст ничего, а если поменять биты портов на 1<<COM1(A,B)0 То выдаст шим 15 гц. на втором выводе то-же, но инверсно...
nkp, Нет, ну голову на отсеченье не даю :) Но правда не могу представить такой причины, что б таймеры рассинхронизовались..
nkp, Нет, ну голову на отсеченье не даю :)
поймите и нас правильно - после нескольких неудачных стартов,и потери нескольких спутников - у нас нет больше
права на ошибку)))
все надежды теперь на ардуино и этот форум
))))
SU-27-16, вы что-то всё наперепутали...ваш скетч во первых с этими настройками не выдаст ничего, а если поменять биты портов на 1<<COM1(A,B)0 То выдаст шим 15 гц. на втором выводе то-же, но инверсно...
значения регистров сравнения и предделитель ( 3 мксек и 122 мксек ) не проверял и не считал, а в режиме 8 получить картинку #15 - можно ( код заменяет работу микросхемы TL494 )
при значениях OCR1A и OCR1B равноудалённых от мин и макс ICR1 и COM1A=10 и COM1B=11 в режиме 8 - будет что надо...
....считать значения для предделителя и уровни сравнения - неохота :(
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. А регулировать как?
спасибо за ремонт :) , WGM13 не в том регистре записал :(
что регулировать ? в комментах в строках #6,7,8 - всё указано :)
что регулировать ? в комментах в строках #6,7,8 - всё указано :)
Как что, сдвиг фаз. Правда ТС не уточнял сколько нужно, но как я понял такая возможность нужна. ICR мы не можем менять, он задаёт частоту. И изменение OCR приведёт к изменению скважности, и нарушения условия (длительность импульса=3us) Получается этот вариант только для жёстко фиксированной дельты между каналами.
что регулировать ? в комментах в строках #6,7,8 - всё указано :)
Как что, сдвиг фаз. Правда ТС не уточнял сколько нужно, но как я понял такая возможность нужна.
да ,именно возможность нужна...
пока определенно величину сказать не могу - будет выясняться опытным путем...
это тоже можно обойти, только придётся в одном периоде жонглировать уровнями сравнения и принудительным изменением состояния пина - FOC1A,B , плюс прерывания прописать по сравнению и переполнению
подождём ТСа - может пропишет задачу поконкретнее-поточнее :)
на картинке у него в сообщении не указан сдвиг, по картинке - 180 градусов
//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
// пока только задумка // сдвиг фазы от 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() {}