Go Down

Topic: Aumentar la frecuencia de muestreo (Solucionado) (Read 27696 times) previous topic - next topic

Igor R

#15
Aug 10, 2011, 12:51 am Last Edit: Aug 10, 2011, 12:53 am by Igor R Reason: 1
je,je,je... por eso!! tiene que estar requetechupao para ti!!  Ahora en serio, lo digo para forzarte un poco. Si después de mirarlo no lo tienes claro, lo volvemos a comentar.
Tienes que mirar la parte de "Analog-to-Digital Converter", dónde explica los registros del mismo y en concreto ADCSRA-ADC Control and Status Register A.
Tendrás una tabla como esta:

Table 23-4. ADC Prescaler Selections
ADPS2 - ADPS1 - ADPS0 - Division Factor
0        - 0       - 0        ->2
0        - 0       - 1        ->2
0        - 1       - 0        ->4
0        - 1       - 1        ->8
1        - 0       - 0        ->16
1        - 0       - 1        ->32
1        - 1       - 0        ->64
1        - 1       - 1        ->128


Ten en cuenta que ya estas empezando a meterte en cosas medio serias, y no queda más remedio que mirarse la documentación de microcontrolador. Es lo bonito de Arduino, que te crea la necesidad por aprender...


;)


CesarCarlos

Sospecho que aca esta bien explicado, http://real2electronics.blogspot.com/2011/01/timer-2.html ya había estado husmeando por ahí hoy donde esta la tablita esa, en el datasheet no logro verla.
Saludos
César
http://anajesusa.wordpress.com/

Igor R

Bueno, el concepto es parecido, pero ahi es la explicación para los timers (en concreto timer 2).
¿No lo encuentras en el datasheet? ¿Qué Arduino tienes, un UNO? Si es así, ¿estás mirando el datasheet del ATmega 328?

CesarCarlos

Es un Duemilanove, y el chip es atmega328p, el datasheet http://www.atmel.com/dyn/resources/prod_documents/8271S.pdf
Cuando veía tu recito termostatizado con un tapper me acordaba de uno que hice, pero mas robusto, ya que lo mantenía a 85°C, también en este caso un ventilador de pc para homogeneizar pero en el interior para que no mande aire frío desde afuera.

Saludos
César
http://anajesusa.wordpress.com/

Igor R

#19
Aug 10, 2011, 03:26 am Last Edit: Aug 10, 2011, 03:37 am by Igor R Reason: 1
Eso es el resumen (summary) del datasheet. Mira esto => http://www.atmel.com/dyn/resources/prod_documents/doc8271.pdf

El taper aguanta bastante temperatura, es de plástico robusto de los que estan preparados para microondas, congelador, etc.
Esta muy bien, porque es fácil de mecanizar con una dremel.
Me gusto hacerlo así para que fuese transparente, rápido de mecanizar y sobretodo...muy barato!! Compre 10 por 1 euros!! je,je,je
En los ejemplos que tengo, los setpoints están alrededor de 60 grados, pero llega a mucha más temperatura sin problemas (más de 110ºC)... Los setpoints los elegí ahí, por el tema de no tener que esperar cuando lo enciendes por primera vez....

Es importante el recipiente, porque al principio recicle uno parecido, que venía hummus (que rico estaba!!) y se derritió nada más meterle caña.... :D

Hay que tener en cuenta que es un proyecto de un finde (48 horas). Se puede mejor mucho, adaptarlo, etc. Estoy deseando que alguien lo mejore!!
La verdad que el resultado no está del todo mal, y se puede jugar (aprender) mucho con el tema de control, y lo montas por un precio más que asequible.

]:D


CesarCarlos

Hola de nuevo, recién hago la prueba de cambiar el factor de división del prescaler lo llevé a 64 y luego a 32 pero hay algo que no me cierra, esto es una copia del archivo que me guarda el realterm
microseg  lectura
61486888 26
61488576 25
61490264 26
61491944 25
61493640 26
61495320 26
61497000 26
61498696 26
La diferencia entre lectura y lectura son 1680 microsegundos, sigo estando en la misma, no hay lecturas intermedias o al menos no se guardan, serán demasiados datos que pasan al puerto serie? para cualquier curva por lo menos necesito tres lecturas
El codigo quedó asi
/* 
Barrera de luz
*/
// to the pins used:


const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
int sensorValue = 0;        // value read from the pot
//int outputValue = 0;        // value output to the PWM (analog out)
unsigned long time;

void setup() {
  pinMode(13, OUTPUT);
  ADCSRA|= (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);
  // initialize serial communications at 9600 bps:
  Serial.begin(115200);
}

