Go Down

Topic: problema velocidad de lectura arduino (Read 854 times) previous topic - next topic

alonsol

Jun 30, 2020, 06:44 pm Last Edit: Jun 30, 2020, 07:23 pm by alonsol
Hola a todos,

Estoy trabajando en una investigación, en la cual debo medir la frecuencia en la cual incide luz en un fotodiodo FDS100, para lo cual estoy utilizando un Arduino Uno para obtener la tensión que genera este.
Requiero tomar una gran cantidad de datos en 1 segundo, si es posible cercano a 1000, pero lo máximo que he logrado hasta ahora son 150 datos por segundo. Sin embargo, también necesito que me vaya entregando el tiempo en que se realizo la medición, para así poder determinar la frecuencia de muestreo..pero al agregar este código se reducen a 87 los datos por segundo.
Cabe destacar que el voltaje que entra al Arduino esta en un rango de 0.2V a 0.4V, de igual manera en un futuro cercano utilizare un Amplificador operacional para aumentar la tensión que entre al arduino....


a continuación les dejo el código que estoy utilizando:

Code: [Select]

int variable= millis();

void setup(void) {

 Serial.begin(9600);

   
}

void loop(void) {
 
 int pinRead0 = analogRead(A0);
 float pVolt0 = pinRead0 / 1024.0 * 5.0;
 int variable= millis();
 int tacu = tacu + variable;
 Serial.print(pVolt0,3);
 Serial.print("\t");
 Serial.print(tacu);
 Serial.println();
 
 
}


Como se puede ver en el código, lo que hace es leer el voltaje (con 3 decimales) a la entrada analógica y una variable va contando los milisegundos en los que se tomo la medición.

He probado variando la cantidad de bps, pero me arroja signos extraños en el monitor.

Mis preguntas son las siguientes, y si tienen opinión de lo que sea ademas de esto, bienvenido sea.

1) He leído en algunos temas anteriores que para hacer que el arduino lea a su máxima velocidad debería ponerlo en modo Free Wheeling, pero no he pillado como hacerlo.

2) Se que se puede utilizar un buffer el cual vaya guardando la información, con el fin de tomar datos mas rápido sin tener que retrasar el traspasar la info al pc, pero luego de que se llena la capacidad se van borrando los datos anteriores, por lo que si saben como podría ir mandandomela periódicamente sin perder información, pero teniendo una mayor velocidad.

3) Si es mas recomendable utilizar otra placa Arduino que tenga una mejor resolución (?), como el Mega que se puede poner como un rango de tensión de entrada, o el Due que tiene 12 bits.

PeterKantTropus

#1
Jun 30, 2020, 06:55 pm Last Edit: Jun 30, 2020, 06:59 pm by PeterKantTropus
Debes publicar  el código  con tags   por favor edítalo.

Tu limitante no es la velocidad de lectura, es la velocidad de trasmisión, a  9600  BPS el buffer serial se saturara enseguida.
Debes aumentar esa velocidad al máximo y  mediante la funcion Milis() maestrear los datos que necesites, ademas puedes fomatear los datos para   no incluir decimales o cifras que no necesites. Cada carácter utilizas 9 bits para transmitir.

Saludo
"Si no entra como tornillo, entra como clavo"

alonsol

Hola peter, gracias por responder :)

Debes publicar  el código  con tags   por favor edítalo.
 
Corregido!

Tu limitante no es la velocidad de lectura, es la velocidad de trasmisión, a  9600  BPS el buffer serial se saturara enseguida.

