ساخت اسیلوسکوپ با ESP32 ارزان قیمت: اسیلوسکوپ یک ابزار آزمایشی ضروری برای هر مهندس الکترونیک است. برای مشاهده سیگنالهای مختلف، معمولاً به صورت یک نمودار دو بعدی با یک یا چند سیگنال در زمان استفاده میشود.
این دستگاه در طراحی و اشکال زدایی دستگاه های الکترونیکی برای مشاهده و مقایسه شکل موج ها و تعیین سطوح ولتاژ، فرکانس، نویز و سایر پارامترهای سیگنال اعمال شده در ورودی آن با تغییر با زمان استفاده می شوند. این امر اسیلوسکوپ را به ابزاری بسیار مهم بر روی میز یک مهندس یا سازنده الکترونیک تبدیل می کند.
با این حال، اسیلوسکوپ ها بسیار گران هستند. مدل های پایه می توانند از 500 تا 2000 دلار قیمت داشته باشند. و اسیلوسکوپ های پیشرفته چند هزار دلار قیمت دارند که آنها را از دسترس کاربران اصلی خارج می کند.
اما چه میشد اگر بتوانیم یکی را بسازیم که ارزانتر، فشردهتر و آسانتر ساخته شود؟ این سوالی است که منجر به آموزش امروز شد.
ویژگی های اسیلوسکوپ با ESP32
- تک کانال
- 1Msps
- بافر 50000 @ 16bit (50ms داده در 1Msps)
- مقیاس از 10us/div به 5ms/div در 1Msps
- حداکثر VPP 3.3 ولت در 1X و 33V در حالت 10X
- کنترل سریع و پاسخگو با استفاده از سوئیچ های فشاری.
- محاسبات فرکانس (20 هرتز به دلیل اندازه بافر)
- فیلتر mean ساده روشن/خاموش
- حداکثر، حداقل، متوسط و ولتاژ پیک پیک
- افست زمان و ولتاژ
- حالت آنالوگ، دیجیتال/داده
- تک TRIGGER
- AUTOSCALE
اجزای مورد نیاز برای ساخت اسیلوسکوپ با ESP32
- ESP32 Devkit
- 1.69” 240×280 Rounded Corner TFT display(ST7789s)
- Tactile switches
- SPDT switches
- 100K resistor
- 10K resistor
- 100nF capacitor
- Copper clad or perfboard
- Soldering tools
شماتیک مدار اسیلوسکوپ با ESP32
شماتیک مدار کامل اسیلوسکوپ با ESP32 در زیر آورده شده است.

ESP32 به عنوان کنترل کننده برای جمع آوری داده ها استفاده می شود. ما از بافر داخلی I2S برای ذخیره و دستکاری سیگنال ها استفاده خواهیم کرد. در اینجا از نوع 38 پین استفاده می شود، اما می توانید از ماژول های توسعه دیگر نیز استفاده کنید.

برای نمایشگر، ما از یک ماژول صفحه نمایش 1.69 اینچی TFT استفاده می کنیم. وضوح تصویر 240×280 پیکسل است. کنترلر نمایشگر ST7789S است و برای درایو آن، از ارتباط SPI استفاده خواهیم کرد.

ماژول همچنین دارای یک اسلات کارت SD است که ما از آن استفاده نکرده ایم. ما می توانیم از این برای ضبط شکل موج یا کاربرد های مشابه در به روز رسانی آینده استفاده کنیم.

صفحه کلید بسیار ساده است. برای این منظور از کلیدهای لمسی با مقاومت پول آپ استفاده می شود. ما از وقفه سخت افزاری برای تشخیص هر فشار کلید استفاده می کنیم.

بخش ورودی آنالوگ نسبتاً ساده است. از دو سوئیچ SPDT برای انتخاب محدوده و انتخاب کوپلینگ AC/DC تشکیل شده است. برای انتخاب محدوده، ما یک تقسیم کننده ولتاژ اضافه کرده ایم که می تواند برای تغذیه سیگنال هایی که ولتاژ پیک بالاتر از 3.3 ولت دارند استفاده شود. تقسیم کننده ولتاژ سیگنال را به نسبت 10:1 تبدیل می کند.

