viernes, 11 de marzo de 2016

Mini osciloscopio (2KHz) con arduino y lcd QC12864

Este es un intento de osciloscopio con arduino, el nano tiene poca velocidad de proceso y poca memoria, por lo que es muy limitado,  apenas para 1 KHz, pero sirve por ejemplo para ver la onda sinusoidal de la red eléctrica o de un 555 configurado a bajas frecuencias.  Un arduino  DUE sería algo más adecuado para esto por trabajar a 82 Mhz en vez de 16.  También se puede dedicar otro arduino exclusivamente a capturar los datos, mejorandose mucho el rendmiento

El zener de 5 V funciona como protección, pues un voltaje mayor de 5V quemaría el arduino aunque podría afectar negativamente al circuito que vamos a medir, para medir voltajes mayores se puede usar un divisor resistivo y con menores de 5V el zener es prescindible.  La punta de prueba negra va a masa y la morada al + del circuito a visualizar.

Uno de los potenciómetros es para controlar el contraste de la pantalla y el otro controla el tiempo que dura el muestreo de datos, la frecuencia muestrada es solo una estimación parcial  basada  en el numero de picos representados en el tiempo muestreado, por lo que sólo va a ser precisa cuando se vean muchos picos,  el motivo de esta inexactitud es para mentener cierta agilidad en la visualización de nuestro mini osciloscopio..

He incluido una variación del sketch donde se modifica el prescaler del arduino y se consigue un muestreo unas 8 veces más rápido, pero su funcionamiento es algo menos fluido . El valor divisor mínimo que admite sin que la visualización resulte muy afectada es 16, con las pruebas configurado a 32 el funcionamiento ha sido impecable y se ganaba una velocidad de aproximadamente el triple.

A partir de 5 mseg, el comnportamiento del programa cambia, se convierte en un pequeño monitor de la tensión adecuado a otros usos.

Para que funcionen  los sketch hay que tener instalada la librería U8glib.







_______________________________________________________________________________________________________


Visualización de una salida PWM de otro arduino y de su filtrado con condensador de 100uF.

Hemos configurado un segundo arduino  producir una salida de tensión PWM , pudiendola variar  mediante un potenciometro y poder visualizarla. Después la hemos filtrado y vemos como se muestra.

PWM 0.3 V
osciloscopio arduino 

 filtrada con condensador en paralelo:


PWM  3V
filtrada (100uF):


PWM 5V:

Video:






Onda senoidal 50Hz (red eléctrica, a través de unas espiras próximas a un  transformador 12V.)






Onda cuadrada IC 555.






Sketch con el prescaler modificado. Descargar.


#include "U8glib.h"

U8GLIB_ST7920_128X64_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);  //For ST7920_128X64 paralelo

 unsigned long sensor; 

int muestreo;
int x;
int y[130];

boolean monitor;

int y2;
unsigned long ycal;
// unsigned long tpo;

byte punto;
byte y3;

float mx;
byte mc;
byte fc;


void setup(void) {
 
}