void loop() {
   digitalWrite(13, HIGH);
  // read the analog in value:
  sensorValue = analogRead(analogInPin);       
  // print the results to the serial monitor:
  //Serial.print("Time:  ");
  time = micros();
  Serial.print(time);     
  Serial.print(" ");     
  Serial.println(sensorValue);   
                   
}

Saludos
César
http://anajesusa.wordpress.com/

Igor R

#21
Aug 10, 2011, 09:00 pm Last Edit: Aug 10, 2011, 09:14 pm by Igor R Reason: 1
El problema es el puerto serie.... ahora mismo estoy haciendo pruebas con cosas parecidas....  ]:D
Las rutinas de Arduino son muy lentas. Existen librerías por la red, que consiguen 1 Mbps y más!!  (google).

No te aseguro que el programa este perfectamento, ya que esta un poco verde (en vez de guardar micros que son 4 bytes (unsigned long), se podría calcular la frecuencia de muestreo, y ya sabrías el tiempo entre dato y dato, pero asi compruebo que todo cuadra).
Es la adquisición de la red eléctrica= 50 Hz (T=20ms) (proveniente de un trafo y adaptada). Lo conecto a la entrada analógica 5.

Code: [Select]

#define mysize 200

unsigned long mytime[mysize];
byte mydata[mysize];

void setup()
{
 Serial.begin(115200);
 
 //Prescaler
 //ADPS2 - ADPS1 - ADPS0 - Division Factor
 //0        - 0       - 0        ->2
 //0        - 0       - 1        ->2
 //0        - 1       - 0        ->4
 //0        - 1       - 1        ->8
 //1        - 0       - 0        ->16
 //1        - 0       - 1        ->32
 //1        - 1       - 0        ->64
 //1        - 1       - 1        ->128
 ADCSRA|= (1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);  //Prescaler=32
 
 //Free running mode
 ADCSRB|=(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);
 
 //Entrada A5
 ADMUX|=(1<<ADLAR)|(0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0);
}


void loop()
{

 for (int i=0; i<mysize;i++)
 {
    mytime[i]=micros();
    mydata[i]=analogReadFast();
    delayMicroseconds(500);
 }
 
 Serial.println("Nuevo");
 for (int i=0; i<mysize;i++)
 {
   Serial.print(mytime[i]);
   Serial.print(" ");
   Serial.println(mydata[i],DEC);
 }
 
}

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


Lo que hago es copiar del texto "Nuevo" al siguiente "Nuevo" capturado por la consola, y lo pego en una hoja de cálculo. Sólo estoy usando 8 bits de resolución.
Como ves me he creado un buffer para guardar los datos y luego los dibujo. He puesto un pequeño delay, porque era demasiada frecuencia de muestreo!!!



Habría que hacer la prueba, usando analogRead que trae Arduino...

Salu2



Igor R.


CesarCarlos

Ese delay me limita a 2ms, se puede quitar? intento medir eventos del orden de los microsegundos.
Saludos
César
http://anajesusa.wordpress.com/

Igor R

#23
Aug 10, 2011, 11:37 pm Last Edit: Aug 11, 2011, 11:21 am by Igor R Reason: 1
He encontrado un gazapo en mi código.... Ahora si funciona como debería! La configuración de los registros con |= no fue buena idea..... :D

Code: [Select]

#define mysize 600

unsigned long tStart;
unsigned long tEnd;
byte mydata[mysize];

void setup()
{
 Serial.begin(115200);
 
 //Prescaler
 //ADPS2 - ADPS1 - ADPS0 - Division Factor
 //0        - 0       - 0        ->2
 //0        - 0       - 1        ->2
 //0        - 1       - 0        ->4
 //0        - 1       - 1        ->8
 //1        - 0       - 0        ->16
 //1        - 0       - 1        ->32
 //1        - 1       - 0        ->64
 //1        - 1       - 1        ->128
 //Configure to Prescaler=32
 bitWrite(ADCSRA,ADPS2,1);
 bitWrite(ADCSRA,ADPS1,0);
 bitWrite(ADCSRA,ADPS0,1);
 
 //Entrada A5
 ADMUX=(1<<ADLAR)|(0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0);
}


void loop()
{

 tStart=micros();
 for (int i=0; i<mysize;i++)
 {
    mydata[i]=analogReadFast();
 }
 tEnd=micros();
 
 Serial.println("NEW ACQUISITION");
 Serial.print("tStart=");
 Serial.println(tStart);
 Serial.print("tEnd=");
 Serial.println(tEnd);
 Serial.print("nPoints=");
 Serial.println(mysize);
 
 for (int i=0; i<mysize;i++)
 {
   Serial.println(mydata[i],DEC);
 }
 
}

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



