Генератор с регулируемоей частотой на ардуино.

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

Иногда при работе с мк бывает нужно подать сигнал определённой частоты, а специального устройства у меня нет, т.к. не сильно то оно нужно, да и ставить ещё один ящик негде. Вот написал скетчик генератора с регулируемой частотой, в большинстве случаев его достаточно. Что он может: -генерит меандр на 16 битном таймере. Диапазон частот 1Гц - 8МГц. Регулировка частоты производится энкодером. До частоты 2,8 кГц разрешение 1 герц, на частотах выше таймер аппаратно уже не может поддерживать это разрешение, поэтому более высокие частоты синтезируются задавая параметром  не требуемую частоту, а просто инкременируя регистр сравнения. Получается чем выше частота -тем больше шаг между щелчками энкодера. Вращая энкодер с ненажатой кнопкой частота меняется на 1Гц , с нажатой кнопкой один шаг -100Гц.  Выше 2,8кГц вращение энкодера с нажатой конпкой так-же ускоряет счёт. Програмного подавления дребезга контактов энкодера нет, поэтому нужно повесить конденсаторы 0,01..0,1 мкф относительно земли. На кнопке конденсатор не обязателен. Рассчитанная математически частота выводится в сериал.  Энкодер использовался самый популярный, для нестандартных возможно придётся корректировать обработчик.

01/* Генератор 1 Hz..8 MHz. Энкодер подключен к пинам A0 и A1, кнопка
02энкодера подключена к A2. Требуется использовать конденсаторы  0,01..0,1uf
03относительно земли на каждый из 2х выводов энкодера.
04Скетч для ардуино на мк atmega328 (UNO,Nano, MiniPro)
05*/
06 
07float freq;
08void setup() {
09pinMode (9,OUTPUT); // выход генератора
10pinMode(A0,INPUT); // с рассчетом, что  энкодере внешняя подтяжка-  
11pinMode(A1,INPUT); // -к шине питания. Если нету, то подтянуть программно.
12pinMode(A2,INPUT_PULLUP); //кнопка энкодера
13 
14Serial.begin(9600);
15PCICR=1<<PCIE1; //разрешить прерывание PCINT
16PCMSK1=(1<<PCINT9);// По сигналу на А1 создавать прерывание
17TCCR1A=1<<COM1A0; //подключить выход OC1A первого таймера
18TCCR1B=0;//
19}
20 
21 
22ISR (PCINT1_vect){
23static boolean gen_mode=0; //флаг режима управления
24static uint32_t enc=1; //переменная счёта энкодера
25uint32_t ocr=OCR1A;
26uint32_t divider=1; //переменная коэфф. деления прескалера
27 
28byte n=PINC&3; //считать значение энкодера
29boolean knopka = PINC&(1<<2); // 0-кнопка нажата, 1-кнопка НЕ нажата.
30if (freq<2848) gen_mode=0; //переключение режима управления по частоте
31if (freq>=2848) gen_mode=1; //переключение режима управления по OCR
32 
33// Если  увеличение частоты
34if (n==3||n==0){
35 if (gen_mode){if (knopka){ if(ocr>0) {ocr--; } } else if(ocr>9)ocr-=10; }   }
36 else knopka?  enc++ : enc+=100; // в нч режиме
37 } //end GetUP
38 
39// Если уменьшение частоты
40if (n==2||n==1){
41 if (gen_mode){ if (knopka){ if(ocr<65535) {ocr++; } } else if(ocr<=65525)ocr+=10; }   }
42 else {if (knopka) { if (enc>=2)enc--;  } else { if (enc>100) enc-=100; }  }
43 } //end GetDown
44 
45 
46if(gen_mode){ OCR1A=ocr;  freq= (float)F_CPU/2 / (OCR1A+1);  }
47else { //расчёт прескалера и OCR по нужной частоте
48divider=1; ocr = (F_CPU / enc /2 /divider) -1;
49if (ocr >65536) { divider=8; ocr = F_CPU / enc /2 /divider;
50    if (ocr >65536) { divider=64; ocr = F_CPU / enc /2 /divider;
51        if (ocr >65536)  {divider=256; ocr = F_CPU / enc /2 /divider;
52            if (ocr >65536) { divider=1024; ocr = F_CPU / enc /2 /divider;
53                if (ocr >65536){ocr=65536; }}}}} OCR1A=ocr-1;
54//запись в регистр прескалера           
55switch (divider) {
56  case 1: TCCR1B=1|(1<<WGM12); break;
57   case 8: TCCR1B=2|(1<<WGM12); break;
58    case 64: TCCR1B=3|(1<<WGM12); break;
59     case 256: TCCR1B=4|(1<<WGM12); break;
60      case 1024: TCCR1B=5|(1<<WGM12); break;  }
61 
62    freq= (float) F_CPU/2 / (OCR1A+1) /divider;
63  } //end if !gen_mode
64}
65 
66 
67void loop() {
68 
69   
70if (freq <10000) { Serial.print(freq,1);Serial.println(" Hz "); }
71if (freq >10000) { Serial.print(freq/1000,3);Serial.println(" kHz");}
72 
73 
74delay(100);
75}

 

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

