Управление частотой и скважностью ШИМ-сигнала

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Добрый день, коллеги!

Прошу у Вас совета по управлению высокочастотным сигналом.

Проблема следующая: Требуется получить световые импульсы (светодиода, лазера и проч. источников) с частотой от 0 до 10 000 Гц, при этом время импульса должно быть управляемым. Импульсы нужны прямоугольные, как на рисунке:

На ум сразу пришло два пути:

1. Управление родным 8-битным ШИМ Arduino. Но тут проблема в частоте - она составляет примерно 500 Гц, не регулируется и даже иногда скачет, как пишут коллеги на форуме. И точность ограничена 8 битами.

2. Управление через классический сценарий мигания светодиодом.

void loop()
{
  digitalWrite(13, HIGH);   // зажигаем светодиод
  delay(1000);              // ждем секунду
  digitalWrite(13, LOW);    // выключаем светодиод
  delay(1000);              // ждем секунду
}

Однако, здесь не понятно - гарантируется ли прямоугольный сигнал или это будет периодическое включение / выключение всё того же сигнала 500 Гц?

Можно ли организовать на Arduino управление частотой прямоугольного сигнала от 0 до 10 000 Гц при заданной скважности?

 

 

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Организовываете прерывание по любому таймеру, например 1раз в 10мкс, затем выставляете значение вывода с нужной частотой и скважностью.

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

Anatolyekb,  это не то что нужно? http://arduino.ru/forum/proekty/generator-s-reguliruemoei-chastotoi-na-a...

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Спасибо! Правда Вы работаете с довольно высокими частотами, мне будет достаточно и 10 кГц. Но скетч, как мне кажется, может подойти. Вообще идея проекта - высокочастотный стробоскоп для съемки летящих со скоростью 10-30 м/с частиц при выдержке фотокамеры 0,01-1 с. Как думаете, можно ли бужет реализовать прерыватель света на таком коде?

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Добрый день!

Я попробовал Ваш код, всё работает.

Только один вопрос:

Как регулировать время импульса? Я пытаюсь задась время импульса от 1 мкс и выше при частоте до 50 кГц.

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

Anatolyekb, не понял вопроса. Что значит время импульса?. В смысле скважность? Там всё написано -энкодером.   Duty cycle регулируется в процентах от 1 до 100.

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Постараюсь объяснить языком неэлектронщика.

Хочу иметь управляющий сигнал для регулирования частоты мерцания светодиода (лазера). Управляющий сигнал будет идти на базу транзистора для управления питанием светодиода (лазера). Предполагается частота до 50 кГц. Но помимо частоты я ещё имею желание управлять временем импульса (чтобы с момента подачи напряжения на базу транзистора до прекращения подачи напряжения проходило заданное время). Время импульса не обязательно задавать в секундах, я был был рад и процентам от "длины волны".

Например, на подграфике "а" я получил частоту 1 Гц, соответственно "длину волны" 1 с, а время импульса 0,5 с (или 50 % от длины волны). А вот на подграфике "б" при тех же Ч = 1 Гц и ДВ = 1 с уже другое время импульса 0,25 с (или 25 % от длины волны).

Как же управлять временем импульса?

Простите, если я нарушил какие законы физики при описании проблемы.

 

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

Anatolyekb, это и есть скважность, или duty cycle  по зарубежному. В чём проблема то, вы не нашли как регулируется скважность?

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Да, я не могу найти, как регулировать скважность. Я использую Ваш код, но в нём нет duty cycle.

void setup()
{
Serial.begin(9600);
pinMode (9,OUTPUT); // выход генератора
TCCR1A=1<<COM1A0; //подключить выход OC1A первого таймера
TCCR1B=0;//
}
void loop()
{
static uint32_t enc=1; //переменная счёта энкодера
uint32_t ocr;
uint32_t divider;
float freq;
if (Serial.available() > 0)
  {
   enc = Serial.parseInt(); //расчёт прескалера и OCR по нужной частоте
   divider=1; ocr = (F_CPU / enc /2 /divider);
   if (ocr >65536) { divider=8; ocr = F_CPU / enc /2 /divider;
   if (ocr >65536) { divider=64; ocr = F_CPU / enc /2 /divider;
   if (ocr >65536) { divider=256; ocr = F_CPU / enc /2 /divider;
   if (ocr >65536) { divider=1024; ocr = F_CPU / enc /2 /divider;
   if (ocr >65536) {ocr=65536; }}}}} OCR1A=ocr-1; 
   //запись в регистр прескалера            
   
   switch (divider)
   {
   case 1: TCCR1B=1|(1<<WGM12); break;
   case 8: TCCR1B=2|(1<<WGM12); break;
   case 64: TCCR1B=3|(1<<WGM12); break;
   case 256: TCCR1B=4|(1<<WGM12); break;
   case 1024: TCCR1B=5|(1<<WGM12); break;
   }
   
   freq= (float) F_CPU/2 / (OCR1A+1) /divider;
   if (freq <10000) { Serial.print(freq,1);Serial.println(" Hz "); }
   if (freq >10000) { Serial.print(freq/1000,3);Serial.println(" kHz");}
  
  } //end if serial..
} //end void loop



 

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

