I am attempting to program a pair of ATtiny84s to communicate via a pair of nRF24L01+ modules (http://www.amazon.com/nRF24L01-Wireless-Transceiver-Arduino-Compatible/dp/B00E594ZX0).
So far, I have gotten the RX device to beep in response to receiving a packet from the TX device. However, I cannot read correct payload data from the RX device. I would like to know what, if anything, I am doing wrong.
This is so far the only thing I have noticed wrong. My ATtiny's are able to read the status register correctly, the correct RX datapipe, even the correct payload width. The only thing I am unable to read is the payload data. It's either not being loaded into the transmitter right, or not being read out of the receiver correctly. Instead of the appropriate locator_ping-packet, I am receiving 01 f6 01 f5 as the data. I've tried for a couple days now to figure this out, and can't.
Even though I'm transmitting at -18 dBm, the radios are less than 2 inches apart. I can't imagine the transmission ebing corrupted over that short a distance. furthermore, the value I get is consistent.
Note that I am not using an Arduino core to program these devices. I wanted to try just using AVR LibC
Here are some relevant snippets of code
The transmitted packets:
// Command packets for transmission
const uint8_t heartbeat_packet[] PROGMEM = { 0xBE, 0xEF, 0xCA, 0xFE };
const uint8_t locator_ping_packet[] PROGMEM = { 0xDE, 0xAD, 0xBE, 0xEF };
TX's main function
int main(void)
{
// Change Clock divider to run from /2 instead of /8.
// Chip can run all the way down to 1.8 V @ 4 MHz
clock_prescale_set( clock_div_2 );
// Set buzzer and LED to output.
sbi( BUZZ_DDR, BUZZ_PIN );
turn_off_buzzer();
sbi( LED_DDR, LED_PIN );
turn_off_LED();
// Set button to input with pullup resistor enabled
cbi( BTN_DDR, BTN_PIN );
sbi( BTN_PORT, BTN_PIN );
// Power down unused modules
ADCSRA = 0; // Disable ADC
power_adc_disable();
power_timer1_disable();
ACSR = _BV(ACD); // Disable Analog Comparator
// enable global interrupts
sei();
// enable LOW level INT0 interrupt
// Set to input with pullup enabled.
cbi( DDRB, PB2 );
sbi( PORTB, PB2 );
// Set input to LOW level
cbi( MCUCR, ISC01 );
cbi( MCUCR, ISC00 );
// Enable INT0 interrupt
sbi( GIMSK, INT0 );
init_millis_timer();
init_usi_spi_master();
_delay_ms(150);
init_nrf24l01p(ADDRESS_WIDTH, COMMAND_PACKET_LENGTH);
set_address_from_eeprom();
uint8_t payload[COMMAND_PACKET_LENGTH];
set_tx_mode();
power_up();
memcpy_P( payload, locator_ping_packet, COMMAND_PACKET_LENGTH );
turn_on_LED();
_delay_ms(500);
turn_off_LED();
_delay_ms(1000);
for(;;)
{
turn_on_LED();
_delay_ms( 50 );
turn_off_LED();
write_tx_payload(payload, COMMAND_PACKET_LENGTH);
set_active();
_delay_us(15);
set_standby();
_delay_ms(1000);
write_command_register(REG_STATUS, _BV(TX_DS));
}
}
RX's main function
int main(void)
{
// Change Clock divider to run from /2 instead of /8.
// Chip can run all the way down to 1.8 V @ 4 MHz
clock_prescale_set( clock_div_2 );
// Set buzzer and LED to output.
sbi( BUZZ_DDR, BUZZ_PIN );
turn_off_buzzer();
sbi( LED_DDR, LED_PIN );
turn_off_LED();
// Power down unused modules
ADCSRA = 0; // Disable ADC
power_adc_disable();
power_timer1_disable();
ACSR = _BV(ACD); // Disable Analog Comparator
// enable global interrupts
sei();
// enable LOW level INT0 interrupt
// Set to input with pullup enabled.
cbi( DDRB, PB2 );
sbi( PORTB, PB2 );
// Set input to LOW level
cbi( MCUCR, ISC01 );
cbi( MCUCR, ISC00 );
// Enable INT0 interrupt
sbi( GIMSK, INT0 );
init_millis_timer();
init_usi_spi_master();
_delay_ms(150);
init_nrf24l01p(ADDRESS_WIDTH, COMMAND_PACKET_LENGTH);
set_address_from_eeprom();
set_rx_mode();
power_up();
set_active();
for(;;)
{
if( last_irq == INTZERO )
{
set_standby();
turn_on_LED();
_delay_ms(50);
turn_off_LED();
uint8_t payload[COMMAND_PACKET_LENGTH];
read_rx_payload(payload, COMMAND_PACKET_LENGTH);
uint8_t status = read_status_register();
if( status & _BV(RX_DR) )
{
uint8_t rx_pl_length = read_rx_payload_width();
eeprom_update_block( payload, payload_eeprom, COMMAND_PACKET_LENGTH );
uint8_t pipe = 0b111 & (status >> RX_P_NO);
if( pipe==1 && rx_pl_length==COMMAND_PACKET_LENGTH /*!memcmp_P(payload, heartbeat_packet, COMMAND_PACKET_LENGTH)*/ )
{
BUZZ_PORT ^= _BV(BUZZ_PIN);
}
}
// write to status register to clear
write_command_register(REG_STATUS, status);
flush_rx_fifo()
// Clear last_irq
last_irq = NONE;
// Reenable INT0 Interrupt
sbi( GIMSK, INT0 );;
set_active();
}
}
}
last_irq is a flag set in ISR(EXT_INT0_vect), which also disables the INT0 interrupt when triggered.
From nrf24l.c (shared between both devices). note that I have turned off auto-retransmit and auto-acknowledge. It's not critical that the packets are received (since they're just a heartbeat and a ping), I just want them to be sent.
void init_nrf24l01p(uint8_t add_w, uint8_t pack_w)
{
// Set SPI Chip Enable pin to output.
sbi(CSN_DDR, CSN_PIN);
// Set SPI Chip Enable pin HIGH.
unlatch_chip();
// Set TX/RX Chip Enable pin to output.
sbi(CE_DDR,CE_PIN);
set_standby();
set_tx_power(TX_POWER_M18_DBM);
set_tx_speed(TX_SPEED_2M);
// Turn off auto-acknowledge for all channels
write_command_register(REG_EN_AA, 0);
// Set addres width
write_command_register(REG_SETUP_AW, add_w-2);
// Set payload packet width
write_command_register(REG_RX_PW_P0, pack_w);
write_command_register(REG_RX_PW_P1, pack_w);
// Disable auto-retransmit
write_command_register(REG_SETUP_RETR, 0);
}
void write_tx_payload(uint8_t payload_buffer[], uint8_t size)
{
latch_chip();
usi_spi_transfer(NRF24_W_TX_PAYLOAD);
uint8_t i;
for( i=0; i<size; i++ )
{
usi_spi_transfer(payload_buffer[i]);
}
unlatch_chip();
}
void read_rx_payload(uint8_t payload_buffer[], uint8_t size)
{
latch_chip();
usi_spi_transfer(NRF24_R_RX_PAYLOAD);
uint8_t i;
for( i=0; i<size; i++ );
{
payload_buffer[i] = usi_spi_transfer(0x00);
}
unlatch_chip();
}
Full code for both devices is attached below.
EDIT: I've verified that I can read the status register correctly. It's only the RX FIFO that I have trouble with. I can't understand what's going on. Now I'm reading 01 f8 01 f7 from the payload, instead of what I was getting before. Does anyone know if these are error values?
Project.zip (87.6 KB)