آی پی امداد
abtahi

آموزشی: ساخت مدار فانکشن ژنراتور 1 کیلو الی 12 مگاهرتز با ماژول AD9833 با آردوینو

Navid-Aref

کاربر vip
vip
کاربر
2008-11-23
438
938
کد :
#include <AD9833.h> // Library for AD9833 Module
#include <Wire.h> // Wire Library for OLED
#include <Adafruit_GFX.h> // Support Library for OLED
#include <Adafruit_SSD1306.h> // OLED library
#include <math.h> // Math Library
#define SCREEN_WIDATA_PINH 128 // OLED display Width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SET_FREQUENCY_HZ A2 // Pushbutton To Set Frequency In Hz
#define SET_FREQUENCY_KHZ A3 // Pushbutton To Set Frequency In Khz
#define SET_FREQUENCY_MHZ A6 // Pushbutton To Set Frequency In Mhz
#define ENABLE_DISABLE_OUTPUT_PIN A7 // Pushbutton To Enable / Disable the Output
#define FNC_PIN 4 // Fsync Required by the AD9833 Module
#define CLK_PIN 8 // Clock Pin of the Encoder
#define DATA_PIN 7 // Data Pin of the Encoder
#define BTN_PIN 9 // Internal Push Button on the Encoder
int counter = 1; // This Counter value will increas or decreas if when the rotarty encoder is turned
int clockPin; // Placeholder por pin status used by the rotary encoder
int clockPinState; // Placeholder por pin status used by the rotary encoder
unsigned long time = 0; // Used for debouncing
unsigned long moduleFrequency; // used to set output frequency
long debounce = 220; // Debounce delay
bool btn_state; // used to enable disable output of the AD98333 Module
bool set_frequency_hz = 1; // Defult frequency of the AD9833 Module
bool set_frequency_khz;
bool set_frequency_mhz;
String waveSelect = "SIN"; // Startup waveform of the module
int encoder_btn_count = 0; // used to check encoder button press
Adafruit_SSD1306 display(SCREEN_WIDATA_PINH, SCREEN_HEIGHT, &Wire, -1);
AD9833 gen(FNC_PIN);
void setup() {
Serial.begin(9600);
gen.Begin(); // This MUST be the first command after declaring the AD9833 object
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);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay(); // Clear the Screen
display.setTextSize(2); // Set text Size
display.setTextColor(WHITE); // set LCD Colour
display.setCursor(30, 0); // Set Cursor Position
display.println("AD9833"); // Print the this Text
display.setCursor(17, 20); // Set Cursor Position
display.println("Function"); // Print the this Text
display.setCursor(13, 40); // Set Cursor Position
display.println("Generator"); // Print the this Text
display.display(); // Update the Display
delay(2000); // Delay of 2 SEC
update_display(); // Call update_display Function
}
void loop()
{
clockPin = digitalRead(CLK_PIN);
if (clockPin != clockPinState && clockPin == 1) {
if (digitalRead(DATA_PIN) != clockPin) {
counter --;
}
else {
counter ++;// Encoder is rotating CW so increment
}
if (counter < 1 ) counter = 1;
Serial.println(counter);
update_display();
}
clockPinState = clockPin; // Remember last CLK_PIN state
//If we detect LOW signal, button is pressed
if ( digitalRead(BTN_PIN) == LOW && millis() - time > debounce) {
encoder_btn_count++; // Increment the values
if (encoder_btn_count > 2) // if value is grater that 2 reset it to 0
{
encoder_btn_count = 0;
}
if (encoder_btn_count == 0) { // if the value is 0 sine wave is selected
waveSelect = "SIN"; // update the string variable with sin value
update_display(); // update the display
}
if (encoder_btn_count == 1) { // if the value is 1 square wave is selected
waveSelect = "SQR"; // update the string variable with SQR value
update_display(); // update the display
}
if (encoder_btn_count == 2) { // if the value is 1 Triangular wave is selected
waveSelect = "TRI"; // update the string variable with TRI value
update_display();// update the display
}
time = millis(); // update the time variable
}
// Check buttton press action with analogread method
// Put in a slight delay to help debounce the reading
if (analogRead(SET_FREQUENCY_HZ) < 30 && millis() - time > debounce) { // check analogpin with debounce delay
//update boolean values
set_frequency_hz = 1;
set_frequency_khz = 0;
set_frequency_mhz = 0;
update_display();// update the display
time = millis();// update the time variable
}
if (analogRead(SET_FREQUENCY_KHZ) < 30 && millis() - time > debounce) { // check analogpin with debounce delay
//update boolean values
set_frequency_hz = 0;
set_frequency_khz = 1;
set_frequency_mhz = 0;
moduleFrequency = counter * 1000;
update_display();// update the display
time = millis();// update the time variable
}
if (analogRead(SET_FREQUENCY_MHZ) < 30 && millis() - time > debounce ) { // check analogpin with debounce delay
//update boolean values
set_frequency_hz = 0;
set_frequency_khz = 0;
set_frequency_mhz = 1;
moduleFrequency = counter * 1000000;
update_display();// update the display
time = millis();// update the time variable
}
if (analogRead(ENABLE_DISABLE_OUTPUT_PIN) < 30 && millis() - time > debounce ) {// check analogpin with debounce delay
btn_state = ! btn_state; // Invert the button state
gen.EnableOutput(btn_state); // Enable / Disable output of the function generator depending on button state
update_display();// update the display


time = millis();// update the time variable
}
}
void update_display()
{
display.clearDisplay(); // FIrst clear the display
display.setTextSize(1); //set text Size
display.setCursor(10, 0); // Set cursor position
display.println("Function Generator"); //print the text
display.setTextSize(2);//set text Size
display.setCursor(0, 20);//Set cursor position
if (set_frequency_hz == 1 && set_frequency_khz == 0 && set_frequency_mhz == 0 ) { // check if button for setting the frequency in Hz is pressed
moduleFrequency = counter; //updayte teh moduleFrequency variable with current counter value
}
if (set_frequency_hz == 0 && set_frequency_khz == 1 && set_frequency_mhz == 0 ) { // check if button for setting the frequency in KHz is pressed
moduleFrequency = counter * 1000;//updayte teh moduleFrequency variable with current counter value but we multiply 1000 to set it on KHZ
}
if (set_frequency_hz == 0 && set_frequency_khz == 0 && set_frequency_mhz == 1) { // check if button for setting the frequency in MHz is pressed
moduleFrequency = counter * 1000000;
if (moduleFrequency > 12000000)
{
moduleFrequency = 12000000; // do not let the frequency to be grater that 12Mhz
counter = 12;
}
}
if (waveSelect == "SIN") { // Sine wave is selected
display.println("SIN");
gen.ApplySignal(SINE_WAVE, REG0, moduleFrequency);
Serial.println(moduleFrequency);
}
if (waveSelect == "SQR") {// Sqr wave is selected
display.println("SQR");
gen.ApplySignal(SQUARE_WAVE, REG0, moduleFrequency);
Serial.println(moduleFrequency);
}
if (waveSelect == "TRI" ) {// Tri wave is selected
display.println("TRI");
gen.ApplySignal(TRIANGLE_WAVE, REG0, moduleFrequency); // update the AD9833 module.
Serial.println(moduleFrequency);
}
display.setCursor(45, 20);
display.println(counter); // print the counter information on teh display.
if (set_frequency_hz == 1 && set_frequency_khz == 0 && set_frequency_mhz == 0 ) {
display.setCursor(90, 20);
display.println("Hz"); // print Hz on the display
display.display(); // when all set update the display
}
if (set_frequency_hz == 0 && set_frequency_khz == 1 && set_frequency_mhz == 0 ) {
display.setCursor(90, 20);
display.println("Khz");
display.display(); // when all set update the display
}
if (set_frequency_hz == 0 && set_frequency_khz == 0 && set_frequency_mhz == 1) {
display.setCursor(90, 20);
display.println("Mhz");
display.display(); // when all set update the display
}
if (btn_state) {
display.setTextSize(1);
display.setCursor(65, 45);
display.print("Output ON"); // print output on to the display
display.display();
display.setTextSize(2);
}
else {
display.setTextSize(1);
display.setCursor(65, 45);
display.print("Output OFF"); // print output off to the display
display.display();
display.setTextSize(2);
}
}
 
