#include #include TFT_eSPI tft = TFT_eSPI(); TFT_eSprite ds = TFT_eSprite(&tft); #define INPUT_PIN 35 #define BL_PIN 27 #define SAMPLES 1024 uint16_t buffer[SAMPLES]; uint32_t delays[] = {1, 2, 4, 8, 16, 32}; const char* labels[] = {"MAX", "x2", "x4", "x8", "x16", "x32"}; int mode = 0; void setup_i2s() { i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN), .sample_rate = 150000, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, .communication_format = I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 2, .dma_buf_len = SAMPLES, .use_apll = false }; i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_7); i2s_adc_enable(I2S_NUM_0); } // Функция калибровки тача void touch_calibrate() { uint16_t calData[5]; tft.fillScreen(TFT_BLACK); tft.setCursor(20, 0); tft.setTextColor(TFT_WHITE); tft.setTextSize(1); tft.println("Нажми на углы, как показано"); tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15); tft.fillScreen(TFT_BLACK); } void setup() { pinMode(BL_PIN, OUTPUT); digitalWrite(BL_PIN, HIGH); pinMode(21, OUTPUT); digitalWrite(21, HIGH); tft.init(); tft.setRotation(1); tft.invertDisplay(false); touch_calibrate(); // Запуск калибровки при старте ds.setColorDepth(8); ds.createSprite(320, 160); setup_i2s(); drawButtons(); } void drawButtons() { tft.setTextSize(1); for (int i = 0; i < 6; i++) { uint16_t btnColor = (i == mode) ? TFT_YELLOW : 0x7BEF; tft.drawRect(i * 53, 195, 52, 44, btnColor); tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setCursor(i * 53 + 5, 215); tft.print(labels[i]); } } void loop() { // 1. ТАЧ (упрощенный опрос) uint16_t tx, ty; if (tft.getTouch(&tx, &ty)) { if (ty > 190) { mode = tx / 53; if (mode > 5) mode = 5; drawButtons(); delay(150); } } // 2. ЗАХВАТ size_t read_len; i2s_read(I2S_NUM_0, (void*)buffer, SAMPLES * 2, &read_len, portMAX_DELAY); // 3. РАСЧЕТ int crossings = 0; int v_max = 0, v_min = 4096; for (int i = 0; i < SAMPLES; i++) { buffer[i] &= 0x0FFF; if (i > 0 && buffer[i-1] < 2048 && buffer[i] >= 2048) crossings++; if (buffer[i] > v_max) v_max = buffer[i]; if (buffer[i] < v_min) v_min = buffer[i]; } // Частота с учетом удвоения и реального времени float freq = (crossings * 150000.0) / SAMPLES / 2.0; // 4. ГРАФИК ds.fillSprite(TFT_BLACK); for(int x=0; x<320; x+=40) ds.drawFastVLine(x, 0, 160, 0x2104); for(int y=0; y<160; y+=40) ds.drawFastHLine(0, y, 320, 0x2104); int step = delays[mode]; for (int i = 1; i < 320; i++) { int idx = i * step; if (idx >= SAMPLES) break; // Автомасштаб по вертикали, чтобы видеть даже слабый сигнал int y1 = map(buffer[idx-step], v_min, v_max, 155, 5); int y2 = map(buffer[idx], v_min, v_max, 155, 5); ds.drawLine(i-1, y1, i, y2, TFT_GREEN); } ds.pushSprite(0, 30); // 5. ТЕКСТ float vpp = ((v_max - v_min) * 3.3) / 4095.0; tft.setCursor(5, 5); tft.setTextColor(TFT_YELLOW, TFT_BLACK); if (vpp > 0.4) { if (freq > 999) tft.printf("Vpp:%.2fV F:%.2fkHz ", vpp, freq / 1000.0); else tft.printf("Vpp:%.2fV F:%.0fHz ", vpp, freq); } else { tft.printf("Vpp:%.2fV F:0Hz ", vpp); } }