Кстати заметил ошибку в стартовом сообщении. В 48 строке нужно убрать -1  в конце строки.

Kolchugin
Offline
Зарегистрирован: 15.12.2013

dimax. Проверил ваш проект в работе.  Смотрел меандр осциллографической приставкой, так же покрутил на частотомере.
Всё отлично! 

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

jeka_tm, вот, модифицировал основной код. Эта версия с регулировкой скважности. Частоту ограничивать в итоге не стал, скважность регулируется на всех частотах, просто начиная с какого-то значения регулируется всё бОльшими рывками. На мегагерце например всего 8 градаций.  Но энкодер всё равно везде счёлкает 100 градаций (в процентах).Некоторое неудобство, но избавится от него малыми силами не выйдет. Хочешь, сам повозись, можно по идее ввести разрядность регулировки скважности в зависимости от частоты.

 

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

Сделал генератор-шилд для UNO, как и задумывал ранее. За основу взята версия с регулировкой скважности, но вместо второго энкодера добавил кнопку, которая переключает  энкодер в режим частоты или скважности.  Фотки и видео:

И видео с демонстрацией режимов (быстрая регулировка частоты, по-герцевая регулировка, регулировка скважности) https://cloud.mail.ru/public/CaFy/QxWcRpwSy

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а можеim скинуть код как в 18 посте но кнопкой плюс энкодер как на видео?

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

jeka_tm, да, конечно. 

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

спасибо. только под 1202 переделаю. кнопка без фиксации?

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

получается почти как у тебя

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

Внёс рацпредложение от Максима в последний код, заодно исправил мелкий баг обратного перехода через частоту 2848. Если уменьшать по-герцу то на частоте 2847 перебрасывалось сразу на 2900, и так по кругу.  Проскочить можно было только щёлкнув в обратную сторону 100 герц.  Последняя версия..

 

Iwan73
Offline
Зарегистрирован: 02.11.2013

jeka_tm печаткой шилда не поделитесь народу ? 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

пожалуйста

https://yadi.sk/d/mYeiZu4jm8cRv

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

Генератор версия 2.0

Позаимствована функция на ассемблере с алгоритмом DDS (отсюда),
с ней добавилось возможность генерить табличные формы сигналов
синуса, треугольника, пилы, можно добавить массив с другой формой сигнала,
свободного места во флэше полно. В качестве АЦП используется традиционная схема R2R. Под АЦП задействован весь порт D (выводы ардуино 0...7). Выход АЦП соединён с выходом таймера, в скетче порты соответствующим образом коммутируются. Точнось резисторов принципиальной роли не играет, 5% вполне достаточно. В идеале нужно ещё
добавить какой нибудь усилитель на скоростном  ОУ  (типа OP37), сделать смещение и регулировку амплитуды. Меня пока устраивает и без всего этого :)

Скетч:

Тех. Характеристики генерации таймером:
Генерация прямоугольного сигнала  0..4 Мгц ,
 минимальный шаг регулировки частоты в диапазоне 0...2,8кГц - 1Гц
 свыше 2,8кГц минимальный шаг постепенно возрастает.
Регулировка коэффициента заполнения (скважности) 1..100%
в диапазоне 1Гц..80кГц регулировка производится с разрешением 1%
Свыше 80кГц разрешение (шаг) регулировки скважности увеличивается.
При изменении рабочей частоты в диапазоне 1Гц-80кГц выбранная скважность сохраняется,
а при изменении частоты свыше 80кГц  сбрасывается на 50 %,
но в режиме регулировки скважности её можно снова изменять.
 

Тех. Характеристики генерации сигнала через DDS:
Почему-то в оригинальной статье автора алгоритма DDS о характеристиках нет ни слова.
Указана только максимальная частота -65кГц. Откуда её взял автор непонятно, я поставил ограничение на 100кГц C увеличением частоты сильно падает разрешение получаемого сигнала на высоких частотах. А конкретно, в диапазонах:
0...6,25 кГц - разрядность от 256 до 128 градаций
6,25...12,5 кГц - разрядность от 128 до 64 градаций
12,5...25кГц -разрядность от 64 до 32 градаций
25кГц...50кГц -разрядность от 32 до 16 градаций
50кГц...100кГц -разрядность от 16 до 8 градаций
Помимо этого с увеличением частоты вырастает джиттер,
особенно заметно на сигналах с резкими фронтами (прямоугольник, пила).
Но на точно установленных частотах 6,25кГц ; 12,5кГц ; 25кГц; 50кГц; 100 кГц джиттера нет, их можно использовать для точных измерений. Остальные частоты для большинства применений тоже подойдут.
Но если нужен идеальный сигнал -то только генерация таймером.
Во всех диапазонах DDS минимальный шаг регулировки частоты - 1Гц.

Для сравнения синус 20кГц и синус 100кГц:

Управление: кнопка переключения режимов переключает последовательно
(0)синус DDS, (1)треугольник DDS, (2)прямоугольник DDS, (3)правая пила DDS,
(4) левая пила DDS. (5) частота генерации таймером (6) скважность генерации таймером

