Project for MPOA 2015/2016. Communication link with nRF24L01+.
Fork of nRF24L01P_Hello_World by
main.cpp@3:10a2f47a53a6, 2016-01-17 (annotated)
- Committer:
- petrsedlacek
- Date:
- Sun Jan 17 19:00:58 2016 +0000
- Revision:
- 3:10a2f47a53a6
- Parent:
- 2:f555c7caa707
Some functions changed to public
Who changed what in which revision?
User | Revision | Line number | New 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 | } |