This software example demonstrates the downlink capabilities of the SIGFOX network.
Dependencies: QW_Sensors mbed
Fork of HelloWorld - QW Development kit by
main.cpp@4:1d707586e24d, 2017-03-14 (annotated)
- Committer:
- quicksand
- Date:
- Tue Mar 14 12:45:21 2017 +0000
- Revision:
- 4:1d707586e24d
- Parent:
- 3:4da15d6e1429
This first version of the QW-Downlink program demonstrates the usage of SIGFOX downlinks to receive data from the cloud on the device.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
quicksand | 0:49858c4c3500 | 1 | #include "mbed.h" |
quicksand | 1:897a1b3f0955 | 2 | #include "math.h" |
quicksand | 0:49858c4c3500 | 3 | |
quicksand | 1:897a1b3f0955 | 4 | /* The 4 onboard LEDs */ |
quicksand | 4:1d707586e24d | 5 | BusOut leds(PB_6, PA_7, PA_6, PA_5); |
quicksand | 4:1d707586e24d | 6 | |
quicksand | 4:1d707586e24d | 7 | /* |
quicksand | 0:49858c4c3500 | 8 | DigitalOut LED_0 (PB_6); |
quicksand | 0:49858c4c3500 | 9 | DigitalOut LED_1 (PA_7); |
quicksand | 0:49858c4c3500 | 10 | DigitalOut LED_2 (PA_6); |
quicksand | 0:49858c4c3500 | 11 | DigitalOut LED_3 (PA_5); |
quicksand | 4:1d707586e24d | 12 | */ |
quicksand | 0:49858c4c3500 | 13 | |
quicksand | 1:897a1b3f0955 | 14 | /* The 2 user buttons */ |
quicksand | 1:897a1b3f0955 | 15 | InterruptIn SW1(PA_8); |
quicksand | 1:897a1b3f0955 | 16 | InterruptIn SW2(PB_10); |
quicksand | 1:897a1b3f0955 | 17 | |
quicksand | 1:897a1b3f0955 | 18 | /* Function prototypes */ |
quicksand | 4:1d707586e24d | 19 | void buttoninterrupt(); |
quicksand | 1:897a1b3f0955 | 20 | void beat(); |
quicksand | 1:897a1b3f0955 | 21 | void sertmout(); |
quicksand | 1:897a1b3f0955 | 22 | bool modem_command_check_ok(char * command); |
quicksand | 1:897a1b3f0955 | 23 | void modem_setup(); |
quicksand | 4:1d707586e24d | 24 | void downlink(); |
quicksand | 4:1d707586e24d | 25 | void error(); |
quicksand | 0:49858c4c3500 | 26 | |
quicksand | 1:897a1b3f0955 | 27 | bool ser_timeout = false; |
quicksand | 4:1d707586e24d | 28 | bool go_downlink = false; |
quicksand | 1:897a1b3f0955 | 29 | |
quicksand | 1:897a1b3f0955 | 30 | /* Serial port over USB */ |
quicksand | 0:49858c4c3500 | 31 | Serial pc(USBTX, USBRX); |
quicksand | 1:897a1b3f0955 | 32 | |
quicksand | 1:897a1b3f0955 | 33 | /* Serial connection to sigfox modem */ |
quicksand | 0:49858c4c3500 | 34 | Serial modem(PA_9, PA_10); |
quicksand | 0:49858c4c3500 | 35 | |
quicksand | 4:1d707586e24d | 36 | void binToString(char *inputData, int dataLength, char *outputData) // Note outputdata must be 2 x inputdata + 1 in size! |
quicksand | 4:1d707586e24d | 37 | { |
quicksand | 4:1d707586e24d | 38 | |
quicksand | 4:1d707586e24d | 39 | for (int i = 0; i<dataLength; i++) { |
quicksand | 4:1d707586e24d | 40 | sprintf(outputData+2*i,"%02X",*(inputData+i)); |
quicksand | 4:1d707586e24d | 41 | } |
quicksand | 4:1d707586e24d | 42 | outputData[dataLength*2] = 0; // in theory redundant, the last sprintf should have done this but just to be sure... |
quicksand | 4:1d707586e24d | 43 | } |
quicksand | 4:1d707586e24d | 44 | |
quicksand | 4:1d707586e24d | 45 | void error() |
quicksand | 4:1d707586e24d | 46 | { |
quicksand | 4:1d707586e24d | 47 | pc.printf("Something went wrong, please try again\n\r"); |
quicksand | 4:1d707586e24d | 48 | int i = 0; |
quicksand | 4:1d707586e24d | 49 | // Failure, blink rapidly: |
quicksand | 4:1d707586e24d | 50 | while(i < 25) { |
quicksand | 4:1d707586e24d | 51 | leds = 0b0000; |
quicksand | 4:1d707586e24d | 52 | wait_ms(100); |
quicksand | 4:1d707586e24d | 53 | leds = 0b1111; |
quicksand | 4:1d707586e24d | 54 | wait_ms(100); |
quicksand | 4:1d707586e24d | 55 | i++; |
quicksand | 4:1d707586e24d | 56 | } |
quicksand | 4:1d707586e24d | 57 | } |
quicksand | 4:1d707586e24d | 58 | |
quicksand | 4:1d707586e24d | 59 | /* Button 1 ISR */ |
quicksand | 4:1d707586e24d | 60 | void buttoninterrupt() |
quicksand | 4:1d707586e24d | 61 | { |
quicksand | 4:1d707586e24d | 62 | go_downlink = true; |
quicksand | 4:1d707586e24d | 63 | } |
quicksand | 1:897a1b3f0955 | 64 | |
quicksand | 1:897a1b3f0955 | 65 | int main() |
quicksand | 1:897a1b3f0955 | 66 | { |
quicksand | 0:49858c4c3500 | 67 | |
quicksand | 1:897a1b3f0955 | 68 | /* Setup TD120x */ |
quicksand | 1:897a1b3f0955 | 69 | wait(3); |
quicksand | 1:897a1b3f0955 | 70 | modem_setup(); |
quicksand | 4:1d707586e24d | 71 | leds = 0b1111; |
quicksand | 1:897a1b3f0955 | 72 | /* Setup button interrupts */ |
quicksand | 4:1d707586e24d | 73 | SW2.fall(&buttoninterrupt); |
quicksand | 4:1d707586e24d | 74 | SW1.fall(&buttoninterrupt); |
quicksand | 1:897a1b3f0955 | 75 | |
quicksand | 1:897a1b3f0955 | 76 | while(1) { |
quicksand | 4:1d707586e24d | 77 | if(go_downlink) { |
quicksand | 4:1d707586e24d | 78 | downlink(); |
quicksand | 4:1d707586e24d | 79 | go_downlink = false; |
quicksand | 4:1d707586e24d | 80 | } |
quicksand | 0:49858c4c3500 | 81 | if(pc.readable()) { |
quicksand | 0:49858c4c3500 | 82 | modem.putc(pc.getc()); |
quicksand | 0:49858c4c3500 | 83 | } |
quicksand | 0:49858c4c3500 | 84 | if(modem.readable()) { |
quicksand | 1:897a1b3f0955 | 85 | pc.putc(modem.getc()); |
quicksand | 0:49858c4c3500 | 86 | } |
quicksand | 0:49858c4c3500 | 87 | } |
quicksand | 0:49858c4c3500 | 88 | } |
quicksand | 1:897a1b3f0955 | 89 | |
quicksand | 4:1d707586e24d | 90 | void downlink() |
quicksand | 1:897a1b3f0955 | 91 | { |
quicksand | 4:1d707586e24d | 92 | leds = 0b0000; |
quicksand | 4:1d707586e24d | 93 | pc.printf("Requesting bidirectional data\n\r"); |
quicksand | 4:1d707586e24d | 94 | if(modem_command_check_ok("AT$SF=0102030405060708090A0B0C,2,1")) { |
quicksand | 4:1d707586e24d | 95 | pc.printf("Done sending request, waiting to start reception...\n\r"); |
quicksand | 4:1d707586e24d | 96 | char * beginString = "+RX BEGIN"; |
quicksand | 4:1d707586e24d | 97 | char * beginStringPtr; |
quicksand | 4:1d707586e24d | 98 | beginStringPtr = beginString; |
quicksand | 4:1d707586e24d | 99 | bool begin_rx = false; |
quicksand | 4:1d707586e24d | 100 | |
quicksand | 4:1d707586e24d | 101 | /* Turn off all LED*/ |
quicksand | 4:1d707586e24d | 102 | leds = 0b1111; |
quicksand | 4:1d707586e24d | 103 | /* Timeout */ |
quicksand | 4:1d707586e24d | 104 | Timeout tmout; |
quicksand | 4:1d707586e24d | 105 | ser_timeout = false; |
quicksand | 4:1d707586e24d | 106 | tmout.attach(&sertmout, 35.0); |
quicksand | 4:1d707586e24d | 107 | /* Animation while waiting for downlink */ |
quicksand | 4:1d707586e24d | 108 | int c; |
quicksand | 4:1d707586e24d | 109 | int animation = 0; |
quicksand | 4:1d707586e24d | 110 | while(!ser_timeout && !begin_rx) { |
quicksand | 1:897a1b3f0955 | 111 | |
quicksand | 4:1d707586e24d | 112 | while (modem.readable() && !ser_timeout && !begin_rx) { |
quicksand | 4:1d707586e24d | 113 | c = modem.getc(); |
quicksand | 4:1d707586e24d | 114 | if ( (char)c == *beginStringPtr ) beginStringPtr++; |
quicksand | 4:1d707586e24d | 115 | else beginStringPtr = beginString; |
quicksand | 4:1d707586e24d | 116 | if ( *beginStringPtr == 0 ) { |
quicksand | 4:1d707586e24d | 117 | begin_rx = true; |
quicksand | 4:1d707586e24d | 118 | pc.printf("Entering reception window\n\r"); |
quicksand | 4:1d707586e24d | 119 | } |
quicksand | 4:1d707586e24d | 120 | } |
quicksand | 4:1d707586e24d | 121 | animation = (animation + 1)%150000; |
quicksand | 4:1d707586e24d | 122 | if(animation == 0) leds = 0b1110; |
quicksand | 4:1d707586e24d | 123 | if(animation == 25000) leds = 0b1101; |
quicksand | 4:1d707586e24d | 124 | if(animation == 50000) leds = 0b1011; |
quicksand | 4:1d707586e24d | 125 | if(animation == 75000) leds = 0b0111; |
quicksand | 4:1d707586e24d | 126 | if(animation == 100000) leds = 0b1011; |
quicksand | 4:1d707586e24d | 127 | if(animation == 125000) leds = 0b1101; |
quicksand | 4:1d707586e24d | 128 | } |
quicksand | 4:1d707586e24d | 129 | /* turn off timeout timer */ |
quicksand | 4:1d707586e24d | 130 | tmout.detach(); |
quicksand | 4:1d707586e24d | 131 | if(ser_timeout) error(); |
quicksand | 4:1d707586e24d | 132 | else { |
quicksand | 4:1d707586e24d | 133 | /* Turn on outer LEDs*/ |
quicksand | 4:1d707586e24d | 134 | leds = 0b0110; |
quicksand | 4:1d707586e24d | 135 | /* Read the data */ |
quicksand | 4:1d707586e24d | 136 | // check if reception window ended |
quicksand | 4:1d707586e24d | 137 | char * readyString = "+RX END"; |
quicksand | 4:1d707586e24d | 138 | char * readyStringPtr; |
quicksand | 4:1d707586e24d | 139 | readyStringPtr = readyString; |
quicksand | 4:1d707586e24d | 140 | bool rx_ready = false; |
quicksand | 4:1d707586e24d | 141 | int c; |
quicksand | 4:1d707586e24d | 142 | char rx_buffer[128]; |
quicksand | 4:1d707586e24d | 143 | int i = 0; |
quicksand | 4:1d707586e24d | 144 | int j = 0; |
quicksand | 4:1d707586e24d | 145 | tmout.attach(&sertmout, 30.0); |
quicksand | 4:1d707586e24d | 146 | ser_timeout = false; |
quicksand | 4:1d707586e24d | 147 | while(modem.readable() && !ser_timeout && !rx_ready) |
quicksand | 4:1d707586e24d | 148 | while (((c = modem.getc()) > 0) && !ser_timeout && !rx_ready) { |
quicksand | 4:1d707586e24d | 149 | rx_buffer[i++] = (char)c; |
quicksand | 4:1d707586e24d | 150 | pc.putc((char)c); |
quicksand | 4:1d707586e24d | 151 | if ( (char)c == *readyStringPtr ) readyStringPtr++; |
quicksand | 4:1d707586e24d | 152 | else readyStringPtr = readyString; |
quicksand | 4:1d707586e24d | 153 | if ( *readyStringPtr == 0 ) { |
quicksand | 4:1d707586e24d | 154 | rx_ready = true; |
quicksand | 4:1d707586e24d | 155 | } |
quicksand | 4:1d707586e24d | 156 | } |
quicksand | 4:1d707586e24d | 157 | rx_buffer[i++] = 0; // EOS |
quicksand | 4:1d707586e24d | 158 | tmout.detach(); |
quicksand | 4:1d707586e24d | 159 | if(ser_timeout) error(); |
quicksand | 4:1d707586e24d | 160 | else { |
quicksand | 4:1d707586e24d | 161 | /* Turn off all LED*/ |
quicksand | 4:1d707586e24d | 162 | leds = 0b1111; |
quicksand | 4:1d707586e24d | 163 | pc.printf("\n\rReception done, received data:\n\r"); |
quicksand | 4:1d707586e24d | 164 | /* removing spaces, new lines, start and end markings */ |
quicksand | 4:1d707586e24d | 165 | for(i = 0, j = 0; i < strlen(rx_buffer); i++) { |
quicksand | 4:1d707586e24d | 166 | rx_buffer[i-j] = rx_buffer[i]; |
quicksand | 4:1d707586e24d | 167 | if(rx_buffer[i] == ' ' || rx_buffer[i] == '\n' || rx_buffer[i] == '\r' || rx_buffer[i] == '+' || rx_buffer[i] == '=' || (rx_buffer[i] > 'A' && rx_buffer[i] < 'Z')) |
quicksand | 4:1d707586e24d | 168 | j++; |
quicksand | 4:1d707586e24d | 169 | } |
quicksand | 4:1d707586e24d | 170 | /* do not forget EOS again! */ |
quicksand | 4:1d707586e24d | 171 | rx_buffer[i-j] = 0; |
quicksand | 4:1d707586e24d | 172 | |
quicksand | 4:1d707586e24d | 173 | if(strlen(rx_buffer) != 0) { |
quicksand | 4:1d707586e24d | 174 | /* Print received data without spaces and markers */ |
quicksand | 4:1d707586e24d | 175 | for(j = 0; j < strlen(rx_buffer); j++) pc.putc(rx_buffer[j]); |
quicksand | 4:1d707586e24d | 176 | |
quicksand | 4:1d707586e24d | 177 | char buff[32]; |
quicksand | 4:1d707586e24d | 178 | |
quicksand | 4:1d707586e24d | 179 | /* Extract tap and store to int (in this case you would have been able to just print the received data)*/ |
quicksand | 4:1d707586e24d | 180 | memcpy( buff, &rx_buffer[0], 8 ); |
quicksand | 4:1d707586e24d | 181 | buff[8] = '\0'; |
quicksand | 4:1d707586e24d | 182 | int tap = (int)strtol(buff, NULL, 16); |
quicksand | 4:1d707586e24d | 183 | |
quicksand | 4:1d707586e24d | 184 | /* Extract Client data*/ |
quicksand | 4:1d707586e24d | 185 | memcpy( buff, &rx_buffer[8], 4 ); |
quicksand | 4:1d707586e24d | 186 | buff[4] = '\0'; |
quicksand | 4:1d707586e24d | 187 | int client = (int)strtol(buff, NULL, 16); |
quicksand | 4:1d707586e24d | 188 | |
quicksand | 4:1d707586e24d | 189 | /* Exctract the RSSI */ |
quicksand | 4:1d707586e24d | 190 | memcpy( buff, &rx_buffer[12], 4 ); |
quicksand | 4:1d707586e24d | 191 | buff[4] = '\0'; |
quicksand | 4:1d707586e24d | 192 | int16_t rssi = (int16_t)strtol(buff, NULL, 16); |
quicksand | 4:1d707586e24d | 193 | |
quicksand | 4:1d707586e24d | 194 | pc.printf("\n\rMessage received on tap: %X\n\r", tap); |
quicksand | 4:1d707586e24d | 195 | pc.printf("Client data: %X\n\r", client); |
quicksand | 4:1d707586e24d | 196 | pc.printf("RSSI level: %d\n\r", rssi); |
quicksand | 4:1d707586e24d | 197 | |
quicksand | 4:1d707586e24d | 198 | if(rssi > -90) leds = 0b0000; |
quicksand | 4:1d707586e24d | 199 | else if (rssi > -110) leds = 0b0001; |
quicksand | 4:1d707586e24d | 200 | else if (rssi > -130) leds = 0b0011; |
quicksand | 4:1d707586e24d | 201 | else leds = 0b0111; |
quicksand | 4:1d707586e24d | 202 | } else { |
quicksand | 4:1d707586e24d | 203 | pc.printf("\n\rNo valid downlink data received!\n\r"); |
quicksand | 4:1d707586e24d | 204 | error(); |
quicksand | 4:1d707586e24d | 205 | } |
quicksand | 4:1d707586e24d | 206 | } |
quicksand | 4:1d707586e24d | 207 | } |
quicksand | 1:897a1b3f0955 | 208 | |
quicksand | 1:897a1b3f0955 | 209 | |
quicksand | 4:1d707586e24d | 210 | } else { |
quicksand | 4:1d707586e24d | 211 | // Failure, blink rapidly indefinetly: |
quicksand | 4:1d707586e24d | 212 | error(); |
quicksand | 4:1d707586e24d | 213 | } |
quicksand | 1:897a1b3f0955 | 214 | } |
quicksand | 1:897a1b3f0955 | 215 | |
quicksand | 1:897a1b3f0955 | 216 | void modem_setup() |
quicksand | 1:897a1b3f0955 | 217 | { |
quicksand | 1:897a1b3f0955 | 218 | /* Reset to factory defaults */ |
quicksand | 1:897a1b3f0955 | 219 | if(modem_command_check_ok("AT&F")) { |
quicksand | 1:897a1b3f0955 | 220 | pc.printf("Factory reset succesfull\r\n"); |
quicksand | 1:897a1b3f0955 | 221 | } else { |
quicksand | 1:897a1b3f0955 | 222 | pc.printf("Factory reset TD120x failed\r\n"); |
quicksand | 1:897a1b3f0955 | 223 | } |
quicksand | 1:897a1b3f0955 | 224 | /* Disable local echo */ |
quicksand | 1:897a1b3f0955 | 225 | modem.printf("ATE0\n"); |
quicksand | 1:897a1b3f0955 | 226 | if(modem_command_check_ok("ATE0")) { |
quicksand | 1:897a1b3f0955 | 227 | pc.printf("Local echo disabled\r\n"); |
quicksand | 1:897a1b3f0955 | 228 | } |
quicksand | 1:897a1b3f0955 | 229 | /* Write to mem */ |
quicksand | 1:897a1b3f0955 | 230 | if(modem_command_check_ok("AT&W")) { |
quicksand | 1:897a1b3f0955 | 231 | pc.printf("Settings saved!\r\n"); |
quicksand | 1:897a1b3f0955 | 232 | } |
quicksand | 1:897a1b3f0955 | 233 | } |
quicksand | 1:897a1b3f0955 | 234 | |
quicksand | 1:897a1b3f0955 | 235 | /* ISR for serial timeout */ |
quicksand | 1:897a1b3f0955 | 236 | void sertmout() |
quicksand | 1:897a1b3f0955 | 237 | { |
quicksand | 1:897a1b3f0955 | 238 | ser_timeout = true; |
quicksand | 1:897a1b3f0955 | 239 | } |
quicksand | 1:897a1b3f0955 | 240 | |
quicksand | 1:897a1b3f0955 | 241 | bool modem_command_check_ok(char * command) |
quicksand | 1:897a1b3f0955 | 242 | { |
quicksand | 1:897a1b3f0955 | 243 | /* first clear serial data buffers */ |
quicksand | 1:897a1b3f0955 | 244 | while(modem.readable()) modem.getc(); |
quicksand | 1:897a1b3f0955 | 245 | /* Timeout for response of the modem */ |
quicksand | 1:897a1b3f0955 | 246 | Timeout tmout; |
quicksand | 1:897a1b3f0955 | 247 | ser_timeout = false; |
quicksand | 4:1d707586e24d | 248 | // check if ok or error is received |
quicksand | 4:1d707586e24d | 249 | char * readyString = "OK"; |
quicksand | 4:1d707586e24d | 250 | char * readyStringPtr; |
quicksand | 4:1d707586e24d | 251 | readyStringPtr = readyString; |
quicksand | 4:1d707586e24d | 252 | char * errorString = "ERROR"; |
quicksand | 4:1d707586e24d | 253 | char * errorStringPtr; |
quicksand | 4:1d707586e24d | 254 | errorStringPtr = errorString; |
quicksand | 1:897a1b3f0955 | 255 | /* Flag to set when we get 'OK' response */ |
quicksand | 1:897a1b3f0955 | 256 | bool ok = false; |
quicksand | 1:897a1b3f0955 | 257 | bool error = false; |
quicksand | 1:897a1b3f0955 | 258 | /* Print command to TD120x */ |
quicksand | 1:897a1b3f0955 | 259 | modem.printf(command); |
quicksand | 1:897a1b3f0955 | 260 | /* Newline to activate command */ |
quicksand | 1:897a1b3f0955 | 261 | modem.printf("\n"); |
quicksand | 4:1d707586e24d | 262 | /* Wait untill serial feedback, max 10 seconds before timeout */ |
quicksand | 4:1d707586e24d | 263 | tmout.attach(&sertmout, 10.0); |
quicksand | 4:1d707586e24d | 264 | int c; |
quicksand | 4:1d707586e24d | 265 | while(!ser_timeout && !ok && !error) |
quicksand | 4:1d707586e24d | 266 | if(modem.readable()) |
quicksand | 4:1d707586e24d | 267 | while (((c = modem.getc()) > 0) && !ser_timeout && !ok && !error) { |
quicksand | 4:1d707586e24d | 268 | if ( (char)c == *readyStringPtr ) readyStringPtr++; |
quicksand | 4:1d707586e24d | 269 | else readyStringPtr = readyString; |
quicksand | 4:1d707586e24d | 270 | if ( *readyStringPtr == 0 ) { |
quicksand | 4:1d707586e24d | 271 | ok = true; |
quicksand | 4:1d707586e24d | 272 | } |
quicksand | 4:1d707586e24d | 273 | if ( (char)c == *errorStringPtr ) errorStringPtr++; |
quicksand | 4:1d707586e24d | 274 | else errorStringPtr = errorString; |
quicksand | 4:1d707586e24d | 275 | if ( *errorStringPtr == 0 ) { |
quicksand | 4:1d707586e24d | 276 | error = true; |
quicksand | 4:1d707586e24d | 277 | } |
quicksand | 1:897a1b3f0955 | 278 | } |
quicksand | 1:897a1b3f0955 | 279 | tmout.detach(); |
quicksand | 4:1d707586e24d | 280 | if(ser_timeout) return false; |
quicksand | 4:1d707586e24d | 281 | else return ok; |
quicksand | 1:897a1b3f0955 | 282 | } |