Ahora son 35.6 kHz!! Es decir, 28 us por sample!! El módulo del ADC con el prescaler=32 está trabajando 500 kHz y estoy utilizando 8 bits.


;)

Sergegsx

Enhorabuena !!

Me encanta cuando se llega a base de quebraderos de cabeza a soluciones asi, en este caso una precisión de muestreo muy superior a la inicial
por ahora esto no me sirve pero estoy seguro que en el futuro le podre dar uso.

al playground ??? ;)

Igor R

Por supuesto que al playground!! http://arduino.cc/playground/Es/FAQ
Ahora hay que investigar unas rutinas mejor optimizadas para conseguir 1Mbps por el puerto serie para poder mostrar los datos a "tiempo real".

:smiley-mr-green:

CesarCarlos

A la pelotita!! con guitarra es otra cosa, apenas llego lo pruebo, eso si me sirve!!!
Saludos
César
http://anajesusa.wordpress.com/

Igor R

#27
Aug 11, 2011, 02:34 am Last Edit: Aug 11, 2011, 12:26 pm by Igor R Reason: 1
¿Puedes probar ha importar los datos adquiridos en KST y hacer un "Power Spectrum" de los datos adquiridos de la guitarra? Te debería salir la frecuencia de la nota tocada...
Como puedes ver el programita envia el tiempo de inicio,de fin de la adquisición (en microsegundos) y el número de puntos. Por lo que de ahí puedes sacar la frecuencia de muestreo para el cálculo de la FFT.
Adjunto lo que se obtiene de la adquisición de la señal de la red.... los 50 Hz, claro!!  :D (En concreto el pico es 51.9 Hz, cuando lo hago con Matlab es 50.21 Hz,aunque no he entrado en detalle sobre las opciones de configuración que te deja el KST ...)


CesarCarlos

#28
Aug 11, 2011, 02:49 am Last Edit: Aug 11, 2011, 05:15 am by CesarCarlos Reason: 1
Estoy renegando, parece que no estoy sabiendo como ver los datos, al principio me marca el tiempo de inicio y fin y todos los datos que vió en ese tiempo en una columna.
Je je me esperaba dos columnas, aca tengo que ingresar el intervalo de tiempo en kst, ya he logrado ver algo pasando un alambre finito frente al sensor a la mayor velocidad que pude, aunque todavía no tengo claro algunas cuestiones, el archivo que me graba esta en intervalos de 600 puntos y 16800 microsegundos 28 microseg por sample, luego otro intervalo igual, no estoy seguro que lee el kst2 cuando pasa de un
período a otro.
Hay algún tutorial de kst2 en español?
Igor, muchas gracias por llevarme el apunte, soy un renovato y sin embargo gastas tu tiempo en contestar y explicar, muchas gracias, creo que estas lejos para mandarte un vino, mejor me lo tomo a tu salud  :)

Saludos
César
http://anajesusa.wordpress.com/

Igor R

#29
Aug 11, 2011, 11:32 am Last Edit: Aug 11, 2011, 11:55 am by Igor R Reason: 1
La verdad que no hay mucha info del KST.... o por lo menos desconozco de algún sitio.

Te explico yo lo que hago para este caso concreto:
1) Lo primero es que no alimento el KST directamente con los datos del puerto serie.
2) Copio de la propia consola serie que viene con el IDE de Arduino de "New Acquisition" hasta el siguiente "New".
3) Lo pego en una hoja de cálculo y la guardo en formato *.csv. Para generar el *.csv, quito en la hoja de cálculo la parte de tstart, tend, número de puntos, etc. (es decir, me quedo sólo los datos adquiridos). Lo que hago es tener dos hojas en la hoja de cálculo, una para copiar tal cual y otra para crear el *.csv.
¿por qué hago ésto? Porque me he creado las cuentas para que automáticamente calcule la frecuencia de muestreo sabiendo tstart,tend y el número de puntos. Ya que para mi aplicación le meto un delayMicroseconds() en el for para poder tener más datos. No necesito ir a la máxima velocidad, ya que estoy muestreando una onda de 50 Hz.
También uso la propia hoja de cálculo para graficar los datos. Para calcular la columna de tiempo, pues el primer dato será 0, el segundo fs, el tercero 3*fs,el cuarto 4*fs..... siendo fs (frecuencia sample). La hoja de cálculo hace todo este trabajo por mi....
4) Importo los datos del fichero *.csv con KST.


¿tiene sentido ésto? Eso sí, cuando lo consigas quiero ver una entrada en tu blog que expliques todo el proceso,así sirve para los demás.... :D
Tengo curiosidad por ver la nota de tu guitarra con la FFT.....je,je,je




;)

Go Up