Code example to regularly report light level and temperature over Sigfox on the QW dev kit

Dependencies:   QW_Sensors mbed

Fork of QW_Temperature_Light_Monitor by Lieven Hollevoet

This is a code example that demonstrates sending the light level sensor and temperature sensor output over Sigfox at regular time intervals.

The payload that is sent over the network consists of 3 bytes:

  • two bytes light level reading
  • one byte temperature reading.

Use this code example as a start to connect your own device over Sigfox with the QW development kit.

main.cpp

Committer:
quicksand
Date:
2016-05-02
Revision:
2:33e92af45279
Parent:
0:9a93fff79b27

File content as of revision 2:33e92af45279:

/* This program is an example application that measures the temperature and the light level
 * and transmits the sensor readings over the Sigfox network.
 * A transmission is scheduled every 15 minutes, and the user can force a transmission 
 * by pressing the user button one.
 * 
 * The data format of the Sigfox payload is:
 * First two bytes of the payload: light level as unsigned 16-bit value.
 * Third byte of the payload: temperature as signed 8-bit value
 * 
 * Open a serial console to the board to get a debug trace.
 *
 * Note: this is a very basic example that has no energy usage optimization. The controller is not put in sleep mode
 * in between readings/Sigfox transmissions in order to keep the code flow linear and short.
 *
 * In the current configuration, the temperature sensor is read once per second and a Sigfox transmission is scheduled every 15 minutes. 
 * Adapt the defines TX_INTERVAL and MEASURE_INTERVAL to change these settings.
 */

#include "mbed.h"
#include "math.h"
#include "LinearTempSensor.h"
#include "VCNL4010.h"

#define SER_BUFFER_SIZE 32

// Interval in minutes for scheduled Tx
#define TX_INTERVAL 15

// Temperature measure interval in seconds
#define MEASURE_INTERVAL 1

/* The 4 onboard LEDs */
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);

/* Proximity and ambient light sensor*/
VCNL40x0 VCNL4010(PB_9, PB_8, VCNL40x0_ADDRESS);      // SDA, SCL pin and I2C address

/*Temperature sensor */
LinearTempSensor sensor(PA_0, 40);

/* Ticker for scheduled transmissions */
Ticker tTX;
Ticker tSense;
Ticker heartbeat;

/* Function prototypes */
void sw1interrupt();
void sw2interrupt();
void sertmout();
bool read_acc(int& x, int& y, int& z);
bool modem_command_check_ok(char * command);
void modem_setup();
void txData();
void dataScheduledTX();
void senseTemperature();

bool ser_timeout = false;
bool handleIRQ1 = false;

/* Serial port over USB */
Serial pc(USBTX, USBRX);

/* Serial connection to sigfox modem */
Serial modem(PA_9, PA_10);

void beat()
{
    LED_3 = !LED_3;
}