Anatolyekb, Это вообще набросок был. Последняя рабочая версия в сообщении #77

Mining
Offline
Зарегистрирован: 31.01.2016

dimax пишет:

Anatolyekb, не понял вопроса. Что значит время импульса?. В смысле скважность? Там всё написано -энкодером.   Duty cycle регулируется в процентах от 1 до 100.

А шаг регулировки какой на один щелчок энкодера? 1%?

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

Mining, да щёлкает по 1 проценту, до тех пор пока есть такая возможность. Ближе к концу верхнего диапазона генерируемых частот возможность кончается, и там как получится. Я писал про этот небольшой недостаток) 

Mining
Offline
Зарегистрирован: 31.01.2016

dimax пишет:

Mining, да щёлкает по 1 проценту, до тех пор пока есть такая возможность. Ближе к концу верхнего диапазона генерируемых частот возможность кончается, и там как получится. Я писал про этот небольшой недостаток) 

А если на DUE реализовать, у DUE генератор тактовой частоты на 84 МГц, можно получить 0,01% ? На частоте 10-40кГц.

Или процессор посчитает а порт не позволит?

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

Mining, я по DUE не специалист :) Но если вам нужно больший диапазон и точность -то есть смысл сделать на специализированном чипе -синтезаторе частот типа ad9850 или аналогичных. У них гораздо лучшее разрешение, и гораздо больший диапазон частот. Практически серьёзная вещь за относительно небольшие деньги.

Mining
Offline
Зарегистрирован: 31.01.2016

dimax пишет:

Mining, я по DUE не специалист :) Но если вам нужно больший диапазон и точность -то есть смысл сделать на специализированном чипе -синтезаторе частот типа ad9850 или аналогичных. У них гораздо лучшее разрешение, и гораздо больший диапазон частот. Практически серьёзная вещь за относительно небольшие деньги.

dimax, я не хотел Ардуино обвешивать дополнительными блоками. Тем более мне частота нужна низкая от0 до 40кГц, а ad9850 до 40МГц. Ну и цена ad9850 как два Ардуино UNO.

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

Mining,  в принципе можно высчитать реальную возможность ардуино в регулировки скважности. Если вы хотите по 0,01% двигать, значит всего нужно 10000 градаций. Вычисляем максимальную частоту, на которой это возможно 16000000 /2 / 10000 = 800герц Аналогично можно прикинуть для DUE, если конечно к ней эти расчёты применимы: 84000000 /2 / 10000 = 4200 Герц Так что с вашими "скромными" запросами покупать синтезатор -единственный вариант.

 

Mining
Offline
Зарегистрирован: 31.01.2016

Спасибо!

Т.е. теоретически можно двигать скважность с точностью 0,1% до 42кГц?

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Уважаемый Mining, можно ли связаться с Вами?

Я ковыряюсь со схемой с переменным успехом. Не поделитесь ли своими наработками по теме?

Mining
Offline
Зарегистрирован: 31.01.2016

Anatolyekb пишет:

Уважаемый Mining, можно ли связаться с Вами?

Я ковыряюсь со схемой с переменным успехом. Не поделитесь ли своими наработками по теме?

Да какие там наработки, это хобби такое. Я взял sketch , который написал dimax вот здесь http://arduino.ru/forum/proekty/generator-s-reguliruemoei-chastotoi-na-a... и изучаю как модифицировать под мои хотелки.

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

Mining пишет:

Т.е. теоретически можно двигать скважность с точностью 0,1% до 42кГц?

В DUE не знаю, я в них не разбираюсь, просто предположил что там скорее всего такой же принцип. В некоторых  МК есть ещё PLL синтезатор, он умеет умножать тактовую частоту в несколько раз. Например в Леонардо есть такой, его таймер можно завести чуть ли ни на 96 (или 64, непомню) МГц. Но для глубокой регулировки скважности он не пойдёт, ибо там только один 10-битный таймер умеет пользоваться PLL клоками. Т.е. на нём можно получить 1024 градации  скважности, но будет всего 15 фиксированных частот, на которых возможна такая регулировка.

ali_vlad
Offline
Зарегистрирован: 20.02.2015

Народ, выручайте!