ساخت و تست مدار
شما می توانید این پروژه را در برد های هزار سوراخ یا برد بورد بسازید یا می توانید فایل ها را از لینک پایین صفحه دانلود کرده و یک PCB بسازید. هر دو فایل PDF برای روش انتقال تونر و فایل Gerber برای ساخت گنجانده شده است. در اینجا طرح PCB برای اسیلوسکوپ آمده است.

نمای قظعات روی برد

نمای PCB سمت پایین.

کد آردوینو
کل کد آردوینو برای اسیلوسکوپ با ESP32 را از این قسمت، دانلود کنید.
در مخزن GitHub، شما همچنین می توانید بایگانی به نام TFT_eSPI را پیدا کنید. این کتابخانه اصلاح شده برای درایو نمایشگر ضروری است. آن را در پوشه کتابخانه آردوینو استخراج کنید.اگر قبلاً کتابخانه TFT_eSPI را نصب کردهاید، قبل از استخراج کتابخانه ویرایششده، حتماً آن را حذف کنید.
پس از اتمام کار، esp32 را در board manager انتخاب کنید. سپس کد را کامپایل کرده و آپلود کنید. این اسیلوسکوپ DIY ما آماده استفاده است. شما می توانید اسیلوسکوپ را با استفاده از پورت Micro USB در پایین تغذیه کنید. این پورت فقط برای پاور است.
#include <Arduino.h> #include <driver/i2s.h> #include <driver/adc.h> #include <soc/syscon_reg.h> #include <TFT_eSPI.h> #include <SPI.h> #include "esp_adc_cal.h" #include "filters.h" //#define DEBUG_SERIAL //#define DEBUG_BUFF #define DELAY 1000 // Width and height of sprite #define WIDTH 240 #define HEIGHT 280 #define ADC_CHANNEL ADC1_CHANNEL_5 // GPIO33 #define NUM_SAMPLES 1000 // number of samples #define I2S_NUM (0) #define BUFF_SIZE 50000 #define B_MULT BUFF_SIZE/NUM_SAMPLES #define BUTTON_Ok 32 #define BUTTON_Plus 15 #define BUTTON_Minus 35 #define BUTTON_Back 34 TFT_eSPI tft = TFT_eSPI(); // Declare object "tft" TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object esp_adc_cal_characteristics_t adc_chars; TaskHandle_t task_menu; TaskHandle_t task_adc; float v_div = 825; float s_div = 10; float offset = 0; float toffset = 0; uint8_t current_filter = 1; //options handler enum Option { None, Autoscale, Vdiv, Sdiv, Offset, TOffset, Filter, Stop, Mode, Single, Clear, Reset, Probe, UpdateF, Cursor1, Cursor2 }; int8_t volts_index = 0; int8_t tscale_index = 0; uint8_t opt = None; bool menu = false; bool info = true; bool set_value = false; float RATE = 1000; //in ksps --> 1000 = 1Msps bool auto_scale = false; bool full_pix = true; bool stop = false; bool stop_change = false; uint16_t i2s_buff[BUFF_SIZE]; bool single_trigger = false; bool data_trigger = false; bool updating_screen = false; bool new_data = false; bool menu_action = false; uint8_t digital_wave_option = 0; //0-auto | 1-analog | 2-digital data (SERIAL/SPI/I2C/etc) int btnok,btnpl,btnmn,btnbk; void IRAM_ATTR btok() { btnok = 1; } void IRAM_ATTR btplus() { btnpl = 1; } void IRAM_ATTR btminus() { btnmn = 1; } void IRAM_ATTR btback() { btnbk = 1; } void setup() { Serial.begin(115200); configure_i2s(1000000); setup_screen(); pinMode(BUTTON_Ok , INPUT); pinMode(BUTTON_Plus , INPUT); pinMode(BUTTON_Minus , INPUT); pinMode(BUTTON_Back , INPUT); attachInterrupt(BUTTON_Ok, btok, RISING); attachInterrupt(BUTTON_Plus, btplus, RISING); attachInterrupt(BUTTON_Minus, btminus, RISING); attachInterrupt(BUTTON_Back, btback, RISING); characterize_adc(); #ifdef DEBUG_BUF debug_buffer(); #endif xTaskCreatePinnedToCore( core0_task, "menu_handle", 10000, /* Stack size in words */ NULL, /* Task input parameter */ 0, /* Priority of the task */ &task_menu, /* Task handle. */ 0); /* Core where the task should run */ xTaskCreatePinnedToCore( core1_task, "adc_handle", 10000, /* Stack size in words */ NULL, /* Task input parameter */ 3, /* Priority of the task */ &task_adc, /* Task handle. */ 1); /* Core where the task should run */ } void core0_task( void * pvParameters ) { (void) pvParameters; for (;;) { menu_handler(); if (new_data || menu_action) { new_data = false; menu_action = false; updating_screen = true; update_screen(i2s_buff, RATE); updating_screen = false; vTaskDelay(pdMS_TO_TICKS(10)); Serial.println("CORE0"); } vTaskDelay(pdMS_TO_TICKS(10)); } } void core1_task( void * pvParameters ) { (void) pvParameters; for (;;) { if (!single_trigger) { while (updating_screen) { vTaskDelay(pdMS_TO_TICKS(1)); } if (!stop) { if (stop_change) { i2s_adc_enable(I2S_NUM_0); stop_change = false; } ADC_Sampling(i2s_buff); new_data = true; } else { if (!stop_change) { i2s_adc_disable(I2S_NUM_0); i2s_zero_dma_buffer(I2S_NUM_0); stop_change = true; } } Serial.println("CORE1"); vTaskDelay(pdMS_TO_TICKS(300)); } else { float old_mean = 0; while (single_trigger) { stop = true; ADC_Sampling(i2s_buff); float mean = 0; float max_v, min_v; peak_mean(i2s_buff, BUFF_SIZE, &max_v, &min_v, &mean); //signal captured (pp > 0.4V || changing mean > 0.2V) -> DATA ANALYSIS if ((old_mean != 0 && fabs(mean - old_mean) > 0.2) || to_voltage(max_v) - to_voltage(min_v) > 0.05) { float freq = 0; float period = 0; uint32_t trigger0 = 0; uint32_t trigger1 = 0; //if analog mode OR auto mode and wave recognized as analog bool digital_data = !false; if (digital_wave_option == 1) { trigger_freq_analog(i2s_buff, RATE, mean, max_v, min_v, &freq, &period, &trigger0, &trigger1); } else if (digital_wave_option == 0) { digital_data = digital_analog(i2s_buff, max_v, min_v); if (!digital_data) { trigger_freq_analog(i2s_buff, RATE, mean, max_v, min_v, &freq, &period, &trigger0, &trigger1); } else { trigger_freq_digital(i2s_buff, RATE, mean, max_v, min_v, &freq, &period, &trigger0); } } else { trigger_freq_digital(i2s_buff, RATE, mean, max_v, min_v, &freq, &period, &trigger0); } single_trigger = false; new_data = true; Serial.println("Single GOT"); //return to normal execution in stop mode } vTaskDelay(pdMS_TO_TICKS(1)); //time for the other task to start (low priorit) } vTaskDelay(pdMS_TO_TICKS(300)); } } } void loop() {}
ویدیو نحوه عملکرد
در این قسمت ویدیویی از نحوه عملکرد پروژه اسیلسکوپ با ESP32 آورده شده توجه کنید که این ویدیو در یوتیوب اپلود شده در صورت نیاز از تحریم شکن استفاده کنید
خسته نباشید ✋
یه سوال واقعا مدار 20 هرتر رو نشون میده ؟ فکر میکنم یه اشتباهی شده خیلی میتونه بالا تر از اینا رو هم نشون بده
سلام وقت بخیر بله همینطور که فرمودید هست در واقع محدودیت در محاسبات فرکانسی بدلیل کمبود حافظه بافر تا ماکزیمم 20 هرتز میتونه باشه
اما پهنای باند فرکانسی مطمئنا بیشتر خواهد بود