Вот в очередной раз столкнулся с проблемой отсутствия генератора сигнала прямоугольной формы. Что делать, бежать в магазин и выкладывать круглую сумму денег, или заказать с Китая подешевле, но ждать доставку, да и денег свободных не очень много.
Я стал изучать эту тему, как построить свой генератор сигнала, да так что бы было практично и удобно. Смотрел статьи в сети, пробовал собирать на коленке, но все не то, то частоты больше хотелось, то качество сигнала оставляет желать лучшего.
Попробовал наверное схем 7-8 пока не наткнулся на нестандартное решение на arduino, хочу подчеркнуть нестандартное, интересные там технические тонкости были. Вот решил собрать, получилось и получилось достойно. Но как говорится много текста, ближе к делу.
Зашел в магазин взял корпус пластиковый, рассыпухи всякой, arduino nano была под рукой, она и спасла ситуацию. Пару вечеров за паяльником неспеша и вот девайс, Частотный генератор v.1.3.
Что получилось, получился генератор прямоугольного сигнала с частотой от 1Гц до 8Мгц. Да да до 8 МГц. Обычно такую частоту на arduin-ке мало кто получает.
Девайс состоит из органов управления представленных 4 кнопками без фиксации, переменным резистором с включением, экраном отображения информации и выходом в виде двух зажимов. Напряжение на выходе до 5 В.
Поворачиваем резистор, слышим щелчок и он включился.
Отображается версия прошивки генератора. Скажу следующее, что это только база, которую в дальнейшем буду совершенствовать, добавлять новый функционал и возможности.
Через пару секунд отобразится заряд и напряжение батареи, а так же оцениваем процент ее зарядки.
Устройство питается от 4х элементов питания по 1,5В (обычные батарейки с «Ленты»). Взял самые дешевые для тестов, в дальнейшем конечно поставлю LiPo аккумулятор с модулем зарядки и возможностью внешнего питания, но это потом в следующих версиях.
Ждем еще секунду и у нас начинается генерация, вот default частота 1кГц.
На дисплеи отображается частота и погрешность. Частоту можно изменять с помощью кнопок с интервалом 1 Гц. Конечно на очень больших частотах и высокая погрешность, изменения в 1 Гц лежат в диапазонах погрешности и почти не влияют на выходной сигнал, но это лучше определять с осциллографом.
Пару нажатий и мы установили частоту 11кГц. Обратим внимание, что изменилась и погрешность. Все погрешности которые математически можно было рассчитать из величины прерываний arduino отражены в коде скетча. Если мы значительно увеличим значение генерируемой частоты то увидим значение погрешности «err». Это значит что погрешность частоты сложно математически оценить.
Но сигнал по прежнему генерируется с хорошей стабильностью.
Установим максимальное значение частоты 8МГц.
Посмотрим полученные осциллограммы.
Да, конечно 8МГц тут есть, но это совсем не прямоугольный сигнал, за то бюджет не пострадал и для опытов самое то.
Частота 1 МГц, уже лучше. Сигнал похож на правду. Меняем частоту дальше (изображения ниже).
Если хорошо увеличить осциллограмму конечно мы увидим всплески, но насколько они не существенны (<100ns). И вспомните это бюджетный генератор со стоимостью всех компонентов не более 600 руб.
К своему генератору я сразу же спаял удобный шнурок с крокодилами, просто мне так удобно его использовать.
Ну что, пришло время посмотреть, что внутри. Откручиваем 4 самореза. И видим сей девайс во всей красе.
Все просто. Arduino Nanoвсем управляет. Питание, с батарейного блока подается через включатель в переменном резисторе, далее на экран и arduino. Кнопки подключены к arduino через подтягивающие резисторы и еще дополнительно поставлены конденсаторы, все чтобы снизить «дребезг» контактов. Скажите можно сделать программно, но захотелось так.
Сигнал с arduin-ки снимается и идет на клеммы.
Как видите все очень просто.
Теперь желающим повторить.
Для работы arduino нужны библиотеки: Wire.h, LiquidCrystal_I2C.h, OneButton.h, GyverPWM.h. Последняя, разработка моего любимого блогера AlexGyver-а, качаем с его сайта.
Текст скетча для arduino ниже (замените 'решетка' на знак решетка, а то ставит хэштег):
'решетка'include <Wire.h>
'решетка'<LiquidCrystal_I2C.h>
'решетка'<OneButton.h>
'решетка'<GyverPWM.h>
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
uint8_t symbol_meandr[4][8] = { //свои символы
{0,14,0,0,0,0,0,0},
{4,14,31,0,0,0,0,0},
{31,14,4,0,0,0,0,0},
{0,4,14,4,0,0,14,0}
};
int pin=12; //pin выход частоты (D12)
long hz=1000; //частота поумолчанию min 1 max 8 MHz (8e6)
unsigned long mn=1; //множитель или разряд изменения
int pos=1; //позиция множителя
int poshz=6; //позиция множителя 2
int posvar=0; //позиция множителя после вычислений
OneButton button1(A0, true);
OneButton button2(A1, true);
OneButton button3(A2, true);
OneButton button4(A3, true);
void setup() {
delay (100);
lcd.init();
lcd.backlight();// Включаем подсветку дисплея
delay (100);
lcd.setCursor(0, 0);
lcd.print ("Chastotnyi");
lcd.setCursor(0, 1);
lcd.print ("generator v1.3.1");
delay (2000);
lcd.clear();
analogReference (INTERNAL);
float Vbat = (float)analogRead(A7)*1.1/1024.0;
float Vin = Vbat / (146.3/(762+146.3)); //R2/(R1+R2)
lcd.setCursor(0, 0);
lcd.print ("V_bat = ");
lcd.setCursor(8, 0);
lcd.print (Vin);
lcd.setCursor(13, 0);
lcd.print ("V");
lcd.setCursor(8, 1);
lcd.print (Vbat/1.1*100);
lcd.setCursor(13, 1);
lcd.print ("%");
delay (4000);
lcd.clear();
lcd.createChar(1, symbol_meandr[0]);// Загружаем символ в ОЗУ дисплея
lcd.createChar(2, symbol_meandr[1]);// Загружаем символ в ОЗУ дисплея
lcd.createChar(3, symbol_meandr[2]);// Загружаем символ в ОЗУ дисплея
lcd.createChar(4, symbol_meandr[3]);// Загружаем символ в ОЗУ дисплея
pinMode(9, OUTPUT);
refresh_hz();
refresh_mn();
button1.attachClick(oneclick1);
button2.attachClick(oneclick2);
button3.attachClick(oneclick3);
button4.attachClick(oneclick4);
button1.attachDuringLongPress(oneclick1);
button2.attachDuringLongPress(oneclick2);
}
void refresh_hz(){
if (hz<1){
hz=1;
}
if (hz>8000000){
hz=8000000;
}
switch (String(hz).length()){
case 1:
poshz=6;
break;
case 2:
poshz=5;
break;
case 3:
poshz=4;
break;
case 4:
poshz=3;
break;
case 5:
poshz=2;
break;
case 6:
poshz=1;
break;
case 7:
poshz=0;
break;
};
lcd.setCursor(0, 0);
lcd.print (" ");
lcd.setCursor(poshz, 0);
lcd.print (hz);
lcd.print ("Hz");
String pogr;
if (hz<=8000000){
pogr="err";
};
if (hz<=90000){
pogr="1kHz";
};
if (hz<=63000){
pogr="500Hz";
};
if (hz<=30000){
pogr="110Hz";
};
if (hz<=20000){
pogr="50Hz";
};
if (hz<=9000){
pogr="10Hz";
};
if (hz<=4000){
pogr="2Hz";
};
if (hz<=3000){
pogr="1Hz";
};
if (hz<=2000){
pogr="0.5Hz";
};
if (hz<=900){
pogr="0.1Hz";
};
if (hz<=700){
pogr="0.05Hz";
};
if (hz<=300){
pogr="0.01Hz";
};
lcd.setCursor(9, 0);
lcd.print ("\4");
lcd.print (pogr);
//tone (pin,hz);
PWM_square_D9(hz);
}
void refresh_mn(){
lcd.setCursor(0, 1);
lcd.print (" ");
posvar=poshz-pos+(String(hz).length());
lcd.setCursor(posvar,1);
lcd.print ("\1");
}
void oneclick1() {
hz=hz+mn;
refresh_hz();
lcd.setCursor(posvar,1);
lcd.print ("\2");
delay (100);
refresh_mn();
}
void oneclick2() {
hz=hz-mn;
refresh_hz();
lcd.setCursor(posvar,1);
lcd.print ("\3");
delay (100);
refresh_mn();
}
void oneclick3() {
mn=mn*10;
pos=pos+1;
if (mn>1000000){
mn=1;
pos=1;
}
if (mn<0){
mn=1;
pos=1;
}
refresh_mn();
}
void oneclick4() {
lcd.setCursor(10, 1);
lcd.print ("set");
}
void mytick(){
button1.tick();
button2.tick();
button3.tick();
button4.tick();
delay (10);
}
void loop() {
mytick();
}
Из кнопок пока задействовано только 3. Как говорил ранее это платформа для дальнейшей доработки, функциональность 4ой кнопки будет добавлена позже.
Погjворим о перспективах и направлениях доработки. Что хочу добавить в проект:
- Усилитель выходного сигнала. Ну что бы не от 0 до 5 В, а побольше.
- Возможность переключения формы сигнала. Синус, пила, треугольный сигнал.
- Немного гламура в виде динамической индикации при генерации сигнала.
Ну вот наверное и все. Спасибо кто дочитал до конца, ставьте палец вверх, оставляйте комментарии.
Ваш 0x41lex