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

Dependencies:   mbed

Fork of nRF24L01P_Hello_World by Owen Edwards

Committer:
petrsedlacek
Date:
Sun Jan 17 18:58:23 2016 +0000
Revision:
2:f555c7caa707
Parent:
1:5be2682710c6
Changed functions to public

Who changed what in which revision?

UserRevisionLine numberNew contents of line
petrsedlacek 2:f555c7caa707 1 //Autor: Petr Sedláček
petrsedlacek 2:f555c7caa707 2 //Project for MPOA 2015/2016, Experimental Point-to-point link with nRF24L01+ in 2.4 GHz ISM band
petrsedlacek 2:f555c7caa707 3
Owen 0:a51a6e7da590 4 #include "mbed.h"
Owen 0:a51a6e7da590 5 #include "nRF24L01P.h"
petrsedlacek 2:f555c7caa707 6 #include <string.h>
petrsedlacek 2:f555c7caa707 7 #include <Timer.h>
petrsedlacek 2:f555c7caa707 8 #include "menu.h"
petrsedlacek 2:f555c7caa707 9
petrsedlacek 2:f555c7caa707 10 #define TRANSFER_SIZE 16 //Maximum data size
petrsedlacek 2:f555c7caa707 11
Owen 0:a51a6e7da590 12
Owen 0:a51a6e7da590 13 Serial pc(USBTX, USBRX); // tx, rx
Owen 0:a51a6e7da590 14
petrsedlacek 2:f555c7caa707 15 nRF24L01P my_nrf24l01p(PTD2, PTD3, PTD1, PTD0, PTD5, PTA13); // mosi, miso, sck, csn, ce, irq
petrsedlacek 2:f555c7caa707 16
petrsedlacek 2:f555c7caa707 17 DigitalOut rled(LED_RED, 1);
petrsedlacek 2:f555c7caa707 18 DigitalOut gled(LED_GREEN, 1);
petrsedlacek 2:f555c7caa707 19
petrsedlacek 2:f555c7caa707 20 Timer rtt_timer; //Timer to measure RTT
petrsedlacek 2:f555c7caa707 21 Ticker rled_ticker; //Tickers for blinking LEDs
petrsedlacek 2:f555c7caa707 22 Ticker gled_ticker;
petrsedlacek 2:f555c7caa707 23
petrsedlacek 2:f555c7caa707 24 static uint16_t error_bits = 0; //static to be only visible in this file
petrsedlacek 2:f555c7caa707 25 static uint16_t all_bits = 0; //static to be only visible in this file
petrsedlacek 2:f555c7caa707 26 uint8_t interval;
petrsedlacek 2:f555c7caa707 27 char txData[TRANSFER_SIZE];
petrsedlacek 2:f555c7caa707 28 int txDataCnt = 0;
petrsedlacek 2:f555c7caa707 29 bool tx_mode;
petrsedlacek 2:f555c7caa707 30 bool keyboard_mode;
petrsedlacek 2:f555c7caa707 31
petrsedlacek 2:f555c7caa707 32 //Functions for LED blinks
petrsedlacek 2:f555c7caa707 33 void led_red_flip() {
petrsedlacek 2:f555c7caa707 34 rled = !rled;
petrsedlacek 2:f555c7caa707 35 rled_ticker.detach();
petrsedlacek 2:f555c7caa707 36
petrsedlacek 2:f555c7caa707 37 }
petrsedlacek 2:f555c7caa707 38
petrsedlacek 2:f555c7caa707 39 void led_green_flip() {
petrsedlacek 2:f555c7caa707 40 gled = !gled;
petrsedlacek 2:f555c7caa707 41 gled_ticker.detach();
petrsedlacek 2:f555c7caa707 42 }
Owen 0:a51a6e7da590 43
petrsedlacek 2:f555c7caa707 44 //Function for BER calculation
petrsedlacek 2:f555c7caa707 45 void ber_calculate(char recData[]) {
petrsedlacek 2:f555c7caa707 46 float ber = 0;
petrsedlacek 2:f555c7caa707 47 char sent_string[] = "ACK\r"; //Compared string
petrsedlacek 2:f555c7caa707 48
petrsedlacek 2:f555c7caa707 49 all_bits += (strlen(recData) *8); //Increase the size if incoming bits
petrsedlacek 2:f555c7caa707 50
petrsedlacek 2:f555c7caa707 51 for (uint8_t i=0; i<= strlen(recData); i++) {
petrsedlacek 2:f555c7caa707 52 recData[i] ^= sent_string[i]; //XOR received data with expected string
petrsedlacek 2:f555c7caa707 53
petrsedlacek 2:f555c7caa707 54 //If there was no error, all bits must be zero
petrsedlacek 2:f555c7caa707 55 while(recData[i] !=0) {
petrsedlacek 2:f555c7caa707 56 //If there was an error, increase number of error bits and shift by one
petrsedlacek 2:f555c7caa707 57 if (recData[i] & 1) {
petrsedlacek 2:f555c7caa707 58 error_bits++;
petrsedlacek 2:f555c7caa707 59 recData[i] >>= 1;
petrsedlacek 2:f555c7caa707 60 }
petrsedlacek 2:f555c7caa707 61 }
petrsedlacek 2:f555c7caa707 62
petrsedlacek 2:f555c7caa707 63
petrsedlacek 2:f555c7caa707 64 }
petrsedlacek 2:f555c7caa707 65 ber = (((float)error_bits)/all_bits) *100; //BER calculation
petrsedlacek 2:f555c7caa707 66 pc.printf("BER: %3.4f %%\n", ber);
petrsedlacek 2:f555c7caa707 67
petrsedlacek 2:f555c7caa707 68 }
petrsedlacek 2:f555c7caa707 69 //Function to send data automatically
petrsedlacek 2:f555c7caa707 70 void send() {
petrsedlacek 2:f555c7caa707 71 //If the device is TX, send ping message
petrsedlacek 2:f555c7caa707 72 if (tx_mode) {
petrsedlacek 2:f555c7caa707 73 sprintf(txData, "ping\r");
petrsedlacek 2:f555c7caa707 74 rtt_timer.start();
petrsedlacek 2:f555c7caa707 75 }
petrsedlacek 2:f555c7caa707 76 //If the device is RX, send ACK message
petrsedlacek 2:f555c7caa707 77 else {
petrsedlacek 2:f555c7caa707 78 sprintf(txData, "ACK\r");
petrsedlacek 2:f555c7caa707 79 }
petrsedlacek 2:f555c7caa707 80 //Print sent data and send it via nrf24l01
petrsedlacek 2:f555c7caa707 81 pc.printf("\nSent: %s", txData);
petrsedlacek 2:f555c7caa707 82 txDataCnt = 4;
petrsedlacek 2:f555c7caa707 83 my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt );
petrsedlacek 2:f555c7caa707 84 //Small blocking delay for LED blink
petrsedlacek 2:f555c7caa707 85 if (!tx_mode) {
petrsedlacek 2:f555c7caa707 86 wait_ms(200);
petrsedlacek 2:f555c7caa707 87 }
petrsedlacek 2:f555c7caa707 88 rled = 0;
petrsedlacek 2:f555c7caa707 89 rled_ticker.attach(&led_red_flip, 0.2);
petrsedlacek 2:f555c7caa707 90 }
petrsedlacek 2:f555c7caa707 91
petrsedlacek 2:f555c7caa707 92
Owen 0:a51a6e7da590 93
Owen 0:a51a6e7da590 94 int main() {
petrsedlacek 2:f555c7caa707 95 Timer send_timer; //Timer for sending automatic messages
petrsedlacek 2:f555c7caa707 96 uint16_t lost_num = 0; //Number of lost packets
petrsedlacek 2:f555c7caa707 97 uint16_t ack_num = 0; //Number of ACKs
petrsedlacek 2:f555c7caa707 98 uint16_t rec_messages = 0; //Number of received messages
petrsedlacek 2:f555c7caa707 99 char rxData[TRANSFER_SIZE];
petrsedlacek 2:f555c7caa707 100
Owen 0:a51a6e7da590 101 my_nrf24l01p.powerUp();
petrsedlacek 2:f555c7caa707 102 settings(); //Function for user menu
petrsedlacek 2:f555c7caa707 103
Owen 0:a51a6e7da590 104 // Display the (default) setup of the nRF24L01+ chip
petrsedlacek 2:f555c7caa707 105 pc.printf( "nRF24L01 Frequency : %d MHz\n", my_nrf24l01p.getRfFrequency() );
petrsedlacek 2:f555c7caa707 106 pc.printf( "nRF24L01 Output power : %d dBm\n", my_nrf24l01p.getRfOutputPower() );
petrsedlacek 2:f555c7caa707 107 pc.printf( "nRF24L01 Data Rate : %d kbps\n", my_nrf24l01p.getAirDataRate() );
petrsedlacek 2:f555c7caa707 108 pc.printf( "nRF24L01 TX Address : 0x%010llX\n", my_nrf24l01p.getTxAddress() );
petrsedlacek 2:f555c7caa707 109 pc.printf( "nRF24L01 RX Address : 0x%010llX\n", my_nrf24l01p.getRxAddress() );
petrsedlacek 2:f555c7caa707 110 //If TX mode and automatic mode are chosen, print the set interval for messages
petrsedlacek 2:f555c7caa707 111 if (tx_mode) {
petrsedlacek 2:f555c7caa707 112 pc.printf( "Message Interval : %d seconds\n", interval);
petrsedlacek 2:f555c7caa707 113 }
petrsedlacek 2:f555c7caa707 114 //If keyboard mode is set, print this message
petrsedlacek 2:f555c7caa707 115 if (keyboard_mode) {
petrsedlacek 2:f555c7caa707 116 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 );
petrsedlacek 2:f555c7caa707 117 }
petrsedlacek 2:f555c7caa707 118 //Set registers for dynamic payload
petrsedlacek 2:f555c7caa707 119 my_nrf24l01p.setRegister(_NRF24L01P_REG_FEATURE, 0x04);
petrsedlacek 2:f555c7caa707 120 my_nrf24l01p.setRegister(_NRF24L01P_REG_DYNPD, 0x01);
petrsedlacek 2:f555c7caa707 121 //Start up the nrf24L01
petrsedlacek 2:f555c7caa707 122 my_nrf24l01p.enable();
petrsedlacek 2:f555c7caa707 123 my_nrf24l01p.setReceiveMode();
petrsedlacek 2:f555c7caa707 124
petrsedlacek 2:f555c7caa707 125 //Start the timer for automatic transmissions
petrsedlacek 2:f555c7caa707 126 if (!keyboard_mode && tx_mode) {
petrsedlacek 2:f555c7caa707 127 send_timer.start();
petrsedlacek 2:f555c7caa707 128 }
Owen 0:a51a6e7da590 129
Owen 0:a51a6e7da590 130
Owen 0:a51a6e7da590 131 while (1) {
petrsedlacek 2:f555c7caa707 132 //Send messages periodically
petrsedlacek 2:f555c7caa707 133 if (!keyboard_mode && tx_mode) {
petrsedlacek 2:f555c7caa707 134 if ((int) send_timer.read_ms() % (interval*1000) == 0) {
petrsedlacek 2:f555c7caa707 135 send();
petrsedlacek 2:f555c7caa707 136 }
petrsedlacek 2:f555c7caa707 137 }
petrsedlacek 2:f555c7caa707 138 //If keyboard mode is activated, read user input
petrsedlacek 2:f555c7caa707 139 if (keyboard_mode) {
petrsedlacek 2:f555c7caa707 140 // If we've received anything over the host serial link...
petrsedlacek 2:f555c7caa707 141 if ( pc.readable() ) {
petrsedlacek 2:f555c7caa707 142 // ...add it to the transmit buffer
petrsedlacek 2:f555c7caa707 143 txData[txDataCnt++] = pc.getc();
petrsedlacek 2:f555c7caa707 144 // If the transmit buffer is full or Enter is pressed
petrsedlacek 2:f555c7caa707 145 if ( txDataCnt >= sizeof( txData ) || txData[txDataCnt-1] == '\r') {
petrsedlacek 2:f555c7caa707 146 // Send the transmit buffer via the nRF24L01+
petrsedlacek 2:f555c7caa707 147 my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt );
petrsedlacek 2:f555c7caa707 148 pc.printf("\nSent: %s\n", txData);
petrsedlacek 2:f555c7caa707 149 //Start the RTT timer in TX Mode
petrsedlacek 2:f555c7caa707 150 if (tx_mode) {
petrsedlacek 2:f555c7caa707 151 rtt_timer.start();
petrsedlacek 2:f555c7caa707 152 }
petrsedlacek 2:f555c7caa707 153 // Blink Red LED to indicate message sent
petrsedlacek 2:f555c7caa707 154 txDataCnt = 0;
petrsedlacek 2:f555c7caa707 155 rled = 0;
petrsedlacek 2:f555c7caa707 156 rled_ticker.attach(&led_red_flip, 0.2);
petrsedlacek 2:f555c7caa707 157 }
petrsedlacek 2:f555c7caa707 158
petrsedlacek 2:f555c7caa707 159 }
petrsedlacek 2:f555c7caa707 160 }
Owen 0:a51a6e7da590 161
Owen 0:a51a6e7da590 162
Owen 0:a51a6e7da590 163 // If we've received anything in the nRF24L01+...
Owen 0:a51a6e7da590 164 if ( my_nrf24l01p.readable() ) {
petrsedlacek 2:f555c7caa707 165 //Stop RTT timer
petrsedlacek 2:f555c7caa707 166 if (tx_mode) {
petrsedlacek 2:f555c7caa707 167 rtt_timer.stop();
petrsedlacek 2:f555c7caa707 168 wait_ms(200);
petrsedlacek 2:f555c7caa707 169 }
Owen 0:a51a6e7da590 170 // ...read the data into the receive buffer
petrsedlacek 2:f555c7caa707 171 my_nrf24l01p.read( NRF24L01P_PIPE_P0, rxData, sizeof( rxData ) );
petrsedlacek 2:f555c7caa707 172 pc.printf("Received: %s", rxData);
petrsedlacek 2:f555c7caa707 173 //Blink green led to indicate message received
petrsedlacek 2:f555c7caa707 174 gled = 0;
petrsedlacek 2:f555c7caa707 175 gled_ticker.attach(led_green_flip, 0.2);
petrsedlacek 2:f555c7caa707 176 //Send automatic response in RX mode
petrsedlacek 2:f555c7caa707 177 if (!keyboard_mode && !tx_mode) {
petrsedlacek 2:f555c7caa707 178 send();
petrsedlacek 2:f555c7caa707 179 }
petrsedlacek 2:f555c7caa707 180
petrsedlacek 2:f555c7caa707 181 if (tx_mode) {
petrsedlacek 2:f555c7caa707 182 //If a message wasn't received between automatic transmissions, increase BER and NACKs
petrsedlacek 2:f555c7caa707 183 if ((int) rtt_timer.read() >= interval && !keyboard_mode) {
petrsedlacek 2:f555c7caa707 184 lost_num = ((int) rtt_timer.read()/interval);
petrsedlacek 2:f555c7caa707 185 error_bits += (strlen(rxData) * 8) * lost_num;
petrsedlacek 2:f555c7caa707 186 all_bits += (strlen(rxData) * 8) * lost_num;
petrsedlacek 2:f555c7caa707 187 }
petrsedlacek 2:f555c7caa707 188 ack_num++; //If message was received between retransmissions, increase number of ACKs
petrsedlacek 2:f555c7caa707 189 pc.printf("RTT: %3.4f\n", rtt_timer.read()); //Print RTT
petrsedlacek 2:f555c7caa707 190 pc.printf("Number of ACKs: %d\n", ack_num); //Number of ACKs
petrsedlacek 2:f555c7caa707 191 pc.printf("Number of NACKs: %d\n", lost_num); //Number of NACKs
petrsedlacek 2:f555c7caa707 192 rtt_timer.reset(); //Reset the RTT timer
petrsedlacek 2:f555c7caa707 193 //Calculate BER, but only in automatic mode
petrsedlacek 2:f555c7caa707 194 if (!keyboard_mode) {
petrsedlacek 2:f555c7caa707 195 ber_calculate(rxData);
petrsedlacek 2:f555c7caa707 196 }
petrsedlacek 2:f555c7caa707 197 //If RX mode is activated, diplay number of received messages
petrsedlacek 2:f555c7caa707 198 } else {
petrsedlacek 2:f555c7caa707 199 rec_messages++;
petrsedlacek 2:f555c7caa707 200 pc.printf("Recieved message No.: %d\n\n", rec_messages);
petrsedlacek 2:f555c7caa707 201 }
petrsedlacek 2:f555c7caa707 202
Owen 0:a51a6e7da590 203
petrsedlacek 2:f555c7caa707 204
petrsedlacek 2:f555c7caa707 205 }
Owen 0:a51a6e7da590 206
Owen 0:a51a6e7da590 207 }
Owen 0:a51a6e7da590 208 }