void loop(void) {


  u8g.firstPage();

  // Captación de muestreo

  muestreo =analogRead(A1);
 

if (muestreo < 512) {    // Osciloscopio


  monitor=0;
 
             if ( muestreo <256 a="" br="" mecha="" nbsp="" osciloscopio="" toda="">

   switch(byte(4+2*float(muestreo/256)))
  {
    case 0: //  <4 br="" malfuncionamiento="">      bitWrite(ADCSRA,ADPS2,0);  bitWrite(ADCSRA,ADPS1,0);  bitWrite(ADCSRA,ADPS0,0);
    break;
    case 1:
    bitWrite(ADCSRA,ADPS2,0);  bitWrite(ADCSRA,ADPS1,1);  bitWrite(ADCSRA,ADPS0,0);
    break;
    case 2:
      bitWrite(ADCSRA,ADPS2,0);  bitWrite(ADCSRA,ADPS1,1);  bitWrite(ADCSRA,ADPS0,1);
    break;
    case 3:
    bitWrite(ADCSRA,ADPS2,1);  bitWrite(ADCSRA,ADPS1,0);  bitWrite(ADCSRA,ADPS0,0);
    break;
    case 4:
      bitWrite(ADCSRA,ADPS2,1);  bitWrite(ADCSRA,ADPS1,0);  bitWrite(ADCSRA,ADPS0,1);
    break;
    case 5:
      bitWrite(ADCSRA,ADPS2,1);  bitWrite(ADCSRA,ADPS1,1);  bitWrite(ADCSRA,ADPS0,0);
    break;
    case 6:
      bitWrite(ADCSRA,ADPS2,1);  bitWrite(ADCSRA,ADPS1,1);  bitWrite(ADCSRA,ADPS0,1);;
    break;
  }
 
    //Analog Input A0 ADMUX=(1<<ADLAR)|(0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);



 muestreo=muestreo/3;



 // Lectura de datos


   if (muestreo <3 br="" muestreo="" nbsp="" turbo="">
     ycal = micros();


  y[0] = analogRead(A0); 
    y[1] = analogRead(A0); 
    y[2] = analogRead(A0); 
    y[3] = analogRead(A0); 
    y[4] = analogRead(A0); 
    y[5] = analogRead(A0);
    y[6] = analogRead(A0); 
    y[7] = analogRead(A0); 
    y[8] = analogRead(A0); 
    y[9] = analogRead(A0); 
    y[10] = analogRead(A0); 
    y[11] = analogRead(A0); 
    y[12] = analogRead(A0); 
    y[13] = analogRead(A0); 
    y[14] = analogRead(A0); 
    y[15] = analogRead(A0); 
    y[16] = analogRead(A0); 
    y[17] = analogRead(A0); 
    y[18] = analogRead(A0); 
    y[19] = analogRead(A0); 
        y[20] = analogRead(A0); 
    y[21] = analogRead(A0); 
    y[22] = analogRead(A0); 
    y[23] = analogRead(A0); 
    y[24] = analogRead(A0); 
    y[25] = analogRead(A0); 
    y[26] = analogRead(A0); 
    y[27] = analogRead(A0); 
    y[28] = analogRead(A0); 
    y[29] = analogRead(A0);
        y[30] = analogRead(A0);
    y[31] = analogRead(A0); 
    y[32] = analogRead(A0); 
    y[33] = analogRead(A0); 
    y[34] = analogRead(A0); 
    y[35] = analogRead(A0); 
    y[36] = analogRead(A0); 
    y[37] = analogRead(A0); 
    y[38] = analogRead(A0); 
    y[39] = analogRead(A0);
    y[40] = analogRead(A0);
    y[41] = analogRead(A0); 
    y[42] = analogRead(A0); 
    y[43] = analogRead(A0); 
    y[44] = analogRead(A0); 
    y[45] = analogRead(A0); 
    y[46] = analogRead(A0); 
    y[47] = analogRead(A0); 
    y[48] = analogRead(A0); 
    y[49] = analogRead(A0);
    y[50] = analogRead(A0); 
    y[51] = analogRead(A0); 
    y[52] = analogRead(A0); 
    y[53] = analogRead(A0); 
    y[54] = analogRead(A0); 
    y[55] = analogRead(A0); 
    y[56] = analogRead(A0); 
    y[57] = analogRead(A0); 
    y[58] = analogRead(A0); 
    y[59] = analogRead(A0);
    y[60] = analogRead(A0); 
    y[61] = analogRead(A0); 
    y[62] = analogRead(A0); 
    y[63] = analogRead(A0); 
    y[64] = analogRead(A0); 
    y[65] = analogRead(A0); 
    y[66] = analogRead(A0); 
    y[67] = analogRead(A0); 
    y[68] = analogRead(A0); 
    y[69] = analogRead(A0);
    y[70] = analogRead(A0); 
    y[71] = analogRead(A0); 
    y[72] = analogRead(A0); 
    y[73] = analogRead(A0); 
    y[74] = analogRead(A0); 
    y[75] = analogRead(A0); 
    y[76] = analogRead(A0); 
    y[77] = analogRead(A0); 
    y[78] = analogRead(A0); 
    y[79] = analogRead(A0);
    y[80] = analogRead(A0); 
    y[81] = analogRead(A0);
    y[82] = analogRead(A0); 
    y[83] = analogRead(A0); 
    y[84] = analogRead(A0); 
    y[85] = analogRead(A0); 
    y[86] = analogRead(A0); 
    y[87] = analogRead(A0); 
    y[88] = analogRead(A0); 
    y[89] = analogRead(A0);
    y[90] = analogRead(A0);
    y[91] = analogRead(A0);
    y[92] = analogRead(A0);
    y[93] = analogRead(A0);
    y[94] = analogRead(A0);
    y[95] = analogRead(A0);
    y[96] = analogRead(A0);
    y[97] = analogRead(A0);
    y[98] = analogRead(A0);
    y[99] = analogRead(A0);
 y[100] = analogRead(A0);
    y[101] = analogRead(A0);
    y[102] = analogRead(A0);
    y[103] = analogRead(A0);
    y[104] = analogRead(A0);
    y[105] = analogRead(A0);
    y[106] = analogRead(A0);
    y[107] = analogRead(A0);
    y[108] = analogRead(A0);
    y[109] = analogRead(A0);
    y[110] = analogRead(A0);
    y[111] = analogRead(A0);
    y[112] = analogRead(A0);
    y[113] = analogRead(A0);
    y[114] = analogRead(A0);
    y[115] = analogRead(A0);
    y[116] = analogRead(A0);
    y[117] = analogRead(A0);
    y[118] = analogRead(A0);
    y[119] = analogRead(A0);
    y[120] = analogRead(A0);
    y[121] = analogRead(A0);
    y[122] = analogRead(A0);
    y[123] = analogRead(A0);
    y[124] = analogRead(A0);
    y[125] = analogRead(A0);
    y[126] = analogRead(A0);
    y[127] = analogRead(A0);

  mx= (micros() - ycal);

}

else {    // muestreo con rapidez alta
 
 ycal = micros();

  for ( punto = 0; punto <= 127; punto++ ) {

    y[punto]=analogRead(A0);
  
     delayMicroseconds(muestreo);
  }
 
  mx= (micros() - ycal);
  
 
  }

sensor = mx;   // tpo muestreo
 
   } // fin muestreo os. seg arduino

 

   else {   // muestreo rapidez media

  
mx=micros();

ycal=9*(muestreo-256); // calibrado tiempo

 for ( punto = 0; punto <= 127; punto++ ) {  //muestreo pinA0 arduino maestro
    x=1;
    y[punto] = analogRead(A0);

   retardo0();

  }

 sensor= (micros()-mx);


 }          // fin osciloscopio


 
  /// Estimación frecuencia   f= picos/tpo muestreo

     mx=0;
 
for ( punto = 0; punto <= 127; punto++ ) {
 
     mx=max(mx,y[punto]);
 
  }
 

 
  fc = 0;
 
  mx = mx*.9  ;  // Pico > 10%


  for ( punto = 0; punto <= 127; punto++ ) {

    if ( (mx < y[punto]) && (mc == 0)) {
      fc = fc + 1;
      mc = 1;
    }

    if (y[punto] < mx) {
      mc = 0;
    }
  }
}                          // <-- br="" cierre="" nbsp="" osciloscopio="">


else {                         // monitoreo del pin A0

   monitor=1;

mx=millis();

   y[128]=0; //media total

x=100;


  y[127]=analogRead(A0);
  retardo();

  ycal=0;
 
   for ( punto = 0; punto <= 126; punto++ ) {
  
 y[punto]=y[punto+1];

       ycal=ycal+y[punto];
  }


  mx=millis()-mx;

y[128]=(ycal+y[127])/128;

}                    // cierre de monitoreo

  /// Dibujar

  do {

    draw();
  } while ( u8g.nextPage() );


  // delay(5000);   // Para congelar imagen entre muestreo y muestreo. Puede ser interesante controlar este parametro mediante potenciómetro.



}


