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

Getting Started Guide

  • Set the JP5 jumper to E5V on the Nucleo
  • Place the Skywire Shield onto the Nucleo as pictured
  • Place the Skywire modem onto the Shield as picture and attach the antenna U.FL coax cable as pictured
  • Plug the 12V wall supply into the Skywire Shield /media/uploads/kholland/st00000002-sm.jpg
  • The new dashboard will show up on you account list under My Freeboards, you can then edit the name to whatever you like /media/uploads/kholland/default_skywire2.jpg
  • Under the Datasources tab on the dashboard, click the skywire link /media/uploads/kholland/default_skywire5.jpg
  • Change the THING NAME field to a unique string, we recommended using the MEID or IMEI on the Skywire Modem, but it could be anything you want. /media/uploads/kholland/default_skywire4.jpg
  • Next, Import the Skywire_Demo program into the online compiler
  • Open main.cpp. Starting at Line 58, there is a list of Skywire Modems. Uncomment the Skywire Modem that you are using. Make sure only one Skywire Modem is uncommented:

main.cpp

/*
 * DEFINE THE SKYWIRE MODEM
 * Uncomment only the modem that you are using.
 * Make sure only one modem is uncommented!
 */
//#define NL_SW_1xRTT_V         // Verizon 2G Modem - CE910-DUAL
//#define NL_SW_1xRTT_S         // Sprint 2G Modem - CE910-DUAL
//#define NL_SW_1xRTT_A         // Aeris 2G Modem - CE910-DUAL
//#define NL_SW_GPRS            // AT&T/T-Mobile 2G Modem
//#define NL_SW_EVDO_V          // Verizon 3G Modem
//#define NL_SW_EVDO_A          // Aeris 3G Modem
//#define NL_SW_HSPAP           // AT&T/T-Mobile 3G Modem
//#define NL_SW_HSPAPG          // AT&T/T-Mobile 3G Modem w/ GPS
//#define NL_SW_HSPAPE          // GSM 3G Modem, EU
//#define NL_SW_LTE_TSVG        // Verizon 4G LTE Modem
//#define NL_SW_LTE_TNAG        // AT&T/T-Mobile 4G LTE Modem
//#define NL_SW_LTE_TEUG        // GSM 4G LTE Modem, EU
//#define NL_SW_LTE_GELS3       // VZW LTE Cat 1 Modem
  • Next, to Line 73 in main.cpp, and change the DeviceID to the THING NAME you entered into your Freeboard:

main.cpp

/* --CHANGE THIS FOR YOUR SETUP" -- */
#define DeviceID "DweetIODeviceName"  //Freeboard DweetIO unique ID
  • If applicable, go to Line 77 in main.cpp and change the APN to your specific APN:

main.cpp

/* --CHANGE THIS FOR YORU SETUP (IF APPLICABLE)-- */
#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
    std::string APN = "yourAPNhere";
#endif
  • Compile and upload to the Nucleo, cycle power to the shield and the sensor data should start to upload to your new Freeboard.

main.cpp

Committer:
kholland
Date:
2016-03-29
Revision:
10:5974a7b2cf38
Parent:
9:555eb4259fc6

File content as of revision 10:5974a7b2cf38:

/* main.cpp */
/* v3.0
 * Copyright (C) 2016 nimbelink.com, MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * DESCRIPTION
 * This code updated sensor data on the Nimbelink ST Development Kit (NL-AB-ST-NCL) and sends
 * the information to www.dweet.io using the Thingname "DeviceID". That information can be
 * viewed using a Freeboard at www.freeboard.io (account required). Depending on your
 * ST Development Kit version, clone the following freeboard:
 * Rev A (Legacy): https://freeboard.io/board/jqlneI
 * Rev B (Current): https://freeboard.io/board/LhnbrX
 *
 * Please consult the wiki for more information
 */

