#include #include TFT_eSPI tft = TFT_eSPI(); TFT_eSprite ds = TFT_eSprite(&tft); #define SAMPLES 1024 #define SAMPLE_RATE 200000 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; uint32_t lastUpdate = 0; float smooth_f = 0; float static_mid = 2048; void setup_i2s() { i2s_driver_uninstall(I2S_NUM_0); i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN), .sample_rate = SAMPLE_RATE, .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 = 8, .dma_buf_len = 512, .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]; // Возвращаем массив из 5 элементов tft.fillScreen(TFT_BLACK); tft.setTextColor(TFT_WHITE); tft.drawCentreString("TOUCH CORNERS", 160, 100, 2); tft.calibrateTouch(calData, TFT_GREEN, TFT_BLACK, 15); tft.setTouch(calData); tft.fillScreen(TFT_BLACK); } void setup() { pinMode(27, OUTPUT); digitalWrite(27, 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(); } void loop() { uint16_t tx, ty; if (tft.getTouch(&tx, &ty)) { if (ty > 190) { mode = tx / 53; if (mode > 5) mode = 5; delay(150); } } size_t bytes_read = 0; uint16_t raw_buf[SAMPLES * 2]; i2s_read(I2S_NUM_0, (void*)raw_buf, SAMPLES * 4, &bytes_read, portMAX_DELAY); int v_max = 0, v_min = 4096; long v_sum_all = 0; for (int i = 0; i < SAMPLES; i++) { buffer[i] = raw_buf[i * 2] & 0x0FFF; v_sum_all += buffer[i]; if (buffer[i] > v_max) v_max = buffer[i]; if (buffer[i] < v_min) v_min = buffer[i]; } int amp = v_max - v_min; float mid = (float)v_sum_all / SAMPLES; // Супер-медленное сглаживание для неподвижной оси static_mid = static_mid * 0.98 + mid * 0.02; int hyst = amp / 4; if (hyst < 80) hyst = 80; int first = -1, last = -1, p_count = 0; bool state = false; if (amp > 100) { for (int i = 1; i < SAMPLES; i++) { if (!state && (float)buffer[i-1] < mid && (float)buffer[i] >= mid) { if (first == -1) first = i; last = i; p_count++; state = true; } else if (state && (float)buffer[i] < mid - hyst) state = false; } } float inst_f = 0; if (p_count > 1 && (last - first) > 0) { inst_f = (((float)(p_count - 1) * SAMPLE_RATE) / (float)(last - first) / 2.0); if (inst_f < 500) inst_f -= 1.0; else if (inst_f < 1000) inst_f -= 2.0; else inst_f -= 20.0; if (inst_f < 0) inst_f = 0; } if (inst_f > 0) { float k = (inst_f > 5000) ? 0.3 : 0.1; smooth_f = smooth_f * (1.0 - k) + inst_f * k; } else smooth_f = 0; int trig = 0; for (int i = 1; i < SAMPLES / 2; i++) { if ((float)buffer[i-1] < mid && (float)buffer[i] >= mid) { trig = i; break; } } 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 axis_y = map((int)static_mid, v_min - 100, v_max + 100, 155, 5); if (axis_y >= 0 && axis_y <= 160) ds.drawFastHLine(0, axis_y, 320, 0x4208); int window = (SAMPLES / 2) / delays[mode]; int py = map(buffer[trig], v_min - 20, v_max + 20, 155, 5); for (int i = 1; i < 320; i++) { int idx = trig + (i * window / 320); if (idx >= SAMPLES) break; int cy = map(buffer[idx], v_min - 20, v_max + 20, 155, 5); ds.drawLine(i - 1, py, i, cy, TFT_GREEN); py = cy; } ds.pushSprite(0, 30); if (millis() - lastUpdate > 300) { tft.fillRect(0, 0, 320, 30, TFT_BLACK); tft.setTextColor(TFT_YELLOW, TFT_BLACK); tft.setTextSize(2); tft.setCursor(5, 5); float vpp = amp * 0.000846; if (amp > 80) { if (smooth_f >= 1000) tft.printf("%.2fV %.2fkHz", vpp, smooth_f/1000.0); else tft.printf("%.2fV %.0fHz", vpp, smooth_f); } else tft.print("0.00V 0.0Hz"); tft.setTextSize(1); for (int i = 0; i < 6; i++) { tft.drawRect(i * 53, 195, 52, 44, (i == mode) ? TFT_YELLOW : 0x7BEF); tft.setTextColor((i == mode) ? TFT_YELLOW : 0x7BEF); tft.drawCentreString(labels[i], i * 53 + 26, 210, 1); } lastUpdate = millis(); } }