El dispositivo Arduino (PanStamp) se bloquea cuando cambio los datos que se envían a través de la serie

1

Tengo un PanStamp (compatible con arduino) y todo funcionaba bien hasta que cambio la cantidad de datos que estoy enviando a través de la serie.

send_altitude se llama cada segundo mediante la interrupción del temporizador (biblioteca de TimerOne).

Esta es la función original que envía datos (y no se bloquea):

void send_altitude()
{
cli();

float_byte altitude;
byte buffer[6];

// Do one trash read to avoid fluctuations
analogRead(ALT_SENSOR);
delay(5);
altitude.asFloat = getAltitude(ALT_SENSOR);

buffer[0] = 0x05; /* Size */
buffer[1] = HUB_DATA;
buffer[2] = altitude.asByte[0];
buffer[3] = altitude.asByte[1];
buffer[4] = altitude.asByte[2];
buffer[5] = altitude.asByte[3];

send_through_serial(6, buffer);

sei();
}

Pero cuando lo cambié a este (básicamente estoy enviando un recuento de paquetes): Siguiendo la sugerencia de PeterJ, moví el búfer y la variable fuera de la función y también eliminé el sei () / cli (), pero no funcionó ... Una cosa que noté es que parece tardar más en colgar sin sei / cli.

float_byte altitude;
unsigned char buffer[10];
void send_altitude()
{
// Increments the counter;
packet_count.asULong = packet_count.asULong + 1;

// Do one trash read to avoid fluctuations
analogRead(ALT_SENSOR);
delay(5);
altitude.asFloat = getAltitude(ALT_SENSOR);

buffer[0] = 0x09; /* Size */
buffer[1] = HUB_DATA;
buffer[2] = altitude.asByte[0];
buffer[3] = altitude.asByte[1];
buffer[4] = altitude.asByte[2];
buffer[5] = altitude.asByte[3];

buffer[6] = packet_count.asByte[0];
buffer[7] = packet_count.asByte[1];
buffer[8] = packet_count.asByte[2];
buffer[9] = packet_count.asByte[3];

send_through_serial(10, buffer);
}

El PanStamp comenzó a colgar sin razón ... packet_count es un ulong_byte .

Las otras funciones y estructuras de datos:

void send_through_serial(int lenght, unsigned char *data)
{
unsigned int i;

/* Send srync word */
Serial.write(0xBA);
Serial.write(0xBA);

/* Send data */
for(i = 0; i < lenght; i++)
{
    Serial.write(data[i]);
}
}

/**
 * @brief getAltitude
 *
 * Return the altitude (Voltage) of a
 * analogue pressure sensor.
 *
 * Maybe later on it will return the
 * altitude
 *
 * @param ain Analogue pin
 * @return Altitude (Voltage)
 */
inline float getAltitude(int ain)
{
    int aRead = analogRead(ain);
    return aRead*(3.3/1023.0);
}


typedef union _float_byte
{
    byte asByte[4];
    float asFloat;
} float_byte;

typedef union _ulong_byte
{
    unsigned long asULong;
    byte asByte[4];
} ulong_byte;

Código de inicialización del temporizador:

Timer1.initialize(1000000);
Timer1.attachInterrupt(send_altitude);

La única "solución" que encontré es usar el WDT para restablecer después de un bloqueo, pero no es bueno porque tengo algunos contadores que no se pueden descansar.

¡Gracias a @JRobert está funcionando ahora! También hice algunos cambios más:

  • La interrupción del temporizador solo establece una bandera booleana;
  • Buffers dentro de la función;
  • Usando sei / cli;
  • getAltitude () ya no es inline .
pregunta Tiago Queiroz

1 respuesta

1

Si nada , pero el tamaño del paquete cambió, entonces el tamaño del paquete está relacionado de alguna manera.

  • ¿Cuál es la velocidad en baudios?
  • ¿Hay alguna razón por la que una iteración de su código demore aproximadamente 1 segundo en ejecutarse?
  • ¿Cuánto tiempo puede tardar en ejecutarse getAltitude ()? ¿Espera hardware?

Hay una gran cantidad de código que se ejecuta en el nivel de interrupción: getAltitude () y send_through_serial () (que también usa E / S impulsada por interrupciones). El primer cambio que haría sería reducir el código de interrupción del temporizador 1 para establecer un bit de bandera. Levante el resto del código de la rutina de interrupción a la línea principal. Llámelo cada vez que se establece el bit de bandera y borre el bit de bandera. Lo peor que debería pasar al hacerlo de esta manera es que podría perder algunas interrupciones si el código de su línea principal se prolonga demasiado. No es que faltar interrupciones es aceptable; pero debería detener el bloqueo y permitirle probar su código aún más para descubrir qué está siendo lento.

Para apilar las colisiones, convertir una variable local en una variable estática no reducirá esa probabilidad; más bien podría aumentarla. Los locales se asignan y se desasignan, por lo que hay ocasiones en que no existen y no pueden contribuir a una falla. La estática siempre existe y siempre reduce la cantidad de memoria para que la pila pueda crecer. Sin embargo, lo que podría cambiar es el comportamiento del programa cuando se produce la colisión. Cuando haces algo estático, se le asignará una ubicación diferente en la memoria; como resultado, diferentes variables pueden estar involucradas cuando ocurre la colisión.

    
respondido por el JRobert

Lea otras preguntas en las etiquetas