/*
 * INSTRUCTIONS FOR USING THIS CODE
 * 1. Under the "DEFINE THE SKYWIRE MODEM" section of the code, uncomment the modem that you
 * are using to enable to proper setup and features of your Skywire modem.
 *
 * NOTE: Make sure the other Skywire modems listed are commented out.
 *
 * 2. Change the "DeviceID" to a unique identifier for your Nucleo board. One recommendation
 * would be to use the MEID/IMEI of your Skywire Modem.
 *
 * 3. If applicable, change the APN for your Skywire Modem.
 */

#include "mbed.h"
#include "LPS331.h"
#include "LIS3DH.h"
#include "LM75B.h"
#include "hts221.h"
#include <string>

/*
 * DEFINE THE SKYWIRE MODEM
 * Uncomment only the modem that you are using.
 * Make sure only one modem is uncommented!
 */
//#define NL_SW_1xRTT_V         // Verizon 2G Modem - CE910-DUAL
//#define NL_SW_1xRTT_S         // Sprint 2G Modem - CE910-DUAL
//#define NL_SW_1xRTT_A         // Aeris 2G Modem - CE910-DUAL
//#define NL_SW_GPRS            // AT&T/T-Mobile 2G Modem
//#define NL_SW_EVDO_V          // Verizon 3G Modem
//#define NL_SW_EVDO_A          // Aeris 3G Modem
//#define NL_SW_HSPAP           // AT&T/T-Mobile 3G Modem
//#define NL_SW_HSPAPG          // AT&T/T-Mobile 3G Modem w/ GPS
//#define NL_SW_HSPAPE          // GSM 3G Modem, EU
//#define NL_SW_LTE_TSVG        // Verizon 4G LTE Modem
//#define NL_SW_LTE_TNAG        // AT&T/T-Mobile 4G LTE Modem
//#define NL_SW_LTE_TEUG        // GSM 4G LTE Modem, EU
//#define NL_SW_LTE_GELS3       // VZW LTE Cat 1 Modem

/* --CHANGE THIS FOR YOUR SETUP-- */
#define DeviceID "yourDeviceIDhere"  //Freeboard DweetIO unique ID

/* --CHANGE THIS FOR YORU SETUP (IF APPLICABLE)-- */
#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
    std::string APN = "yourAPNhere";
#endif

DigitalOut myled(LED1);                             // Main LED
DigitalOut skywire_en(PA_6);                        // Skywire Enable
DigitalOut skywire_rts(PA_7);                       // Skywire Send
DigitalOut green_LED(PA_1);                         // Green LED
DigitalOut red_LED(PA_4);                           // Red LED
DigitalOut blue_LED(PB_0);                          // Blue LED

AnalogIn photo_trans(PA_0);                         // Photo Transistor
AnalogIn pot(PC_0);                                 // Potentiometer
DigitalIn button1(PB_3);                            // Button 1
DigitalIn button2(PC_1);                            // Button 2

Serial skywire(PA_9,PA_10);                         // Serial comms to Skywire
Serial debug_pc(USBTX, USBRX);                      // USB connection to PC

I2C i2c(PB_9,PB_8);                                 // Setup I2C bus for sensors
bool sw1;                                           // Boolean to check if button 1 is pressed
bool sw2;                                           // Boolean to check if button 2 is pressed

LPS331 pressure(i2c);                               // Pressure Sensor
LM75B LM75_temp(PB_9,PB_8);                         // Temp Sensor
// Accelerometer
LIS3DH accel(i2c, LIS3DH_V_CHIP_ADDR, LIS3DH_DR_NR_LP_100HZ, LIS3DH_FS_2G);
HTS221 humidity(PB_9, PB_8);                        // Humidity Sensor

// char array for reading from Skywire
char str[255];

// Variables for GPS
float latitude;
float longitude;
int number;

// Variables for UART comms
volatile int rx_in=0;
volatile int rx_out=0;
const int buffer_size = 600;
char rx_buffer[buffer_size+1];
char rx_line[buffer_size];

