Initial Program for MultiTech Dragonfly to communicate to PTC ThingWorx. Sensors are from Rohm version1

Dependencies:   MbedJSONValue mbed mtsas

Fork of UUU_MultiTech_Dragonfly_Sprint by Paul Jaeger

Committer:
mfiore
Date:
Thu Sep 24 17:56:49 2015 +0000
Revision:
0:a44e71488e1f
Child:
1:a049d113e250
first commit - mtsas doesn't play nice with rtos. think it's a serial irq + rtos issue

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mfiore 0:a44e71488e1f 1 /*************************************************************************
mfiore 0:a44e71488e1f 2 * Dragonfly Example program for 2015 AT&T Government Solutions Hackathon
mfiore 0:a44e71488e1f 3 *
mfiore 0:a44e71488e1f 4 * The following hardware is required to successfully run this program:
mfiore 0:a44e71488e1f 5 * - MultiTech UDK2 (4" square white PCB with Arduino headers, antenna
mfiore 0:a44e71488e1f 6 * connector, micro USB ports, and 40-pin connector for Dragonfly)
mfiore 0:a44e71488e1f 7 * - MultiTech Dragonfly (1"x2" green PCB with Telit radio)
mfiore 0:a44e71488e1f 8 * - Seeed Studio Base Shield
mfiore 0:a44e71488e1f 9 * - Grove moisture sensor (to connect to Base Shield)
mfiore 0:a44e71488e1f 10 * - Grove button (to connect to Base Shield)
mfiore 0:a44e71488e1f 11 * - MEMs Inertial and Environmental Nucleo Expansion board (LSM6DS0
mfiore 0:a44e71488e1f 12 * 3-axis accelerometer + 3-axis gyroscope, LIS3MDL 3-axis
mfiore 0:a44e71488e1f 13 * magnetometer, HTS221 humidity and temperature sensor and LPS25HB
mfiore 0:a44e71488e1f 14 * pressure sensor)
mfiore 0:a44e71488e1f 15 *
mfiore 0:a44e71488e1f 16 * What this program does:
mfiore 0:a44e71488e1f 17 * - reads data from all sensors on MEMs board and moisture sensor on a
mfiore 0:a44e71488e1f 18 * periodic basis
mfiore 0:a44e71488e1f 19 * - prints all sensor data to debug port on a periodic basis
mfiore 0:a44e71488e1f 20 * - optionally send a SMS containing sensor data when the Grove Button
mfiore 0:a44e71488e1f 21 * is pushed (phone number must be configured)
mfiore 0:a44e71488e1f 22 * - optionally send sensor data to AT&T M2X cloud platform (user must
mfiore 0:a44e71488e1f 23 * create own M2X account and configure a device) if sensor data
mfiore 0:a44e71488e1f 24 * crosses established thresholds
mfiore 0:a44e71488e1f 25 *
mfiore 0:a44e71488e1f 26 * Setup:
mfiore 0:a44e71488e1f 27 * - Correctly insert SIM card into Dragonfly
mfiore 0:a44e71488e1f 28 * - Seat the Dragonfly on the UDK2 board
mfiore 0:a44e71488e1f 29 * - Connect an antenna to the connector on the Dragonfly labled "M"
mfiore 0:a44e71488e1f 30 * - Stack the Base Shield on the UDK2 Arduino headers
mfiore 0:a44e71488e1f 31 * - Connect the Grove button to the D8 socket on the Base Shield
mfiore 0:a44e71488e1f 32 * - Connect the Grove moisture sensor to the A0 socket on the Base
mfiore 0:a44e71488e1f 33 * Shield
mfiore 0:a44e71488e1f 34 * - Stack the MEMs board on top of the Base Shield
mfiore 0:a44e71488e1f 35 * - Plug in the power cable
mfiore 0:a44e71488e1f 36 * - Plug a micro USB cable into the port below and slightly to the
mfiore 0:a44e71488e1f 37 * left of the Dragonfly (NOT the port on the Dragonfly)
mfiore 0:a44e71488e1f 38 *
mfiore 0:a44e71488e1f 39 * Go have fun and make something cool!
mfiore 0:a44e71488e1f 40 *
mfiore 0:a44e71488e1f 41 ************************************************************************/
mfiore 0:a44e71488e1f 42
mfiore 0:a44e71488e1f 43 #include "mbed.h"
mfiore 0:a44e71488e1f 44 #include "rtos.h"
mfiore 0:a44e71488e1f 45 #include "mtsas.h"
mfiore 0:a44e71488e1f 46 #include "x_nucleo_iks01a1.h"
mfiore 0:a44e71488e1f 47 #include "MbedJSONValue.h"
mfiore 0:a44e71488e1f 48 #include <string>
mfiore 0:a44e71488e1f 49
mfiore 0:a44e71488e1f 50 // Debug serial port
mfiore 0:a44e71488e1f 51 static Serial debug(USBTX, USBRX);
mfiore 0:a44e71488e1f 52
mfiore 0:a44e71488e1f 53 // MTSSerialFlowControl - serial link between processor and radio
mfiore 0:a44e71488e1f 54 static MTSSerialFlowControl io(SERIAL_TX, SERIAL_RX, SERIAL_RTS, SERIAL_CTS);
mfiore 0:a44e71488e1f 55
mfiore 0:a44e71488e1f 56 // Cellular - radio object for cellular operations (SMS, TCP, etc)
mfiore 0:a44e71488e1f 57 Cellular* radio;
mfiore 0:a44e71488e1f 58
mfiore 0:a44e71488e1f 59 // APN associated with SIM card
mfiore 0:a44e71488e1f 60 //static const std::string apn = "";
mfiore 0:a44e71488e1f 61 static const std::string apn = "b2b.tmobile.com";
mfiore 0:a44e71488e1f 62
mfiore 0:a44e71488e1f 63 // Phone number to send SMS messages to
mfiore 0:a44e71488e1f 64 //static const std::string phone_number = "1xxxxxxxxxx";
mfiore 0:a44e71488e1f 65 static const std::string phone_number = "19524062053";
mfiore 0:a44e71488e1f 66
mfiore 0:a44e71488e1f 67 // handle to MEMs board object
mfiore 0:a44e71488e1f 68 static X_NUCLEO_IKS01A1* mems = X_NUCLEO_IKS01A1::Instance();
mfiore 0:a44e71488e1f 69
mfiore 0:a44e71488e1f 70 // Moisture sensor
mfiore 0:a44e71488e1f 71 AnalogIn moisture_sensor(A0);
mfiore 0:a44e71488e1f 72
mfiore 0:a44e71488e1f 73 // Button
mfiore 0:a44e71488e1f 74 DigitalIn button(D8);
mfiore 0:a44e71488e1f 75
mfiore 0:a44e71488e1f 76 // variables for sensor data
mfiore 0:a44e71488e1f 77 float temp_celsius;
mfiore 0:a44e71488e1f 78 float temp_fahrenheit;
mfiore 0:a44e71488e1f 79 float humidity_percent;
mfiore 0:a44e71488e1f 80 float pressure_mbar;
mfiore 0:a44e71488e1f 81 float moisture_percent;
mfiore 0:a44e71488e1f 82 int32_t mag_mgauss[3];
mfiore 0:a44e71488e1f 83 int32_t acc_mg[3];
mfiore 0:a44e71488e1f 84 int32_t gyro_mdps[3];
mfiore 0:a44e71488e1f 85
mfiore 0:a44e71488e1f 86 // mutexes
mfiore 0:a44e71488e1f 87 Mutex data_mutex;
mfiore 0:a44e71488e1f 88 Mutex mtsas_mutex;
mfiore 0:a44e71488e1f 89
mfiore 0:a44e71488e1f 90 // misc variables
mfiore 0:a44e71488e1f 91 static char wall_of_dash[] = "--------------------------------------------------";
mfiore 0:a44e71488e1f 92 bool radio_ok = false;
mfiore 0:a44e71488e1f 93 static int thp_interval_ms = 2000;
mfiore 0:a44e71488e1f 94 static int motion_interval_ms = 250;
mfiore 0:a44e71488e1f 95 static int print_interval_ms = 5000;
mfiore 0:a44e71488e1f 96 int debug_baud = 115200;
mfiore 0:a44e71488e1f 97
mfiore 0:a44e71488e1f 98 // function prototypes
mfiore 0:a44e71488e1f 99 bool init_mtsas();
mfiore 0:a44e71488e1f 100 void sensor_thread(void const* args);
mfiore 0:a44e71488e1f 101 void print_thread(void const* args);
mfiore 0:a44e71488e1f 102 void sms_thread(void const* args);
mfiore 0:a44e71488e1f 103 void read_temperature();
mfiore 0:a44e71488e1f 104 void read_humidity();
mfiore 0:a44e71488e1f 105 void read_pressure();
mfiore 0:a44e71488e1f 106 void read_moisture();
mfiore 0:a44e71488e1f 107 void read_magnetometer();
mfiore 0:a44e71488e1f 108 void read_accelerometer();
mfiore 0:a44e71488e1f 109 void read_gyroscope();
mfiore 0:a44e71488e1f 110 void button_irq();
mfiore 0:a44e71488e1f 111
mfiore 0:a44e71488e1f 112 // main
mfiore 0:a44e71488e1f 113 int main() {
mfiore 0:a44e71488e1f 114 mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
mfiore 0:a44e71488e1f 115 debug.baud(debug_baud);
mfiore 0:a44e71488e1f 116 logInfo("starting...");
mfiore 0:a44e71488e1f 117
mfiore 0:a44e71488e1f 118 radio_ok = init_mtsas();
mfiore 0:a44e71488e1f 119 if (! radio_ok)
mfiore 0:a44e71488e1f 120 logError("MTSAS init failed");
mfiore 0:a44e71488e1f 121 else
mfiore 0:a44e71488e1f 122 logInfo("MTSAS is ok");
mfiore 0:a44e71488e1f 123
mfiore 0:a44e71488e1f 124 Thread sensors(sensor_thread);
mfiore 0:a44e71488e1f 125 Thread prints(print_thread);
mfiore 0:a44e71488e1f 126 Thread sms(sms_thread);
mfiore 0:a44e71488e1f 127
mfiore 0:a44e71488e1f 128 while (true) {
mfiore 0:a44e71488e1f 129 }
mfiore 0:a44e71488e1f 130 }
mfiore 0:a44e71488e1f 131
mfiore 0:a44e71488e1f 132 // init functions
mfiore 0:a44e71488e1f 133 bool init_mtsas() {
mfiore 0:a44e71488e1f 134 io.baud(115200);
mfiore 0:a44e71488e1f 135
mfiore 0:a44e71488e1f 136 mtsas_mutex.lock();
mfiore 0:a44e71488e1f 137 radio = CellularFactory::create(&io);
mfiore 0:a44e71488e1f 138 mtsas_mutex.unlock();
mfiore 0:a44e71488e1f 139 if (! radio)
mfiore 0:a44e71488e1f 140 return false;
mfiore 0:a44e71488e1f 141
mfiore 0:a44e71488e1f 142 mtsas_mutex.lock();
mfiore 0:a44e71488e1f 143 Code ret = radio->setApn(apn);
mfiore 0:a44e71488e1f 144 mtsas_mutex.unlock();
mfiore 0:a44e71488e1f 145 if (ret != MTS_SUCCESS)
mfiore 0:a44e71488e1f 146 return false;
mfiore 0:a44e71488e1f 147
mfiore 0:a44e71488e1f 148 return true;
mfiore 0:a44e71488e1f 149 }
mfiore 0:a44e71488e1f 150
mfiore 0:a44e71488e1f 151 // thread "main" functions
mfiore 0:a44e71488e1f 152 void sensor_thread(void const* args) {
mfiore 0:a44e71488e1f 153 Timer thp_timer;
mfiore 0:a44e71488e1f 154 Timer motion_timer;
mfiore 0:a44e71488e1f 155
mfiore 0:a44e71488e1f 156 thp_timer.start();
mfiore 0:a44e71488e1f 157 motion_timer.start();
mfiore 0:a44e71488e1f 158 while (true) {
mfiore 0:a44e71488e1f 159 if (motion_timer.read_ms() > motion_interval_ms) {
mfiore 0:a44e71488e1f 160 read_magnetometer();
mfiore 0:a44e71488e1f 161 read_accelerometer();
mfiore 0:a44e71488e1f 162 read_gyroscope();
mfiore 0:a44e71488e1f 163 motion_timer.reset();
mfiore 0:a44e71488e1f 164 }
mfiore 0:a44e71488e1f 165
mfiore 0:a44e71488e1f 166 if (thp_timer.read_ms() > thp_interval_ms) {
mfiore 0:a44e71488e1f 167 read_temperature();
mfiore 0:a44e71488e1f 168 read_humidity();
mfiore 0:a44e71488e1f 169 read_pressure();
mfiore 0:a44e71488e1f 170 thp_timer.reset();
mfiore 0:a44e71488e1f 171 }
mfiore 0:a44e71488e1f 172
mfiore 0:a44e71488e1f 173 Thread::wait(100);
mfiore 0:a44e71488e1f 174 }
mfiore 0:a44e71488e1f 175 }
mfiore 0:a44e71488e1f 176
mfiore 0:a44e71488e1f 177 void print_thread(void const* args) {
mfiore 0:a44e71488e1f 178 Timer print_timer;
mfiore 0:a44e71488e1f 179
mfiore 0:a44e71488e1f 180 print_timer.start();
mfiore 0:a44e71488e1f 181 while (true) {
mfiore 0:a44e71488e1f 182 if (print_timer.read_ms() > print_interval_ms) {
mfiore 0:a44e71488e1f 183 data_mutex.lock();
mfiore 0:a44e71488e1f 184 logDebug("%s", wall_of_dash);
mfiore 0:a44e71488e1f 185 logDebug("SENSOR DATA");
mfiore 0:a44e71488e1f 186 logDebug("temperature: %f C\t%f F", temp_celsius, temp_fahrenheit);
mfiore 0:a44e71488e1f 187 logDebug("humidity: %f%%", humidity_percent);
mfiore 0:a44e71488e1f 188 logDebug("pressure: %f mbar", pressure_mbar);
mfiore 0:a44e71488e1f 189 logDebug("moisture: %f%%", moisture_percent);
mfiore 0:a44e71488e1f 190 logDebug("magnetometer:\r\n\tx: %ld\ty: %ld\tz: %ld\tmgauss", mag_mgauss[0], mag_mgauss[1], mag_mgauss[2]);
mfiore 0:a44e71488e1f 191 logDebug("accelerometer:\r\n\tx: %ld\ty: %ld\tz: %ld\tmg", acc_mg[0], acc_mg[1], acc_mg[2]);
mfiore 0:a44e71488e1f 192 logDebug("gyroscope:\r\n\tx: %ld\ty: %ld\tz: %ld\tmdps", gyro_mdps[0], gyro_mdps[1], gyro_mdps[2]);
mfiore 0:a44e71488e1f 193 logDebug("%s", wall_of_dash);
mfiore 0:a44e71488e1f 194 data_mutex.unlock();
mfiore 0:a44e71488e1f 195 print_timer.reset();
mfiore 0:a44e71488e1f 196 }
mfiore 0:a44e71488e1f 197
mfiore 0:a44e71488e1f 198 Thread::wait(1000);
mfiore 0:a44e71488e1f 199 }
mfiore 0:a44e71488e1f 200 }
mfiore 0:a44e71488e1f 201
mfiore 0:a44e71488e1f 202 void sms_thread(void const* args) {
mfiore 0:a44e71488e1f 203 while (true) {
mfiore 0:a44e71488e1f 204 if (button) {
mfiore 0:a44e71488e1f 205 logInfo("Button was pressed");
mfiore 0:a44e71488e1f 206 if (radio_ok) {
mfiore 0:a44e71488e1f 207 MbedJSONValue sms_json;
mfiore 0:a44e71488e1f 208 string sms_str;
mfiore 0:a44e71488e1f 209
mfiore 0:a44e71488e1f 210 sms_json["temp_C"] = temp_celsius;
mfiore 0:a44e71488e1f 211 sms_json["temp_F"] = temp_fahrenheit;
mfiore 0:a44e71488e1f 212 sms_json["humidity_percent"] = humidity_percent;
mfiore 0:a44e71488e1f 213 sms_json["pressure_mbar"] = pressure_mbar;
mfiore 0:a44e71488e1f 214 sms_json["moisture_percent"] = moisture_percent;
mfiore 0:a44e71488e1f 215 sms_json["mag_mgauss"]["x"] = mag_mgauss[0];
mfiore 0:a44e71488e1f 216 sms_json["mag_mgauss"]["y"] = mag_mgauss[1];
mfiore 0:a44e71488e1f 217 sms_json["mag_mgauss"]["z"] = mag_mgauss[2];
mfiore 0:a44e71488e1f 218 sms_json["acc_mg"]["x"] = acc_mg[0];
mfiore 0:a44e71488e1f 219 sms_json["acc_mg"]["y"] = acc_mg[1];
mfiore 0:a44e71488e1f 220 sms_json["acc_mg"]["z"] = acc_mg[2];
mfiore 0:a44e71488e1f 221 sms_json["gyro_mdps"]["x"] = gyro_mdps[0];
mfiore 0:a44e71488e1f 222 sms_json["gyro_mdps"]["y"] = gyro_mdps[1];
mfiore 0:a44e71488e1f 223 sms_json["gyro_mdps"]["z"] = gyro_mdps[2];
mfiore 0:a44e71488e1f 224
mfiore 0:a44e71488e1f 225 sms_str = "SENSOR DATA: ";
mfiore 0:a44e71488e1f 226 sms_str += sms_json.serialize();
mfiore 0:a44e71488e1f 227
mfiore 0:a44e71488e1f 228 logDebug("sending SMS to %s:\r\n%s", phone_number.c_str(), sms_str.c_str());
mfiore 0:a44e71488e1f 229 mtsas_mutex.lock();
mfiore 0:a44e71488e1f 230 Code ret = radio->sendSMS(phone_number, sms_str);
mfiore 0:a44e71488e1f 231 mtsas_mutex.unlock();
mfiore 0:a44e71488e1f 232 if (ret != MTS_SUCCESS)
mfiore 0:a44e71488e1f 233 logError("sending SMS failed");
mfiore 0:a44e71488e1f 234 }
mfiore 0:a44e71488e1f 235 }
mfiore 0:a44e71488e1f 236
mfiore 0:a44e71488e1f 237 Thread::wait(200);
mfiore 0:a44e71488e1f 238 }
mfiore 0:a44e71488e1f 239 }
mfiore 0:a44e71488e1f 240
mfiore 0:a44e71488e1f 241 // Sensor data acquisition functions
mfiore 0:a44e71488e1f 242 void read_temperature() {
mfiore 0:a44e71488e1f 243 int ret;
mfiore 0:a44e71488e1f 244
mfiore 0:a44e71488e1f 245 data_mutex.lock();
mfiore 0:a44e71488e1f 246 ret = mems->ht_sensor->GetTemperature(&temp_celsius);
mfiore 0:a44e71488e1f 247 data_mutex.unlock();
mfiore 0:a44e71488e1f 248 if (ret)
mfiore 0:a44e71488e1f 249 logError("reading temp (C) failed");
mfiore 0:a44e71488e1f 250
mfiore 0:a44e71488e1f 251 data_mutex.lock();
mfiore 0:a44e71488e1f 252 ret = mems->ht_sensor->GetFahrenheit(&temp_fahrenheit);
mfiore 0:a44e71488e1f 253 data_mutex.unlock();
mfiore 0:a44e71488e1f 254 if (ret)
mfiore 0:a44e71488e1f 255 logError("reading temp (F) failed");
mfiore 0:a44e71488e1f 256 }
mfiore 0:a44e71488e1f 257
mfiore 0:a44e71488e1f 258 void read_humidity() {
mfiore 0:a44e71488e1f 259 int ret;
mfiore 0:a44e71488e1f 260
mfiore 0:a44e71488e1f 261 data_mutex.lock();
mfiore 0:a44e71488e1f 262 ret = mems->ht_sensor->GetHumidity(&humidity_percent);
mfiore 0:a44e71488e1f 263 data_mutex.unlock();
mfiore 0:a44e71488e1f 264 if (ret)
mfiore 0:a44e71488e1f 265 logError("reading humidity failed");
mfiore 0:a44e71488e1f 266 }
mfiore 0:a44e71488e1f 267
mfiore 0:a44e71488e1f 268 void read_pressure() {
mfiore 0:a44e71488e1f 269 int ret;
mfiore 0:a44e71488e1f 270
mfiore 0:a44e71488e1f 271 data_mutex.lock();
mfiore 0:a44e71488e1f 272 ret = mems->pt_sensor->GetPressure(&pressure_mbar);
mfiore 0:a44e71488e1f 273 data_mutex.unlock();
mfiore 0:a44e71488e1f 274 if (ret)
mfiore 0:a44e71488e1f 275 logError("reading pressure failed");
mfiore 0:a44e71488e1f 276 }
mfiore 0:a44e71488e1f 277
mfiore 0:a44e71488e1f 278 void read_moisture() {
mfiore 0:a44e71488e1f 279 data_mutex.lock();
mfiore 0:a44e71488e1f 280 moisture_percent = moisture_sensor;
mfiore 0:a44e71488e1f 281 data_mutex.unlock();
mfiore 0:a44e71488e1f 282 }
mfiore 0:a44e71488e1f 283
mfiore 0:a44e71488e1f 284 void read_magnetometer() {
mfiore 0:a44e71488e1f 285 int ret;
mfiore 0:a44e71488e1f 286
mfiore 0:a44e71488e1f 287 data_mutex.lock();
mfiore 0:a44e71488e1f 288 ret = mems->magnetometer->Get_M_Axes(mag_mgauss);
mfiore 0:a44e71488e1f 289 data_mutex.unlock();
mfiore 0:a44e71488e1f 290 if (ret)
mfiore 0:a44e71488e1f 291 logError("reading magnetometer failed");
mfiore 0:a44e71488e1f 292 }
mfiore 0:a44e71488e1f 293
mfiore 0:a44e71488e1f 294 void read_accelerometer() {
mfiore 0:a44e71488e1f 295 int ret;
mfiore 0:a44e71488e1f 296
mfiore 0:a44e71488e1f 297 data_mutex.lock();
mfiore 0:a44e71488e1f 298 ret = mems->GetAccelerometer()->Get_X_Axes(acc_mg);
mfiore 0:a44e71488e1f 299 data_mutex.unlock();
mfiore 0:a44e71488e1f 300 if (ret)
mfiore 0:a44e71488e1f 301 logError("reading accelerometer failed");
mfiore 0:a44e71488e1f 302 }
mfiore 0:a44e71488e1f 303
mfiore 0:a44e71488e1f 304 void read_gyroscope() {
mfiore 0:a44e71488e1f 305 int ret;
mfiore 0:a44e71488e1f 306
mfiore 0:a44e71488e1f 307 data_mutex.lock();
mfiore 0:a44e71488e1f 308 ret = mems->GetGyroscope()->Get_G_Axes(gyro_mdps);
mfiore 0:a44e71488e1f 309 data_mutex.unlock();
mfiore 0:a44e71488e1f 310 if (ret)
mfiore 0:a44e71488e1f 311 logError("reading gyroscope failed");
mfiore 0:a44e71488e1f 312 }