Кнопка на энкодере переключает шаг изменения частоты 1000-1-10-100
в режиме регулировки скважности(6) нажатие на кнопку переключает энкодер в режим (5).

Особенности:
(1) Функция на ассемблере использует не стандартный способ чтения массива, записанного через PROGMEM Для этого способа требуется что бы расположение всех таблиц-массивов было кратно адресу 0x100 В ардуино нет штатных средств что бы положить конкретный массив по конкретному адресу во флэш область, поэтому пришлось обойти этот недостаток не очень красивым способом.  Я создал специальный массив musor_mass, который занимает всё свободное место вплоть до адреса 0x100, а после него массивы с таблицами сами попадают точно на нужные адреса. Что бы компилятор не выбросил этот массив пришлось его как-то задействовать ( в строке 147 сетапа). При изменении в коде или при использовании версии ардуино отличной от 1.6.8 возможно потребуется изменение размера мусорного массива таким образом, что бы первый байт табличных массивов сел точно на адрес 0x100. Возможно в какой-то версии компилятора musor_mass нужно будет расположить в скетче не последним, а первым. После нажатия кнопки "проверить" лучше сразу заглянуть в скомпилившийся hex файл. Пример правильного расположения массивов на картинке.

(2) В функции на ассемблере использован свободный 7й бит регистра PORTB, нога физически отключена и задействавана под кварц, так что бит можно использовать в своих целях в качестве булевой переменной. А у автора оригинального DDS генератора в  аналогичных нетрадиционных целях задействован бит регистра SPCR (конфигурационный регистр SPI)

В данном скетче вывод информации происходит через Serial, в функции monitor_out() можно настроить вывод на свой дисплей, на плате ардуино ещё свободны 7 выводов (11,12,13,A2-A5).
 

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

Версия под дисплей NOKIA 5110

 

Дисплей подключен на пины A2-A5.  Других отличий от сериальной нет. Библа для дисплея LCD5510  от  ринки-динка, но подпатченная нашим форумчанином  ssvs111 что б дисплей работал на 4 пинах, ссылка на пропатченую версию была тут Скетч:

 

Лекс 59
Лекс 59 аватар
Offline
Зарегистрирован: 02.04.2016

Ну пока без энкодера. Проба пера. ЦАП и выходные цепи использую с ранее сделаного генератора с Паяльника, который меня не устроил.

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

Ну и для полной коллекции -последняя версия с более удобной распиновкой дисплея и кнопок для печатной платы. Так же вроде подправил все мелкие недочёты.

Из существенный отличий -использовал 8 ногу для включения/отключения подсветки. Либо можно что-то ещё включать, например сделать управляемое смещение, или переключать выход релюшкой , или ещё что - пригодится в любом случае. Включается комбинацией- нажать кнопку энкодера, + удерживая её нажать кнопку режима. Затем отпустить кнопку энкодера, и последней отпустить кнопку режима. Скетч:

Как и первый вариант генератора сделал в виде шилда для UNO.

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

dimax, спасибо, замечательное устройство.

Предполагаемую схему на ОУ для смещения нуля попробовал, но убедился, что LM358 для этих целей не подходит. Заказал LM833, а пока собрал схему в пректически неизменном варианте:

ftor
Offline
Зарегистрирован: 27.06.2016

dimax, спасибо

Кстати, не получаеться исправить в новой версии кода сам енкодер. Пробовал вставить исправления не получилось считает по два.

Етот генератор можно использовать как медицынский прибор при частоте 10Кгц и Синусе после усиления до 60В получиться аналог русского миостимулятора Мион-1

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

ftor, фикс  двойного щелчка энкодера

