Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

10 votos

La impresión en serie de Arduino cambia el comportamiento del programa de forma no deseada

Estoy usando un contador de bucle, declarado en una cabecera:

int loop_counter = 0;

Utilizo este contador para activar un evento cada cierto tiempo. Solía usar un módulo para este mismo tipo de comportamiento, pero lo simplifiqué para que sea más fácil trabajar con él (sigue dando como resultado el mismo comportamiento)

void loop() {
    if(loop_counter > 100) loop_counter = 0;
    else loop_counter++;

    //Serial.println("hey");

    if(loop_counter == 0) {
         //do_something_important();
    }      
}

Todo va bien, hasta que intento comunicarme con Serial descomentando el //Serial.println("hey"); ( "hey" en este ejemplo porque, para mí, este comportamiento es absurdo).

Esto da lugar a loop_counter Nunca se activa el do_something_important(); sección de código. He probado a declarar loop_counter como volatile eso no cambió nada. Intenté Serial.print en loop_counter Y también estaba obteniendo un comportamiento impar (se congelaba el bucle). Serial.println("hey"); funciona en el sentido de que en el monitor Serial obtengo un montón de "hey", (es decir, rápidamente mucho más de 100 "heys", el número de iteraciones en el que la otra sección de código debe disparar)

¿Qué podría estar causando el uso de Serial con datos que no están (hasta donde yo sé) vinculados a loop_counter ¿Impedir por completo que funcione correctamente?

EDITAR : Aquí está la parte del archivo principal que terminó planteando el problema (bueno, contribuyendo al máximo a él (usando demasiada memoria)):

void display_state() {
  int i,j,index=0;
  short alive[256][2];

 for(i=0;i<num_rows;i++) { 
   for(j=0;j<num_cols;j++) {
     if(led_matrix[i][j]==1) { 
       alive[index][0]=i;
       alive[index][1]=j;
       index++;
     }
   }
 }
 alive[index][0]=NULL; //Null-terminate.
 alive[index][1]=NULL;

 //383 is a great number
 for(int idx=0;idx < index; idx++) {
   display(alive[idx][0],alive[idx][1]);
   delayMicroseconds(283);
 }
}

Aquí está "letters.h":

    #ifndef _MY_LETTERS_H
    #define _MY_LETTERS_H

Algo más de información: - Estoy usando un Uno (ATMega328)

0 votos

¿Cuál es el tamaño de su pila? ¿Hay alguna posibilidad de pintar tu pila y ver si se está corrompiendo? ¿La impresión en serie utiliza interrupciones, es su código reentrante?

0 votos

La impresión Serial no es disparada por ninguna interrupción, la estoy usando sólo en el loop() función. ¿Cómo debo pintar mi pila si el único método de salida que tengo ( Serial.print() ) me está fallando?

2 votos

Para eliminar posibles errores y efectos secundarios malinterpretados de cambios aparentemente triviales, sustituya el código de su pregunta por un literal, carácter exacto copia de un boceto reducirse al mínimo necesario para desencadenar el problema . No "este es mi programa que falla si yo.." sino exactamente el programa mínimo que falla de esta manera.

4voto

letronje Puntos 128

¿Su código inicializa el puerto serie? Ej.

void setup()
{
    Serial.begin(9600);
}

Si no se hace esto, podría producirse un fallo en el primer uso de la serie.

0 votos

Sí, lo tengo.

3voto

Arvin Puntos 837

¿Quizás te estás quedando sin memoria? Todas las cadenas que imprimes con Serial.print("algo") tienen lugar en la SRAM, igual al número de caracteres de esa cadena + 1 para el \0 terminador. Es posible quedarse sin memoria incluso si el tamaño compilado de tu sketch es mucho menor que la memoria flash del Arduino, porque la SRAM es de sólo 2048 bytes para el Atmega328 y 1024 bytes para el Atmega 168. Yo tuve un problema similar, que resolví acortando todos los textos y eliminando los mensajes de depuración innecesarios.

0 votos

Hmm. Tengo varias matrices multidimensionales declaradas en mi cabecera, ¿quizás ese sea el problema? ¿Están almacenados en SRAM?

1 votos

@nrhine1: En ese caso, probablemente deberías mostrarnos todo tu boceto, no sólo las partes en las que usted creen que está el problema.

0 votos