Нужен генератор импульсов от 350 герц до 4000 герц с шагом 100 герц. Длительность импульсов не должна зависеть от частоты и должна регулироваться отдельно в диапазоне от 1 милисекунды до 50 милисекунд с шагом 0.5 милисекунды. Очень надо!

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

ali_vlad, а какая по-вашему частота будет у импульса длиной 50ms ? :)

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Если у вас есть куча времени, а также неиссякаемое желание геморроиться с Ардуиной, синтезаторами, сдвиговыми чипами и всем прочим в отсутствие подробнейших консультаций со стороны "шаг за шагом" - пройдите по ссылке в первых сообщениях. Там вкратце разобрано как сделать чудо-машинку на Ардуине и дополнительных микросхемках. Ещё понадобится рублей 700-1500 на Ардуинку и доп. детали.

Если у Вас нет времени и тяга к неизведанному не бъёт во всех сферах жизни, то купите готовое решение за 3900 рублей. Я пытался собрать схему, как описывают господа на форуме, но ничего не вышло.

http://www.aliexpress.com/item/200MSa-s-25MHz-Dual-channel-Signal-Source-Generator-High-Precision-Arbitrary-Waveform-Frequency-Meter-Digital-DDS/32437000474.html?spm=2114.13010608.0.95.8kZCZv

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Для деревяного клепания можно взять это. Дешево и сердито. кхе очень сердито. кхе очень дешево.

void antidelayMicroseconds(unsigned long timing){
timing += micros();
while(micros()<=timing);
}
void setup() {
 pinMode(13, OUTPUT);
}
void loop() {
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  antidelayMicroseconds(1000000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  antidelayMicroseconds(1000000);  
}

 

Anatolyekb
Offline
Зарегистрирован: 06.11.2015

Да, Вы правы, это один из самых простых кодов. А как будет выглядеть меандр на осцилоскопе?

a5021
Offline
Зарегистрирован: 07.07.2013

Зловеще.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Anatolyekb пишет:

Да, Вы правы, это один из самых простых кодов. А как будет выглядеть меандр на осцилоскопе?

Дальше надо "пилить напильником".  Текущий вроде 1 секунда. Но надо мерить. Нужны новые параметры генератора , то делать нову прошивку. Наберете статистику, прикрутите управление и генератор с нужными параметрами готов.

ali_vlad
Offline
Зарегистрирован: 20.02.2015

dimax пишет:

ali_vlad, а какая по-вашему частота будет у импульса длиной 50ms ? :)

Тупанул я что-то

От 350 герц до 6000 герц с шагом 50 герц. Длинна импулься от 2 до 20 МИКРОсекунд с шагом 0.1 микросекунда.

Запуск по умолчанию с нижних границ, изменение энкодером.

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

ali_vlad, у меня был похожий шаблончик, подогнал  немножко под вашу задачу. Энкодер прикрутите самостоятельно :)

Терминал принимает два числа через пробел. Первое - (целое) число герц (от 123) , второе  (float) длительность импульса в микросекундах. Например "320 10.5"   шаг  регулировки длительности - 0.0625 микросекунд.

void setup() {
Serial.begin(9600);
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
OCR1A=0; ICR1=0;
}

void loop() {
if (Serial.available()) { 
 uint16_t x = Serial.parseInt();
 float y = Serial.parseFloat();
   ICR1= (F_CPU/x)-1; 
   OCR1A=  ((float) y / 0.0625 ) -1  ; 
   }
 }

 

ali_vlad
Offline
Зарегистрирован: 20.02.2015

Огромное спасибо, попробую. На Arduino Pro Micro (ATmega23U4), надеюсь, заработает. Энкодер и дисплей сам прикручу.

Н_Андрей_Ю
Н_Андрей_Ю аватар
Offline
Зарегистрирован: 22.12.2016

Привет!Я начинающий, я  испльзую написаный табою код. Подскажи пожалуста кокое максимальное значение может иметь antidelayMicroseconds(????????)

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014
rybakv
Offline
Зарегистрирован: 04.09.2017

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

для начала, идти майнить познания. 

AndreyTU
Offline
Зарегистрирован: 24.03.2018

Вот здесь оно, скетч №2, регулировка энкодером частоты и скважности. Проверял до частоты 32 кГц.

http://cyber-place.ru/showthread.php?t=2703

AndreyTU
Offline
Зарегистрирован: 24.03.2018

dimax, а как в этом примере: ali_vlad, у меня был похожий шаблончик, подогнал  немножко под вашу задачу. Энкодер прикрутите самостоятельно :)

сделать так, чтобы каждый 4 импульс был с другой скважностью?

 

