Project for MPOA 2015/2016. Communication link with nRF24L01+.
Fork of nRF24L01P_Hello_World by
Diff: main.cpp
- Revision:
- 2:f555c7caa707
- Parent:
- 1:5be2682710c6
--- a/main.cpp Wed Jan 19 23:53:19 2011 +0000 +++ b/main.cpp Sun Jan 17 18:58:23 2016 +0000 @@ -1,75 +1,208 @@ +//Autor: Petr Sedláček +//Project for MPOA 2015/2016, Experimental Point-to-point link with nRF24L01+ in 2.4 GHz ISM band + #include "mbed.h" #include "nRF24L01P.h" +#include <string.h> +#include <Timer.h> +#include "menu.h" + +#define TRANSFER_SIZE 16 //Maximum data size + Serial pc(USBTX, USBRX); // tx, rx -nRF24L01P my_nrf24l01p(p5, p6, p7, p8, p9, p10); // mosi, miso, sck, csn, ce, irq +nRF24L01P my_nrf24l01p(PTD2, PTD3, PTD1, PTD0, PTD5, PTA13); // mosi, miso, sck, csn, ce, irq + +DigitalOut rled(LED_RED, 1); +DigitalOut gled(LED_GREEN, 1); + +Timer rtt_timer; //Timer to measure RTT +Ticker rled_ticker; //Tickers for blinking LEDs +Ticker gled_ticker; + +static uint16_t error_bits = 0; //static to be only visible in this file +static uint16_t all_bits = 0; //static to be only visible in this file +uint8_t interval; +char txData[TRANSFER_SIZE]; +int txDataCnt = 0; +bool tx_mode; +bool keyboard_mode; + +//Functions for LED blinks +void led_red_flip() { + rled = !rled; + rled_ticker.detach(); + +} + +void led_green_flip() { + gled = !gled; + gled_ticker.detach(); +} -DigitalOut myled1(LED1); -DigitalOut myled2(LED2); +//Function for BER calculation +void ber_calculate(char recData[]) { + float ber = 0; + char sent_string[] = "ACK\r"; //Compared string + + all_bits += (strlen(recData) *8); //Increase the size if incoming bits + + for (uint8_t i=0; i<= strlen(recData); i++) { + recData[i] ^= sent_string[i]; //XOR received data with expected string + + //If there was no error, all bits must be zero + while(recData[i] !=0) { + //If there was an error, increase number of error bits and shift by one + if (recData[i] & 1) { + error_bits++; + recData[i] >>= 1; + } + } + + + } + ber = (((float)error_bits)/all_bits) *100; //BER calculation + pc.printf("BER: %3.4f %%\n", ber); + +} +//Function to send data automatically +void send() { + //If the device is TX, send ping message + if (tx_mode) { + sprintf(txData, "ping\r"); + rtt_timer.start(); + } + //If the device is RX, send ACK message + else { + sprintf(txData, "ACK\r"); + } + //Print sent data and send it via nrf24l01 + pc.printf("\nSent: %s", txData); + txDataCnt = 4; + my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt ); + //Small blocking delay for LED blink + if (!tx_mode) { + wait_ms(200); + } + rled = 0; + rled_ticker.attach(&led_red_flip, 0.2); +} + + int main() { - -// The nRF24L01+ supports transfers from 1 to 32 bytes, but Sparkfun's -// "Nordic Serial Interface Board" (http://www.sparkfun.com/products/9019) -// only handles 4 byte transfers in the ATMega code. -#define TRANSFER_SIZE 4 - - char txData[TRANSFER_SIZE], rxData[TRANSFER_SIZE]; - int txDataCnt = 0; - int rxDataCnt = 0; - + Timer send_timer; //Timer for sending automatic messages + uint16_t lost_num = 0; //Number of lost packets + uint16_t ack_num = 0; //Number of ACKs + uint16_t rec_messages = 0; //Number of received messages + char rxData[TRANSFER_SIZE]; + my_nrf24l01p.powerUp(); - + settings(); //Function for user menu + // Display the (default) setup of the nRF24L01+ chip - pc.printf( "nRF24L01+ Frequency : %d MHz\r\n", my_nrf24l01p.getRfFrequency() ); - pc.printf( "nRF24L01+ Output power : %d dBm\r\n", my_nrf24l01p.getRfOutputPower() ); - pc.printf( "nRF24L01+ Data Rate : %d kbps\r\n", my_nrf24l01p.getAirDataRate() ); - pc.printf( "nRF24L01+ TX Address : 0x%010llX\r\n", my_nrf24l01p.getTxAddress() ); - pc.printf( "nRF24L01+ RX Address : 0x%010llX\r\n", my_nrf24l01p.getRxAddress() ); + pc.printf( "nRF24L01 Frequency : %d MHz\n", my_nrf24l01p.getRfFrequency() ); + pc.printf( "nRF24L01 Output power : %d dBm\n", my_nrf24l01p.getRfOutputPower() ); + pc.printf( "nRF24L01 Data Rate : %d kbps\n", my_nrf24l01p.getAirDataRate() ); + pc.printf( "nRF24L01 TX Address : 0x%010llX\n", my_nrf24l01p.getTxAddress() ); + pc.printf( "nRF24L01 RX Address : 0x%010llX\n", my_nrf24l01p.getRxAddress() ); + //If TX mode and automatic mode are chosen, print the set interval for messages + if (tx_mode) { + pc.printf( "Message Interval : %d seconds\n", interval); + } + //If keyboard mode is set, print this message + if (keyboard_mode) { + pc.printf( "Type keys to test transfers:\r\n (transfers are grouped into variable characters, maximum is a group of %d characters)\r\n", TRANSFER_SIZE ); + } + //Set registers for dynamic payload + my_nrf24l01p.setRegister(_NRF24L01P_REG_FEATURE, 0x04); + my_nrf24l01p.setRegister(_NRF24L01P_REG_DYNPD, 0x01); + //Start up the nrf24L01 + my_nrf24l01p.enable(); + my_nrf24l01p.setReceiveMode(); + + //Start the timer for automatic transmissions + if (!keyboard_mode && tx_mode) { + send_timer.start(); + } - pc.printf( "Type keys to test transfers:\r\n (transfers are grouped into %d characters)\r\n", TRANSFER_SIZE ); - - my_nrf24l01p.setTransferSize( TRANSFER_SIZE ); - - my_nrf24l01p.setReceiveMode(); - my_nrf24l01p.enable(); while (1) { - - // If we've received anything over the host serial link... - if ( pc.readable() ) { - - // ...add it to the transmit buffer - txData[txDataCnt++] = pc.getc(); - - // If the transmit buffer is full - if ( txDataCnt >= sizeof( txData ) ) { + //Send messages periodically + if (!keyboard_mode && tx_mode) { + if ((int) send_timer.read_ms() % (interval*1000) == 0) { + send(); + } + } + //If keyboard mode is activated, read user input + if (keyboard_mode) { + // If we've received anything over the host serial link... + if ( pc.readable() ) { + // ...add it to the transmit buffer + txData[txDataCnt++] = pc.getc(); + // If the transmit buffer is full or Enter is pressed + if ( txDataCnt >= sizeof( txData ) || txData[txDataCnt-1] == '\r') { + // Send the transmit buffer via the nRF24L01+ + my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt ); + pc.printf("\nSent: %s\n", txData); + //Start the RTT timer in TX Mode + if (tx_mode) { + rtt_timer.start(); + } + // Blink Red LED to indicate message sent + txDataCnt = 0; + rled = 0; + rled_ticker.attach(&led_red_flip, 0.2); + } + + } + } - // Send the transmitbuffer via the nRF24L01+ - my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt ); - - txDataCnt = 0; - } - - // Toggle LED1 (to help debug Host -> nRF24L01+ communication) - myled1 = !myled1; - } // If we've received anything in the nRF24L01+... if ( my_nrf24l01p.readable() ) { - + //Stop RTT timer + if (tx_mode) { + rtt_timer.stop(); + wait_ms(200); + } // ...read the data into the receive buffer - rxDataCnt = my_nrf24l01p.read( NRF24L01P_PIPE_P0, rxData, sizeof( rxData ) ); - - // Display the receive buffer contents via the host serial link - for ( int i = 0; rxDataCnt > 0; rxDataCnt--, i++ ) { + my_nrf24l01p.read( NRF24L01P_PIPE_P0, rxData, sizeof( rxData ) ); + pc.printf("Received: %s", rxData); + //Blink green led to indicate message received + gled = 0; + gled_ticker.attach(led_green_flip, 0.2); + //Send automatic response in RX mode + if (!keyboard_mode && !tx_mode) { + send(); + } + + if (tx_mode) { + //If a message wasn't received between automatic transmissions, increase BER and NACKs + if ((int) rtt_timer.read() >= interval && !keyboard_mode) { + lost_num = ((int) rtt_timer.read()/interval); + error_bits += (strlen(rxData) * 8) * lost_num; + all_bits += (strlen(rxData) * 8) * lost_num; + } + ack_num++; //If message was received between retransmissions, increase number of ACKs + pc.printf("RTT: %3.4f\n", rtt_timer.read()); //Print RTT + pc.printf("Number of ACKs: %d\n", ack_num); //Number of ACKs + pc.printf("Number of NACKs: %d\n", lost_num); //Number of NACKs + rtt_timer.reset(); //Reset the RTT timer + //Calculate BER, but only in automatic mode + if (!keyboard_mode) { + ber_calculate(rxData); + } + //If RX mode is activated, diplay number of received messages + } else { + rec_messages++; + pc.printf("Recieved message No.: %d\n\n", rec_messages); + } + - pc.putc( rxData[i] ); - } + + } - // Toggle LED2 (to help debug nRF24L01+ -> Host communication) - myled2 = !myled2; - } } }