Code example to regularly report light level and temperature over Sigfox on the QW dev kit
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 bye temperature reading.
Use this code example as a start to connect your own device over Sigfox with the Quicksand QW development kit.
Diff: main.cpp
- Revision:
- 0:9a93fff79b27
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Mar 08 09:46:45 2016 +0000 @@ -0,0 +1,250 @@ +/* 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; + +/* 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); + +int main() +{ + /* 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"); +} + +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 + tAvg = sensor.GetAverageTemp(); + tAvgByte = (int8_t)tAvg; + ambiValueShort = (uint16_t)ambiValue; + + sprintf(command, "AT$SF=%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); +}