1void up_down(boolean x){ // управление регулировками
2static boolean n=0;  if (n=!n){return;} //далее без изменений

 

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

Дело было вечером, делать было нечего.. А сделать что-то хотелось. Решил добавить в поделку пару полезных функций:

Генератор V2.4, в код  добавлены частотометр и вольтметр.

Частотометр -измеряет  методом тактирования первого таймера от источника сигнала. Измеряемый диапазон: 1Гц ... 7,999 МГц*
* при превышении верхнего диапазона частотометр будет выдавать неправильные показания. Точность измерений зависит от точности установленного на плате кварцевого резонатора.
Вход подключать к пину D5, в идеале отключая от этой ноги резистор из схемы ЦАП. Но можно и не отключать, -работает и так.

Вольтметр - Измеряет постоянное напряжение на шине Vcc и на пинах A4, A5. Используется оверсемплинг до псевдо 14 бит разрешения. , Вольтметр самокалибруется по встроенному в М.К. И.О.Н. на 1,1 вольта.
Измеряемое напряжение от 0в до напряжения питания М.К. (Vcc), отображаемое разрешение -1мв.


При загрузке можно кнопками выбрать что запускать, вольтметр или частотометр. Генератор запустится через 5 секунд по умолчанию, если выбор не сделан. Выхода из выбранных режимов не предусмотрено, только перезапуск по питанию или ресетом.

Обновлённая схема:

Скетч:

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

кстати правильно что свою. я резисторы цапа слишком близко друг другу расположил, неудобно было паять. у меня на 70% спаянная

+ не тестировал, просто включил. вроде работает, экран показывает, режимы переключаются

man_200
Offline
Зарегистрирован: 29.04.2016

treur
Offline
Зарегистрирован: 18.10.2015

Доброго времени суток dimax,

воспользовался кодом из поста #6 и появилось 2 вопроса:

1. Даю генератору частоту 0Hz, результат - если сразу после запуска, то не генерит, если до этого была дана частота, генерит предыдущую заданную. Как заставить остановиться по 0?

2. Есть ли какая возможность перевесить выход с D9 на D3?

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

"Терминальная" версия генератора. Запустить терминалку, послать требуемую частоту в герцах. В ответ напишется та частота, которую смог сделать МК.

01void setup() {
02Serial.begin(9600);
03pinMode (9,OUTPUT); // выход генератора
04TCCR1A=0;TCCR1B=0;
05}
06void loop() {
07static uint32_t reqfreq=0; //переменная запроса частоты
08uint32_t ocr=OCR1A;  uint16_t divider=1;  float freq;
09if (Serial.available() > 0){ reqfreq = Serial.parseInt();
10if (reqfreq==0 || reqfreq>F_CPU/2) {return;}
11 ocr = (F_CPU / reqfreq /2 /divider);
12  byte shifts[] = {3,3,2,2};
13   for(byte i = 0; i < 4; i++){
14     if (ocr > 65536) { divider <<= shifts[i];
15       ocr = F_CPU / reqfreq /2 /divider; }
16      else { TCCR1B = (i+1)|(1<<WGM12);  break; }  } //Mode4 (CTC)
17     OCR1A=ocr-1; TCCR1A=1<<COM1A0;
18    freq= (float) F_CPU/2 / (OCR1A+1) /divider;
19  if (freq <10000) { Serial.print(freq,1);Serial.println(" Hz "); }
20 if (freq >=10000) { Serial.print(freq/1000,3);Serial.println(" kHz");}
21 }
22}

 

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

Сделал новую версию генератора полностью на новом железе. (Все картинки кликабельны).

На написание ушёл месяц -учитывая что было освоение доселе неизвестного МК, а программа вышла под 400 строк - то наверное это не долго :) В качестве контроллера использована плата на МК STM32F103C8T6, в качестве среды программирования всё тот-же Arduino IDE, но с установленным аддоном для stm32. О плате, и о том как поставить аддон и зашить в неё USB-бутлоадер красочно рассказал наш коллега HWMan, так что освещать этот вопрос не буду. Так же использовал современный TFT дисплей на контроллере st7735, что-б устройство было посимпатичнее. Строка для поиска дисплея на Али 1.8" inch TFT LCD Display module ST7735S 128x160 От кнопки для переключения режимов отказался. Теперь всё делает энкодер. Из-за особенностей обработчика нужно что-бы энкодер выдавал на один щелчок один или два полных импульса. Классический энкодер ардуинщиков ky-040 выдаёт половинку импульса, поэтому крайне не рекомендуется. Он работать будет, но срабатывать станет через щелчок. Строка для поиска на Али: "Rotary encoder EC11"

 

                                        Тех. характеристики:

Генерация прямоугольного сигнала от 1Гц до 36МГц.  От 1Гц  д   8кГц  возможен шаг изменения  1Герц, далее мин.шаг увеличивается в соответствии с делением тактовой частоты (72МГц) на целочисленные делители. Для понимания масштаба: на 20кГц шаг уже 6 Герц, на 50 кГц -35гц, на 100кГц - 140Гц на 500кГц - шаг уже 3,5кГц. на 1МГц -шаг 14кГц. Последние частоты в шкале возможных, на которых будет работать генератор такие: 8Мгц, 9МГц, 10.286МГц,12МГц, 14.4МГц, 18МГц, 24МГц, 36МГц Регулировка шага изменения частоты. 1-10-100-1000 Герц В pwm-режиме на частотах свыше 8кГц шаг уже не означает чёткую привязку к Герцам, т.к. шаг тут перепривязан к делителю таймера. Регулировка заполнения( далее duty) в процентах. До частоты 720кГц с шагом 1%. При изменении частоты выбранный duty сохраняется. Выше 720кГц шаг начинает возрастать, но вращение энкодера по прежнему меняет по 1% , т.е. возникает пустой ход. Этот момент я не исправлял в связи с ненадобностью такой регулировки на высоких частотах. duty при регулировке частоты свыше 720кГц сбрасыватся на 50%, но в режиме регулировки duty его снова можно изменить. В режиме DDS возможен выбор следующих форм сигналов: синус, треугольник, пила двух видов, меандр. В этом режиме шаг чётко соответсвует фактическому шагу в герцах. Частота условно ограничена на 200кГц. Ограничение можно изменить в 259 строке. До 100кГц сигнал вполне приличный, без существенных изломов. О фактической разрядности DDS уточнение будет ниже. На осцилограмме синус 150кГц

