This software example demonstrates the downlink capabilities of the SIGFOX network.

Dependencies:   QW_Sensors mbed

Fork of HelloWorld - QW Development kit by Quicksand micro-electronics

Files at this revision

API Documentation at this revision

Comitter:
quicksand
Date:
Tue Mar 14 12:45:21 2017 +0000
Parent:
3:4da15d6e1429
Commit message:
This first version of the QW-Downlink program demonstrates the usage of SIGFOX downlinks to receive data from the cloud on the device.

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 4da15d6e1429 -r 1d707586e24d main.cpp
--- a/main.cpp	Mon May 02 12:04:13 2016 +0000
+++ b/main.cpp	Tue Mar 14 12:45:21 2017 +0000
@@ -1,32 +1,31 @@
 #include "mbed.h"
 #include "math.h"
-#include "LinearTempSensor.h"
 
 /* The 4 onboard LEDs */
+BusOut leds(PB_6, PA_7, PA_6, PA_5);
+
+/*
 DigitalOut LED_0 (PB_6);
 DigitalOut LED_1 (PA_7);
 DigitalOut LED_2 (PA_6);
 DigitalOut LED_3 (PA_5);
+*/
 
 /* The 2 user buttons */
 InterruptIn SW1(PA_8);
 InterruptIn SW2(PB_10);
 
-/*Temperature sensor */
-LinearTempSensor sensor(PA_0, 5);
-
 /* Function prototypes */
-void sw1interrupt();
-void sw2interrupt();
+void buttoninterrupt();
 void beat();
 void sertmout();
 bool modem_command_check_ok(char * command);
 void modem_setup();
-void txData(uint8_t btn);
+void downlink();
+void error();
 
 bool ser_timeout = false;
-
-Ticker heartbeat;
+bool go_downlink = false;
 
 /* Serial port over USB */
 Serial pc(USBTX, USBRX);
@@ -34,6 +33,34 @@
 /* Serial connection to sigfox modem */
 Serial modem(PA_9, PA_10);
 
+void binToString(char *inputData, int dataLength, char *outputData)   // Note outputdata must be 2 x inputdata + 1 in size!
+{
+
+    for (int i = 0; i<dataLength; i++) {
+        sprintf(outputData+2*i,"%02X",*(inputData+i));
+    }
+    outputData[dataLength*2] = 0; // in theory redundant, the last sprintf should have done this but just to be sure...
+}
+
+void error()
+{
+    pc.printf("Something went wrong, please try again\n\r");
+    int i = 0;
+    // Failure, blink rapidly:
+    while(i < 25) {
+        leds = 0b0000;
+        wait_ms(100);
+        leds = 0b1111;
+        wait_ms(100);
+        i++;
+    }
+}
+
+/* Button 1 ISR */
+void buttoninterrupt()
+{
+    go_downlink = true;
+}
 
 int main()
 {
@@ -41,24 +68,16 @@
     /* Setup TD120x */
     wait(3);
     modem_setup();
-    /* Test temperature sensor */
-    float vOut = sensor.Sense();
-    pc.printf("\n\rMCP9700 reading:  Vout: %.2f mV", vOut);
-
-    /* Turn off all LED */
-    LED_0 = 1;
-    LED_1 = 1;
-    LED_2 = 1;
-    LED_3 = 1;
-
-    /* Blinking LED */
-    heartbeat.attach(&beat, 0.5);
-
+    leds = 0b1111;
     /* Setup button interrupts */
-    SW2.fall(&sw2interrupt);
-    SW1.fall(&sw1interrupt);
+    SW2.fall(&buttoninterrupt);
+    SW1.fall(&buttoninterrupt);
 
     while(1) {
+        if(go_downlink) {
+            downlink();
+            go_downlink = false;
+        }
         if(pc.readable()) {
             modem.putc(pc.getc());
         }
@@ -68,46 +87,130 @@
     }
 }
 
