This software example demonstrates the downlink capabilities of the SIGFOX network.
Dependencies: QW_Sensors mbed
Fork of HelloWorld - QW Development kit by
Revision 4:1d707586e24d, committed 2017-03-14
- 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 |
--- 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
