Cómo hacer un mini-osciloscopio en casa con Arduino Nano

 

Cómo hacer un mini osciloscopio en casa con Arduino Nano

Cómo hacer un mini-osciloscopio en casa con Arduino Nano

 

ard nano
arduino nano r3
× 1
LCD OLED 128x64 1
Módulo de pantalla OLED 64×128 de 0,96″ ElectroPeak
× 1
19c7994 40
Interruptor táctil, accionado desde arriba
× 9
Imagen Fairchild semiconductor 1n4148
1N4148 – Interruptor rápido de uso general
× 4

Aplicaciones y servicios en línea

idea web
IDE de Arduino

Acerca de este proyecto

tutorial completo

En este video te mostraré cómo hacer tu propio mini osciloscopio en casa. Es simple y fácil de hacer. Este no es mi propio código, solo estoy haciendo un tutorial para ustedes. Para llevar a cabo este proyecto, dependía del código fuente de terceros, cuyo enlace se proporciona a continuación. Si tiene alguna pregunta o sugerencia, no dude en comentar en mi video de youtube y no olvides darle me gusta y suscribirte a mi canal de youtube.

Haga clic aquí para ver el tutorial completo y el código fuente.

Mi GI: https://www.instagram.com/pm.goharian/

Componentes necesarios

  • arduino nano
  • Pantalla OLED SSD1306
  • 1N4148
  • Micro interruptor
  • 104 condensador
  • Resistencias: 100Ω, 12k, 120k, 510k

¿Qué es un osciloscopio?

Un «osciloscopio», anteriormente llamado «oscilógrafo», e informalmente conocido como alcance Dónde alcance,CRO (para osciloscopio de rayos catódicos), o DSO (para el osciloscopio de almacenamiento digital más moderno), es un tipo de instrumento de prueba electrónico que muestra gráficamente una señal variable [voltages], generalmente como un gráfico bidimensional de una o más señales contra el tiempo. Otras señales (como sonidos o vibraciones) pueden convertirse en voltajes y mostrarse.

Los osciloscopios muestran el cambio de una señal eléctrica a lo largo del tiempo, con el voltaje y el tiempo como ejes Y y X, respectivamente, en una escala calibrada. Luego, la forma de onda se puede analizar en busca de propiedades como amplitud, frecuencia, tiempo de subida, intervalo de tiempo, distorsión, etc. Los instrumentos digitales modernos pueden calcular y mostrar directamente estas propiedades. Originalmente, calcular estos valores requería medir manualmente la forma de onda contra escalas integradas en la pantalla del instrumento.

diagramas de proyecto

Notar: Asegúrese de que todas las conexiones en su circuito sean exactamente iguales a las que se muestran en los diagramas.

 

referencia :

http://radiopench.blog96.fc2.com/blog-entry-893.html

https://www.wikipedia.org/

codificado

codificadoC/C++
/*
     (_20190212_OLEDoscilloscope.ino)
     1285byte ram free
    2019/02/12 
*/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <avr/pgmspace.h>               // PROGMEM
#include <EEPROM.h>

#define SCREEN_WIDTH 128                // OLED display width
#define SCREEN_HEIGHT 64                // OLED display height
#define REC_LENGTH 200                  // 

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1      // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//
const char vRangeName[10][5] PROGMEM = {"A50V", "A 5V", " 50V", " 20V", " 10V", "  5V", "  2V", "  1V", "0.5V", "0.2V"}; // \0
const char * const vstring_table[] PROGMEM = {vRangeName[0], vRangeName[1], vRangeName[2], vRangeName[3], vRangeName[4], vRangeName[5], vRangeName[6], vRangeName[7], vRangeName[8], vRangeName[9]};
const char hRangeName[8][6] PROGMEM = {" 50ms", " 20ms", " 10ms", "  5ms", "  2ms", "  1ms", "500us", "200us"};          // (48
const char * const hstring_table[] PROGMEM = {hRangeName[0], hRangeName[1], hRangeName[2], hRangeName[3], hRangeName[4], hRangeName[5], hRangeName[6], hRangeName[7]};

int waveBuff[REC_LENGTH];      //  (RAM)
char chrBuff[10];              // 
String hScale = "xxxAs";
String vScale = "xxxx";

float lsb5V = 0.0055549;       // 5V0.005371 V/1LSB
float lsb50V = 0.051513;       // 50V 0.05371

