Looking for code help with 433MHz RF modules.

Thread Starter

agroom

Joined Oct 15, 2010
60
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!
 

Attachments

AlexLPD

Joined Aug 22, 2010
60
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.
 

Thread Starter

agroom

Joined Oct 15, 2010
60
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:
#define ADDR      0x44
#define LED_ON    0x11
#define LED_OFF   0x22

#include <avr/io.h>
#include "manchesterRX-tiniy2313.h"

void initPorts(void);
void startUp(void);

/*******************************************************************
* Main routine
*******************************************************************/
int main(void) {
  
   initPorts();
   initManchester();
   startUp();
   sei();               // Enable global interrupts
  
   while(1) {}          // Do nothing, all handled in interrupts
   return 0;
}

/*******************************************************************
* Initializes I/O Ports.
*******************************************************************/
void initPorts(void) {

   // "Remote" LED
   SETBIT(DDRD, DDD6);     // PD6 (Toggle led) as output
   LEDOFF(PORTD, PD6);     // Led off
  
   // Status LEDs for debug
   SETBIT(DDRB, DDB1);     // PB1 (Stat led1) as output
   LEDOFF(PORTB, PB1);     // Led off
   SETBIT(DDRB, DDB2);     // PB2 (Stat led2) as output
   LEDOFF(PORTB, PB2);     // Led off
   SETBIT(DDRB, DDB3);     // PB3 (Stat led3) as output
   LEDOFF(PORTB, PB3);     // Led off
   SETBIT(DDRB, DDB5);     // PB5 (Stat led4) as output
   LEDOFF(PORTB, PB5);     // Led off
}

/*******************************************************************
* Stuff to run at startup. Just flashes LED for now.
*******************************************************************/
void startUp(void) {

   for(int i = 0; i < 6; i++) {
      TOGGLEBIT(PORTD, PD6);
      TOGGLEBIT(PORTB, PB1);
      TOGGLEBIT(PORTB, PB2);
      TOGGLEBIT(PORTB, PB3);
      TOGGLEBIT(PORTB, PB5);
      _delay_ms(200);
   }
}
manchesterRX-tiny2313.h
Code:
#include "manchesterGlobal.h"
#include <util/delay.h>
#include <avr/interrupt.h>

void initManchester(void);
uint8_t timedWaitForSync(void);
void waitForSync(void);
uint8_t getByte(void);
uint8_t decodeNibble(uint8_t);

/*******************************************************************
* Initialize USART
*******************************************************************/
void initManchester(void) {
  
   UBRRH = (unsigned char)(MYUBRR>>8);
   UBRRL = (unsigned char)MYUBRR;
   SETBIT(UCSRB,RXCIE);                   // Enable RX Interrupt
   SETBIT(UCSRB,RXEN);                    // Enable USART RX
}

/*******************************************************************
* Waits for USART to receive the SYNC byte.
*******************************************************************/
uint8_t timedWaitForSync(void) {
  
   uint8_t decodedByte = 0;
  
   TCNT1 = 0;                       // Initialize Timer1 count
   SETBIT(TCCR1B,CS12);             // Start Timer1 w clk/256 prescaler
  
   while(TCNT1 < 65000) {           // Timeout after 2 seconds
  
      while (!(UCSRA & (1<<RXC)));  // Wait for next RX byte to arrive

      // Lower nibble of decodedByte is shifted out and the newly read
      // Manchester decoded nibble is added to the high side.
      decodedByte = (decodeNibble(UDR) << 4)|(decodedByte >> 4);
     
      if(decodedByte == SYNC_BYTE) {
         CLEARBIT(TCCR1B,CS12);     // Stop Timer1
         return 0;      
      }
   }
  
   CLEARBIT(TCCR1B,CS12);           // Stop Timer1
   return 1;
}

/*******************************************************************
* Waits for USART to receive the SYNC byte. Identical to the above
* routine, though omits the time-out, so it waits indefinitely
* until it finds the sync byte. I made this for testing to see if
* omitting the timer did anything.
*******************************************************************/
void waitForSync(void) {
  
   uint8_t decodedByte = 0;
  
   while(1) {
  
      while (!(UCSRA & (1<<RXC)));
      decodedByte = (decodeNibble(UDR) << 4)|(decodedByte >> 4);
     
      if(decodedByte == SYNC_BYTE) {
         break;      
      }
   }
}

/*******************************************************************
* Decodes the received USART byte and returns the nibble.
*******************************************************************/
uint8_t getByte(void) {
  
   uint8_t decodedByte = 0;
  
   while (!(UCSRA & (1<<RXC)));
   decodedByte = (decodeNibble(UDR) & 0x0F); // Add lower nibble
   while (!(UCSRA & (1<<RXC)));
   decodedByte |= (decodeNibble(UDR) << 4);  // Shift & add high nibble
  
   return decodedByte;
}

/*******************************************************************
* Decodes a USART Manchester encoded byte into original nibble.
*******************************************************************/
uint8_t decodeNibble(uint8_t nibble) {

   for(uint8_t i = 0; i <= 15; i++) {
      if(encodeDEC[i] == nibble) {
         return i;
      }
   }
   return 0;
}

/*******************************************************************
* USART RX Complete Interrupt.
*******************************************************************/
ISR(USART_RX_vect) {
  
   uint8_t address, cmd, checksum;
  
   CLEARBIT(UCSRB,RXCIE);        // disable RX Interrupt
  
   // If sync byte is not found in 2 seconds, exit ISR
   if(timedWaitForSync()) {
      SETBIT(UCSRB,RXCIE);       // Enable RX Interrupt
      return;                    // Exit ISR
   }
   //waitForSync();                 // Added for testing purposes

   address  = getByte();         // Get address
   cmd      = getByte();         // Get data
   checksum = getByte();         // Get checksum
  
   if(checksum == (address + cmd)) {
     
      if (address == ADDR) {

         if(cmd == LED_ON) {
            LEDON(PORTD, PD6);
         }
         else if(cmd == LED_OFF) {
            LEDOFF(PORTD, PD6);
         }
         else {                  // If some other command
            for(uint8_t i = 0; i < 8; i++) {
               TOGGLEBIT(PORTD, PD6);
               _delay_ms(150);
            }
         }
      }
   }
   SETBIT(UCSRB,RXCIE);                   // Enable RX Interrupt
}
manchesterGlobal.h
Code:
#define F_CPU 8000000UL

#include <stdint.h>

#define BAUDRATE 1200
#define MYUBRR ((F_CPU/(BAUDRATE*16UL))-1)
#define SYNC_BYTE 0x07

#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define TOGGLEBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))

#define LEDON(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define LEDOFF(ADDRESS,BIT) (ADDRESS |= (1<<BIT))

uint8_t encodeDEC[16] = {
   170, 169, 166, 165, 154, 153, 150, 149,
   106, 105, 102, 101, 90 , 89 , 86 , 85 };
 

Attachments

Top