Oscilloscope DIY ESP32

Oscilloscope DIY ESP32

Oscilloscope de bricolage utilisant ESP32 – Aperçu rapide

Construire le temps: 6-8 heures | Coût: 30-50 $ | Difficulté: Intermédiaire

Ce que vous apprendrez: Échantillonnage ADC, communication SPI, interfaçage d’affichage TFT, manipulation d’interruption

Applications: Débogage du signal, analyse des formes d’onde, mesure de fréquence, surveillance de la tension

Fonctionnalité Spécification Performance
Canaux Canal unique Est-ce que le travail pour l’analyse du signal de base
Taux d’échantillonnage 1MSPS Idéal pour l’analyse audio, capteur et à basse fréquence
Tampon 50000 @ 16bits Capture de données 50 ms à 1MSPS
Échelle de temps 10us / div à 5ms / div Options de synchronisation polyvalente
Tension d’entrée 3,3 V (1x), 33V (10x) Plage d’exploitation sûre
Temps de réponse Contrôle tactile rapide Surveillance du signal en temps réel
Gamme de fréquences 20 Hz minimum Limité par les contraintes de tampon

»Il a une fonctionnalité de filtre moyenne sur / désactivée simple
»Mesures de tension max, min, moyenne et crête de pointe
»Ajustements de décalage de temps et de tension
»Fonctionnement du mode analogique et numérique / données
»Capacité de déclenchement unique
»Fonction à l’échelle automatique pour la configuration automatique

Composant Spécification Quantité But
ESP32 Devkit Variante à 38 broches recommandée 1 Le microcontrôleur principal
Affichage TFT 1,69 « 240×280 ST7789 1 Visualisation du signal
Commutateurs tactiles 6 mm standard 6 Contrôle de l’interface utilisateur
Commutateurs SPDT Type à bascule 2 Sélection de plage / couplage
Résistances 100k, 10k 1 chacun Conditionnement d’entrée
Condensateur Céramique 100NF 1 Couplage AC
PCB / Perfboard Cuivre vêtu de cuivre 1 Assemblage de circuit

1755837101 509 Comment fonctionne un module de carte micro SD et comment

»Rendu de forme d’onde haute résolution
»Mises à jour du signal en temps réel
»Esclot de carte SD intégré pour la journalisation des données futures
»La conception maintient la consommation d’énergie au minimum

»Mesure de tension à double portée (3,3 V et 33 V)
»Sélection de couplage AC / DC
»Circuits de protection d’entrée
»Division de tension de précision

»Route de signal optimisé pour un bruit minimal
»Conception de facteur de forme compact
»Accessibilité des composants faciles
»Compatible pour la fabrication professionnelle

Processus d’assemblage:

»Vérification du placement des composants
»Optimisation de séquence de soudage
»Test de chemin de signal
»Procédures d’étalonnage

Étapes de programmation:

»Installation de la bibliothèque: Extraire le dossier de bibliothèque TFT_ESPI modifié à Arduino
»Sélection du conseil: Choisissez ESP32 dans Arduino Board Manager
»Compilation de code: Vérifiez la compilation de code sans erreurs
»Télécharger le processus: Flash firmware sur ESP32 via USB
»Configuration de l’alimentation: utilisez le port micro USB pour l’alimentation 5V

Caractéristiques du code:

»Gestion de tampon I2S optimisée
»Rendu de forme d’onde en temps réel
»Interface utilisateur axée sur l’interruption
»Routines d’étalonnage
»Algorithmes de traitement du signal

Référentiel GitHub

Questions courantes sur ce projet d’oscilloscope ESP32

Q1. Cela peut-il remplacer un véritable oscilloscope?
Pas vraiment. Un DSO commercial (Rigol, Siglent, etc.) peut goûter des centaines de fois plus rapidement et a une mémoire profonde, plusieurs canaux et des fins frontales précises. Cette version ESP32 est plus une «portée d’apprentissage», idéale pour l’audio, les capteurs et les signaux numériques lents, mais il ne captera pas des problèmes à grande vitesse ou une activité de bus MHZ.

Q2. Quelle est la plage d’entrée sûre?
Avec le diviseur de tension, vous pouvez regarder des signaux jusqu’à environ 33 V pic. Sans cela, l’ESP32 ne tolère que 3,3 V max. Ne connectez pas cela directement aux secteur (120/230 V AC) ou quoi que ce soit de haute énergie. Ce n’est pas isolé et vous frirez la planche (ou vous-même).

Q3. Pourquoi la forme d’onde a-t-elle l’air bruyante ou un peu «déchiquetée»?
C’est juste l’ADC de l’ESP32. Ce n’est pas de qualité en laboratoire. Il y a du bruit de quantification et de la non-linéarité. Le filtre moyen aide, mais vous devez vous attendre à des parcelles «assez bonnes», pas à des signaux de rasoir comme vous le verriez sur un tektronix.

Q4. Quel est le signal de fréquence le plus élevé que je peux mesurer?
Réfléchissez dans les dizaines de KHZ, peut-être des centaines basses si vous n’êtes pas pointilleux sur la précision. La fréquence d’échantillonnage 1 MSPS et la taille du tampon limitent la bande passante. C’est bien pour les données PWM, audio et capteurs. Pas pour RF ou des bus numériques rapides comme SPI ou USB.

Q5. Est-ce vraiment «en temps réel»?
Sorte de. L’affichage met à jour assez rapidement pour qu’il se sente en direct pour les signaux lents et à mi-vitesse. Mais par rapport à une portée commerciale, il y a un décalage notable et la profondeur de capture est peu profonde. C’est assez en temps réel pour le travail de passe-temps, pas pour déboguer un circuit complexe.

Compteur de puissance basé sur Arduino et ESP32Générateur de fonctions basé sur AD9833 et Arduino

Générateur de fonctions basé sur AD9833 et Arduino

Dans cet article, nous allons construire un générateur de signaux simple avec un module de générateur de fonction ARDUINO et AD9833 qui peut produire des ondes sinusoïdales, carrées et triangulaires avec une fréquence maximale de 12 MHz à la sortie.

Lecteur audio basé sur DIY ESP32

Lecteur audio basé sur DIY ESP32

Ici, nous utilisons LM386 et un haut-parleur avec ESP32 pour lire des fichiers musicaux. La sortie audio n’est peut-être pas bruyante, mais cette application montre la capacité de la carte ESP32 à lire des fichiers audio.

Code de projet complet

Copier de code

#include 
#include 
#include 
#include 
#include 
#include 
#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() {}

Retrouvez l’histoire de Raspberry Pi dans cette vidéo :

YouTube video

  • ESP32 4-Channel Relay Module Ulegqin ESP32-WROOM Relay Carte de développement avec WIFI Bluetooth BLE Alimentation AC/DC pour Projets de programmation DIY(LC-Relay-ESP32-4R-A2)
  • BSIDE OT5 Mini Oscilloscope Numérique Portable 50MHz Bande Passante 200MSa/s Échantillonnage Oscilloscope de Poche Rechargeable Ultra Mince avec Écran Couleur 3,2” pour Électronique Audio Automobile