Найти в Дзене
0x41lex

Генератор сигнала на Arduino своими руками

Вот в очередной раз столкнулся с проблемой отсутствия генератора сигнала прямоугольной формы. Что делать, бежать в магазин и выкладывать круглую сумму денег, или заказать с Китая подешевле, но ждать доставку, да и денег свободных не очень много.
Кстати с Китая есть неплохие интересные варианты, но когда будет денежка.
Хочу себе такой купить )
Я стал изучать эту тему, как построить свой генератор

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

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

Попробовал наверное схем 7-8 пока не наткнулся на нестандартное решение на arduino, хочу подчеркнуть нестандартное, интересные там технические тонкости были. Вот решил собрать, получилось и получилось достойно. Но как говорится много текста, ближе к делу.

Зашел в магазин взял корпус пластиковый, рассыпухи всякой, arduino nano была под рукой, она и спасла ситуацию. Пару вечеров за паяльником неспеша и вот девайс, Частотный генератор v.1.3.

Мой получившийся девайс
Мой получившийся девайс

Что получилось, получился генератор прямоугольного сигнала с частотой от 1Гц до 8Мгц. Да да до 8 МГц. Обычно такую частоту на arduin-ке мало кто получает.

Девайс состоит из органов управления представленных 4 кнопками без фиксации, переменным резистором с включением, экраном отображения информации и выходом в виде двух зажимов. Напряжение на выходе до 5 В.

Поворачиваем резистор, слышим щелчок и он включился.

После включения
После включения

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

Через пару секунд отобразится заряд и напряжение батареи, а так же оцениваем процент ее зарядки.

Заряд батареи
Заряд батареи

Устройство питается от 4х элементов питания по 1,5В (обычные батарейки с «Ленты»). Взял самые дешевые для тестов, в дальнейшем конечно поставлю LiPo аккумулятор с модулем зарядки и возможностью внешнего питания, но это потом в следующих версиях.

Ждем еще секунду и у нас начинается генерация, вот default частота 1кГц.

Отображаем частоту генерации
Отображаем частоту генерации

На дисплеи отображается частота и погрешность. Частоту можно изменять с помощью кнопок с интервалом 1 Гц. Конечно на очень больших частотах и высокая погрешность, изменения в 1 Гц лежат в диапазонах погрешности и почти не влияют на выходной сигнал, но это лучше определять с осциллографом.

11кГц
11кГц

Пару нажатий и мы установили частоту 11кГц. Обратим внимание, что изменилась и погрешность. Все погрешности которые математически можно было рассчитать из величины прерываний arduino отражены в коде скетча. Если мы значительно увеличим значение генерируемой частоты то увидим значение погрешности «err». Это значит что погрешность частоты сложно математически оценить.

2915400 Гц
2915400 Гц

Но сигнал по прежнему генерируется с хорошей стабильностью.

8МГц
8МГц

Установим максимальное значение частоты 8МГц.

Посмотрим полученные осциллограммы.

8МГц на осциллографе
8МГц на осциллографе

Да, конечно 8МГц тут есть, но это совсем не прямоугольный сигнал, за то бюджет не пострадал и для опытов самое то.

1МГц на осциллографе
1МГц на осциллографе

Частота 1 МГц, уже лучше. Сигнал похож на правду. Меняем частоту дальше (изображения ниже).

100кГц на осциллографе
100кГц на осциллографе
10кГц на осциллографе
10кГц на осциллографе
1кГц на осциллографе
1кГц на осциллографе

Если хорошо увеличить осциллограмму конечно мы увидим всплески, но насколько они не существенны (<100ns). И вспомните это бюджетный генератор со стоимостью всех компонентов не более 600 руб.

-13

К своему генератору я сразу же спаял удобный шнурок с крокодилами, просто мне так удобно его использовать.

Удобный шнурок с крокодилами
Удобный шнурок с крокодилами

Ну что, пришло время посмотреть, что внутри. Откручиваем 4 самореза. И видим сей девайс во всей красе.

Девайс внутри
Девайс внутри

Все просто. Arduino Nanoвсем управляет. Питание, с батарейного блока подается через включатель в переменном резисторе, далее на экран и arduino. Кнопки подключены к arduino через подтягивающие резисторы и еще дополнительно поставлены конденсаторы, все чтобы снизить «дребезг» контактов. Скажите можно сделать программно, но захотелось так.

Сигнал с arduin-ки снимается и идет на клеммы.

Батарейный блок
Батарейный блок
Экран и arduino
Экран и arduino
Полет arduino
Полет arduino

Как видите все очень просто.

Теперь желающим повторить.

Для работы 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ворим о перспективах и направлениях доработки. Что хочу добавить в проект:

  1. Усилитель выходного сигнала. Ну что бы не от 0 до 5 В, а побольше.
  2. Возможность переключения формы сигнала. Синус, пила, треугольный сигнал.
  3. Немного гламура в виде динамической индикации при генерации сигнала.

Ну вот наверное и все. Спасибо кто дочитал до конца, ставьте палец вверх, оставляйте комментарии.

Ваш 0x41lex