volatile int vRange;           //   0:A50V, 1:A 5V, 2:50V, 3:20V, 4:10V, 5:5V, 6:2V, 7:1V, 8:0.5V
volatile int hRange;           // 0:50m, 1:20m, 2:10m, 3:5m, 4;2m, 5:1m, 6:500u, 7;200u
volatile int trigD;            // 0:1:
volatile int scopeP;           //  0:, 1:, 2:
volatile boolean hold = false; // 
volatile boolean paraChanged = false; //  true
volatile int saveTimer;        // EEPROM
int timeExec;                  // (ms)

int dataMin;                   // (min:0)
int dataMax;                   // (max:1023)
int dataAve;                   // 10 max:10230)
int rangeMax;                  // 
int rangeMin;                  // 
int rangeMaxDisp;              // max100
int rangeMinDisp;              // min
int trigP;                     // 
boolean trigSync;              // 
int att10x;                    // 1

void setup() {
  pinMode(2, INPUT_PULLUP);    // (int0
  pinMode(8, INPUT_PULLUP);    // Select
  pinMode(9, INPUT_PULLUP);    // Up
  pinMode(10, INPUT_PULLUP);   // Down
  pinMode(11, INPUT_PULLUP);   // Hold 
  pinMode(12, INPUT);          // 1/10
  pinMode(13, OUTPUT);         // 

  //     Serial.begin(115200);        // RAM
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
    //       Serial.println(F("SSD1306 failed"));
    for (;;);                               // Don't proceed, loop forever
  }
  loadEEPROM();                             // EEPROM
  analogReference(INTERNAL);                // ADC1.1Vvref)
  attachInterrupt(0, pin2IRQ, FALLING);     // 
  startScreen();                            // 
}

void loop() {
  digitalWrite(13, HIGH);
  setConditions();                          // RAM40
  readWave();                               //  (1.6ms )
  digitalWrite(13, LOW);                    //
  dataAnalize();                            // (0.4-0.7ms)
  writeCommonImage();                       // (4.6ms)
  plotData();                               // (5.4ms+)
  dispInf();                                // (6.2ms)
  display.display();                        // (37ms)
  saveEEPROM();                             // EEPROM
  while (hold == true) {                    // Hold
    dispHold();
    delay(10);
  }
}

void setConditions() {   // 
  // PROGMEM
  strcpy_P(chrBuff, (char*)pgm_read_word(&(hstring_table[hRange])));  // 
  hScale = chrBuff;                                                   // hScale

  // 
  strcpy_P(chrBuff, (char*)pgm_read_word(&(vstring_table[vRange])));  // 
  vScale = chrBuff;                                                   // vScale

  switch (vRange) {              // 
    case 0: {                    // Auto50V
        //        rangeMax = 1023;
        //        rangeMin = 0;
        att10x = 1;              // 
        break;
      }
    case 1: {                    // Auto 5V
        //        rangeMax = 1023;
        //        rangeMin = 0;
        att10x = 0;              // 
        break;
      }
    case 2: {                    // 50V
        rangeMax = 50 / lsb50V;  // 
        rangeMaxDisp = 5000;     // 100
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 1;              // 
        break;
      }
    case 3: {                    // 20V
        rangeMax = 20 / lsb50V;  // 
        rangeMaxDisp = 2000;
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 1;              // 
        break;
      }
    case 4: {                    // 10V
        rangeMax = 10 / lsb50V;  // 
        rangeMaxDisp = 1000;
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 1;              // 
        break;
      }
    case 5: {                    // 5V
        rangeMax = 5 / lsb5V;    // 
        rangeMaxDisp = 500;
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 0;              // 
        break;
      }
    case 6: {                    // 2V
        rangeMax = 2 / lsb5V;    // 
        rangeMaxDisp = 200;
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 0;              // 
        break;
      }
    case 7: {                    // 1V
        rangeMax = 1 / lsb5V;    // 
        rangeMaxDisp = 100;
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 0;              // 
        break;
      }
    case 8: {                    // 0.5V
        rangeMax = 0.5 / lsb5V;  // 
        rangeMaxDisp = 50;
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 0;              // 
        break;
      }
    case 9: {                    // 0.5V
        rangeMax = 0.2 / lsb5V;  // 
        rangeMaxDisp = 20;
        rangeMin = 0;
        rangeMinDisp = 0;
        att10x = 0;              // 
        break;
      }
  }
}