// Interrupt for the Skywire
void Skywire_Rx_interrupt()
{
// Loop just in case more than one character is in UART's receive FIFO buffer
// Stop if buffer full
    while ((skywire.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
        rx_buffer[rx_in] = skywire.getc();
        rx_in = (rx_in + 1) % buffer_size;
    }
    return;
}

// Function to blink LEDs for debugging
// NOTE: Currently not used
void blink_leds(int num) 
{
    for (int i = 0; i < num; i++) {
        blue_LED = 0;
        wait(0.5);
        blue_LED = 1;
        wait(0.5);
    }
}

// Read line from the UART
void read_line() 
{
    int i;
    i = 0;
// Start Critical Section - don't interrupt while changing global buffer variables
    __disable_irq();
// Loop reading rx buffer characters until end of line character
    while ((i==0) || (rx_line[i-1] != '\n')) {
// Wait if buffer empty
        if (rx_in == rx_out) {
// End Critical Section - need to allow rx interrupt to get new characters for buffer
            __enable_irq();
            while (rx_in == rx_out) {
            }
// Start Critical Section - don't interrupt while changing global buffer variables
            __disable_irq();
        }
        rx_line[i] = rx_buffer[rx_out];
        i++;
        rx_out = (rx_out + 1) % buffer_size;
    }
// End Critical Section
    __enable_irq();
    rx_line[i-1] = 0;
    return;
}

// Wait for specific response
int WaitForResponse(char* response, int num) 
{
    do {
        read_line();
        debug_pc.printf("Waiting for: %s, Recieved: %s\r\n", response, rx_line);
    } while (strncmp(rx_line, response, num));
    return 0;
}

int main() 
{
    float axis[3];
    float press;
    float temp;
    float humi;
    float dummy_temp;

    // Setup serial comms with Skywire and PC
    debug_pc.baud(115200);
    skywire.baud(115200);
    debug_pc.printf("SystemCoreClock = %d Hz\r\n", SystemCoreClock);
    skywire.attach(&Skywire_Rx_interrupt, Serial::RxIrq);

    // Turn on blue LED
    green_LED = 0;
    red_LED = 0;
    blue_LED = 1;

    skywire_rts=0;
    myled=0;
    debug_pc.printf("Starting Demo...\r\n");
    debug_pc.printf("Waiting for Skywire to Boot...\r\n");

    //Enable Skywire
    skywire_en=0;
    wait(2);
    skywire_en=1;
    wait(2);
    skywire_en=0;

    myled=1;

    // Wait for modem to initialize
    // Wait time is different for each modem
    #if defined NL_SW_LTE_GELS3
        wait(60);
    #elif defined NL_SW_LTE_TSVG || defined NL_SW_LTE_TNAG || defined NL_SW_LTE_TEUG
        wait(15);
    #else
        wait(5);
    #endif

    // Start temp reading
    LM75_temp.open();

    //Turn off echo
    // Helps with checking responses from Skywire
    debug_pc.printf("Turning off echo...\r\n");
    skywire.printf("ATE0\r\n");
    WaitForResponse("OK", 2);

    // Turn on DNS Response Caching
    // Used on the Telit-based Skywires
    #if !defined NL_SW_LTE_GELS3
        debug_pc.printf("Turning on DNS Cacheing to improve speed...");
        skywire.printf("AT#CACHEDNS=1\r\n");
        WaitForResponse("OK", 2);
    #endif

    debug_pc.printf("Connecting to Network...\r\n");
    // get IP address
    #if defined NL_SW_LTE_GELS3
        // The last parameter in AT+SQNSCFG sets the timeout if transmit buffer is not full
        // Time is in hundreds of ms: so, a value of 5 = 500ms
        debug_pc.printf("Configuring context part 1...\r\n");
        skywire.printf("AT+SQNSCFG=3,3,300,90,600,5\r\n");
        WaitForResponse("OK", 2);
        wait(1);
        debug_pc.printf("Configuring context part 2...\r\n");
        skywire.printf("AT+CGDCONT=3,\"IP\",\"vzwinternet\"\r\n");
        WaitForResponse("OK", 2);
        wait(1);
        debug_pc.printf("Activating context...\r\n");
        skywire.printf("AT+CGACT=1,3\r\n");
    #elif defined NL_SW_LTE_TSVG
        // The last parameter in AT#SCFG sets the timeout if transmit buffer is not full
        // Time is in hundreds of ms: so, a value of 5 = 500 ms
        skywire.printf("AT#SCFG=3,3,300,90,600,5\r\n");
        WaitForResponse("OK", 2);
        wait(1);
        skywire.printf("AT+CGDCONT=3,\"IP\",\"%s\"\r\n", APN);
        WaitForResponse("OK", 2);
        wait(1);
        skywire.printf("AT#SGACT=3,1\r\n");
        WaitForResponse("#SGACT", 6);
    #else
        // The last parameter in AT#SCFG sets the timeout if transmit buffer is not full
        // Time is in hundreds of ms: so, a value of 5 = 500 ms
        skywire.printf("AT#SCFG=1,1,300,90,600,5\r\n");
        WaitForResponse("OK", 2);
        skywire.printf("AT#SGACT=1,1\r\n");
        WaitForResponse("#SGACT", 6);
    #endif
    WaitForResponse("OK", 2);

    // Get triangulation data
    // NOTE: This only works on the below modems!
    #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
        //get location approximation from cell tower information
        skywire.printf("AT#AGPSSND\r\n");
        WaitForResponse("#AGPSRING:", 10);
        sscanf(rx_line, "%s %d,%f,%f,", str, &number, &latitude, &longitude);
        debug_pc.printf("Location: Latt:%f, Long:%f\r\n", latitude, longitude);
    #endif

    red_LED = 0;
    blue_LED = 0;
    green_LED = 1;

    while(1) {
        // Green on to indicate code position
        // Start of loop. Either entered loop for the first time or just sent to dweet.io
        red_LED = 0;
        blue_LED = 0;
        green_LED = 1;
        // connect to dweet.io
        #if defined NL_SW_LTE_GELS3
            skywire.printf("AT+SQNSD=3,0,80,\"dweet.io\"\r\n");
        #elif defined NL_SW_LTE_TSVG
            skywire.printf("AT#SD=3,0,80,\"dweet.io\"\r\n");
        #else
            skywire.printf("AT#SD=1,0,80,\"dweet.io\"\r\n");
        #endif
        WaitForResponse("CONNECT", 7);


        // Update the sensors
        temp = (float)LM75_temp;
        //temp = (temp * 9)/5 + 32;                     // convert C to F
        debug_pc.printf("Temp = %.3f\r\n", temp);
        press=(float)pressure.value() / 4096;
        debug_pc.printf("Pressure = %.3f\r\n", press);
        humidity.ReadTempHumi(&dummy_temp, &humi);
        debug_pc.printf("Humidity = %.3f\r\n", humi);
        accel.read_data(axis);
        debug_pc.printf("Accel = %.3f, %.3f, %.3f\r\n", axis[0], axis[1], axis[2]);

        wait(1);

        // Check buttons for presses
        if (button1 == 0)
            sw1 = 0;
        else
            sw1 = 1;
        if (button2 == 0)
            sw2 = 0;
        else
            sw2 = 1;
        
        // Green on to indicate code position:
        // Sensors updated, have not sent to dweet.io
        red_LED = 1;
        green_LED = 0;
        blue_LED = 0;

        debug_pc.printf("Sending information...\r\n");
        // Report the sensor data to dweet.io
        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);

        // Blue on to indicate code position
        // Data sent to dweet
        red_LED = 0;
        green_LED = 0;
        blue_LED = 1;

        // Wait for response from dweet.io
        #if defined NL_SW_LTE_GELS3
            WaitForResponse("OK", 2);
            wait(1);
        #else
            WaitForResponse("NO CARRIER", 10);
        #endif
    }
}