I am trying to create a RF project where it communicates from one AVR to another. I decided to start with a simple transmitter/receiver combo (Maybe my first mistake of many!) I am following the tutorial from: http://winavr.scienceprog.com/example-a … llers.html and I modified the code for the AVR I am using, ATMega168A. I utilized an external crystal to get reliable USART results and made sure the CKDIV8 was not programmed. Of course, after I wired everything, it didn’t work Sad So now I need to figure out why. I thought I should be able to see the signal being transmitted by connecting an oscilloscope to tx pin of the AVR and see the wave generated since it should be at 1200 baud or about 1/1000 of a second. The output was a steady positive voltage (VDD)Any suggestions on debugging this? Here is the transmitter code I am using:
/*
* transmitter168P.cpp
*
* Created: 5/30/2013 9:49:40 PM
* Author: RTS
* first version for use with:
* tx433 and Atmega168A using 11.0592MHz crystal
* Note: for initial testing purposes connect TX to RX and connect LEDs on same board
*/
#define F_CPU 11059200
#include <avr/io.h>
#include <util/delay.h>
//Set desired baud rate
#define BAUDRATE 1200
//calculate UBRR value (Using UBBR0)
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
//define transmit parameters
#define SYNCBIT 0xAA //syncronization bit (10101010)
#define RADDR 0x44 //Transmitter ID # (01000100) Change this to two hex numbers in Ver 2.
#define LEDON 0x11 //turn on LED command
#define LEDOFF 0x22 //turn off LED command
void USART_Init(void) //initialize USART settings
{
//set baud rate in USART Baud Rate Register (UBRR0)
UBRR0L= (uint8_t) UBRRVAL; //low byte
UBRR0H= (UBRRVAL>>8); //high byte
//set data frame format: asynchronous mode, no parity, 1 stop bit, 8 bit size
UCSR0B=(1<<RXEN0)|(1<<TXEN0); //sets to mode to receive and transmit...probably don't need RXEN in final version
UCSR0C=(0<<USBS0)|(3<<UCSZ00);//0<<USBS0 sets 1 stop bit. 3<<UCSZ00 sets 8 data bits *** Check this in simulator
}
void USART_vSendByte(uint8_t u8Data)
{
while (!(UCSR0A &(1<<UDRE0))); //wait for transmit buffer to be empty
UDR0=u8Data; //puts data into send buffer and sends it
}
void Send_Packet(uint8_t addr,uint8_t cmd)
{
USART_vSendByte(SYNCBIT); //sends sync byte
USART_vSendByte(addr); //sends tx address...change to RADDR?
USART_vSendByte(cmd); //sends data byte....add additional bytes here after functioning
USART_vSendByte((addr+cmd)); //send checksum for error checking.
}
void delayms(uint8_t t) //delay in ms...use delay function instead?
{
for (int i=0;t;i++)
_delay_ms(1);
}
int main(void)
{
USART_Init();
while(1)
{
Send_Packet(RADDR, LEDON);
delayms(100);
Send_Packet(RADDR, LEDOFF);
delayms(100);
}
return 0;
}
void delayms(uint8_t t) //delay in ms...use delay function instead?
{
for (int i=0;t;i++)
_delay_ms(1);
}
should have been:
void delayms(uint8_t t) //delay in ms...use delay function instead?
{
for (int i=0;i<t;i++)
_delay_ms(1);
}
So now the problem is with the receiver portion. With an oscilloscope, the rx pin on the MCU is receiving a wave that “looks” the same as the one being sent by the transmitter (I am going to pick up a second probe to see both waves at the same time to verify) but the circuit is not working. What can I do to trace the probable problem? Here is the receiver code:
/*
* receiver168A.cpp
*first version for use with:
*rx413 and Atmega168A using 11.0592MHz crystal
* Created: 6/10/2013 9:32:49 PM
* Author: RTS
*/
#define F_CPU 11059200UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//Set desired baud rate
#define BAUDRATE 1200UL
//calculate UBRR value (Using UBBR0)
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
//define transmit parameters
#define SYNCBIT 0xAA //synchronization bit (10101010)
#define RADDR 0x44 //Transmitter ID # (01000100) Change this to two hex numbers in Ver 2 and read from EEPROM
#define LEDON 0x11 //turn on LED command
#define LEDOFF 0x22 //turn off LED command
void USART_Init(void) //initialize USART settings
{
//set baud rate in USART Baud Rate Register (UBRR0)
UBRR0L= (uint8_t) UBRRVAL; //low byte
UBRR0H= (UBRRVAL>>8); //high byte
//set data frame format: asynchronous mode, no parity, 1 stop bit, 8 bit size
UCSR0B=(1<<RXEN0)|(1<<RXCIE0)|(1<<TXEN0); //sets to mode to receive and transmit also sets up RX complete interrupt...probably don't need TXEN in final version
UCSR0C=(0<<USBS0)|(3<<UCSZ00);//0<<USBS0 sets 1 stop bit. 3<<UCSZ00 sets 8 data bits *** Check this in simulator
}
uint8_t USART_vReceiveByte(void)
{
while (!(UCSR0A &(1<<RXC0))); //wait for data to be received
return UDR0;
}
void Main_Init(void) // initialization...move to main()
{
DDRC=(1<<PC0); //define PORTC pin0 as output, use appropriate mask!!
PORTC|=(1<<0); //LED off
sei();
}
int main(void)
{
Main_Init();
USART_Init();
uint8_t raddress, data,chk; //define variables for transmitter address, data and checksum
while(USART_vReceiveByte() !=SYNCBIT){}//wait for correct data
raddress=USART_vReceiveByte();//get transmitter address (add routine for multiple TX and two bytes)
data=USART_vReceiveByte();//get transmitted data(in future version will be beam break status?)
chk=USART_vReceiveByte();//get checksum to validate data
if (chk==(raddress+data)) //if correct data, continue
{
if(raddress==RADDR) //check for valid transmitter address add switch () case for all valid...check time for many addresses. Might have to limit to certain number
{
if(data==LEDON) //data sent is to turn on LED
{
PORTC &=~(1<<0); //Turn on Portc Pin0
}
else if (data==LEDOFF) //data sent to turn off LED
{
PORTC |=(1<<0); //Turn off PORTC Pin0
}
else //bad data blink error
{
PORTC |=(1<<0); //LED on
_delay_ms(10);
PORTC &=~(1<<0); //LED off
}
}
}
return 0;
}
They are pretty close, not sure where the longer portion of the waves come from?
Here is the code I used:
/*
* transmitter168P.cpp
*
* Created: 5/30/2013 9:49:40 PM
* Author: RTS
* first version for use with:
* tx433 and Atmega168A using 11.0592MHz crystal
* Note: for initial testing purposes connect TX to RX and connect LEDs on same board
*/
#define F_CPU 11059200
#include <avr/io.h>
#include <util/delay.h>
//Set desired baud rate
#define BAUDRATE 2400
//calculate UBRR value (Using UBBR0)
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
//define transmit parameters
#define SYNCBIT 0xAA //synchronization bit (10101010)
#define RADDR 0xAA
#define LEDON 0xAA
void USART_Init(void) //initialize USART settings
{
//set baud rate in USART Baud Rate Register (UBRR0)
UBRR0L= (uint8_t) UBRRVAL; //low byte
UBRR0H= (UBRRVAL>>8); //high byte
//set data frame format: asynchronous mode, no parity, 1 stop bit, 8 bit size
UCSR0B=(1<<RXEN0)|(1<<TXEN0); //sets to mode to receive and transmit...probably don't need RXEN in final version
UCSR0C=(0<<USBS0)|(3<<UCSZ00);//0<<USBS0 sets 1 stop bit. 3<<UCSZ00 sets 8 data bits *** Check this in simulator
}
void USART_vSendByte(uint8_t u8Data)
{
while (!(UCSR0A &(1<<UDRE0))); //wait for transmit buffer to be empty
UDR0=u8Data; //puts data into send buffer and sends it
}
Where do I go from here?
void Send_Packet(uint8_t addr,uint8_t cmd)
{
USART_vSendByte(SYNCBIT); //sends sync byte
USART_vSendByte(addr); //sends tx address...change to RADDR?
USART_vSendByte(cmd); //sends data byte....add additional bytes here after functioning
}
void delayms(uint8_t t) //delay in ms...use delay function instead?
{
for (int i=0;i<t;i++)
_delay_ms(1);
}
int main(void)
{
USART_Init();
while(1)
{
Send_Packet(RADDR, LEDON);
}
return 0;
}
I didn’t think about the start and stop bits, but it looks like there are not enough signals between the “pauses” and why would the positive pulses be shorter than the others. I would think that for timing purposes they should be identical?
Is the top trace from the UART output? I guess that it is and there the 0’s and 1’s have equal periods.
Guess then the bottom trace is out of the RF receiver and is not surprising that there 1’ and 0 periods are not equal. This is due to these RF modules are OOK modulation (I am surprised the receiver signals are that good). I’ll bet that the first bytes sent do not look good at all and may not be good if sending more 0’s or 1’s in a single byte.
What character are you receiving when sending 0x55 (ASCII ‘U’)?? Don’t send 0xaa since this is not a printable ASCII character.
Google OOK modulation to learn how this actually works and some solutions for using it.
Then read and study the code in the VirtualWire code:
1- Its in my post, 0x55 is an ASCII ‘U’. Or google “ASCII Table” to learn all of the ASCII characters.
2- In a terminal program running on your PC (use a MAX232 between the RF receiver and a PC com port).
Or output the received data from the UART to an 8bit port on the AVR that drives LEDs.
3- VirtualWire is written in C which is very portable between processors. The only changes needed is processor hardware dependencies like PORT addresses, setup registers, UART setup and data. These functions should be written in a low level module that the VirtualWire high level functions call.