@DaveTweed Sí, lo haré.

2voto

Blackbelt Puntos 108

Yo también tuve un problema similar a este, y estoy muy seguro de que el tuyo también está relacionado con el espacio de la pila. Intenta reducir el código lo máximo posible.

En mi caso el código a veces se ejecutaba cuando tenía un mensaje serial, pero luego parecía no ejecutarse cuando no lo tenía. También tuve un caso en el que el envío de mensajes en serie hacía que el arduino se reiniciara sin parar.

También estaba usando un arduino328. Probablemente deberías reducir el tamaño de tu matriz si tienes alguna al tamaño más pequeño que sea aceptable.

0 votos

Gracias, tú y Dave Tweed lo habéis conseguido. He refactorizado la función display_state() para no necesitar esa asignación extra. ¡Rara vez hago procesamiento embebido, supongo que todos tenemos que golpear la pared de la memoria en algún momento!

0 votos

Hola, tengo una situación similar. Cambio el tamaño del array de 128 a 96 y mi programa funciona bien. Pero creo que este problema es realmente fuera de rastro para depurar, porque el tamaño de mi matriz es menor que el tamaño de la pila declarar. ¿Sabes dónde puedo encontrar información para tratar este tipo de problema?

1voto

Bernd Puntos 61

No has mostrado el código que inicializa la variable "loop_counter". ¿Es eso fuera del bucle() ¿Rutina?

¿Es posible que haya declarado que es adyacente a otra área de almacenamiento de memoria que está operando fuera de su tamaño declarado y este tromping en la variable loop_counter?

0 votos

He intentado declararlo de muchas maneras diferentes, en muchos lugares diferentes. En la cabecera, justo encima de loop() etc. ¿Está diciendo que el Serial.print() ¿podría estar sobrescribiendo el método de alguna manera?

0 votos

Lo que quería decir con el comentario anterior es que estoy casi seguro de haber aislado el "mal" comportamiento a la existencia del Serial.print(). Cuando no está ahí, las cosas funcionan bien.

0 votos

@nrbine1 - Me parece que tu variable global "loop_counter" está siendo pisada por el método Serial.print() como sugerí en mi respuesta. En la respuesta de posipiet se le ha preguntado si el objeto Serial se ha inicializado correctamente. Si eso no se ha hecho puede explicar el "trompeteo" en su contador ya que Serial.print() intenta usar un buffer que no ha sido correctamente asignado y configurado.

1voto

Morris Maynard Puntos 49

No veo en tu código dónde estás llamando a loop() . Tampoco parece que estés usando loop_counter fuera de esa función. ¿Hay alguna razón por la que lo declaras global? Supongo que es porque quieres que conserve su valor entre llamadas. Usted podría hacer esto con un variable local estática en su lugar.

void loop() {
    static int loop_counter = 0;

    if(loop_counter > 100)
    {
        loop_counter = 0;
    }
    else
    {
        loop_counter++;
    }

    Serial.println("hey");

    if(loop_counter == 0)
    {
         //do_something_important();
    }      
}

Eso debería asegurar que ninguna otra función externa pueda pisotearla. Siempre debes declarar tus variables en el ámbito más pequeño posible para evitar comportamientos no deseados.

Si eso no funciona, tendrá que analizar realmente el uso de la memoria. Compruebe esta pregunta de EE.SE para ver varios ejemplos de código para hacer esto dentro de un Arduino.

0 votos

Ya intenté hacerlo estático. No sirvió de nada. Esta es una iteración diferente. setup() y loop() son funciones que arduino ejecuta por defecto, setup() primero, loop() segundo. loop() es esencialmente como main() , excepto que se llama repetidamente. referencia: arduino.cc/es/Referencia/loop Comprobaré ese enlace.

0 votos

De nuevo, como he mencionado en otros comentarios, no puedo depurar con Serial.print() . Parece que tendré que fuera de lo normal processing IDE si quiero poder utilizar GDB

0 votos

@nrhine1 Has dicho que Serial.print() funcionaba bien en el sentido de que imprimía mucho "hey". Es loop_counter que te está dando un problema. Pruebe a quitar el if(loop_counter == 0) y poniendo el get_free_memory() código (dejar el loop_counter incremento) y ejecutarlo. Esto al menos le dirá si tiene algún principal problemas con su asignación de memoria.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X