-void beat()
-{
-    LED_0 = !LED_0;
-}
-
-/* Button 1 ISR */
-void sw1interrupt()
+void downlink()
 {
-    pc.printf("\n\rButton 1 pressed\n\r");
-    LED_1 = 0;
-    txData(1);
-}
+    leds = 0b0000;
+    pc.printf("Requesting bidirectional data\n\r");
+    if(modem_command_check_ok("AT$SF=0102030405060708090A0B0C,2,1")) {
+        pc.printf("Done sending request, waiting to start reception...\n\r");
+        char * beginString = "+RX BEGIN";
+        char * beginStringPtr;
+        beginStringPtr = beginString;
+        bool begin_rx = false;
+
+        /* Turn off all LED*/
+        leds = 0b1111;
+        /* Timeout */
+        Timeout tmout;
+        ser_timeout = false;
+        tmout.attach(&sertmout, 35.0);
+        /* Animation while waiting for downlink */
+        int c;
+        int animation = 0;
+        while(!ser_timeout && !begin_rx) {
 
-/* Button 2 ISR */
-void sw2interrupt()
-{
-    pc.printf("\n\rButton 2 pressed\n\r");
-    LED_2 = 0;
-    txData(2);
-}
+            while (modem.readable() && !ser_timeout && !begin_rx) {
+                c = modem.getc();
+                if ( (char)c == *beginStringPtr ) beginStringPtr++;
+                else beginStringPtr = beginString;
+                if ( *beginStringPtr == 0 ) {
+                    begin_rx = true;
+                    pc.printf("Entering reception window\n\r");
+                }
+            }
+            animation = (animation + 1)%150000;
+            if(animation == 0)      leds = 0b1110;
+            if(animation == 25000)  leds = 0b1101;
+            if(animation == 50000)  leds = 0b1011;
+            if(animation == 75000)  leds = 0b0111;
+            if(animation == 100000) leds = 0b1011;
+            if(animation == 125000) leds = 0b1101;
+        }
+        /* turn off timeout timer */
+        tmout.detach();
+        if(ser_timeout) error();
+        else {
+            /* Turn on outer LEDs*/
+            leds = 0b0110;
+            /* Read the data */
+            // check if reception window ended
+            char * readyString = "+RX END";
+            char * readyStringPtr;
+            readyStringPtr = readyString;
+            bool rx_ready = false;
+            int c;
+            char rx_buffer[128];
+            int i = 0;
+            int j = 0;
+            tmout.attach(&sertmout, 30.0);
+            ser_timeout = false;
+            while(modem.readable() && !ser_timeout && !rx_ready)
+                while (((c = modem.getc()) > 0) && !ser_timeout && !rx_ready) {
+                    rx_buffer[i++] = (char)c;
+                    pc.putc((char)c);
+                    if ( (char)c == *readyStringPtr ) readyStringPtr++;
+                    else readyStringPtr = readyString;
+                    if ( *readyStringPtr == 0 ) {
+                        rx_ready = true;
+                    }
+                }
+            rx_buffer[i++] = 0; // EOS
+            tmout.detach();
+            if(ser_timeout) error();
+            else {
+                /* Turn off all LED*/
+                leds = 0b1111;
+                pc.printf("\n\rReception done, received data:\n\r");
+                /* removing spaces, new lines, start and end markings */
+                for(i = 0, j = 0; i < strlen(rx_buffer); i++) {
+                    rx_buffer[i-j] = rx_buffer[i];
+                    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'))
+                        j++;
+                }
+                /* do not forget EOS again! */
+                rx_buffer[i-j] = 0;
+
+                if(strlen(rx_buffer) != 0) {
+                    /* Print received data without spaces and markers */
+                    for(j = 0; j < strlen(rx_buffer); j++) pc.putc(rx_buffer[j]);
+
+                    char buff[32];
+
+                    /* Extract tap and store to int (in this case you would have been able to just print the received data)*/
+                    memcpy( buff, &rx_buffer[0], 8 );
+                    buff[8] = '\0';
+                    int tap = (int)strtol(buff, NULL, 16);
+
+                    /* Extract Client data*/
+                    memcpy( buff, &rx_buffer[8], 4 );
+                    buff[4] = '\0';
+                    int client = (int)strtol(buff, NULL, 16);
+
+                    /* Exctract the RSSI */
+                    memcpy( buff, &rx_buffer[12], 4 );
+                    buff[4] = '\0';
+                    int16_t rssi = (int16_t)strtol(buff, NULL, 16);
+
+                    pc.printf("\n\rMessage received on tap: %X\n\r", tap);
+                    pc.printf("Client data: %X\n\r", client);
+                    pc.printf("RSSI level: %d\n\r", rssi);
+
+                    if(rssi > -90) leds = 0b0000;
+                    else if (rssi > -110) leds = 0b0001;
+                    else if (rssi > -130) leds = 0b0011;
+                    else leds = 0b0111;
+                } else {
+                    pc.printf("\n\rNo valid downlink data received!\n\r");
+                    error();
+                }
+            }
+        }
 
 
-/* TX data over Sigfox */
-void txData (uint8_t btn)
-{
-
-    float    tAvg;
-    char     command[32];
-    sensor.Sense();
-    tAvg = sensor.GetAverageTemp();
-    char temperature[6] ="";
-    sprintf(temperature, "%3.1f", tAvg);
-    for(int i = 0; i < 5; i++)
-        if(temperature[i]==0) temperature[i] = ' ';
-    sprintf(command, "AT$SF=0142544e%x20%x%x%x%x%x43,2,0\n", btn+48, temperature[0],temperature[1],temperature[2],temperature[3],temperature[4]);
-    pc.printf("Sending pressed button %d and temperature %s C over Sigfox.\n", btn, temperature);
-    pc.printf("using modem command: %s", command);
-    modem_command_check_ok(command);
-    LED_1 = 1;
-    LED_2 = 1;
+    } else {
+        // Failure, blink rapidly indefinetly:
+        error();
+    }
 }
 
 void modem_setup()
