- Какво представлява генераторът на функции DDS?
- Разберете работата на интегралната схема на генератора на функции AD9833
- Компоненти, необходими за изграждане на генератор на функции, базиран на AD9833
- Генератор на функции, базиран на AD9833 - Схематична диаграма
- Генератор на функции AD9833 - Код на Arduino
- Тестване на генератор на функции, базиран на AD9833
- Допълнителни подобрения
Ако сте електронен ентусиаст като мен, който иска да се оправя с различни електронни схеми, понякога наличието на достоен генератор на функции става задължително. Но притежаването на такъв е проблем, тъй като такова основно оборудване може да струва цяло състояние. Изграждането на собствено тестово оборудване е не само по-евтино, но и чудесен начин да подобрите знанията си.
Така че в тази статия ще изградим прост генератор на сигнали с модул за генериране на функции Arduino и AD9833 DDS, който може да генерира синусоидални, квадратни и триъгълни вълни с максимална честота 12 MHz на изхода. И накрая ще тестваме изходната честота с помощта на нашия осцилоскоп.
Преди това сме изградили обикновен генератор на синусоидални вълни, генератор на квадратни вълни и генератор на триъгълни вълни с помощта на основни аналогови схеми. Можете да ги проверите, ако търсите някои основни схеми за генератор на вълни. Също така, ако искате да създадете по-евтин генератор на функции Arduino, без да използвате модула AD9833, можете да проверите проекта за генератор на вълнови форми DIY Arduino.
Какво представлява генераторът на функции DDS?
Както подсказва името, генераторът на функции е устройство, което може да изведе определена форма на вълната с определена честота при настройка. Например, помислете, че имате LC филтър, за който искате да тествате вашата честотна характеристика на изхода, можете лесно да го направите с помощта на генератор на функции. Всичко, което трябва да направите, е да зададете желаната изходна честота и форма на вълната, след което можете да я завъртите надолу или нагоре, за да тествате реакцията. Това беше само един пример, можете да правите повече неща с него, докато списъкът продължава.
DDS означава Direct Digital Synthesis. Това е тип генератор на форма на вълната, който използва цифрово-аналогови преобразуватели (ЦАП) за изграждане на сигнал от нулата. Този метод се използва специално за генериране на синусоида. Но IC, която използваме, може да генерира квадратни или триъгълни вълнови сигнали. Операциите, които се случиха в DDS чип, са цифрови, така че той може да превключва честотата много бързо или може да превключва от един сигнал на друг много бързо. Това устройство има фина честотна разделителна способност с широк честотен спектър.
Разберете работата на интегралната схема на генератора на функции AD9833
В основата на нашия проект е интегралната схема за програмиране на вълнови форми AD9833, която е проектирана и разработена от аналогови устройства. Това е програмируем генератор с ниска мощност, който може да генерира синусоидална, триъгълна и квадратна вълна с максимална честота 12 MHz. Това е много уникална интегрална схема, която може да променя изходната честота и фаза само със софтуерна програма. Той има 3-жичен SPI интерфейс, поради което комуникацията с тази интегрална схема става много проста и лесна. Функционалната блок-схема на този IC е показана по-долу.
Работата на този IC е много проста. Ако разгледаме функционалната блок-схема по-горе, ще забележим, че имаме Фазов акумулатор, чиято работа е да съхранява всички възможни цифрови стойности на синусоида, започвайки от 0 до 2π. След това имаме SIN ROM, чиято работа е да преобразува фазовата информация, която по-късно може да бъде директно преобразувана в амплитуда. SIN ROM използва информацията за цифровата фаза като адрес към таблица за търсене и преобразува информацията за фазата в амплитуда. И накрая, имаме 10-битов цифрово-аналогов преобразувател, чиято работа е да получава цифровите данни от SIN ROM и да ги преобразува в съответните аналогови напрежения, това е, което получаваме от изхода. На изхода имаме и превключвател, който можем да включим или изключим само с малко софтуерен код. Ще говорим за това по-нататък в статията.Детайлите, които виждате по-горе, са много опростена версия на това, което се случва вътре в интегралната схема и Повечето детайли, които виждате по-горе, са взети от таблицата с данни AD9833, можете също да я проверите за допълнителна информация
Компоненти, необходими за изграждане на генератор на функции, базиран на AD9833
Компонентите, необходими за изграждането на базиран на AD9833 функционален генератор, са изброени по-долу, ние проектирахме тази схема с много общи компоненти, което прави процеса на репликация много лесен.
- Arduino Nano - 1
- AD9833 DDS функционален генератор - 1
- 128 X 64 OLED дисплей - 1
- Общ ротационен кодер - 1
- DC барел жак - 1
- LM7809 Регулатор на напрежение - 1
- Кондензатор 470uF - 1
- Кондензатор 220uF - 1
- Кондензатор 104pF - 1
- 10K резистор - 6
- Тактилни превключватели - 4
- Винтова клема 5,04 мм - 1
- Женска заглавна част - 1
- Източник на захранване 12V - 1
Генератор на функции, базиран на AD9833 - Схематична диаграма
Пълната електрическа схема за AD9833 и Arduino базиран функционален генератор е показана по-долу.
Ще използваме AD9833 с Arduino, за да генерираме желаната честота. И в този раздел ще обясним всички подробности с помощта на схемата; позволете ми да ви дам кратък преглед на това, което се случва с веригата. Нека започнем с модула AD9833. Модулът AD9833 е модулът на генератора на функции и е свързан с Arduino съгласно схемата. За захранване на веригата използваме интегрална схема на регулатора на напрежение LM7809 с приличен разединителен кондензатор, това е необходимо, тъй като захранващият шум може да повлияе на изходния сигнал, което води до нежелан изход. Както винаги, Arduino работи като мозък за този проект. За да покажем зададената честота и друга ценна информация, ние свързахме 128 X 64 OLED дисплеен модул. За да променим честотния диапазон, използваме три превключвателя. Първият настройва честотата на Hz, вторият задава изходната честота на KHz, а третият задава честотата на MHz, имаме и друг бутон, който може да се използва за активиране или деактивиране на изхода. И накрая, имаме ротационен енкодер,и ние трябва да прикачим малко издърпващ резистор с него, в противен случай тези превключватели няма да работят, защото проверяваме събитието за натискане на бутона в метода за обединяване. Въртящият се енкодер се използва за промяна на честотата, а тактилният превключвател вътре в ротационния енкодер се използва за избор на зададената форма на вълната.
Генератор на функции AD9833 - Код на Arduino
Пълният код, използван в този проект, може да бъде намерен в долната част на тази страница. След добавяне на необходимите заглавни файлове и изходни файлове, трябва да можете да компилирате директно файла Arduino. Можете да изтеглите библиотеката ad9833 Arduino и други библиотеки от връзката, дадена по-долу, или можете да използвате метода на диспечера на борда, за да инсталирате библиотеката.
- Изтеглете библиотеката AD9833 от Бил Уилямс
- Изтеглете SSD1306 OLED библиотека от Adafruit
- Изтеглете библиотеката на Adafruit GFX
Обяснението на кода в ino. файлът е както следва. Първо, започваме с включването на всички необходими библиотеки. Библиотеката за модула AD9833 DDS първо е последвана от библиотеката за OLED и математическата библиотека е необходима за някои от нашите изчисления.
#include // LIbrary за модул AD9833 #include
След това дефинираме всички необходими входни и изходни щифтове за бутоните, превключвателя, въртящия се енкодер и OLED.
#define SCREEN_WIDATA_PINH 128 // Ширина на OLED дисплея в пиксели #define SCREEN_HEIGHT 64 // OLED височина на дисплея, в пиксели #define SET_FREQUENCY_HZ A2 // Бутон за задаване на честота в Hz #define SET_FREQUENCY_KHZ AH // SET Бутон SET H A6 // Бутон за задаване на честота в Mhz #define ENABLE_DISABLE_OUTPUT_PIN A7 // Бутон за активиране / деактивиране на изхода #define FNC_PIN 4 // Fsync Изисква се от AD9833 Модул #define CLK_PIN 8 // Часовник ПИН на кодера #PIN 7 / Дефиниране / Дефиниране / ПИН за данни на кодера #define BTN_PIN 9 // Вътрешен бутон на кодера
След това дефинираме всички необходими променливи, които се изискват в този код. Първо, дефинираме брояч на целочислена променлива, който ще съхранява стойността на въртящия се енкодер. Следващите две променливи clockPin и clockPinState съхраняват статуята на щифта, която е необходима за разбиране на посоката на кодера. Имаме времева променлива, която съдържа текущите стойности на брояча на таймера, тази променлива се използва за отмяна на бутона. След това имаме неподписан дълъг променлив модулFrequency, който съдържа изчислената честота, която ще бъде приложена. След това имаме забавяне на дебюнса. Това забавяне може да се коригира според изискванията. След това имаме три булеви променливи set_frequency_hz,set_frequency_Khz и set_frequency_Mhz тези три променливи се използват за определяне на текущата настройка на модула. Ще говорим за това по-подробно по-нататък в статията. След това имаме променливата, която съхранява състоянието на изходната форма на вълната, а изходната форма по подразбиране е синусоида. И накрая, имаме променливата encoder_btn_count, която съдържа броя на кодовете -бутони, която се използва за задаване на изходната форма на вълната.
int брояч = 1; // Тази стойност на брояча ще се увеличи или намали, ако когато въртящият се енкодер бъде завъртян int clockPin; // Placeholder за статус на пина, използван от ротационния енкодер int clockPinState; // Placeholder за статус на щифта, използван от въртящия се енкодер неподписан дълго време = 0; // Използва се за денонсиране на неподписан дълъг moduleFrequency; // използва се за задаване на изходна честота long debounce = 220; // bool за забавяне на дебаунта btn_state; // използва се за активиране на деактивирането на изхода на модула AD98333 bool set_frequency_hz = 1; // Честота на повреда на модула AD9833 bool set_frequency_khz; bool set_frequency_mhz; String waveSelect = "SIN"; // Стартираща форма на вълната на модула int encoder_btn_count = 0; // използва се за проверка на бутона за кодиране, натиснете След това имаме нашите два обекта, единият е за OLED дисплея, а друг е за модула AD9833Дисплей Adafruit_SSD1306 (SCREEN_WIDATA_PINH, SCREEN_HEIGHT, & Wire, -1); AD9833 gen (FNC_PIN);
След това имаме нашата функция setup (), в тази функция за настройка започваме с активирането на Serial за отстраняване на грешки. Инициализираме модула AD9833 с помощта на метода begin (). След това задаваме всички зададени щифтове на въртящия се енкодер като вход. И съхраняваме стойността на щифта на часовника в променливата clockPinState, това е необходима стъпка за въртящия се енкодер.
След това задаваме всички щифтове на бутоните като вход и активираме OLED дисплея с помощта на метода display.begin () , а също така проверяваме за грешки с оператор if . Когато това приключи, изчистваме дисплея и отпечатваме начален начален екран, добавяме закъснение от 2 секунди, което е и закъснението за началния екран и накрая извикваме функцията update_display (), която изчиства екрана и актуализира дисплей за пореден път. Подробностите за метода update_display () ще бъдат обсъдени по-нататък в статията.
void setup () {Serial.begin (9600); // Активиране на Serial @ 9600 baud gen.Begin (); // Това ТРЯБВА да е първата команда след деклариране на обекта AD9833 pinMode (CLK_PIN, INPUT); // Задаване на щифтове като входен pinMode (DATA_PIN, INPUT); pinMode (BTN_PIN, INPUT_PULLUP); clockPinState = digitalRead (CLK_PIN); pinMode (SET_FREQUENCY_HZ, INPUT); // Задаване на щифтове като входен pinMode (SET_FREQUENCY_KHZ, INPUT); pinMode (SET_FREQUENCY_MHZ, INPUT); pinMode (ENABLE_DISABLE_OUTPUT_PIN, INPUT); ако (! display.begin (SSD1306_SWITCHCAPVCC, 0x3C)) {// Адрес 0x3D за 128x64 Serial.println (F ("SSD1306 разпределението не бе успешно")); за (;;); } display.clearDisplay (); // Изчистване на екрана display.setTextSize (2); // Задаване на размер на текста display.setTextColor (БЯЛ); // задаване на цветен LCD дисплей.setCursor (30, 0); // Задаване на позиция на курсора display.println ("AD9833"); // Отпечатайте този текстов дисплей.setCursor (17, 20); // Задаване на позиция на курсора display.println ("Функция"); // отпечатваме този текстов дисплей.setCursor (13, 40); // Задаване на позиция на курсора display.println ("Генератор"); // отпечатваме този текст display.display (); // Актуализиране на забавянето на дисплея (2000); // Забавяне на 2 SEC update_display (); // Функция за повикване на update_display}
След това имаме нашата функция loop (), всички основни функционалности са написани в раздела за цикъл.
Първо четем щифта Clock на ротационния енкодер и го съхраняваме в променливата clockPin, която сме декларирали по-рано. След това в оператора if проверяваме дали предишната стойност на щифта и текущата стойност на щифта е сходна или не и проверяваме и текущата стойност на щифта. Ако всичко е вярно, проверяваме за ПИН за данни, ако е вярно, това означава, че кодерът се върти обратно на часовниковата стрелка и намаляваме стойността на брояча с помощта на counter-- command. В противен случай увеличаваме стойността на брояча с командата counter ++. И накрая, поставяме друг оператор if , за да зададем минималната стойност на 1. След това актуализираме clockPinState с текущия clockPinстойност за бъдеща употреба.
празен цикъл () {clockPin = digitalRead (CLK_PIN); if (clockPin! = clockPinState && clockPin == 1) {if (digitalRead (DATA_PIN)! = clockPin) {counter -; } else {брояч ++; // Кодерът се върти CW, така че инкремент} if (брояч <1) брояч = 1; Serial.println (брояч); update_display (); }
След това разполагаме с нашия код за откриване на натискане на бутон. В този раздел открихме бутона вътре в кодера с помощта на някои вложени оператори if, if (digitalRead (BTN_PIN) == LOW && millis () - time> denounce), в това изявление първо проверяваме дали бутонът щифтът е нисък или не, ако е нисък, тогава е натиснат. След това отново проверяваме стойността на таймера със забавяне на дебюнса, ако и двете изявления са верни, тогава го обявяваме за успешно действие при натискане на бутон, ако така увеличим стойността на encoder_btn_count. След това декларираме друг оператор if, за да зададем максималната стойност на брояча на 2, имаме нужда от него, защото го използваме за задаване на изходна форма на вълната.Последователните три оператора if правят това, ако стойността е нула, се избира форма на синусоида, ако е една, това е квадратна вълна и ако стойността е 2, това е триъгълна вълна. И в трите тези if инструкции актуализираме дисплея с функцията update_display () . И накрая, актуализираме времевата променлива с текущата стойност на брояча на таймера.
// Ако открием НИЗКИ сигнал, бутонът се натиска, ако (digitalRead (BTN_PIN) == LOW && millis () - time> debounce) {encoder_btn_count ++; // Увеличаваме стойностите if (encoder_btn_count> 2) // ако стойността е по-голяма от 2, нулирайте я на 0 {encoder_btn_count = 0; } if (encoder_btn_count == 0) {// ако стойността е 0 е избрана синусоида waveSelect = "SIN"; // актуализираме променливата на низа със стойност на греха update_display (); // актуализираме дисплея} if (encoder_btn_count == 1) {// ако стойността е 1 квадратна вълна е избрана waveSelect = "SQR"; // актуализираме променливата на низа със SQR стойност update_display (); // актуализираме дисплея} if (encoder_btn_count == 2) {// ако стойността е 1 Избрана е триъгълна вълна waveSelect = "TRI"; // актуализира низовата променлива с TRI стойност update_display ();// актуализираме дисплея} time = millis (); // актуализиране на времевата променлива}
След това дефинираме целия необходим код, който е необходим за настройка на всички бутони със забавяне на отпадане. Тъй като бутоните са свързани към аналоговите щифтове на Arduino, ние използваме командата за аналогово четене, за да идентифицираме натискане на бутон, ако стойността на аналоговото четене достигне под 30, след това откриваме успешното му натискане на бутон и чакаме 200 ms проверете дали това е действително натискане на бутон или само шум. Ако това твърдение е вярно, ние присвояваме булевите променливи със стойности, които се използват за задаване на стойностите на Hz, Khz и Mhz на генератора на функции. След това актуализираме дисплея и актуализираме времевата променлива. Правим това за всичките четири бутона, свързани с Arduino.
if (analogRead (SET_FREQUENCY_HZ) <30 && millis () - time> debounce) {set_frequency_hz = 1; // актуализиране на булеви стойности set_frequency_khz = 0; set_frequency_mhz = 0; update_display (); // актуализиране на времето за показване = милис (); // актуализиране на времевата променлива} if (analogRead (SET_FREQUENCY_KHZ) <30 && millis () - time> debounce) {set_frequency_hz = 0; // актуализиране на булеви стойности set_frequency_khz = 1; set_frequency_mhz = 0; moduleFrequency = брояч * 1000; update_display (); // актуализиране на времето за показване = милис (); // актуализиране на времевата променлива} if (analogRead (SET_FREQUENCY_MHZ) <30 && millis () - time> debounce) {// проверете аналоговия щифт със забавяне на debounce set_frequency_hz = 0; // актуализиране на булеви стойности set_frequency_khz = 0; set_frequency_mhz = 1; moduleFrequency = брояч * 1000000; update_display ();// актуализираме времето за показване = милис (); // актуализираме времевата променлива} if (analogRead (ENABLE_DISABLE_OUTPUT_PIN) <30 && millis () - time> debounce) {// проверяваме аналогов щифт със забавяне на debounce btn_state =! btn_state; // Обръщане на състоянието на бутона gen.EnableOutput (btn_state); // Активиране / деактивиране на изхода на генератора на функции в зависимост от състоянието на бутона update_display (); // актуализиране на времето за показване = милис (); // актуализиране на променливата на времето}}// актуализиране на времевата променлива}}// актуализиране на времевата променлива}}
И накрая, имаме нашата функция update_display (). В тази функция направихме много повече от просто актуализиране на този дисплей, защото определена част от дисплея не може да бъде актуализирана в OLED. За да го актуализирате, трябва да го пребоядисате с нови стойности. Това прави процеса на кодиране много по-труден.
Вътре в тази функция започваме с изчистване на дисплея. След това задаваме необходимия размер на текста. След това зададохме курсора и отпечатахме Генератор на функции с display.println („Функционална функция“); команда. Отново задаваме размера на текста на 2 и курсора на (0,20) с помощта на функцията display.setCursor (0, 20).
Тук отпечатваме информацията за каква вълна е.
display.clearDisplay (); // Първо изчистете дисплея display.setTextSize (1); // задаване на размер на текста display.setCursor (10, 0); // Задаване на позиция на курсора display.println ("Генератор на функции"); // отпечатваме text display.setTextSize (2); // задаваме размер на текста display.setCursor (0, 20); // задаваме позиция на курсора
След това проверяваме булевите променливи за подробности за честотата и актуализираме стойността в променливата moduleFrequency. Правим това за Hz, kHz и MHz стойности. След това проверяваме променливата waveSelect и идентифицираме коя вълна е избрана. Сега имаме стойностите, за да зададем типа и честотата на вълната.
if (set_frequency_hz == 1 && set_frequency_khz == 0 && set_frequency_mhz == 0) {// проверете дали е натиснат бутон за настройка на честотата в Hz moduleFrequency = брояч; // актуализираме променливата moduleFrequency с текуща стойност на брояча} if (set_frequency_hz == 0 && set_frequency_khz == 1 && set_frequency_mhz == 0) {// проверете дали е натиснат бутон за настройка на честотата в KHz moduleFrequency = брояч * 1000; // актуализирайте променливата moduleFrequency с текуща стойност на брояча, но умножаваме 1000, за да я настроим на KHZ} if (set_frequency_hz == 0 && set_frequency_khz == 0 && set_frequency_mhz == 1) {// проверете дали е натиснат бутон за настройка на честотата в MHz, moduleFrequency = брояч * 1000000; if (moduleFrequency> 12000000) {moduleFrequency = 12000000;// не позволявайте на честотата да бъде по-голяма от 12Mhz брояч = 12; }} if (waveSelect == "SIN") {// Синусоида е избрана display.println ("SIN"); gen.ApplySignal (SINE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "SQR") {// Sqr вълна е избрана display.println ("SQR"); gen.ApplySignal (SQUARE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "TRI") {// Tri wave е избрана display.println ("TRI"); gen.ApplySignal (TRIANGLE_WAVE, REG0, moduleFrequency); // актуализираме модула AD9833. Serial.println (moduleFrequency); }} if (waveSelect == "SQR") {// Sqr вълна е избрана display.println ("SQR"); gen.ApplySignal (SQUARE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "TRI") {// Tri wave е избрана display.println ("TRI"); gen.ApplySignal (TRIANGLE_WAVE, REG0, moduleFrequency); // актуализираме модула AD9833. Serial.println (moduleFrequency); }} if (waveSelect == "SQR") {// Sqr вълна е избрана display.println ("SQR"); gen.ApplySignal (SQUARE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "TRI") {// Tri wave е избран display.println ("TRI"); gen.ApplySignal (TRIANGLE_WAVE, REG0, moduleFrequency); // актуализираме модула AD9833. Serial.println (moduleFrequency); }
Поставяме курсора отново и актуализираме стойностите на брояча. Отново проверяваме булевата стойност, за да актуализираме честотния диапазон на дисплея, трябва да направим това, защото принципът на работа на OLED е много странен.
display.setCursor (45, 20); display.println (брояч); // отпечатваме информацията за брояча на дисплея. if (set_frequency_hz == 1 && set_frequency_khz == 0 && set_frequency_mhz == 0) {display.setCursor (90, 20); display.println ("Hz"); // отпечатваме Hz на дисплея display.display (); // когато всички комплекти актуализират дисплея} if (set_frequency_hz == 0 && set_frequency_khz == 1 && set_frequency_mhz == 0) {display.setCursor (90, 20); display.println ("Khz"); display.display (); // когато всички комплекти актуализират дисплея} if (set_frequency_hz == 0 && set_frequency_khz == 0 && set_frequency_mhz == 1) {display.setCursor (90, 20); display.println ("Mhz"); display.display (); // когато всички настроени актуализират дисплея}
След това проверяваме променливата за натискане на бутона, за да отпечатаме изхода за включване / извеждане на OLED. Отново това трябва да се направи заради OLED модула.
ако (btn_state) {display.setTextSize (1); display.setCursor (65, 45); display.print ("Output ON"); // отпечатване на изход на дисплея display.display (); display.setTextSize (2); } else {display.setTextSize (1); display.setCursor (65, 45); display.print ("Output OFF"); // отпечатване на изхода на дисплея display.display (); display.setTextSize (2); }
Това бележи края на нашия процес на кодиране. Ако сте объркани в този момент, можете да проверите коментарите в кода за по-нататъшно разбиране.
Тестване на генератор на функции, базиран на AD9833
За тестване на веригата се използва горната настройка. Както можете да видите, ние сме свързали 12V DC захранващ адаптер към гнездото за DC барел и сме свързали осцилоскопа Hantek към изхода на веригата. Също така сме свързали осцилоскопа към лаптопа, за да визуализираме и измерим изходната честота.
След като това беше направено, ние зададохме изходната честота на 5Khz с помощта на ротационния енкодер и тестваме изходната синусоида и със сигурност, това е 5Khz синусоида на изхода.
След това променихме изходната форма на вълната на триъгълна вълна, но честотата остана същата, изходната форма на вълната е показана по-долу.
След това променихме изхода на квадратна вълна и наблюдавахме изхода и това беше идеална квадратна вълна.
Също така променихме честотните диапазони и тествахме изхода и той работеше добре.
Допълнителни подобрения
Тази схема е само доказателство за концепция и се нуждае от допълнителни подобрения. Първо, ние се нуждаем от качествена печатна платка и някакъв качествен BNC конектор за изхода, в противен случай не можем да получим по-висока честота. Амплитудата на модула е много ниска, така че за да го подобрим, са ни необходими някои оп-усилвателни вериги за усилване на изходното напрежение. Потенциометър може да бъде свързан, за да варира амплитудата на изхода. Може да се свърже превключвател за компенсиране на сигнала; това също е задължителна функция. И освен това кодът се нуждае от много подобрения, тъй като е малко бъги. И накрая, OLED дисплеите трябва да бъдат променени, иначе е невъзможно да се напише лесно разбираем код.
Това бележи края на този урок, надявам се статията да ви е харесала и да сте научили нещо ново. Ако имате някакви въпроси относно статията, можете да ги оставите в раздела за коментари по-долу или да използвате нашия електронен форум.