El bps máximos es 115200 no?, en caso de ser así te adjunto una foto con lo que me arroja la consola al tratar de realizar las mediciones con esa cantidad de bps ( en caso de que no se vea, me arroja puros signos tipo %$#%!#&"$!#)...


Debes aumentar esa velocidad al máximo y  mediante la función Milis() maestrear los datos que necesites, ademas puedes fomatear los datos para   no incluir decimales o cifras que no necesites. Cada carácter utilizas 9 bits para transmitir.

También ocupo la función millis() para ir contando el tiempo y me los va imprimiendo.. (nose si te referías a esto).

Por ultimo necesito esos 3 decimales, ya que al ser tan baja la tensión que entra por el pin análogo me sirve para ver con mayor precisión su variación.



PeterKantTropus

¿Cambiaste la configuración de la consola serial para adaptarla a la nueva velocidad?

La funcion milis() debes utilizarla para que cada tantos milisegundos haga  una medida, es decir el analog read y el serial print debe ir dentro de un " if" 

"Si no entra como tornillo, entra como clavo"

PeterKantTropus

Por ejemplo tu enviás 0,303, puedes multiplicarlo por 1000 y enviar 303  te ahorras un cero y un punto
"Si no entra como tornillo, entra como clavo"

tauro0221

Hi,
Para leer un voltaje  de menos de un voltio  puedes cambiar la referencia del a/d a 1.1 usando el comando analog reference(). Tambien cuando lees los milli() este te va a disminuir la velocidad de las lecturas. Puede hacer una cosa para aumentar la velocidad de las lecturas es de usar un for/loop pero antes lees los millis() y despues que termine el loop lees los millis y compara el tiempo.  Despues aumenta/disminuyes  las   lecturas del loop hasta que llegue el tiempo de lecturas que deseas.

alonsol

¿Cambiaste la configuración de la consola serial para adaptarla a la nueva velocidad?

La funcion milis() debes utilizarla para que cada tantos milisegundos haga  una medida, es decir el analog read y el serial print debe ir dentro de un " if"  


se me habia olvidado hacer eso!, es que aun soy nuevo en esto jajaja... muchas gracias  :)

Por ejemplo tu enviás 0,303, puedes multiplicarlo por 1000 y enviar 303  te ahorras un cero y un punto
buena idea, la voy aplicar.

Hi,
Para leer un voltaje  de menos de un voltio  puedes cambiar la referencia del a/d a 1.1 usando el comando analog reference(). Tambien cuando lees los milli() este te va a disminuir la velocidad de las lecturas. Puede hacer una cosa para aumentar la velocidad de las lecturas es de usar un for/loop pero antes lees los millis() y despues que termine el loop lees los millis y compara el tiempo.  Despues aumenta/disminuyes  las   lecturas del loop hasta que llegue el tiempo de lecturas que deseas.
muchas gracias, lo voy a implementar tambien!


PeterKantTropus

#7
Jun 30, 2020, 09:15 pm Last Edit: Jun 30, 2020, 09:18 pm by PeterKantTropus
Me voy a adelantar a otro problema que vas a tener: La saturación del buffer.

primero utilizaste 9600, bps si lo divides por 9 bits por caracteres y 9 caracteres por dato ( las tabulaciones y fin de carro también son un caracter) te da 128 datos por minuto.
Si utilizas 115200 BPs te da que puedes transmitir 1422 datos ¿Cual es el problema?
Si te fijas en la captura que colocaste, estas generando un dato con menos de un milisegundo, es decir puedes tomar 60000 datos, pero no transmitirlos.
Si no limitas la cantidad de medidas a menores de 1422 datos, la diferencia se acumula en el Buffer y luego de algún tiempo empiezas a tener datos trocados, porque se perderán parte de los datos.

Una forma de solucionarlo es enviar datos a una tasa fija utilizando milis() y si lo que te interesa es enviar datos "a lo que de" es asegurarte que el buffer este vacío antes de enviar un dato nuevo.
Y por ahora dejamos los Bytes para otra ocasión (es la mejor forma de enviarlos).
Saludos.
"Si no entra como tornillo, entra como clavo"

alonsol

Una forma de solucionarlo es enviar datos a una tasa fija utilizando milis() y si lo que te interesa es enviar datos "a lo que de" es asegurarte que el buffer este vacío antes de enviar un dato nuevo.
Y por ahora dejamos los Bytes para otra ocasión (es la mejor forma de enviarlos).
Saludos.
esa tasa fija sería como el comentario de arriba utilizando un For en el cual pueda poner un limite de tiempo en las mediciones...? algo asi(?)


de ante mano muchas gracias por la ayuda!!!

PeterKantTropus

Mira la documentación del foro sobre millis,  esta mucho mas claro que lo que te podría explicar aquí.
"Si no entra como tornillo, entra como clavo"

alonsol

Primero que nada, disculpa la demora en responder y muchas gracias por la ayuda PeterKantTropus..

