Project for MPOA 2015/2016. Communication link with nRF24L01+.

Dependencies:   mbed

Fork of nRF24L01P_Hello_World by Owen Edwards

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;
-        }
     }
 }