Частотометр. Измеряемый диапазон от 1Герца до 32МГц. Менее одного герца -покажет 0. Более 33МГц начнёт врать. Относительная точность измерения на частотах до 1кГц -примерно 0,1Гц Выше 1кГц -1 Герц. Вольтметр как в версии 2.4 не стал делать за не надобностью. Да и встроенного опорника в этом МК нету. Но свободный аналоговый вход если что остался (PB1). Теоретически возможно дописать в устройство и функцию осциллографа, - благо и флеша и памяти ещё очень много. Но мне он не нужен, а в образовательных целях ломливо.. так что функционально проект развиваться дальше не будет :(

                                    Интерфейсы.

Устройство имеет: вход частотометра. Ввиду отсутствия каких-либо входных цепей подразумевается подача TTL уровней (размахом 3..5 вольт). Два комплементарных выхода таймера (A8 и A7). И выход DDS. Один из комплементарных выходов таймера (А7) физически сидит на старшем бите порта АЦП, поэтому в PWM Mode можно снимать сигнал таймера как с пина A7, так и с выхода R2R АЦП, но стоит учитывать, что фронты на высоких частотах будут сильно сглаживаться. Поэтому для работы с В.Ч. предпочтительней использовать отдельный выход с пина. Выход PWM2 по умолчанию негатив, его можно изменить на позитив в первом дефайне программы. Комплементарные выходы можно сделать с настраиваемым dead-таймом, но за отсутствием надобности и в связи с тем, что это не увязывается с регулировкой заполнения, я в программе не использовал такую возможность. Но пример использования оставил в закомментированной строчке 293. В ней максимальный дидтайм, и выглядит это вот так:

На дисплее отображается название режима, частота. В режимах PWMMode, Duty, Freq.meter так же отображатся условная осциллограмма , тайминги, и процент заполнения. В DDS режимах отображается статическая картинка режима. Так же добавлен электромагнитный излучатель (без встроенного генератора!) для "озвучивания" энкодера. Каждое переключение (частота/режим/ шаг) сопровождается звуковым сигналом соответствующей тональности. С озвучкой работа с генератором стала удобнее. Уровни выходных сигналов: С выходов PWM -стандартный TTL 3.3v . С выхода DDS 1,2v амплитудное (0,9v rms) -это конечно маловато, но я не вспомнил случаев когда мне требовалось напряжение более 1 вольта. А вот менее вольта -часто требовалось, поэтому установил ещё подстроечный резистор на всякий случай. Если его не ставить, то напряжение будет выше. В идеале конечно стоит установить ОУ на выход DDS что б усилить сигнал по напряжению и по току. Мне было лень..) Монтаж: когда развёл в спринте половину платы то понял, что кол-во перемычек уже превышает здравый смысл. Нужно было перерисовывать на 2х сторонний вариант. Это показалось долгим и нудным, поэтому сделал просто на макетке, и все соединения МГТФом. На разведённой печатке только матрица R2R.

                           Управление:

Вращение ручки энкодера меняет частоту с установленным шагом. Если вращать с нажатой ручкой то будет меняться режим работы Если просто нажать и отпустить ручку - меняется шаг. Если в режиме Duty нажать и отпустить -перейдёт обратно в режим PWM Mode

                              Схема:

Что бы не делать кучу разъёмов можно использовать реле, которое будет коммутировать выходы на разъём в зависимости от текущего режима.  

                             Программа:

pwm генератор работает на тех-же принципах что и в предыдущей версии, изменения коснулись сущих мелочей. DDS генератор благодаря 32-битному МК упростился, теперь вставка на ассемблере не нужна. Алгоритм написан буквально в одной строчке на Си. Синус и прочие формы рассчитываются перед запуском режима автоматически и записываются в буфер на 512 байт. Скорость отправки на R2R АЦП примерно 3M Samples/sec Что в два раза больше, чем было на меге328. Соответссно полная таблица wave-формы может считываться до частоты ~6кГц На более высоких частотах алгоритм начинает пропуски элементов таблицы. Нетрудно подсчитать число фактических градаций сигнала: нужно 3М разделить на частоту сигнала. Частотометр изменяет частоту в два захода. В первом измеряется количество тактов входящего сигнала за 1 секунду - в этом режиме трудятся в симбиозе аж три таймера. Первый даёт разрешение на счёт в течении 1 секунды второму таймеру. Второй досчитав до 65535 даёт такт третьему таймеру, а сам продолжает с ноля. Всё без использования прерываний. Таким образом суммарное разрешение таймеров в этом режиме 32 бита. Если измеренная частота оказалась ниже 1МГц, то вторым этапом измеряется длина единицы и ноля, вычисляется duty. Я не придавал особого значения точности, второй режим как дополнительный для украшения дисплея псевдо-осциллограмкой, которая отображает только соотношения распознанных 0 и 1 , но не форму сигнала. Но частоты менее 1кГц он измеряет точнее чем первый проход. Поэтому как конечный результат измерения в этом случае выводится результат второго захода. Программа написана с использованием возможностей Maple Library Это библиотека поддержки перефирии STM32 от компании Лифлабс, производителя ардуино-образных плат на мк STM, которая уже входит в состав аддонa для Arduino IDE. Для дисплея используется две библиотеки. Одна (Adafruit_GFX) уже есть в составе аддона. Вторую нужно поставить дополнительно, брать тут.