void writeCommonImage() {     // 
  display.clearDisplay();                   // (0.4ms)
  display.setTextColor(WHITE);              // 
  display.setCursor(86, 0);                 // Start at top-left corner
  display.println(F("av    V"));            // 1
  display.drawFastVLine(26, 9, 55, WHITE);  // 
  display.drawFastVLine(127, 9, 55, WHITE); // 

  display.drawFastHLine(24, 9, 7, WHITE);   // Max
  display.drawFastHLine(24, 36, 2, WHITE);  //
  display.drawFastHLine(24, 63, 7, WHITE);  //

  display.drawFastHLine(51, 9, 3, WHITE);   // Max
  display.drawFastHLine(51, 63, 3, WHITE);  //

  display.drawFastHLine(76, 9, 3, WHITE);   // Max
  display.drawFastHLine(76, 63, 3, WHITE);  //

  display.drawFastHLine(101, 9, 3, WHITE);  // Max
  display.drawFastHLine(101, 63, 3, WHITE); //

  display.drawFastHLine(123, 9, 5, WHITE);  // Max
  display.drawFastHLine(123, 63, 5, WHITE); // 

  for (int x = 26; x <= 128; x += 5) {
    display.drawFastHLine(x, 36, 2, WHITE); // ()
  }
  for (int x = (127 - 25); x > 30; x -= 25) {
    for (int y = 10; y < 63; y += 5) {
      display.drawFastVLine(x, y, 2, WHITE); // 3
    }
  }
}

void readWave() {                            // 
  if (att10x == 1) {                         // 1/10
    pinMode(12, OUTPUT);                     // 
    digitalWrite(12, LOW);                   // LOW
  } else {                                   // 
    pinMode(12, INPUT);                      // Hi-z
  }

  switch (hRange) {                          // 

    case 0: {                                // 50ms
        timeExec = 400 + 50;                 // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x07;              // 128 (arduino
        for (int i = 0; i < REC_LENGTH; i++) {     // 200
          waveBuff[i] = analogRead(0);       // 112s
          delayMicroseconds(1888);           // 
        }
        break;
      }

    case 1: {                                // 20ms
        timeExec = 160 + 50;                 // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x07;              // 128 (arduino
        for (int i = 0; i < REC_LENGTH; i++) {     // 200
          waveBuff[i] = analogRead(0);       // 112s
          delayMicroseconds(688);            // 
        }
        break;
      }

    case 2: {                                // 10 ms
        timeExec = 80 + 50;                  // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x07;              // 128 (arduino
        for (int i = 0; i < REC_LENGTH; i++) {     // 200
          waveBuff[i] = analogRead(0);       // 112s
          delayMicroseconds(288);            // 
        }
        break;
      }

    case 3: {                                // 5 ms
        timeExec = 40 + 50;                  // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x07;              // 128 (arduino
        for (int i = 0; i < REC_LENGTH; i++) {     // 200
          waveBuff[i] = analogRead(0);       // 112s
          delayMicroseconds(88);             // 
        }
        break;
      }

    case 4: {                                // 2 ms
        timeExec = 16 + 50;                  // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x06;              // 64 (0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128)
        for (int i = 0; i < REC_LENGTH; i++) {     // 200
          waveBuff[i] = analogRead(0);       // 56s
          delayMicroseconds(24);             // 
        }
        break;
      }

    case 5: {                                // 1 ms
        timeExec = 8 + 50;                   // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x05;              // 16 (0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128)
        for (int i = 0; i < REC_LENGTH; i++) {     // 200
          waveBuff[i] = analogRead(0);       // 28s
          delayMicroseconds(12);             // 
        }
        break;
      }

    case 6: {                                // 500us
        timeExec = 4 + 50;                   // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x04;              // 16(0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128)
        for (int i = 0; i < REC_LENGTH; i++) {     // 200
          waveBuff[i] = analogRead(0);       // 16s
          delayMicroseconds(4);              // 
          // 1.875snop 110.0625s @16MHz)
          asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
          asm("nop"); asm("nop"); asm("nop");
        }
        break;
      }

    case 7: {                                // 200us
        timeExec = 2 + 50;                   // (ms) EEPROM
        ADCSRA = ADCSRA & 0xf8;              // 3
        ADCSRA = ADCSRA | 0x02;              // :4(0x1=2, 0x2=4, 0x3=8, 0x4=16, 0x5=32, 0x6=64, 0x7=128)
        for (int i = 0; i < REC_LENGTH; i++) {
          waveBuff[i] = analogRead(0);       // 6s
          // 1.875snop 110.0625s @16MHz)
          asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
          asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
          asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
        }
        break;
      }
  }
}