void retardo0()    // retardo osciloscopio arduino maestro
{
   if (x   y[punto]=(analogRead(A0)+y[punto])/2;
  x=x+2;
     retardo0();
   }

}

void retardo()   // retardo monitor
{

if (x<((30*(analogRead(A1)-512)))) {
    y[127]=((analogRead(A0))+y[127])/2;
  x=x+1;
retardo();
}

}

///////////////////    GRAFICA

void draw(void) {

  // graphic commands to redraw the complete screen should be placed here

  // u8g.drawFrame(0,0,128,56);  //marco exterior

  for ( punto = 21; punto <= 106; punto = punto + 42 ) {       // punto vertical cada 1V

    u8g.drawPixel(punto, 10);  u8g.drawPixel(punto, 21); u8g.drawPixel(punto, 32); u8g.drawPixel(punto, 43);

  }

 u8g.setFontPosTop();
 

  // Grafica de la onda

  y3 = 55 - 27 * float(y[0]) / 512;  ///  54/1024

  for ( punto = 1; punto <= 127; punto++ ) {


    ycal = 55 - 28 * float(y[punto]) / 512;    ///  54/1024


    u8g.drawLine(punto - 1, y3, punto, ycal);

    y3 = ycal;
  }


  // Leyenda

  u8g.setFont(u8g_font_04b_03);

  u8g.setPrintPos(0, 56);
 
  if (monitor==1){

    u8g.print(String(float(y[127])*5/1024) +"V.  /"+ String(float(.19+mx/1000)) + " Seg.  Med: "+String(float(y[128])*5/1024)+"V.");   ///   x5V
  }
  else {
    u8g.print( String(float((sensor+.5)/1000)) + " mSeg. /Estm: " + String(long(float(1000000*fc/(sensor+.5) ))) + " Hz ");
  }

}


int analogReadFast()
{
 ADCSRA|=(1<<ADSC);
 // ADSC is cleared when the conversion finishes
 while (bit_is_set(ADCSRA, ADSC));
        return ADCH;
}




No hay comentarios: