Xbee no responde a tiempo. Gran retraso entre cada transmisión.

4

He preparado una configuración para 2 Xbees, una conectada a la PC a través de XCTU y la otra con interfaz Atmega 168. El software del terminal enviará 1 y el xbee con Atmega 168 devolverá 1.

El código es el siguiente.

#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>

    unsigned char data; //to store received data from UDR1



//Function To Initialize UART0
// desired baud rate:9600
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
 UCSR0B = 0x00; //disable while setting baud rate
 UCSR0A = 0x00;
 UCSR0C = 0x06;
 UBRR0L = 0x06; //set baud rate lo
 UBRR0H = 0x00; //set baud rate hi
 UCSR0B = 0x98;
}


ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x31)
    UDR0 = data;                //echo data back to PC

}

//Function To Initialize all The Devices
void init_devices()
{
 cli(); //Clears the global interrupts
 uart0_init(); //Initailize UART0 for serial communiaction
 sei();   //Enables the global interrupts
}

//Main Function
int main(void)
{
    init_devices();
    while(1);
}

Este código funciona bien y el siguiente es el resultado deseado y el obtenido ...

Ahoraelproblemaescuandoquieroobtenerlarespuesta3paraunatransmisiónde3desdelaPC.Estoyusandoavrstudio4(sí,yaséqueestoyatrasado)yAtmega168PA-PU.Laconfiguraciónparaamboscasosescomosemuestraenlaimagen...

Así que copié el programa anterior totalmente y solo cambié la línea

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x31)
    UDR0 = data;                //echo data back to PC

}

a lo siguiente

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x33)
    UDR0 = data;                //echo data back to PC

}

Pero la salida obtenida no está ni cerca de lo que se supone que es. La siguiente imagen debe aclarar.

PS: utilizamos por separado (Atmega 168A-PU & Atmega 168PA-PU) para los dos programas. Puede suceder que haya alguna discrepancia en el oscilador interno. He leído en alguna parte que puede haber una inexactitud de +/- 10%.

    

2 respuestas

0

Este problema no se relaciona con su software, porque ejecutó el mismo programa en ambos casos, ¿verdad? Así que debe ser hardware. La irregularidad en el segundo caso sugiere que hay un cierto desajuste de velocidad en baudios. Así que concluyo que el problema es definitivamente debido a los osciladores RC internos que no son precisos como usted mismo mencionó.

Intenta usar un oscilador de cuarzo externo. Conéctalo con XTAL1 & XTAL2 con capacitores adecuados. Personalmente uso 12MHz con tapas de 22pF. Cambie la configuración del fusible antes de grabar el programa. Intente con Google avrdude fuse calculator .

    
respondido por el Rambo partyush
2

No estoy 100% seguro de que esto solucione su problema, pero normalmente antes de enviar datos, querría verificar que el registro de retención del transmisor esté vacío antes de enviar un carácter. Puedes intentar esto:

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x33)
    {
        while(!(UCSR0A & (1 << UDRE0))) // Wait for data register to be empty
            ;
        UDR0 = data;                //echo data back to PC
    }
}

Pero hacer la espera dentro de la interrupción puede hacer que pierdas los caracteres recibidos. En su lugar, normalmente haría algo más como esto:

volatile unsigned char data, got_data;
unsigned char buffered_data;

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    got_data = 1;
}

int main(void)
{
    init_devices();
    while (1)
    {
        if (got_data)
        {
            // Ideally you should disable interrupts here
            buffered_data = data;
            got_data = 0;
            // And re-enable interrupts here
            if (buffered_data == 0x33)
            {
                while(!(UCSR0A & (1 << UDRE0))) // Wait for data register to be empty
                    ;
                UDR0 = buffered_data;                //echo data back to PC
            }
       }
    }
}

También me acabo de dar cuenta de que su adición sobre el reloj tiene una inexactitud potencial de +/- 10%, lo que es un poco grande para comunicaciones confiables. Si bien normalmente aspiro a un 2% de precisión cuando utilizo comunicaciones en serie, deberías apuntar a menos del 5%, de lo contrario, puedes sacar la mitad de un bit al final de 10 bits.

    
respondido por el PeterJ

Lea otras preguntas en las etiquetas