int main()
{
    /* Blinking LED */
    heartbeat.attach(&beat, 0.5);
    /* Storage for VCNL4010 readout */
    unsigned char ID=0, Current=0;
    //unsigned int  ProxiValue=0, AmbiValue=0;

    /* Variables that will store analog temperature sensor reading */
    //float Tav, To;
    
    /* Setup TD120x */
    wait(3);
    modem_setup();

    /* Turn off all LED */
    LED_0 = 1;
    LED_1 = 1;
    LED_2 = 1;
    LED_3 = 1;

    /* Setup button interrupts */
    SW2.fall(&sw2interrupt);
    SW1.fall(&sw1interrupt);

    /* Read VCNL40x0 product ID revision register */
    VCNL4010.ReadID (&ID);
    pc.printf("\nVCNL4010 Product ID Revision Register: %d", ID);

    VCNL4010.SetCurrent (20);                        // Set current to 200mA
    VCNL4010.ReadCurrent (&Current);                 // Read back IR LED current
    pc.printf("\nVCNL4010 IR LED Current: %d\n\n", Current);

    // Sense temperature for the first time
    senseTemperature();
    
    wait_ms(3000);                                   // wait 3s (only for display)

    tTX.attach(&dataScheduledTX, TX_INTERVAL*60);               // Attach the timer for TX
    tSense.attach(&senseTemperature, MEASURE_INTERVAL);           // Attach the timer for sensing the temperature
    
    while(1) 
    {
        /*
        // VCNL4010 reading 
        VCNL4010.ReadProxiOnDemand (&ProxiValue);    // read prox value on demand
        VCNL4010.ReadAmbiOnDemand (&AmbiValue);      // read ambi value on demand
        // MCP9700 reading 
        Tav  = sensor.GetAverageTemp();
        To   = sensor.GetLatestTemp();

        pc.printf("\n\rVCNL4010 report: Proximity: %5.0i cts, Ambient light: %5.0i cts, Illuminance: %7.2f lx\n\rMCP9700 report:  Average Temp: %.2f %cC, Latest Temp: %.2f %cC", ProxiValue, AmbiValue, AmbiValue/4.0, Tav, 176, To, 176);
        wait_ms(5000);
        */
        
        if (handleIRQ1) {
            txData();
            handleIRQ1 = false;
        }
    }
}

void modem_setup()
{
    /* Reset to factory defaults */
    if(modem_command_check_ok("AT&F")) 
    {
        pc.printf("Factory reset succesfull\r\n");
    }
    else 
    {
        pc.printf("Factory reset TD120x failed\r\n");
    }
    /* Disable local echo */
    modem.printf("ATE0\n");
    if(modem_command_check_ok("ATE0")) 
    {
        pc.printf("Local echo disabled\r\n");
    }
    /* Write to mem */
    if(modem_command_check_ok("AT&W")) 
    {
        pc.printf("Settings saved!\r\n");
    }
}

bool modem_command_check_ok(char * command)
{
    /* first clear serial data buffers */
    while(modem.readable()) modem.getc();
    /* Timeout for response of the modem */
    Timeout tmout;
    ser_timeout = false;
    /* Buffer for incoming data */
    char responsebuffer[6];
    /* Flag to set when we get 'OK' response */
    bool ok = false;
    bool error = false;
    /* Print command to TD120x */
    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];
            }
            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;
}

/* Button 1 ISR */
void sw1interrupt()
{
    pc.printf("\n\rButton 1 pressed\n\r");
    LED_1 = 0;
    handleIRQ1 = true;
}

/* Button 2 ISR */
void sw2interrupt()
{
    pc.printf("\n\rButton 2 pressed\n\r");
    LED_1 = 0;
    handleIRQ1 = true;
}

void dataScheduledTX()
{
    pc.printf("\n\rScheduled Sigfox TX triggered\n\r");
    LED_1 = 0;
    handleIRQ1 = true;
}

/* ISR for serial timeout */
void sertmout()
{
    ser_timeout = true;
}

/* TX data over Sigfox */
void txData (){

    unsigned int ambiValue = 0;
    int8_t   tAvgByte = 0;
    uint16_t ambiValueShort;
    float    tAvg;
    char     command[32];
    
    VCNL4010.ReadAmbiOnDemand (&ambiValue);      // read ambi value on demand
    sensor.Sense();
    tAvg = sensor.GetAverageTemp();
    tAvgByte = (int8_t)tAvg;
    ambiValueShort = (uint16_t)ambiValue;

    sprintf(command, "AT$SF=02%04X%02X,2,0\n", ambiValueShort, tAvgByte);
    
    pc.printf("Sending ambient light level %i cts and temperature %i degrees C over Sigfox\n", ambiValueShort, tAvgByte);
    pc.printf("using modem command: %s", command);
    modem_command_check_ok(command);
    LED_1 = 1;
}

void senseTemperature() {
    float vOut = sensor.Sense();
    //pc.printf("\n\rMCP9700 reading:  Vout: %.2f mV", vOut);
}