Mira la documentación del foro sobre millis,  esta mucho mas claro que lo que te podría explicar aquí.
He estado leyendo y tratando de entender la función millis(), pero no he logrado dar con algo que me ayude a definir como un limite de transferencia de datos.... Sin embargo, creo que con este código que hice (que es bastante burdo..) puedo hacer que me entregue mediciones a casi 1 milisegundo teniendo casi 970 mediciones por segundo, pero de igual forma tratar de llegar a los 1300 o 1400 datos.. pero no se me ocurre el como.



Code: [Select]

unsigned long t;

void setup(void) {

  Serial.begin(115200);
  t=millis();
     
}
 
void loop(void) {
 
  if(millis() - t >= 1){
    int pinRead0 = analogRead(A0);
    float pVolt0 = (pinRead0 / 1024.0 * 5.0)*1000;
    Serial.print(millis());
    Serial.print("\t");
    Serial.println(pVolt0,0);
    t=millis();
  }
     
}



Pense que de igual forma si lograba leer más datos (para acercarme a los 1300...), puede que este código sea un poco mas rápido, ya que no debe imprimir constantemente el tiempo en el que realizo la medida.



Code: [Select]

unsigned long t;
unsigned long p;


void setup(void) {

  Serial.begin(115200);
  t=millis();
  p=millis();
}
 
void loop(void) {
   
  if(millis()-p >= 1000){
    Serial.print(millis());
    Serial.print("\t");
    p=millis();
  }
 
  if(millis() - t >= 1){
    int pinRead0 = analogRead(A0);
    float pVolt0 = (pinRead0 / 1024.0 * 5.0)*1000;

    Serial.println(pVolt0,0);
    t=millis();
  }


}



Estos códigos solucionarían el problema de sobrecargar el buffer con la cantidad de datos medidos?

Y una ultima pregunta me surge de momento, ya que ahora que me mencionaste que a la larga el buffer me entregara datos erroneos por mediciones anteriores, la foto que adjunto se podría deber a esto?. Me explico, cuando comienzo a tomar mediciones, siempre o casi siempre los primeros datos tienen mas números o signos.... pero luego se estabiliza todo...

De las fotos error 2, corresponde al primer código y Error 1 al segundo. (zrry si el nombre del archivo confunde).

tauro0221

Hi,
Posiblemente la velocidad del baud rate es muy alta. Haz una prueba anadele un pequeno de la despues que escrabas la informacion. Trata un delay de un de como delay(25) y mira ver si resolve el problema.El delay lo puedes subir un bajar.

PeterKantTropus

Efectivamente esos errores se dan por la saturación de buffer
Una forma elegante de solucionarlo es solo medir si no hay nada en el fuffer ( hasta que aprendas como se utiliza millis())

Code: [Select]

void loop(void) {
if (Serial.available() == 0) {
  // acá todo el código  de medición y salida serial
}



}



De esa manera solo generas datos si el buffer esta vacío y se generan datos según la velocidad de transmisión.
"Si no entra como tornillo, entra como clavo"

tauro0221

Hi,
Esos es correcto y es la forma correcta de hacerlo cuando uno envia informacion hacia un modulo. Hay que interrogarlo para ver si esta listo para recibir informacion.Si no lo hace entonces esta mandando la informacion en la forma de kamikaze.

alonsol

Nuevamente, gracias peter por seguir respondiéndome y ayudándome al igual que tauro0221, pero a pesar del código que me diste para solucionar lo del buffer mientras tanto, me sigue arrojando los mismos problemas de las fotos que subí anteriormente... Probé insertando un Serial.println("hola") de la siguiente forma, para ver que me arrojaba... y me lanzaba lo mismo.

Este es el código, y adjunto imagen de la consola.

Code: [Select]


unsigned long t;

void setup(void) {

  Serial.begin(115200);
  t=millis();
     
}
 
void loop(void) {
  if (Serial.available() == 0) {
   
    Serial.println("Hola");
    if(millis() - t >= 1){
      int pinRead0 = analogRead(A0);
      float pVolt0 = (pinRead0 / 1024.0 * 5.0)*1000;
      Serial.print(millis());
      Serial.print("\t");
      Serial.println(pVolt0,0);
      t=millis();
    }
 
  }

}

Go Up