Problema con comunicación serial e interrupciones en arduino

Hola, espero se encuentren bien, el problema es el siguiente:
Resulta que voy a hacer un controlador PID en el arduino, para lo cual necesito asegurar un periodo de muestreo de Tm=100mS, entonces, para ello voy a utilizar una ISR, de esta manera lo puedo garantizar, sin embargo tengo un problema con esto, y es que necesito obtener los datos de setpoint de una raspberry pi, por medio de comunicación serial (supongo), entonces, primero que todo, de entrada dentro de la interrupción no me está permitiendo leer un dato del buffer serial, entiendo más o menos que la interrupción desactiva las interrupciones de baja prioridad, entre esas la responsable de (leer el dato?), bueno, total, necesito una forma de asegurar ese muestreo en cuanto a la comunicación también, pero he visto que cuando arduino recibe un dato de Serial tiene cierto retardo, esto a qué se deberá y si hay alguien que sepa cómo solucionar esto, si es que tiene solución, gracias.
Aquí abajo les dejo un código para que puedan visualizar la demora a la que me refiero, solo deben entrar al puerto serial y enviar un número, ahí se podrá visualizar que el retardo al recibir dicho dato es de 1 segundo

int currentime=0,previoustime=0,counter=0;
String datain;
void setup() {
  Serial.begin(115200);
}
void loop() {
  currentime=millis();
   if(Serial.available()){
    counter=counter+1;
    datain=Serial.readString();}
  Serial.print(currentime-previoustime);
  previoustime=currentime;
  Serial.print("  Counter: ");
  Serial.println(counter);
}

Su publicacion se MUEVE a su ubicacion actual ya que es mas adecuada.

Hola UKHelibob, no entiendo a qué te refieres, pero he dejado un pequeño código de prueba para que verifique quien quiera el retardo al que me refiero, gracias.

Hola bienvenido al foro, como no se que microcontrolador estas usando asumiré que puede ser algún AVR y tengo entendido que en AVR no hay prioridades de interrupción.
Revisaste lo que dice la función que estas utilizando Serial.readString(), según la documentación en la seccion de Notas y advertencias

La función no termina antes de tiempo si los datos contienen caracteres de final de línea.

Si no la función termina si se agota el tiempo de espera Serial.setTimeout() y esta el valor predeterminado es de 1000 ms, que es lo que mencionas que es de 1 segundo, puedes utilizar la función Serial.read() pero esta va a leer carácter por carácter.

1 Like

Seguramente publicaste en el foro en inglés y lo movió al español, que es donde deberías haberlo publicado.

@Swift ha sido muy claro en su explicación y agrego: hay que acostumbrarse a leer la documentación de arduino, la mayor parte de los problemas surgen por no hacerlo.

Por otro lado, debes usar readStringUntil() en su lugar, así lee hasta que encuentra el final de línea (caracter '\n') que por supuesto deberá enviar la Raspi luego del dato (si estás usando python lo hace por defecto, si no me equivoco).
Sobre readStringUntil(), lee la documentación.

1 Like

Olvida al RPi e imagina que tu cambiarías la información de Setpoint via Serial. Dime para que esperas que lo haga en la ISR si te sobra tiempo dentro del loop?
Una cosa es la ISR y otra su setpoint.
Normalmente un setpoint no se cambia pero esporádicamente si, y estoy de acuerdo con el planteo, por eso solo debes compartir variables del tipo volatil entre loop y la ISR para que ese datos setpoint sea utilizado por tu rutina.

1 Like

Agrego a lo que dije en el post anterior y lo que dice @Surbyte.

En principio entiendo que tu código fue solo para mostrarnos el retardo (debido al timeout como ya lo ha explicado @Swift), sino no tiene otro uso, y previendo que vas enviar por serial los setpoints es que te dije que uses readStringUntil().

Ahora, tu timer dispara la interrupción cada 100 mseg, a 115200 bps un caracter tarda en completarse 87 useg, o sea que en 100 mseg podrían transmitirse algo más de 1100 caracteres de los que apenas enviarías un puñado.
¿Te parece que no hay tiempo para leer el puerto serie y fijar los setpoints entre interrupción e interrupción?

Recuerda siempre usar variables de 32 bits para valores asociados con millis()

unsigned int currentime, etc
1 Like

Gracias Swift, así era, la función Serial.readString está sujeta a ese parámetro, por eso tardaba 1s exactamente, por tanto hay que bajar el parametro en el timeout o bien simplemente usar Serial.readStringUntil("\n"); que finaliza apenas encuentre el "\n".

Sí, lo realizaré de esa manera para evitar conflictos en lectura, lo que tengo que tener en cuenta en ese caso es que el código que tengo en el loop no demore tanto como para que la velocidad de muestreo no desmejore significativamente y logre captar bien los cambios en los tiempos permisibles.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.