آخرین ویرایش:
  • Like
واکنش‌ها[ی پسندها]: masuodd55

Navid-Aref

کاربر vip
vip
کاربر
2008-11-23
438
938
با کمک ماژول AD9833 می توان یک فانکشن ژنراتور 1 هرتز الی 12 مگاهرتز برای تولید سه نوع موج سینوسی، مثلثی و مربعی درست کرد. البته نیاز به آردوینو نانو، ماژول نمایشگر OLED زرد-آبی یا سفید 0.96 اینچ دارای ارتباط I2C، ماژول روتاری انکودر، چهار عدد تک سوئیچ 12*12 و چندین قطعه الکترونیکی ساده دیگر مثل، رگولاتور ولتاژ7809، خازن الکترولیت و مقاومت و... هست. من نسخه اولیه این مدار را در وبسایت circuitdigest.com پیدا کردم. البته در شماتیک مدار محل اتصال data و clk ماژول AD9833 به آردوینو جابجا رسم شده که در کامنتهایش اشاره شده و برای خودم موقع مونتاژ قطعات بر روی برد بورد مشکل ساز شده بود. مشکل دیگر آموزش آن وبسایت، اجرای مدار بر روی بورد سوراخدار بود که زیاد جالب نبود، بنابراین توسط نرم افزار پروتئوس مدار آن را (در حد مبتدی است و ممکن است از لحاظ الکترونیک حرفه ای قابل قبول نباشد) ترسیم کردم که در ادامه برای استفاده دوستان قرار میدهم. (در شماتیک از روتاری انکودر ساده استفاده شده و برای همین مقاومت به آن متصل شده است ولی در بازار ماژول روتاری انکودر موجود است و نیازی به سه مقاومت اطرافش نیست).