Убедительная просьба не использовать кнопку "Цитировать" под этим постом, т.к. у меня пропадёт возможность редактировать ошибки, да и просто засирать тему повторной информацией не стоит.

240265
240265 аватар
Offline
Зарегистрирован: 12.08.2015

V3_128

Переделал под 128х128 экран (st7735  ) , цвета синий с красным попутаны. Но оно и не мешает.

DIMAX СПАСИБО !

240265
240265 аватар
Offline
Зарегистрирован: 12.08.2015

Т.К. энкодер у меня не тот , прилепил кнопки.

Дребезг убрал аппаратно.

Тед
Offline
Зарегистрирован: 06.11.2017
Здравствуйте
Терминальная" версия генератора. Запустить терминалку, послать требуемую частоту в герцах. В ответ напишется та частота, которую смог сделать МК.
Есть ли у вас такая программа для стм32f103 ?
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Тед, в начале изучения  stm32 делал что-то похожее, проверять в лом:

терминал принимает два числа через пробел. Частоту и дьюти в процентах. Если дьюти не задать, то он по умолчанию 50%

vismajor
Offline
Зарегистрирован: 16.12.2017

Спасибо автору за проделанную работу и великолепно поданный материал!

Развел в Sprint Layout 6.0 для односторонки. Первый опыт для данной программы... но если кому полезно могу сбросить... не понял пока как прикрепить к сообщению.

Для "OLED I2C"  - Необходимо заменить библиотеку и инициализацию, а также добавить update в конце отрабатки процедуры вывода.

На повторение, версии - 2.3, ушло 5 часов.

 

Ihor
Offline
Зарегистрирован: 10.11.2017

Вот так выглядит первое включение осциллографа с генератором V2.4. До 25 кГц работает. Хорошая игрушка.

Конечно можно смотреть и более высокие частоты, но с 25 кГц завал частотной характеристики. Экран неплохой. Применения не вижу. К приборам это отношения не имеет. Я планирую использовать как макет. Поиграться с выводом на экран, попробовать АЦП .

svm
Offline
Зарегистрирован: 06.11.2016

Информация на всякий пожарный:

Загрузил скетч на чистую 328 . Чтобы запустить приходится неско раз жать ресет. Заменил дисплей все Ок!

С другими библиотеками дисплей работает без проблем. 

svm
Offline
Зарегистрирован: 06.11.2016

Решил тоже собратьгенератор, но не заморачиваться с печаткой. Взял голую 328, приложил к плате дисплея, исходя из наиболее выгодного расположения подкорректировал скетч и дальше вспомнил радиолюбительскую молодость и начал лепиь навесухой. В принципе на все ушло около четырех часов. Работает неплохо. Правда пила немного не идеальна, но я еще немного грешу на матрицу резисторов. В наличии были только 1,2  и  2,2 кОм. На них и собрал. Конструкция получилась достаточно компактная и жесткая. Максимальная высота монтажа не превышает толщину энкодера. Осталось корпус, но это уже не сегодня. 

Вид спереди и сзади.

 

Осциллограма

apeks1
apeks1 аватар
Offline
Зарегистрирован: 19.05.2016

есть у кого осцилограммы с данного генератора 1МГц-4МГц

нужна визуальная привязка для настройки входного уся цыфрового осцилографа

зараннее благодарен!

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

apeks1, да не жалко, вот вам 4МГц, с моего генератора версии 2.3.

Focus
Offline
Зарегистрирован: 05.04.2015

dimax пишет:

ADMUX = (1<<REFS0)|(1<<MUX2)|(1<<MUX1); //ADC6 measure

ADMUX = (1<<REFS0)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0); //ADC7 measure

Спасибо! Вроде всё работает.

Версия 2.4 под экранчик ssd1306 128х32 I2C, вдруг кому надо :) На A4 и A5 вешается экран, A6 и A7 входы вольтометра. Библиотеку ставил через стандартный менеджер библиотек ардуино IDE, на всякий случай в коде указал ссылку на гитхаб либы. Думаю экранчик ssd1306 128х64 I2C тоже заведётся, нужно будет только поменять координаты строк ну и увеличить шрифт где нужно. А, ещё тут указать что 64 пиксела высота: ssd1306_128x64_i2c_init();

 

АндрейS
Offline
Зарегистрирован: 13.04.2018

Цитата:

Очевидно, что вместо 2E5 какое-то другое число :)


Мне было не очевидно :) Я делал перистальтический насос на ардуине там было ограничение на кол-во оборотов простой цифрой, вот там мне было очевидно, а тут мой проц завис :)  Оказалось что 2E5 это число)))) Погуглил, хоть и не понял что это за числа, методом научного тыка написал то что мне надо. Спасибо за помощь.