void dataAnalize() {                   // 
  int d;
  long sum = 0;

  // 
  dataMin = 1023;                         // 
  dataMax = 0;                            // 
  for (int i = 0; i < REC_LENGTH; i++) {  // 
    d = waveBuff[i];
    sum = sum + d;
    if (d < dataMin) {                    // 
      dataMin = d;
    }
    if (d > dataMax) {                    // 
      dataMax = d;
    }
  }

  // 
  dataAve = (sum + 10) / 20;               // 10

  // max,min
  if (vRange <= 1) {                       // Auto1
    rangeMin = dataMin - 20;               // -20
    rangeMin = (rangeMin / 10) * 10;       // 10
    if (rangeMin < 0) {
      rangeMin = 0;                        // 0
    }
    rangeMax = dataMax + 20;               // +20
    rangeMax = ((rangeMax / 10) + 1) * 10; // 10
    if (rangeMax > 1020) {
      rangeMax = 1023;                     // 10201023
    }

    if (att10x == 1) {                            // 
      rangeMaxDisp = 100 * (rangeMax * lsb50V);   // ADC
      rangeMinDisp = 100 * (rangeMin * lsb50V);   // 
    } else {                                      // 
      rangeMaxDisp = 100 * (rangeMax * lsb5V);
      rangeMinDisp = 100 * (rangeMin * lsb5V);
    }
  } else {                                   // 
    // 
  }

  // 
  for (trigP = ((REC_LENGTH / 2) - 51); trigP < ((REC_LENGTH / 2) + 50); trigP++) { // 
    if (trigD == 0) {                        // 0
      if ((waveBuff[trigP - 1] < (dataMax + dataMin) / 2) && (waveBuff[trigP] >= (dataMax + dataMin) / 2)) {
        break;                              // 
      }
    } else {                                // 0
      if ((waveBuff[trigP - 1] > (dataMax + dataMin) / 2) && (waveBuff[trigP] <= (dataMax + dataMin) / 2)) {
        break;
      }                                    // 
    }
  }
  trigSync = true;
  if (trigP >= ((REC_LENGTH / 2) + 50)) {  // 
    trigP = (REC_LENGTH / 2);
    trigSync = false;                      // Unsync
  }
}

void startScreen() {                 // 
  display.clearDisplay();
  display.setTextSize(1);            // 2
  display.setTextColor(WHITE);       //
  display.setCursor(10, 25);         //
  display.println(F("PM.GOHARIAN"));   // 
  display.setCursor(10, 45);         //
  display.println(F("Pen oscope"));
  display.display();                 // 
  delay(5000);
  display.clearDisplay();
  display.setTextSize(1);            // 
}

void dispHold() {                            // Hold
  display.fillRect(32, 12, 24, 8, BLACK);    // 4
  display.setCursor(32, 12);
  display.print(F("Hold"));                  // Hold 
  display.display();                         //
}

void dispInf() {                             // 
  float voltage;
  // 
  display.setCursor(2, 0);                   // 
  display.print(vScale);                     // 
  if (scopeP == 0) {                         // 
    display.drawFastHLine(0, 7, 27, WHITE);  // 
    display.drawFastVLine(0, 5, 2, WHITE);
    display.drawFastVLine(26, 5, 2, WHITE);
  }

  // 
  display.setCursor(34, 0);                  //
  display.print(hScale);                     // (time/div)
  if (scopeP == 1) {                         // 
    display.drawFastHLine(32, 7, 33, WHITE); // 
    display.drawFastVLine(32, 5, 2, WHITE);
    display.drawFastVLine(64, 5, 2, WHITE);
  }

  // 
  display.setCursor(75, 0);                  // 
  if (trigD == 0) {
    display.print(char(0x18));               // 
  } else {
    display.print(char(0x19));               //               
  }
  if (scopeP == 2) {      // 
    display.drawFastHLine(71, 7, 13, WHITE); // 
    display.drawFastVLine(71, 5, 2, WHITE);
    display.drawFastVLine(83, 5, 2, WHITE);
  }

  // 
  if (att10x == 1) {                         // 10
    voltage = dataAve * lsb50V / 10.0;       // 50V
  } else {
    voltage = dataAve * lsb5V / 10.0;        // 5V
  }
  dtostrf(voltage, 4, 2, chrBuff);           // x.xx 
  display.setCursor(98, 0);                  // 
  display.print(chrBuff);                    // 
  //  display.print(saveTimer);                  // 

  // 
  voltage = rangeMaxDisp / 100.0;            // Max
  if (vRange == 1 || vRange > 4) {           // 5VAuto5V
    dtostrf(voltage, 4, 2, chrBuff);         //  *.** 
  } else {                                   //
    dtostrf(voltage, 4, 1, chrBuff);         // **.* 
  }
  display.setCursor(0, 9);
  display.print(chrBuff);                    // Max

  voltage = (rangeMaxDisp + rangeMinDisp) / 200.0; // 
  if (vRange == 1 || vRange > 4) {           // 5VAuto5V
    dtostrf(voltage, 4, 2, chrBuff);         // 2
  } else {                                   //
    dtostrf(voltage, 4, 1, chrBuff);         // 1
  }
  display.setCursor(0, 33);
  display.print(chrBuff);                    // 

  voltage = rangeMinDisp / 100.0;            // Min
  if (vRange == 1 || vRange > 4) {           // 5VAuto5V
    dtostrf(voltage, 4, 2, chrBuff);         // 2
  } else {
    dtostrf(voltage, 4, 1, chrBuff);         // 1
  }
  display.setCursor(0, 57);
  display.print(chrBuff);                    // Min

  // 
  if (trigSync == false) {                   // 
    display.setCursor(60, 55);               // 
    display.print(F("Unsync"));              // Unsync 
  }
}

