Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp@5:fb39c8c13b34, 2020-11-23 (annotated)
- Committer:
- timo_k2
- Date:
- Mon Nov 23 12:48:48 2020 +0000
- Revision:
- 5:fb39c8c13b34
- Parent:
- 2:150dadff3c6b
- Child:
- 6:11edc8f9d870
Testing with the UDP_RoundTripEcho completed.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
timo_k2 | 0:2a5da7b2278c | 1 | /* |
timo_k2 | 0:2a5da7b2278c | 2 | * Copyright (c) 2006-2020 Arm Limited and affiliates. |
timo_k2 | 0:2a5da7b2278c | 3 | * SPDX-License-Identifier: Apache-2.0 |
timo_k2 | 0:2a5da7b2278c | 4 | *********************************** |
timo_k2 | 0:2a5da7b2278c | 5 | * Round trip delay meter. Date and time is taken from a NTP server. |
timo_k2 | 0:2a5da7b2278c | 6 | * A microcontroller board with an Ethernet interface. |
timo_k2 | 5:fb39c8c13b34 | 7 | * An other microcontroller with "Round trip echo" will be needed. |
timo_k2 | 0:2a5da7b2278c | 8 | * NXP FRDM-K64F used for testing. |
timo_k2 | 0:2a5da7b2278c | 9 | * |
timo_k2 | 0:2a5da7b2278c | 10 | * Timo Karppinen 20.11.2020 |
timo_k2 | 0:2a5da7b2278c | 11 | ***********************************/ |
timo_k2 | 0:2a5da7b2278c | 12 | #include "mbed.h" |
timo_k2 | 0:2a5da7b2278c | 13 | #include "EthernetInterface.h" |
timo_k2 | 0:2a5da7b2278c | 14 | #include "ntp-client/NTPClient.h" |
timo_k2 | 0:2a5da7b2278c | 15 | |
timo_k2 | 0:2a5da7b2278c | 16 | #define REMOTE_PORT 5000 |
timo_k2 | 0:2a5da7b2278c | 17 | #define LOCAL_PORT 5001 |
timo_k2 | 0:2a5da7b2278c | 18 | #define BUFF_SIZE 128 |
timo_k2 | 0:2a5da7b2278c | 19 | |
timo_k2 | 0:2a5da7b2278c | 20 | //Network interface |
timo_k2 | 0:2a5da7b2278c | 21 | EthernetInterface net; |
timo_k2 | 0:2a5da7b2278c | 22 | |
timo_k2 | 0:2a5da7b2278c | 23 | //Threads |
timo_k2 | 0:2a5da7b2278c | 24 | Thread ntp_thread; |
timo_k2 | 0:2a5da7b2278c | 25 | Thread recv_thread; |
timo_k2 | 0:2a5da7b2278c | 26 | Thread send_thread; |
timo_k2 | 0:2a5da7b2278c | 27 | |
timo_k2 | 0:2a5da7b2278c | 28 | // UDP |
timo_k2 | 0:2a5da7b2278c | 29 | SocketAddress clientUDP; // Client on remote device |
timo_k2 | 0:2a5da7b2278c | 30 | UDPSocket serverUDP; // UDP server in this device |
timo_k2 | 0:2a5da7b2278c | 31 | |
timo_k2 | 0:2a5da7b2278c | 32 | |
timo_k2 | 0:2a5da7b2278c | 33 | //NTP server is a time server used for delivering timing information for networks. |
timo_k2 | 0:2a5da7b2278c | 34 | // Returns 32 bits for seconds and 32 bits for fraction of seconds. |
timo_k2 | 0:2a5da7b2278c | 35 | //#define ntpAddress "2.pool.ntp.org" |
timo_k2 | 0:2a5da7b2278c | 36 | #define ntpAddress "time.mikes.fi" // The VTT Mikes in Helsinki |
timo_k2 | 0:2a5da7b2278c | 37 | #define ntpPort 123 |
timo_k2 | 0:2a5da7b2278c | 38 | |
timo_k2 | 0:2a5da7b2278c | 39 | // Functions |
timo_k2 | 0:2a5da7b2278c | 40 | time_t getNTP(); |
timo_k2 | 0:2a5da7b2278c | 41 | void udpReceive( void ); |
timo_k2 | 0:2a5da7b2278c | 42 | void udpSend( void ); |
timo_k2 | 0:2a5da7b2278c | 43 | |
timo_k2 | 5:fb39c8c13b34 | 44 | DigitalIn sw2(SW2); // sw2 on K64F, button pressed = FALSE |
timo_k2 | 5:fb39c8c13b34 | 45 | DigitalOut led2(LED2); // RGB LED green on K64F |
timo_k2 | 0:2a5da7b2278c | 46 | int sw2state = 0; |
timo_k2 | 0:2a5da7b2278c | 47 | int sw2old = 1; |
timo_k2 | 0:2a5da7b2278c | 48 | |
timo_k2 | 0:2a5da7b2278c | 49 | char in_data[BUFF_SIZE]; |
timo_k2 | 0:2a5da7b2278c | 50 | int newDatagram = 0; |
timo_k2 | 2:150dadff3c6b | 51 | int newDatagramOld = 0; |
timo_k2 | 0:2a5da7b2278c | 52 | time_t timeNTP = 0; |
timo_k2 | 0:2a5da7b2278c | 53 | |
timo_k2 | 1:961861d73841 | 54 | //using namespace std::chrono; |
timo_k2 | 0:2a5da7b2278c | 55 | Timer stopwatch; |
timo_k2 | 2:150dadff3c6b | 56 | Timer armedFor; |
timo_k2 | 0:2a5da7b2278c | 57 | |
timo_k2 | 0:2a5da7b2278c | 58 | int main() { |
timo_k2 | 5:fb39c8c13b34 | 59 | printf("\nRound trip delay in UDP messaging (using Ethernet)\n"); |
timo_k2 | 0:2a5da7b2278c | 60 | |
timo_k2 | 0:2a5da7b2278c | 61 | //Bring up the network interface |
timo_k2 | 0:2a5da7b2278c | 62 | net.connect(); |
timo_k2 | 0:2a5da7b2278c | 63 | |
timo_k2 | 0:2a5da7b2278c | 64 | // Show network address |
timo_k2 | 0:2a5da7b2278c | 65 | SocketAddress netAddress; |
timo_k2 | 0:2a5da7b2278c | 66 | net.get_ip_address(&netAddress); |
timo_k2 | 0:2a5da7b2278c | 67 | printf("\n\n NTPClient - UDPServer IP Address: %s\n", netAddress.get_ip_address() ? netAddress.get_ip_address():"None"); |
timo_k2 | 0:2a5da7b2278c | 68 | |
timo_k2 | 0:2a5da7b2278c | 69 | // NTP client at ntp thread |
timo_k2 | 0:2a5da7b2278c | 70 | ntp_thread.start(getNTP); |
timo_k2 | 0:2a5da7b2278c | 71 | |
timo_k2 | 0:2a5da7b2278c | 72 | // UDP server |
timo_k2 | 0:2a5da7b2278c | 73 | |
timo_k2 | 0:2a5da7b2278c | 74 | serverUDP.open(&net); |
timo_k2 | 0:2a5da7b2278c | 75 | int err = serverUDP.bind(LOCAL_PORT); |
timo_k2 | 0:2a5da7b2278c | 76 | printf("Port status is: %d\n",err); |
timo_k2 | 0:2a5da7b2278c | 77 | |
timo_k2 | 0:2a5da7b2278c | 78 | recv_thread.start(udpReceive); |
timo_k2 | 0:2a5da7b2278c | 79 | printf("Listening has been started at port number %d\n", LOCAL_PORT); |
timo_k2 | 0:2a5da7b2278c | 80 | |
timo_k2 | 0:2a5da7b2278c | 81 | send_thread.start(udpSend); |
timo_k2 | 0:2a5da7b2278c | 82 | printf("Sending out demo data to port number %d", REMOTE_PORT); |
timo_k2 | 0:2a5da7b2278c | 83 | printf(" has been started.\n"); |
timo_k2 | 0:2a5da7b2278c | 84 | printf("The IP will be taken from the incoming message\n"); |
timo_k2 | 0:2a5da7b2278c | 85 | |
timo_k2 | 0:2a5da7b2278c | 86 | |
timo_k2 | 0:2a5da7b2278c | 87 | while(1) { |
timo_k2 | 0:2a5da7b2278c | 88 | sw2state = sw2.read(); |
timo_k2 | 5:fb39c8c13b34 | 89 | printf( "\nsw2state is %d\n", sw2state); |
timo_k2 | 0:2a5da7b2278c | 90 | |
timo_k2 | 0:2a5da7b2278c | 91 | if((sw2state == 0)&&(sw2state != sw2old)) { |
timo_k2 | 0:2a5da7b2278c | 92 | led2.write(0); |
timo_k2 | 2:150dadff3c6b | 93 | armedFor.reset(); // reset timer to zero |
timo_k2 | 0:2a5da7b2278c | 94 | stopwatch.reset(); // reset stopwatch timer to zero |
timo_k2 | 0:2a5da7b2278c | 95 | timeNTP = getNTP(); |
timo_k2 | 2:150dadff3c6b | 96 | armedFor.start(); |
timo_k2 | 0:2a5da7b2278c | 97 | stopwatch.start(); |
timo_k2 | 0:2a5da7b2278c | 98 | udpSend(); |
timo_k2 | 0:2a5da7b2278c | 99 | |
timo_k2 | 0:2a5da7b2278c | 100 | |
timo_k2 | 2:150dadff3c6b | 101 | // Start polling for the incomening "Echo" UDP datagram |
timo_k2 | 2:150dadff3c6b | 102 | while ( armedFor.elapsed_time().count() < 8000000 ){ |
timo_k2 | 2:150dadff3c6b | 103 | if((newDatagram == 1)&&(newDatagram != newDatagramOld)){ |
timo_k2 | 2:150dadff3c6b | 104 | char firstChar; |
timo_k2 | 2:150dadff3c6b | 105 | firstChar = in_data[0]; |
timo_k2 | 2:150dadff3c6b | 106 | if (firstChar == 69){ // ASCII symbol 69 = "E" for the Echo |
timo_k2 | 2:150dadff3c6b | 107 | stopwatch.stop(); |
timo_k2 | 2:150dadff3c6b | 108 | printf( "firstChar: %s\n", &firstChar); |
timo_k2 | 2:150dadff3c6b | 109 | } |
timo_k2 | 2:150dadff3c6b | 110 | for (int k =0; k < BUFF_SIZE; k++){ |
timo_k2 | 2:150dadff3c6b | 111 | in_data[k] = 0; |
timo_k2 | 2:150dadff3c6b | 112 | } |
timo_k2 | 0:2a5da7b2278c | 113 | } |
timo_k2 | 2:150dadff3c6b | 114 | newDatagramOld = newDatagram; //Reading the stopwatch once only |
timo_k2 | 2:150dadff3c6b | 115 | |
timo_k2 | 0:2a5da7b2278c | 116 | } |
timo_k2 | 2:150dadff3c6b | 117 | |
timo_k2 | 2:150dadff3c6b | 118 | // printing for testing. Replace with writing once to a SD memory card. |
timo_k2 | 2:150dadff3c6b | 119 | printf("Current time in day month hour.min.sec year is %s\r\n", ctime(&timeNTP)); |
timo_k2 | 2:150dadff3c6b | 120 | printf("The time taken was %llu microseconds\n", stopwatch.elapsed_time().count()); |
timo_k2 | 0:2a5da7b2278c | 121 | } |
timo_k2 | 2:150dadff3c6b | 122 | newDatagram = 0; |
timo_k2 | 0:2a5da7b2278c | 123 | sw2old = sw2state; // Once only with pushing the button as long as you like. |
timo_k2 | 0:2a5da7b2278c | 124 | led2.write(1); |
timo_k2 | 2:150dadff3c6b | 125 | armedFor.stop(); |
timo_k2 | 0:2a5da7b2278c | 126 | stopwatch.stop(); // Stop the stopwatch if we did not receive the echo. |
timo_k2 | 0:2a5da7b2278c | 127 | |
timo_k2 | 0:2a5da7b2278c | 128 | printf("\nWe stopped sending more UDP packets to the server.\nYou can unplug your device!\n"); |
timo_k2 | 2:150dadff3c6b | 129 | ThisThread::sleep_for(4000ms); |
timo_k2 | 0:2a5da7b2278c | 130 | } |
timo_k2 | 0:2a5da7b2278c | 131 | } |
timo_k2 | 0:2a5da7b2278c | 132 | |
timo_k2 | 0:2a5da7b2278c | 133 | // The functions |
timo_k2 | 0:2a5da7b2278c | 134 | |
timo_k2 | 0:2a5da7b2278c | 135 | time_t getNTP() { |
timo_k2 | 0:2a5da7b2278c | 136 | NTPClient ntp(&net); |
timo_k2 | 0:2a5da7b2278c | 137 | ntp.set_server(ntpAddress, ntpPort); |
timo_k2 | 0:2a5da7b2278c | 138 | time_t timestamp = ntp.get_timestamp(); |
timo_k2 | 0:2a5da7b2278c | 139 | if (timestamp < 0) { |
timo_k2 | 0:2a5da7b2278c | 140 | printf("An error occurred when getting the time. Code: %u\r\n", timestamp); |
timo_k2 | 0:2a5da7b2278c | 141 | } |
timo_k2 | 0:2a5da7b2278c | 142 | else { // the printings for testing only! |
timo_k2 | 0:2a5da7b2278c | 143 | //printf("The timestamp seconds from the NTP server in\r\n 32 bit hexadecimal number is %X\r\n", timestamp); |
timo_k2 | 0:2a5da7b2278c | 144 | //printf(" decimal number is %u\r\n", timestamp); |
timo_k2 | 0:2a5da7b2278c | 145 | timestamp += (60*60*2); // GMT +2 for Finland for the winter time. |
timo_k2 | 0:2a5da7b2278c | 146 | //printf("Current time is %s\r\n", ctime(×tamp)); |
timo_k2 | 0:2a5da7b2278c | 147 | } |
timo_k2 | 0:2a5da7b2278c | 148 | return timestamp; |
timo_k2 | 0:2a5da7b2278c | 149 | } |
timo_k2 | 0:2a5da7b2278c | 150 | |
timo_k2 | 0:2a5da7b2278c | 151 | void udpReceive() |
timo_k2 | 0:2a5da7b2278c | 152 | { |
timo_k2 | 0:2a5da7b2278c | 153 | int bytes; |
timo_k2 | 0:2a5da7b2278c | 154 | while(1) { |
timo_k2 | 0:2a5da7b2278c | 155 | bytes = serverUDP.recvfrom(&clientUDP, &in_data, BUFF_SIZE); |
timo_k2 | 5:fb39c8c13b34 | 156 | newDatagram = 1; // set this before using time for printing |
timo_k2 | 0:2a5da7b2278c | 157 | printf("\n"); |
timo_k2 | 0:2a5da7b2278c | 158 | printf("bytes received: %d\n",bytes); |
timo_k2 | 0:2a5da7b2278c | 159 | printf("string: %s\n",in_data); |
timo_k2 | 0:2a5da7b2278c | 160 | printf("client address: %s\n", clientUDP.get_ip_address()); |
timo_k2 | 0:2a5da7b2278c | 161 | printf("\n"); |
timo_k2 | 5:fb39c8c13b34 | 162 | |
timo_k2 | 0:2a5da7b2278c | 163 | } |
timo_k2 | 0:2a5da7b2278c | 164 | } |
timo_k2 | 0:2a5da7b2278c | 165 | |
timo_k2 | 0:2a5da7b2278c | 166 | void udpSend() |
timo_k2 | 0:2a5da7b2278c | 167 | { |
timo_k2 | 0:2a5da7b2278c | 168 | char out_data[BUFF_SIZE]; |
timo_k2 | 0:2a5da7b2278c | 169 | |
timo_k2 | 2:150dadff3c6b | 170 | snprintf(out_data, BUFF_SIZE, "UDP message for getting the Echo" ); |
timo_k2 | 0:2a5da7b2278c | 171 | clientUDP.set_port(REMOTE_PORT); |
timo_k2 | 0:2a5da7b2278c | 172 | serverUDP.sendto(clientUDP, out_data, sizeof(out_data)); |
timo_k2 | 0:2a5da7b2278c | 173 | printf("Sending out: %s\n", out_data); |
timo_k2 | 0:2a5da7b2278c | 174 | printf("with %d" , sizeof(out_data)); |
timo_k2 | 0:2a5da7b2278c | 175 | printf(" data bytes in UDP datagram\n"); |
timo_k2 | 0:2a5da7b2278c | 176 | |
timo_k2 | 0:2a5da7b2278c | 177 | } |