Example program for MultiTech Dragonfly using ST MEMs sensor shield, Grove moisture sensor, and Grove button.
Dependencies: MbedJSONValue X_NUCLEO_IKS01A1 mbed mtsas
main.cpp
- Committer:
- mfiore
- Date:
- 2015-09-26
- Revision:
- 5:a946ef74a8c4
- Parent:
- 4:730b61258422
File content as of revision 5:a946ef74a8c4:
/*************************************************************************
* Dragonfly Example program for 2015 AT&T Government Solutions Hackathon
*
* The following hardware is required to successfully run this program:
* - MultiTech UDK2 (4" square white PCB with Arduino headers, antenna
* connector, micro USB ports, and 40-pin connector for Dragonfly)
* - MultiTech Dragonfly (1"x2" green PCB with Telit radio)
* - Seeed Studio Base Shield
* - Grove moisture sensor (to connect to Base Shield)
* - Grove button (to connect to Base Shield)
* - MEMs Inertial and Environmental Nucleo Expansion board (LSM6DS0
* 3-axis accelerometer + 3-axis gyroscope, LIS3MDL 3-axis
* magnetometer, HTS221 humidity and temperature sensor and LPS25HB
* pressure sensor)
*
* What this program does:
* - reads data from all sensors on MEMs board and moisture sensor on a
* periodic basis
* - prints all sensor data to debug port on a periodic basis
* - optionally send a SMS containing sensor data when the Grove Button
* is pushed
* - you need to set the "phone_number" field
* - optionally sends sensor data to AT&T M2X cloud platform (user must
* create own M2X account and configure a device)
* - you need to set the "m2x_api_key" field and the "m2x_device_id"
* field based on your M2X account for this to work
* - you need to set the "do_cloud_post" flag to true for this to
* work
*
* Setup:
* - Correctly insert SIM card into Dragonfly
* - Seat the Dragonfly on the UDK2 board
* - Connect an antenna to the connector on the Dragonfly labled "M"
* - Stack the Base Shield on the UDK2 Arduino headers
* - Connect the Grove button to the D8 socket on the Base Shield
* - Connect the Grove moisture sensor to the A0 socket on the Base
* Shield
* - Make sure the reference voltage selector switch (next to the A0
* socket) is switched to 5V so you get accurate analog readings
* - Stack the MEMs board on top of the Base Shield
* - Plug in the power cable
* - Plug a micro USB cable into the port below and slightly to the
* left of the Dragonfly (NOT the port on the Dragonfly)
*
* Go have fun and make something cool!
*
************************************************************************/
#include "mbed.h"
#include "mtsas.h"
#include "x_nucleo_iks01a1.h"
#include "MbedJSONValue.h"
#include "HTTPJson.h"
#include <string>
// Debug serial port
static Serial debug(USBTX, USBRX);
// MTSSerialFlowControl - serial link between processor and radio
static MTSSerialFlowControl* io;
// Cellular - radio object for cellular operations (SMS, TCP, etc)
Cellular* radio;
// APN associated with SIM card
// this APN should work for the AT&T SIM that came with your Dragonfly
//static const std::string apn = "";
static const std::string apn = "broadband";
// Phone number to send SMS messages to
// just change the x digits - the 1 needs to stay!
static const std::string phone_number = "1xxxxxxxxxx";
// see https://m2x.att.com/developer/documentation/v2/overview for M2X API documentation
// M2X device ID
static const std::string m2x_device_id = "";
// M2X primary API key
static const std::string m2x_api_key = "";
// set to true if you want to post to the cloud
// you need to have you M2X account set up properly for this to work?
//bool do_cloud_post = false;
bool do_cloud_post = true;
std::string url = "http://api-m2x.att.com/v2/devices/" + m2x_device_id + "/update";
// handle to MEMs board object
static X_NUCLEO_IKS01A1* mems = X_NUCLEO_IKS01A1::Instance();
// Moisture sensor
AnalogIn moisture_sensor(A0);
// Button
InterruptIn button(D8);
bool button_pressed = false;
// variables for sensor data
float temp_celsius;
float temp_fahrenheit;
float humidity_percent;
float pressure_mbar;
float moisture_percent;
int32_t mag_mgauss[3];
int32_t acc_mg[3];
int32_t gyro_mdps[3];
// misc variables
static char wall_of_dash[] = "--------------------------------------------------";
bool radio_ok = false;
static int thpm_interval_ms = 2000;
static int motion_interval_ms = 250;
static int print_interval_ms = 10000;
static int post_interval_ms = 30000;
int debug_baud = 115200;
// function prototypes
bool init_mtsas();
void read_temperature();
void read_humidity();
void read_pressure();
void read_moisture();
void read_magnetometer();
void read_accelerometer();
void read_gyroscope();
void button_irq();
// main
int main() {
mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
debug.baud(debug_baud);
logInfo("starting...");
radio_ok = init_mtsas();
if (! radio_ok)
logError("MTSAS init failed");
else
logInfo("MTSAS is ok");
button.fall(&button_irq);
Timer thpm_timer;
Timer motion_timer;
Timer print_timer;
Timer post_timer;
thpm_timer.start();
motion_timer.start();
print_timer.start();
post_timer.start();
while (true) {
if (motion_timer.read_ms() > motion_interval_ms) {
read_magnetometer();
read_accelerometer();
read_gyroscope();
motion_timer.reset();
}
if (thpm_timer.read_ms() > thpm_interval_ms) {
read_temperature();
read_humidity();
read_pressure();
read_moisture();
thpm_timer.reset();
}
if (print_timer.read_ms() > print_interval_ms) {
logDebug("%s", wall_of_dash);
logDebug("SENSOR DATA");
logDebug("temperature: %f C\t%f F", temp_celsius, temp_fahrenheit);
logDebug("humidity: %f%%", humidity_percent);
logDebug("pressure: %f mbar", pressure_mbar);
logDebug("moisture: %f%%", moisture_percent);
logDebug("magnetometer:\r\n\tx: %ld\ty: %ld\tz: %ld\tmgauss", mag_mgauss[0], mag_mgauss[1], mag_mgauss[2]);
logDebug("accelerometer:\r\n\tx: %ld\ty: %ld\tz: %ld\tmg", acc_mg[0], acc_mg[1], acc_mg[2]);
logDebug("gyroscope:\r\n\tx: %ld\ty: %ld\tz: %ld\tmdps", gyro_mdps[0], gyro_mdps[1], gyro_mdps[2]);
logDebug("%s", wall_of_dash);
print_timer.reset();
}
if (button_pressed) {
logInfo("Button was pressed");
button_pressed = false;
if (radio_ok) {
MbedJSONValue sms_json;
string sms_str;
sms_json["temp_C"] = temp_celsius;
sms_json["temp_F"] = temp_fahrenheit;
sms_json["humidity_percent"] = humidity_percent;
sms_json["pressure_mbar"] = pressure_mbar;
sms_json["moisture_percent"] = moisture_percent;
sms_json["mag_mgauss"]["x"] = mag_mgauss[0];
sms_json["mag_mgauss"]["y"] = mag_mgauss[1];
sms_json["mag_mgauss"]["z"] = mag_mgauss[2];
sms_json["acc_mg"]["x"] = acc_mg[0];
sms_json["acc_mg"]["y"] = acc_mg[1];
sms_json["acc_mg"]["z"] = acc_mg[2];
sms_json["gyro_mdps"]["x"] = gyro_mdps[0];
sms_json["gyro_mdps"]["y"] = gyro_mdps[1];
sms_json["gyro_mdps"]["z"] = gyro_mdps[2];
sms_str = "SENSOR DATA:\n";
sms_str += sms_json.serialize();
logDebug("sending SMS to %s:\r\n%s", phone_number.c_str(), sms_str.c_str());
Code ret = radio->sendSMS(phone_number, sms_str);
if (ret != MTS_SUCCESS)
logError("sending SMS failed");
}
}
if (post_timer.read_ms() > post_interval_ms && do_cloud_post) {
if (radio->connect()) {
logDebug("posting sensor data");
HTTPClient http;
MbedJSONValue http_json_data;
std::string http_json_str;
std::string m2x_header = "X-M2X-KEY: " + m2x_api_key + "\r\n";
int ret;
char http_response_buf[256];
HTTPText http_response(http_response_buf, sizeof(http_response_buf));
// temp_c, temp_f, humidity, pressure, and moisture are all stream IDs for my device in M2X
// modify these to match your streams or give your streams the same name
http_json_data["values"]["temp_c"] = temp_celsius;
http_json_data["values"]["temp_f"] = temp_fahrenheit;
http_json_data["values"]["humidity"] = humidity_percent;
http_json_data["values"]["pressure"] = pressure_mbar;
http_json_data["values"]["moisture"] = moisture_percent;
http_json_str = http_json_data.serialize();
// add extra header with M2X API key
http.setHeader(m2x_header.c_str());
HTTPJson http_json((char*) http_json_str.c_str());
ret = http.post(url.c_str(), http_json, &http_response);
if (ret != HTTP_OK)
logError("posting data to cloud failed: [%d][%s]", ret, http_response_buf);
else
logDebug("post result [%d][%s]", http.getHTTPResponseCode(), http_response_buf);
radio->disconnect();
} else {
logError("establishing PPP link failed");
}
post_timer.reset();
}
wait_ms(10);
}
}
// init functions
bool init_mtsas() {
io = new MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS);
if (! io)
return false;
io->baud(115200);
radio = CellularFactory::create(io);
if (! radio)
return false;
Code ret = radio->setApn(apn);
if (ret != MTS_SUCCESS)
return false;
Transport::setTransport(radio);
return true;
}
// Sensor data acquisition functions
void read_temperature() {
int ret;
ret = mems->ht_sensor->GetTemperature(&temp_celsius);
if (ret)
logError("reading temp (C) failed");
ret = mems->ht_sensor->GetFahrenheit(&temp_fahrenheit);
if (ret)
logError("reading temp (F) failed");
}
void read_humidity() {
int ret;
ret = mems->ht_sensor->GetHumidity(&humidity_percent);
if (ret)
logError("reading humidity failed");
}
void read_pressure() {
int ret;
ret = mems->pt_sensor->GetPressure(&pressure_mbar);
if (ret)
logError("reading pressure failed");
}
void read_moisture() {
moisture_percent = moisture_sensor * 100.0;
}
void read_magnetometer() {
int ret;
ret = mems->magnetometer->Get_M_Axes(mag_mgauss);
if (ret)
logError("reading magnetometer failed");
}
void read_accelerometer() {
int ret;
ret = mems->GetAccelerometer()->Get_X_Axes(acc_mg);
if (ret)
logError("reading accelerometer failed");
}
void read_gyroscope() {
int ret;
ret = mems->GetGyroscope()->Get_G_Axes(gyro_mdps);
if (ret)
logError("reading gyroscope failed");
}
void button_irq() {
button_pressed = true;
}