01 void setup() {
02 Serial.begin(9600);
03 pinMode(9,OUTPUT);
04 TCCR1A=(1<<COM1A1)|(1<<WGM11);
05 TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
06 OCR1A=0; ICR1=0;
07 }
08  
09 void loop() {
10 if (Serial.available()) {
11  uint16_t x = Serial.parseInt();
12  float y = Serial.parseFloat();
13    ICR1= (F_CPU/x)-1;
14    OCR1A=  ((float) y / 0.0625 ) -1  ;
15    }
16  }

 

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

AndreyTU, настроить прерывание по совпадению с регистром сравнения, каждый вход в перывание считать. На 3-ем входе изменить регистр сравнения до нужной величины, на 4-ом вернуть обратно и обнулить счётчик входов.

AndreyTU
Offline
Зарегистрирован: 24.03.2018

Спасибо, понял.

us__007
Offline
Зарегистрирован: 26.09.2013

Всем добрый день.
Коллеги прошу помощи в решении задачи, суть ее такова нужно генерировать ШИМ на двух пинах с зависимой регулируемой скважностью и частотой, частота изменяется от от 20 до 200 Гц скважность как на картинке. суммарно заполнение обоих импульсов всегда 100%

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Т.к. не указан контроллер, а частоты достаточно низкие, могу предположить, что самый простой и универсальный метод - программный. Т.е. пресловутый blink, с delay[Microseconds]() или millis()/micros() по вкусу.

us__007
Offline
Зарегистрирован: 26.09.2013

пододет с millis()/micros(), забыл нарисовать DeadTime между импульсами по форнту и по спаду

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

что мешаеть сделать 1 ногу Шим  + простейший инвертор на ЛА3?

edcop
Offline
Зарегистрирован: 23.07.2016

А если, скажем, нужно период 10 с и скважность от 2% до 50%, которая будет функцией температуры в узком диапазоне. Сгодится ли предлагаемый выше вариант?

Есть готовая библиотека TimerOne, но там тоже оперируется микросекундами. А delay плохо дружит с DS18B20.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

edcop пишет:

А если, скажем, нужно период 10 с и скважность от 2% до 50%, которая будет функцией температуры в узком диапазоне. Сгодится ли предлагаемый выше вариант?

Ну так попробуйте и потом нам расскажете.

Цитата:

Есть готовая библиотека TimerOne, но там тоже оперируется микросекундами. А delay плохо дружит с DS18B20.

Вы бы предпочли, чтобы оперировали месяцами? Притом, только в целых числах?

Или Вы не знаете, как переводить микросекунды в секунды, минуты и часы?

edcop
Offline
Зарегистрирован: 23.07.2016

andriano пишет:

Вы бы предпочли, чтобы оперировали месяцами? Притом, только в целых числах?

Или Вы не знаете, как переводить микросекунды в секунды, минуты и часы?

Для этой библиотеки верхний предел 8,3 сек. А мне нужно минимум 10 сек период.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

edcop пишет:

andriano пишет:

Вы бы предпочли, чтобы оперировали месяцами? Притом, только в целых числах?

Или Вы не знаете, как переводить микросекунды в секунды, минуты и часы?

Для этой библиотеки верхний предел 8,3 сек. А мне нужно минимум 10 сек период.

И что? Вызывать раз в 5 сек и реагировать только на каждый второй вызов не судьба?

edcop
Offline
Зарегистрирован: 23.07.2016

andriano пишет:

И что? Вызывать раз в 5 сек и реагировать только на каждый второй вызов не судьба?

И при этом нужно управлять скважностью в зависимости от температуры. Пока не придумал как.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Возможность управления скважностью в зависимости от температуры как-то зависит от величины периода?

edcop
Offline
Зарегистрирован: 23.07.2016

Бился с разными готовыми библиотеками. Пытался в таймер вставить переменную, но к сожалению ничего не получилось. (((

Т.к. с таймерами и прерываниями я пока плохо дружу и на уровне регистров "нихт фершеен", может кто подскажет, как можно изящно решить эту задачу? Чтобы скважность менялась в зависимости от температуры.

b707
Offline
Зарегистрирован: 26.05.2017

edcop пишет:

Т.к. с таймерами и прерываниями я пока плохо дружу и на уровне регистров "нихт фершеен", может кто подскажет, как можно изящно решить эту задачу? Чтобы скважность менялась в зависимости от температуры.

если правильно понял, период ШИМ у вас 10 секунд? - то есть частота = 0.1 гц?

Для таких длинных периодов никакие таймеры и прерывания. имхо, не нужны, все достаточно легко сделать программно.

edcop
Offline
Зарегистрирован: 23.07.2016

b707 пишет:

если правильно понял, период ШИМ у вас 10 секунд? - то есть частота = 0.1 гц?

Для таких длинных периодов никакие таймеры и прерывания. имхо, не нужны, все достаточно легко сделать программно.

без delay? т.к. ds18b20 не дружит с delay. хоть примерно подскажите как