Генератор на ардуине собирал на макетной плате проводами 1,5 дня, замучился. Решил что надо осваивать изготовление печатных плат. Выбрал KiCad, на осваивание программы и создание платы ушло 3 дня. Травил час, собирал около 3. Вот что получилось:

Не без косяков конечно :) Считал считал, но почему то у энкодера посадочные места по длине растянулись, но он все равно встал, не сделал переходные отверстия для питания экрана и энкодера, решил просто, припаял кусок провода. Не стал лудить, думал покрою лаком, но пока паял все заляпал. Придется теперь лудить. Ну вот вроде бы все.

Файлы KiCad https://yadi.sk/d/9IRSuFxi3X578E посадочные места под энкодер поправил, а вот с переходным отверстия так и не разобрался, наверно надо посадочные отверстия поставить, и не нашел у себя пищалку, соответственно ее не мерил и посадочные места под не из библиотеки.
dimax, еще раз спасибо за проект и поддержку :)

step64
Offline
Зарегистрирован: 01.04.2013

Респект автору за генератор, работает стабильно, правда частоту врёт на доли Герца, но это уж придирки)) Не могу понять чем отличается PWM и Duty режимы, в обои регулируется и частота и длительность, зачем их дублировать было?) Кстати у stm32f103  очень крутые фронты выходных сигналов, около 5 нс.

Focus
Offline
Зарегистрирован: 05.04.2015

Добрый вечер! Сделал платку под голую Atmega328 TQFP32 по схеме v2.4, спаял, плата как бы запускается, шим норм идёт, а вот синус получил такой:

 

Проверил схему на 2 раза, вроде всё верно, помыл от канифоли - не помогает. сейчас заметил, что в версии 2.0 нижний резистор в делителе, который идёт на массу, номиналом 1к, а в версиях 2.3, 2.4 номинал 2к, не думаю что это так сильно бы изуродовало синус, но может я просто не знаю физику процесса? Голую атмегу первый раз шил (до этого только тиньки), фьюзы никакие не выставлял, просто загрузчик сперва записал, потом скеч (говорят загрузчик ставить фьюзы как надо) шил USBASP через Arduino IDE. 

Может картинка кому то подскажет чего я накосячил? :)

Плата в формате Sprint Layout 5: https://yadi.sk/d/K0Lq2Inu3YVVkQ

Фотовид (картинка кликабельна): 

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

Focus,  Похоже на сдвиг массива, почитайте внимательнее параграф "Особенности" в описании версии 2.0

Focus
Offline
Зарегистрирован: 05.04.2015

Поперемещал архив туда-сюда,даже адрес начала у него всегда больше сотни, потом добавил в него нулей х2, синус почти стал походить на синус. Убрал по чуть чуть пару строк нулей - теперь синус как синус. Но адрес помоему получился не кратный 100... Массив пила2 начинается со 100500

Все остальные формы так же пришли в форму :) . 

А резистор нижний в делителе всётаки 2к должен быть? или 1к?

 

Rashen
Offline
Зарегистрирован: 24.08.2018

Повторил конструкцию.

2 выход через полевой транзистор дл управления нагрузкой

https://mega.nz/#!zR9T3Rib!G8u6PgksZBSvkkWdyijTcffjNB3y4wmQEGyeMM3EKgs

Спасибо.

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

Версия 2.5 написана под микроконтроллер LGT8F328P, который обозревался недавно тут.   Функционально представляет из себя немного окультуренную версию 2.4.  Так-же может потребовать подгонки массивов (подробно описано в 2.0) Отличия от 2.4 :  убрана дополнительная кнопка, всё управление производится одним энкодером. Вращение энкодера не нажимая его кнопки -меняет частоту. Вращение энкодера с нажатой кнопкой -меняет режимы. Однократное нажатие/отпускание кнопки меняет шаг. Вольтметр и частотометр перенесены в общее меню. Частотометр нормально измеряет примерно до 12МГц (при тактовой МК 32МГц). Вольтметр улучшен, умеет автоматически выбирать нужный референс. (1,024/2,048/4,096 или Vcc)  Адаптирована под этот МК функция DDS-синтеза (линк на автора метода). Скорострельность DDS синтеза достигла очень высокого значения -4MS/sec, (в версии 2.4 -1,6MS/Sec)  это даже существенно быстрее чем в версии 3.0 на stm32 (2,6MS/Sec) Однако же вкусить плоды такой скорости не представляется возможным, т.к. ЦАП на этом МК сделали с высокоомным выходом, поэтому на высоких частотах он начинает образовывать фильтр, который заметно ухудшает характеристики. Это надо смотреть визуально, что бы понять.  На осциллограмме слева -синус на 100кГц с этого ЦАПа сильно перекошён , но не изломанный как был на версии 2.0 (осцилограмма справа).

В связи с этим желательно поставить на выход ЦАПа опер. усилитель, что б ещё сильнее не ухудшить сигнал при подключении нагрузки.  Уровень сигнала с ЦАП можно сделать фиксированным с референсом от одного из внутренних опорных напряжений, либо регулируемым, для этого на вход AREF нужно подать напряжение от 0 до Vcc например с переменного резистора.

Схема:

Скетч:

 

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

