Demo using a Nimbelink Skywire cellular modem paired with ST Nucleo. This demo reads several sensors and reports them to a Freeboard dashboard using dweet.io from Buglabs

Dependencies:   LIS3DH LM75B LPS331 hts221 mbed

Fork of Skywire_Demo by NimbeLink

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* main.cpp */
00002 /* v3.0
00003  * Copyright (C) 2016 nimbelink.com, MIT License
00004  *
00005  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00006  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00007  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00008  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in all copies or
00012  * substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00015  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00016  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00017  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00019  */
00020 
00021 /*
00022  * DESCRIPTION
00023  * This code updated sensor data on the Nimbelink ST Development Kit (NL-AB-ST-NCL) and sends
00024  * the information to www.dweet.io using the Thingname "DeviceID". That information can be
00025  * viewed using a Freeboard at www.freeboard.io (account required). Depending on your
00026  * ST Development Kit version, clone the following freeboard:
00027  * Rev A (Legacy): https://freeboard.io/board/jqlneI
00028  * Rev B (Current): https://freeboard.io/board/LhnbrX
00029  *
00030  * Please consult the wiki for more information
00031  */
00032 
00033 /*
00034  * INSTRUCTIONS FOR USING THIS CODE
00035  * 1. Under the "DEFINE THE SKYWIRE MODEM" section of the code, uncomment the modem that you
00036  * are using to enable to proper setup and features of your Skywire modem.
00037  *
00038  * NOTE: Make sure the other Skywire modems listed are commented out.
00039  *
00040  * 2. Change the "DeviceID" to a unique identifier for your Nucleo board. One recommendation
00041  * would be to use the MEID/IMEI of your Skywire Modem.
00042  *
00043  * 3. If applicable, change the APN for your Skywire Modem.
00044  */
00045 
00046 #include "mbed.h"
00047 #include "LPS331.h"
00048 #include "LIS3DH.h"
00049 #include "LM75B.h"
00050 #include "hts221.h"
00051 #include <string>
00052 
00053 /*
00054  * DEFINE THE SKYWIRE MODEM
00055  * Uncomment only the modem that you are using.
00056  * Make sure only one modem is uncommented!
00057  */
00058 //#define NL_SW_1xRTT_V         // Verizon 2G Modem - CE910-DUAL
00059 //#define NL_SW_1xRTT_S         // Sprint 2G Modem - CE910-DUAL
00060 //#define NL_SW_1xRTT_A         // Aeris 2G Modem - CE910-DUAL
00061 //#define NL_SW_GPRS            // AT&T/T-Mobile 2G Modem
00062 //#define NL_SW_EVDO_V          // Verizon 3G Modem
00063 //#define NL_SW_EVDO_A          // Aeris 3G Modem
00064 //#define NL_SW_HSPAP           // AT&T/T-Mobile 3G Modem
00065 //#define NL_SW_HSPAPG          // AT&T/T-Mobile 3G Modem w/ GPS
00066 //#define NL_SW_HSPAPE          // GSM 3G Modem, EU
00067 //#define NL_SW_LTE_TSVG        // Verizon 4G LTE Modem
00068 //#define NL_SW_LTE_TNAG        // AT&T/T-Mobile 4G LTE Modem
00069 //#define NL_SW_LTE_TEUG        // GSM 4G LTE Modem, EU
00070 //#define NL_SW_LTE_GELS3       // VZW LTE Cat 1 Modem
00071 
00072 /* --CHANGE THIS FOR YOUR SETUP-- */
00073 #define DeviceID "yourDeviceIDhere"  //Freeboard DweetIO unique ID
00074 
00075 /* --CHANGE THIS FOR YORU SETUP (IF APPLICABLE)-- */
00076 #if defined NL_SW_HSPAP || defined NL_SW_HSPAPG || defined NL_SW_HSPAPE || defined NL_SW_LTE_TSVG || defined NL_SW_LTE_TNAG || defined NL_SW_LTE_TEUG || defined NL_SW_LTE_GELS3
00077     std::string APN = "yourAPNhere";
00078 #endif
00079 
00080 DigitalOut myled(LED1);                             // Main LED
00081 DigitalOut skywire_en(PA_6);                        // Skywire Enable
00082 DigitalOut skywire_rts(PA_7);                       // Skywire Send
00083 DigitalOut green_LED(PA_1);                         // Green LED
00084 DigitalOut red_LED(PA_4);                           // Red LED
00085 DigitalOut blue_LED(PB_0);                          // Blue LED
00086 
00087 AnalogIn photo_trans(PA_0);                         // Photo Transistor
00088 AnalogIn pot(PC_0);                                 // Potentiometer
00089 DigitalIn button1(PB_3);                            // Button 1
00090 DigitalIn button2(PC_1);                            // Button 2
00091 
00092 Serial skywire(PA_9,PA_10);                         // Serial comms to Skywire
00093 Serial debug_pc(USBTX, USBRX);                      // USB connection to PC
00094 
00095 I2C i2c(PB_9,PB_8);                                 // Setup I2C bus for sensors
00096 bool sw1;                                           // Boolean to check if button 1 is pressed
00097 bool sw2;                                           // Boolean to check if button 2 is pressed
00098 
00099 LPS331 pressure(i2c);                               // Pressure Sensor
00100 LM75B LM75_temp(PB_9,PB_8);                         // Temp Sensor
00101 // Accelerometer
00102 LIS3DH accel(i2c, LIS3DH_V_CHIP_ADDR, LIS3DH_DR_NR_LP_100HZ, LIS3DH_FS_2G);
00103 HTS221 humidity(PB_9, PB_8);                        // Humidity Sensor
00104 
00105 // char array for reading from Skywire
00106 char str[255];
00107 
00108 // Variables for GPS
00109 float latitude;
00110 float longitude;
00111 int number;
00112 
00113 // Variables for UART comms
00114 volatile int rx_in=0;
00115 volatile int rx_out=0;
00116 const int buffer_size = 600;
00117 char rx_buffer[buffer_size+1];
00118 char rx_line[buffer_size];
00119 
00120 // Interrupt for the Skywire
00121 void Skywire_Rx_interrupt()
00122 {
00123 // Loop just in case more than one character is in UART's receive FIFO buffer
00124 // Stop if buffer full
00125     while ((skywire.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
00126         rx_buffer[rx_in] = skywire.getc();
00127         rx_in = (rx_in + 1) % buffer_size;
00128     }
00129     return;
00130 }
00131 
00132 // Function to blink LEDs for debugging
00133 // NOTE: Currently not used
00134 void blink_leds(int num) 
00135 {
00136     for (int i = 0; i < num; i++) {
00137         blue_LED = 0;
00138         wait(0.5);
00139         blue_LED = 1;
00140         wait(0.5);
00141     }
00142 }
00143 
00144 // Read line from the UART
00145 void read_line() 
00146 {
00147     int i;
00148     i = 0;
00149 // Start Critical Section - don't interrupt while changing global buffer variables
00150     __disable_irq();
00151 // Loop reading rx buffer characters until end of line character
00152     while ((i==0) || (rx_line[i-1] != '\n')) {
00153 // Wait if buffer empty
00154         if (rx_in == rx_out) {
00155 // End Critical Section - need to allow rx interrupt to get new characters for buffer
00156             __enable_irq();
00157             while (rx_in == rx_out) {
00158             }
00159 // Start Critical Section - don't interrupt while changing global buffer variables
00160             __disable_irq();
00161         }
00162         rx_line[i] = rx_buffer[rx_out];
00163         i++;
00164         rx_out = (rx_out + 1) % buffer_size;
00165     }
00166 // End Critical Section
00167     __enable_irq();
00168     rx_line[i-1] = 0;
00169     return;
00170 }
00171 
00172 // Wait for specific response
00173 int WaitForResponse(char* response, int num) 
00174 {
00175     do {
00176         read_line();
00177         debug_pc.printf("Waiting for: %s, Recieved: %s\r\n", response, rx_line);
00178     } while (strncmp(rx_line, response, num));
00179     return 0;
00180 }
00181 
00182 int main() 
00183 {
00184     float axis[3];
00185     float press;
00186     float temp;
00187     float humi;
00188     float dummy_temp;
00189 
00190     // Setup serial comms with Skywire and PC
00191     debug_pc.baud(115200);
00192     skywire.baud(115200);
00193     debug_pc.printf("SystemCoreClock = %d Hz\r\n", SystemCoreClock);
00194     skywire.attach(&Skywire_Rx_interrupt, Serial::RxIrq);
00195 
00196     // Turn on blue LED
00197     green_LED = 0;
00198     red_LED = 0;
00199     blue_LED = 1;
00200 
00201     skywire_rts=0;
00202     myled=0;
00203     debug_pc.printf("Starting Demo...\r\n");
00204     debug_pc.printf("Waiting for Skywire to Boot...\r\n");
00205 
00206     //Enable Skywire
00207     skywire_en=0;
00208     wait(2);
00209     skywire_en=1;
00210     wait(2);
00211     skywire_en=0;
00212 
00213     myled=1;
00214 
00215     // Wait for modem to initialize
00216     // Wait time is different for each modem
00217     #if defined NL_SW_LTE_GELS3
00218         wait(60);
00219     #elif defined NL_SW_LTE_TSVG || defined NL_SW_LTE_TNAG || defined NL_SW_LTE_TEUG
00220         wait(15);
00221     #else
00222         wait(5);
00223     #endif
00224 
00225     // Start temp reading
00226     LM75_temp.open();
00227 
00228     //Turn off echo
00229     // Helps with checking responses from Skywire
00230     debug_pc.printf("Turning off echo...\r\n");
00231     skywire.printf("ATE0\r\n");
00232     WaitForResponse("OK", 2);
00233 
00234     // Turn on DNS Response Caching
00235     // Used on the Telit-based Skywires
00236     #if !defined NL_SW_LTE_GELS3
00237         debug_pc.printf("Turning on DNS Cacheing to improve speed...");
00238         skywire.printf("AT#CACHEDNS=1\r\n");
00239         WaitForResponse("OK", 2);
00240     #endif
00241 
00242     debug_pc.printf("Connecting to Network...\r\n");
00243     // get IP address
00244     #if defined NL_SW_LTE_GELS3
00245         // The last parameter in AT+SQNSCFG sets the timeout if transmit buffer is not full
00246         // Time is in hundreds of ms: so, a value of 5 = 500ms
00247         debug_pc.printf("Configuring context part 1...\r\n");
00248         skywire.printf("AT+SQNSCFG=3,3,300,90,600,5\r\n");
00249         WaitForResponse("OK", 2);
00250         wait(1);
00251         debug_pc.printf("Configuring context part 2...\r\n");
00252         skywire.printf("AT+CGDCONT=3,\"IP\",\"vzwinternet\"\r\n");
00253         WaitForResponse("OK", 2);
00254         wait(1);
00255         debug_pc.printf("Activating context...\r\n");
00256         skywire.printf("AT+CGACT=1,3\r\n");
00257     #elif defined NL_SW_LTE_TSVG
00258         // The last parameter in AT#SCFG sets the timeout if transmit buffer is not full
00259         // Time is in hundreds of ms: so, a value of 5 = 500 ms
00260         skywire.printf("AT#SCFG=3,3,300,90,600,5\r\n");
00261         WaitForResponse("OK", 2);
00262         wait(1);
00263         skywire.printf("AT+CGDCONT=3,\"IP\",\"%s\"\r\n", APN);
00264         WaitForResponse("OK", 2);
00265         wait(1);
00266         skywire.printf("AT#SGACT=3,1\r\n");
00267         WaitForResponse("#SGACT", 6);
00268     #else
00269         // The last parameter in AT#SCFG sets the timeout if transmit buffer is not full
00270         // Time is in hundreds of ms: so, a value of 5 = 500 ms
00271         skywire.printf("AT#SCFG=1,1,300,90,600,5\r\n");
00272         WaitForResponse("OK", 2);
00273         skywire.printf("AT#SGACT=1,1\r\n");
00274         WaitForResponse("#SGACT", 6);
00275     #endif
00276     WaitForResponse("OK", 2);
00277 
00278     // Get triangulation data
00279     // NOTE: This only works on the below modems!
00280     #if defined NL_SW_1xRTT_V || defined NL_SW_1xRTT_S || defined NL_SW_1xRTT_A || defined NL_SW_GPRS || defined NL_SW_EVDO_V || defined NL_SW_EVDO_A || defined NL_SW_HSPAP || defined NL_SW_HSPAPG || defined NL_SW_HSPAPE
00281         //get location approximation from cell tower information
00282         skywire.printf("AT#AGPSSND\r\n");
00283         WaitForResponse("#AGPSRING:", 10);
00284         sscanf(rx_line, "%s %d,%f,%f,", str, &number, &latitude, &longitude);
00285         debug_pc.printf("Location: Latt:%f, Long:%f\r\n", latitude, longitude);
00286     #endif
00287 
00288     red_LED = 0;
00289     blue_LED = 0;
00290     green_LED = 1;
00291 
00292     while(1) {
00293         // Green on to indicate code position
00294         // Start of loop. Either entered loop for the first time or just sent to dweet.io
00295         red_LED = 0;
00296         blue_LED = 0;
00297         green_LED = 1;
00298         // connect to dweet.io
00299         #if defined NL_SW_LTE_GELS3
00300             skywire.printf("AT+SQNSD=3,0,80,\"dweet.io\"\r\n");
00301         #elif defined NL_SW_LTE_TSVG
00302             skywire.printf("AT#SD=3,0,80,\"dweet.io\"\r\n");
00303         #else
00304             skywire.printf("AT#SD=1,0,80,\"dweet.io\"\r\n");
00305         #endif
00306         WaitForResponse("CONNECT", 7);
00307 
00308 
00309         // Update the sensors
00310         temp = (float)LM75_temp;
00311         //temp = (temp * 9)/5 + 32;                     // convert C to F
00312         debug_pc.printf("Temp = %.3f\r\n", temp);
00313         press=(float)pressure.value() / 4096;
00314         debug_pc.printf("Pressure = %.3f\r\n", press);
00315         humidity.ReadTempHumi(&dummy_temp, &humi);
00316         debug_pc.printf("Humidity = %.3f\r\n", humi);
00317         accel.read_data(axis);
00318         debug_pc.printf("Accel = %.3f, %.3f, %.3f\r\n", axis[0], axis[1], axis[2]);
00319 
00320         wait(1);
00321 
00322         // Check buttons for presses
00323         if (button1 == 0)
00324             sw1 = 0;
00325         else
00326             sw1 = 1;
00327         if (button2 == 0)
00328             sw2 = 0;
00329         else
00330             sw2 = 1;
00331         
00332         // Green on to indicate code position:
00333         // Sensors updated, have not sent to dweet.io
00334         red_LED = 1;
00335         green_LED = 0;
00336         blue_LED = 0;
00337 
00338         debug_pc.printf("Sending information...\r\n");
00339         // Report the sensor data to dweet.io
00340         skywire.printf("POST /dweet/for/%s?temp=%.3f&p=%.3f&X=%.3f&Y=%.3f&Z=%.3f&La=%f&Lo=%f&sw1=%d&sw2=%d&pot=%.3f&photo=%.3f&humidity=%.3f HTTP/1.0\r\n\r\n", DeviceID, temp, press, axis[0], axis[1], axis[2], latitude, longitude, sw1, sw2, (pot * 3), (photo_trans * 100), humi);
00341 
00342         // Blue on to indicate code position
00343         // Data sent to dweet
00344         red_LED = 0;
00345         green_LED = 0;
00346         blue_LED = 1;
00347 
00348         // Wait for response from dweet.io
00349         #if defined NL_SW_LTE_GELS3
00350             WaitForResponse("OK", 2);
00351             wait(1);
00352         #else
00353             WaitForResponse("NO CARRIER", 10);
00354         #endif
00355     }
00356 }