@@ -142,8 +245,13 @@
     /* Timeout for response of the modem */
     Timeout tmout;
     ser_timeout = false;
-    /* Buffer for incoming data */
-    char responsebuffer[6];
+    // check if ok or error is received
+    char * readyString = "OK";
+    char * readyStringPtr;
+    readyStringPtr = readyString;
+    char * errorString = "ERROR";
+    char * errorStringPtr;
+    errorStringPtr = errorString;
     /* Flag to set when we get 'OK' response */
     bool ok = false;
     bool error = false;
@@ -151,22 +259,24 @@
     modem.printf(command);
     /* Newline to activate command */
     modem.printf("\n");
-    /* Wait untill serial feedback, max 3 seconds before timeout */
-    tmout.attach(&sertmout, 3.0);
-    while(!modem.readable()&& ser_timeout == false);
-    while(!ok && !ser_timeout && !error) {
-        if(modem.readable()) {
-            for(int i = 0; i < 5; i++) {
-                responsebuffer[i] = responsebuffer[i+1];
+    /* Wait untill serial feedback, max 10 seconds before timeout */
+    tmout.attach(&sertmout, 10.0);
+    int c;
+    while(!ser_timeout && !ok && !error)
+        if(modem.readable())
+            while (((c = modem.getc()) > 0) && !ser_timeout  && !ok && !error) {
+                if ( (char)c == *readyStringPtr ) readyStringPtr++;
+                else readyStringPtr = readyString;
+                if ( *readyStringPtr == 0 ) {
+                    ok = true;
+                }
+                if ( (char)c == *errorStringPtr ) errorStringPtr++;
+                else errorStringPtr = errorString;
+                if ( *errorStringPtr == 0 ) {
+                    error = true;
+                }
             }
-            responsebuffer[5] = modem.getc();
-            if(responsebuffer[0] == '\r' && responsebuffer[1] == '\n' && responsebuffer[2] == 'O' && responsebuffer[3] == 'K' && responsebuffer[4] == '\r' && responsebuffer[5] == '\n' ) {
-                ok = true;
-            } else if(responsebuffer[0] == '\r' && responsebuffer[1] == '\n' && responsebuffer[2] == 'E' && responsebuffer[3] == 'R' && responsebuffer[4] == 'R' && responsebuffer[5] == 'O' ) {
-                error = true;
-            }
-        }
-    }
     tmout.detach();
-    return ok;
+    if(ser_timeout) return false;
+    else return ok;
 }
\ No newline at end of file