void plotData() {                    // 
  long y1, y2;
  for (int x = 0; x <= 98; x++) {
    y1 = map(waveBuff[x + trigP - 50], rangeMin, rangeMax, 63, 9); // 
    y1 = constrain(y1, 9, 63);                                     // 
    y2 = map(waveBuff[x + trigP - 49], rangeMin, rangeMax, 63, 9); //
    y2 = constrain(y2, 9, 63);                                     //
    display.drawLine(x + 27, y1, x + 28, y2, WHITE);               // 
  }
}

void saveEEPROM() {                    // EEPROM
  if (paraChanged == true) {           // 
    saveTimer = saveTimer - timeExec;  // 
    if (saveTimer < 0) {               // 
      paraChanged = false;             // 
      EEPROM.write(0, vRange);        // 
      EEPROM.write(1, hRange);
      EEPROM.write(2, trigD);
      EEPROM.write(3, scopeP);
    }
  }
}

void loadEEPROM() {                // EEPROM
  int x;
  x = EEPROM.read(0);             // vRange
  if ((x < 0) || (x > 9)) {        // 0-9
    x = 3;                         // 
  }
  vRange = x;

  x = EEPROM.read(1);             // hRange
  if ((x < 0) || (x > 7)) {        // 0-9
    x = 3;                         // 
  }
  hRange = x;
  x = EEPROM.read(2);             // trigD
  if ((x < 0) || (x > 1)) {        // 0-9
    x = 1;                         // 
  }
  trigD = x;
  x = EEPROM.read(3);             // scopeP
  if ((x < 0) || (x > 2)) {        // 0-9
    x = 1;                         // 
  }
  scopeP = x;
}

void pin2IRQ() {                   // Pin2(int0)
  //pin8,9,10,11Pin2
  //

  int x;                           // 
  x = PINB;                        // B

  if ( (x & 0x07) != 0x07) {       // 3High
    saveTimer = 5000;              // EEPROM(ms
    paraChanged = true;            // ON
  }

  if ((x & 0x01) == 0) {
    scopeP++;
    if (scopeP > 2) {
      scopeP = 0;
    }
  }

  if ((x & 0x02) == 0) {           // UP
    if (scopeP == 0) {             // 
      vRange++;
      if (vRange > 9) {
        vRange = 9;
      }
    }
    if (scopeP == 1) {             // 
      hRange++;
      if (hRange > 7) {
        hRange = 7;
      }
    }
    if (scopeP == 2) {             // 
      trigD = 0;                   // 
    }
  }

  if ((x & 0x04) == 0) {           // DOWN
    if (scopeP == 0) {             // 
      vRange--;
      if (vRange < 0) {
        vRange = 0;
      }
    }
    if (scopeP == 1) {             // 
      hRange--;
      if (hRange < 0) {
        hRange = 0;
      }
    }
    if (scopeP == 2) {             // 
      trigD = 1;                   // 
    }
  }

  if ((x & 0x08) == 0) {           // HOLD
    hold = ! hold;                 // 
  }
}

diagramas

circuito
Descargar
20190213schemoscllo 8etd29hcjp

Fuente Arduino.cc