j0jzy1rp5lg9.jpg

rie8ief1c366.png


سطح مسی و سطح رویی مدار چاپی که براساس شماتیک بالا و رفع ایراد آن آماده کردم:
https://s6.uplod.ir/i/01041/8hmc0d9qlaxk.jpg
https://s6.uplod.ir/i/01041/yynt9yu89jd0.jpg

در پست اول فایل پروگرام کردن آردوینو و در پست بعدی عکس های مدار آماده و مونتاژ شده نهایی را قرار می دهم. در ضمن با کارت اسیلوسکوپ خروجی چک شد و به خوبی عمل می کند. فقط در رنج مگاهرتز از 8 مگ به بالا دچار کمی اعوجاج می شود. نکته مهم اینکه حتما مراقب باشید که خروجی ماژول AD9833 مخصوصا در حالت موج مربعی که سطح ولتاژ بالاتری دارد به هم اتصال نکند زیرا موجب صدمه به چیپ آن می شود. ولتاژ ورودی اعمال شده به ای سی رگولاتور 7809 می تواند 12 ولت باشد که محل اتصال آن در تصویر سطح رویی مدار چاپی در مرکز برد و کنار خازنهای الکترولیت مشخص شده است. البته با ولتاژ پورت USB متصل به آردوینو هم مدار کار می کند ولی ثبات کافی ندارد.(یک خازن عدسی 100 نانو فاراد (104) هم اگر با خازن الکترولیت C1 از زیر برد موازی کنید به عملکرد تغذیه مدار کمک می کند).
 
آخرین ویرایش:

Navid-Aref

کاربر vip
vip
کاربر
2008-11-23
438
938
کد کتابخانه ماژول نمایشگر را هم از اینجا دانلود کنید:
GitHub - jlegas/OLED_I2C: 128x64 pixel OLED display library based on the SSD1306 for ARduino / ChipKit / PIC32-PINGUINO

عکس نمونه ساخته شده بر روی برد بورد:
hlebooz5v7ik.jpeg


و نمونه دارای مدار چاپی:
در زیر نمایشگر نیاز هست دو تکه سیم را در محلهای J1 و J2 به عنوان جامپر لحیم کرد. برای اتصال راحتتر آردوینو و ماژول فانکشن و نمایشگر به بورد می توانید از پین هدر مادگی صاف 2.54 میلی متری استفاده کنید. ولی بهتر است ماژول روتاری انکودر را مستقیم لحیم کنید تا موقع چرخاندن و همچنین فشردن بابت تعویض حالت موج با ثبات بماند. (باید پین هدر انکودر را جدا کنید و وارونه لحیم کنید تا انکودر امکان اتصال به برد مدار چاپی را پیدا کند). در مدار آماده زیر که نسخه اول است اتصال دو پین DATA و CLK ماژول روتاری انکودر به آردوینو برعکس بود که مشکلی از بابت کارکرد ایجاد نمی کند ولی جهت چرخش دسته روتاری برعکس بود و ساعتگرد کم میشد (اصولا ساعتگرد باید افزایشی باشد) که در طرح مدار چاپی آپلود شده در پست قبل تصحیح شده است.
sh843h6ccfnp.jpeg

76i388ef5l5n.jpeg

i0ulimks0m36.jpeg
 
آخرین ویرایش:

Navid-Aref

کاربر vip
vip
کاربر
2008-11-23
438
938
پاسخ : ساخت مدار فانکشن ژنراتور 1 هرتز الی 12 مگاهرتز با ماژول AD9833 و آردوینو

چهار کتابخانه مورد نیاز این پروژه را در یک فایل زیپ برای دانلود قرار دادم. و به راحتی می توان آنها از طریق منوی Sketch و زیر منوی Include Library و گزینه ی Add .ZIP Library به نرم افزار آردوینو افزود.
از وبسایت گیت هاب هم قابل دسترس هستند و اگر خواستید از آنجا دانلود کنید.
https://github.com/Billwilliams1952/AD9833-Library-Arduino
https://github.com/adafruit/Adafruit-GFX-Library
https://github.com/adafruit/Adafruit_SSD1306
https://github.com/adafruit/Adafruit_BusIO
 

پیوست‌ها

Navid-Aref

کاربر vip
vip
کاربر
2008-11-23
438
938
عکس ها پاک شدن و مجدد به همراه فایل پروتئوس پروژه آپلودشان می کنم:
اسم درستش هم «فانکشن ژنراتور 1 هرتز الی 12 مگاهرتز با ماژول AD9833 و مدیریت آردوینو» هست. برای منبع تغذیه اش هم استفاده از ترانس با خروجی به خوبی رگوله شده ِ بدون نویز 9 الی 12 ولت - 500 میلی آمپر توصیه می شود تا عملکرد درست و با ثباتی تا فرکانس های بالا داشته باشد. باتری کتابی و منبع تغذیه سوئیچینگ برایش مناسب نیست.
 

پیوست‌ها

آخرین ویرایش:
  • Like
واکنش‌ها[ی پسندها]: meahdi
بالا