Looking for code help with 433MHz RF modules.

Discussion in 'Wireless & RF Design' started by agroom, Feb 13, 2015.

  1. agroom

    Thread Starter Active Member

    Oct 15, 2010
    60
    1
    I purchased a few pair of these 433MHz RF Tx/Rx modules and am working on getting some basic code functionality on two AVRs with intermittent success. I've gotten the modules to work near flawlessly with two Arduino's using the RCSwitch.h library, so I'm assuming my issue lies somewhere in my code.

    The setup takes a button input on the TX MCU (mega328) and toggles a local LED. It also transmits a 4-byte packet to the RX MCU (tiny2313). The packet consists of a sync , address, command and checksum byte precluded by a stream of 25 0xAA bytes to get the RX module 'tuned in'. The RX MCU then turns on/off a remote LED based on the command sent. The 4-byte packet is Manchester encoded before sent (which technically turns it into 8 encoded bytes) and sent/received via USART.

    I've used a logic analyzer to test both the transmitted and received data stream, and the data being sent is identical to the data received. I don't have an example of the analyzer's output saved, nor the setup with me at the moment, but I can set it up and post an image of it tomorrow. However, assuming that it is sending and receiving the data properly, the issue must be with my RX code.

    The project consists of 5 files:
    • ATmega328Tx.c - Main program for the mega328
    • manchesterTX-mega328.h - header file with the USART send routines
    • ATtiny2313Rx.c - Main program for the tiny2313
    • manchesterRX-tiny2313.h - header file with the USART receive routines
    • manchesterGlobal.h - common header file for both Tx and Rx programs
    I PDF'd and attached the files since posting them all here would likely be too much.

    Now before I start getting hated on, I know I shouldn't be doing all the Rx routines from within the ISR. However, since the only function of the RX MCU is to wait for data, process it then wait again, I didn't see the harm in it while testing. Once I get it all figured out, I'll pull it out of the ISR...assuming the problem isn't because it's in the ISR :) However, it has worked intermittently, so I doubt that's the root cause.

    I'm sure there's a bunch of info I'm missing, so please just ask and I'll gladly provide anything I'm missing. I'll also try to post images of the data streams in the morning as well. But I think this is enough to at least get some initial feedback. Thanks in advance for any help, it's greatly appreciated!
     
  2. AlexLPD

    Member

    Aug 22, 2010
    21
    1
    Currently I'm working on a Bluetooth data... I'm not an expert and I didn't know the tx and Rx has logical 3.3v instead of 5V.

    Other than that.... I can't be much more help, I have stumble across something else.. I post it.
     
  3. agroom

    Thread Starter Active Member

    Oct 15, 2010
    60
    1
    Here's the data stream analysis along with a circuit diagram. I also thought it might be best to just display the 3 RX files since those are the ones I think are the issue. Specifically the manchesterRX-tiny2313.h since it has the USART RX routines.

    ATtiny2313Rx.c
    Code (Text):
    1.  
    2. #define ADDR      0x44
    3. #define LED_ON    0x11
    4. #define LED_OFF   0x22
    5.  
    6. #include <avr/io.h>
    7. #include "manchesterRX-tiniy2313.h"
    8.  
    9. void initPorts(void);
    10. void startUp(void);
    11.  
    12. /*******************************************************************
    13. * Main routine
    14. *******************************************************************/
    15. int main(void) {
    16.  
    17.    initPorts();
    18.    initManchester();
    19.    startUp();
    20.    sei();               // Enable global interrupts
    21.  
    22.    while(1) {}          // Do nothing, all handled in interrupts
    23.    return 0;
    24. }
    25.  
    26. /*******************************************************************
    27. * Initializes I/O Ports.
    28. *******************************************************************/
    29. void initPorts(void) {
    30.  
    31.    // "Remote" LED
    32.    SETBIT(DDRD, DDD6);     // PD6 (Toggle led) as output
    33.    LEDOFF(PORTD, PD6);     // Led off
    34.  
    35.    // Status LEDs for debug
    36.    SETBIT(DDRB, DDB1);     // PB1 (Stat led1) as output
    37.    LEDOFF(PORTB, PB1);     // Led off
    38.    SETBIT(DDRB, DDB2);     // PB2 (Stat led2) as output
    39.    LEDOFF(PORTB, PB2);     // Led off
    40.    SETBIT(DDRB, DDB3);     // PB3 (Stat led3) as output
    41.    LEDOFF(PORTB, PB3);     // Led off
    42.    SETBIT(DDRB, DDB5);     // PB5 (Stat led4) as output
    43.    LEDOFF(PORTB, PB5);     // Led off
    44. }
    45.  
    46. /*******************************************************************
    47. * Stuff to run at startup. Just flashes LED for now.
    48. *******************************************************************/
    49. void startUp(void) {
    50.  
    51.    for(int i = 0; i < 6; i++) {
    52.       TOGGLEBIT(PORTD, PD6);
    53.       TOGGLEBIT(PORTB, PB1);
    54.       TOGGLEBIT(PORTB, PB2);
    55.       TOGGLEBIT(PORTB, PB3);
    56.       TOGGLEBIT(PORTB, PB5);
    57.       _delay_ms(200);
    58.    }
    59. }
    60.  
    manchesterRX-tiny2313.h
    Code (Text):
    1.  
    2. #include "manchesterGlobal.h"
    3. #include <util/delay.h>
    4. #include <avr/interrupt.h>
    5.  
    6. void initManchester(void);
    7. uint8_t timedWaitForSync(void);
    8. void waitForSync(void);
    9. uint8_t getByte(void);
    10. uint8_t decodeNibble(uint8_t);
    11.  
    12. /*******************************************************************
    13. * Initialize USART
    14. *******************************************************************/
    15. void initManchester(void) {
    16.  
    17.    UBRRH = (unsigned char)(MYUBRR>>8);
    18.    UBRRL = (unsigned char)MYUBRR;
    19.    SETBIT(UCSRB,RXCIE);                   // Enable RX Interrupt
    20.    SETBIT(UCSRB,RXEN);                    // Enable USART RX
    21. }
    22.  
    23. /*******************************************************************
    24. * Waits for USART to receive the SYNC byte.
    25. *******************************************************************/
    26. uint8_t timedWaitForSync(void) {
    27.  
    28.    uint8_t decodedByte = 0;
    29.  
    30.    TCNT1 = 0;                       // Initialize Timer1 count
    31.    SETBIT(TCCR1B,CS12);             // Start Timer1 w clk/256 prescaler
    32.  
    33.    while(TCNT1 < 65000) {           // Timeout after 2 seconds
    34.  
    35.       while (!(UCSRA & (1<<RXC)));  // Wait for next RX byte to arrive
    36.  
    37.       // Lower nibble of decodedByte is shifted out and the newly read
    38.       // Manchester decoded nibble is added to the high side.
    39.       decodedByte = (decodeNibble(UDR) << 4)|(decodedByte >> 4);
    40.      
    41.       if(decodedByte == SYNC_BYTE) {
    42.          CLEARBIT(TCCR1B,CS12);     // Stop Timer1
    43.          return 0;      
    44.       }
    45.    }
    46.  
    47.    CLEARBIT(TCCR1B,CS12);           // Stop Timer1
    48.    return 1;
    49. }
    50.  
    51. /*******************************************************************
    52. * Waits for USART to receive the SYNC byte. Identical to the above
    53. * routine, though omits the time-out, so it waits indefinitely
    54. * until it finds the sync byte. I made this for testing to see if
    55. * omitting the timer did anything.
    56. *******************************************************************/
    57. void waitForSync(void) {
    58.  
    59.    uint8_t decodedByte = 0;
    60.  
    61.    while(1) {
    62.  
    63.       while (!(UCSRA & (1<<RXC)));
    64.       decodedByte = (decodeNibble(UDR) << 4)|(decodedByte >> 4);
    65.      
    66.       if(decodedByte == SYNC_BYTE) {
    67.          break;      
    68.       }
    69.    }
    70. }
    71.  
    72. /*******************************************************************
    73. * Decodes the received USART byte and returns the nibble.
    74. *******************************************************************/
    75. uint8_t getByte(void) {
    76.  
    77.    uint8_t decodedByte = 0;
    78.  
    79.    while (!(UCSRA & (1<<RXC)));
    80.    decodedByte = (decodeNibble(UDR) & 0x0F); // Add lower nibble
    81.    while (!(UCSRA & (1<<RXC)));
    82.    decodedByte |= (decodeNibble(UDR) << 4);  // Shift & add high nibble
    83.  
    84.    return decodedByte;
    85. }
    86.  
    87. /*******************************************************************
    88. * Decodes a USART Manchester encoded byte into original nibble.
    89. *******************************************************************/
    90. uint8_t decodeNibble(uint8_t nibble) {
    91.  
    92.    for(uint8_t i = 0; i <= 15; i++) {
    93.       if(encodeDEC[i] == nibble) {
    94.          return i;
    95.       }
    96.    }
    97.    return 0;
    98. }
    99.  
    100. /*******************************************************************
    101. * USART RX Complete Interrupt.
    102. *******************************************************************/
    103. ISR(USART_RX_vect) {
    104.  
    105.    uint8_t address, cmd, checksum;
    106.  
    107.    CLEARBIT(UCSRB,RXCIE);        // disable RX Interrupt
    108.  
    109.    // If sync byte is not found in 2 seconds, exit ISR
    110.    if(timedWaitForSync()) {
    111.       SETBIT(UCSRB,RXCIE);       // Enable RX Interrupt
    112.       return;                    // Exit ISR
    113.    }
    114.    //waitForSync();                 // Added for testing purposes
    115.  
    116.    address  = getByte();         // Get address
    117.    cmd      = getByte();         // Get data
    118.    checksum = getByte();         // Get checksum
    119.  
    120.    if(checksum == (address + cmd)) {
    121.      
    122.       if (address == ADDR) {
    123.  
    124.          if(cmd == LED_ON) {
    125.             LEDON(PORTD, PD6);
    126.          }
    127.          else if(cmd == LED_OFF) {
    128.             LEDOFF(PORTD, PD6);
    129.          }
    130.          else {                  // If some other command
    131.             for(uint8_t i = 0; i < 8; i++) {
    132.                TOGGLEBIT(PORTD, PD6);
    133.                _delay_ms(150);
    134.             }
    135.          }
    136.       }
    137.    }
    138.    SETBIT(UCSRB,RXCIE);                   // Enable RX Interrupt
    139. }
    manchesterGlobal.h
    Code (Text):
    1.  
    2. #define F_CPU 8000000UL
    3.  
    4. #include <stdint.h>
    5.  
    6. #define BAUDRATE 1200
    7. #define MYUBRR ((F_CPU/(BAUDRATE*16UL))-1)
    8. #define SYNC_BYTE 0x07
    9.  
    10. #define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
    11. #define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
    12. #define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
    13. #define TOGGLEBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
    14.  
    15. #define LEDON(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
    16. #define LEDOFF(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
    17.  
    18. uint8_t encodeDEC[16] = {
    19.    170, 169, 166, 165, 154, 153, 150, 149,
    20.    106, 105, 102, 101, 90 , 89 , 86 , 85 };
     
Loading...