Генератор V3.1 (для МК STM32F103C8T6)
-добавил в программу поддержку тактовой частоты 128МГц, которая появилась в последних аддонах.


-программный DDS синтезатор переписал на ассемблере, скорость работы в сравнении с версией 3.0 выросла примерно в 2 раза, и стала 5 и 9 MSamples/Sec соответственно для тактовых 72 и 128 МГц. Это существенно расширило качественный диапазон. Теперь синус 500кГц вполне прилично выглядит. Пила на той же частоте правда уже не очень.


-добавил поддержку чипа- тактового синтезатора Si5351. С ним возможно устанавливать частоты с любым шагом от 4кГц до 225МГц. Из 3х выходов на si5351 использовал только один, с двух других можно вывести например фиксированные частоты. Пример есть в скетче.
-подключил все 3  выхода и вход через мультиплексор ADG704. (удобно, что-бы всё вывести на один разъём)

Все аппаратные доработки уместились в прежнем корпусе. Модуль si5351 припаял вторым этажом над R2R, а мультиплексор втиснулся рядом с разъёмом.

Схема: Минимальный набор для сборки по прежнему -плата с МК, дисплей и энкодер. Микросхемы мультиплексора и тактового синтезатора ставить не обязательно, синтезатор даже не отобразится в меню, если при старте программа не обнаружила его подключенным. В схеме есть небольшое отличие от версии 3.0  Нужно было освободить пин B8 для шины I2C, и кнопку энкодера я перекинул на PB1 В остальном  распиновка совместима с 3.0

Библиотека для si5351  примечание:  в этой библиотеке в файлике si5351.cpp нужно найти строчку Wire.requestFrom(i2c_bus_addr, (uint8_t)1, (uint8_t)false); и удалить выделенный операнд. Это нужно для совместимости с библиотекой wire.h.  Библиотека для дисплея st7735.   Библиотека Adafruit_GFX,  и на всякий случай готовая прошивка.

Скетч:

 

 

miklin
miklin аватар
Offline
Зарегистрирован: 08.06.2018

 Доделал свой DDS v3.0, зделал корпус.

 Автору большая благодарность.

Правда есть проблемы,для контроля выходного сигнала,проходится использовать осцилограф.

Линейных перемеников для печатных плат ненашол,применил что было а они нелинейны.

Нужно переделывать шкалы резисторов.

 

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

Генератор v3.2

-изменён вывод на дисплей, каждые три знака в значении частоты разделяются пробелом.

-добавлен шаг 0,1 Гц для частот до 1кГц. Минимальная частота тоже стала 0,1 Герц

-устранены мелкие недочёты в частотометре.

 Схема как в версии 3.1 , без изменений.

Готовая прошивка

Скетч:

 

PS обновлено 12.01.2019  в связи с тем, что у многих проблемы правильно вставить библиотеки, выкладываю полный архив моей arduino IDE со всеми библиотеками и с самим скетчем в примерах. Останется только запустить Arduino.exe и выбрать в примерах скетч.  Архив в зипе.   Размер архива 430МБ.

 

 

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Получил сегодня Si5351 и решил замерить точность установки частоты. На частоте 36 МГц в режиме PWM отклонение около 800 Гц, а у Si5351 - немного более 3 кГц, а на 145 МГц - более 10 кГц. Мерил трансивером по нулевым биениям, предварительно проверив его по сигналам эталонных частот.

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

MAG-N, да похоже на правду. По крайней мере по части таймера МК, у меня тоже примерно такие цифры. Можно попробывать прописать свой дефайн F_CPU что б подогнать под истину, но этот вариант я не тестировал.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

800 Гц на такой частоте - вполне нормально, а вот в разы большая погрешность у специально заточенной  микросхемы - это не есть хорошо. Возможно, резонатор на платке "кривоватый", всё же китайская поделка.

#define F_CPU попробовал, но при этом изменяется частота на экране.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Поигрался с Si5351. Подцепил к Ардуино Нано и стал гонять примеры из библиотеки Si5351Arduino-master. Пример si5351_calibration натолкнул на некоторые мысли, в результате чего скетч генератора дополнился строкой (после стр. 45)

si5351.set_correction(80000, SI5351_PLL_INPUT_XO);

Ошибка убралась почти на "0", надо точнее подобрать величину коррекции. В примере всё это делается достаточно наглядно через монитор порта, потом только результат подставить. Всё это индивидуально для каждой платы,  так что кому надо - может сделать.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Кстати, применённая микросхема позволяет задействовать для стабилизации частоты технологию GPSDO и, в частности одно из предложенных радиолюбителями решений выполнено Кареном Тадевосяном RA3APW )))

 

На диапазоне 10м в режиме GPSDO среднеквадратическое отклонение несущей частоты составляет примерно 7 миллиГц, а пиковое значение примерно 90 миллиГц.

Дима, что ты там говорил о любительских конструкциях )))
 

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

По-моему, для данного генератора это уже перебор, тем более что надо тащить кабель от подоконника до стола с генератором для антенны GPS. Врядли внутри помещения Глонасс-ГПС будет работать.