el tono () y la lectura de datos en serie están colisionando

4

En mi bucle principal de croquis, utilicé SoftwareSerial para leer datos de gps.

void loop()  
{ 
  while (nss.available())
  {
    if (gps.encode(nss.read()))
    {
     ...

También tengo un ISR de temporizador, que se llama cada segundo o menos, donde enciendo el timbre

ISR(TIMER1_COMPA_vect)
{
  tone(8, 1000, 200); 
  // digitalWrite(9, 1); delay(200); digitalWrite(9, 0);

}

El problema es que, cuando escucho el tono y al mismo tiempo hay datos gps entrantes, el tono está dañado. Cuando se terminan los datos, el tono es claro. Así que de alguna manera la entrada serial y el tono están interfiriendo entre sí.

Incluso sin el código, es decir, los datos ( nss.available() y nss.read() ), si solo comento nss.begin(57600); , entonces el problema está resuelto.

¿Cómo puedo resolver esto?

    
pregunta Pablo

2 respuestas

8

Si puede conformarse con un tono de frecuencia de 976.5625 Hz en lugar de los 1000 Hz en su código, aquí está la solución (supuesto: Arduino Uno o Duemilanove, no estoy seguro de la Mega):

Conecte su salida al Pin 5 o 6 (los pines PWM) en lugar del pin 8. Crea una variable global volátil:

  

volatile int_8 tone_tracker = 0;

Cambie su ISR Timer1 para que sea llamado cada 200 ms .

En el código ISR, cuente hasta 4 guardando el valor en tone_tracker, luego:

  

analogWrite (SPKR_PIN, 127);

La próxima vez que se invoque el ISR, establezca tone_tracker en 0 y:

  

analogWrite (SPKR_PIN, 0);

El problema debe resolverse.

Por qué funciona esto:

El código Timer0 ISR ahora simplemente activa y desactiva el tono a horas establecidas, dejando la generación de tonos real al hardware del microcontrolador.

El frecuencia de PWM predeterminada de Arduino en los pines 5 y 6 es 976.5625 Hz a menos que está modificando Timer0 en otra parte de su código (o haciendo otra cosa con PWM donde las bibliotecas realizan algunos cambios "invisibles").

Escribir el análogo 127 en el pin PWM genera una onda cuadrada de ciclo de trabajo del 50% en la frecuencia predeterminada de PWM. Eso genera el tono requerido.

En este enfoque, la generación real de tonos se realiza mediante la salida PWM del microcontrolador, no a través de un código de frecuencia variable impulsado por interrupciones, como se usa en la biblioteca de tonos.

El malabarismo con tone_tracker te da 200 x 4 = 800 mS de silencio, luego 200 x 1 = 200 mS de salida de tono. El temporizador ISR y el ISR serial pueden entrar en conflicto, pero eso no afecta a la generación de PWM. Por lo tanto, en el peor de los casos, el tono puede durar unos microsegundos más, o puede comenzar unos microsegundos más tarde, si la MCU está ocupada con comunicaciones en serie en ese momento, pero esto no sería perceptible para los oídos humanos.

Por supuesto, esto no funcionará tan fácilmente si necesita cualquier frecuencia de tono, excepto 976.5625 Hz (en los pines 5 y 6) o 488.28125 Hz (en los pines 3, 9, 10 y 11).

    
respondido por el Anindo Ghosh
4

Arduino hace que las cosas simples sean fáciles, pero hace que las cosas complejas sean más difíciles. Te estás metiendo en el reino en el que Arduino simplemente se cae.

Tanto SoftwareSerial como Tone son tareas que requieren un uso intensivo de la CPU con requisitos de tiempo muy estrictos. El enfoque Arduino setup() ... loop() no es capaz de lidiar con hacer ambos simultáneamente, aunque cualquiera de los dos funciona bien. Debe usar interrupciones, pero las rutinas de servicio de interrupción (ISR) en las bibliotecas de Arduino no están diseñadas para cooperar entre sí.

Específicamente, el módulo Serie de software funciona interrumpiendo el inicio del bit de inicio de cada carácter entrante, y luego vincula la CPU hasta que se haya recibido el carácter completo. El módulo de tono utiliza un temporizador de hardware para generar la frecuencia correcta, pero (supongo) utiliza una interrupción para actualizar el pin de salida seleccionado en cada borde. El ISR serial largo impide que el ISR del temporizador se ejecute tan regularmente como sea necesario. Esto es lo que causa la corrupción que estás escuchando.

En este punto, es casi necesario que abandone las bibliotecas de Arduino y comience a programar en el nivel "básico", ya sea escribiendo sus propios módulos de biblioteca o cambiando a otro entorno de desarrollo de software (p. ej., WinAVR ).

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas