Workshop example
Dependencies: X_NUCLEO_COMMON ST_INTERFACES
Diff: main.cpp
- Revision:
- 10:b27c962b3c3f
- Parent:
- 9:265744785d33
- Child:
- 11:8df4529f060d
--- a/main.cpp Sun Oct 14 19:01:53 2018 +0100 +++ b/main.cpp Sat Dec 08 01:46:22 2018 +0000 @@ -18,7 +18,26 @@ #ifndef MBED_TEST_MODE #include "mbed.h" #include "simple-mbed-cloud-client.h" -#include "FATFileSystem.h" +#include "LittleFileSystem.h" + +//#define SENSORS_AND_BUTTONS +#ifdef SENSORS_AND_BUTTONS +#include "HTS221Sensor.h" +#include "LPS22HBSensor.h" +#include "LSM6DSLSensor.h" +#include "lis3mdl_class.h" +#include "VL53L0X.h" + +static DevI2C devI2c(PB_11,PB_10); +static HTS221Sensor hum_temp(&devI2c); +static LPS22HBSensor press_temp(&devI2c); +static LSM6DSLSensor acc_gyro(&devI2c,LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW,PD_11); // low address +static LIS3MDL magnetometer(&devI2c); +static DigitalOut shutdown_pin(PC_6); +static VL53L0X range(&devI2c, &shutdown_pin, PC_7); + +InterruptIn button(USER_BUTTON); +#endif /* SENSORS_AND_BUTTONS */ // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads) // This is great because things such as network operations are illegal in ISR, so updating a resource in a button's fall() function is not allowed @@ -29,19 +48,30 @@ // Default block device BlockDevice* bd = BlockDevice::get_default_instance(); -FATFileSystem fs("sd", bd); +SlicingBlockDevice sd(bd, 0, 2*1024*1024); +LittleFileSystem fs("fs", &sd); // Declaring pointers for access to Pelion Client resources outside of main() MbedCloudClientResource *button_res; MbedCloudClientResource *pattern_res; -// This function gets triggered by the timer. It's easy to replace it by an InterruptIn and fall() mode on a real button -void fake_button_press() { - int v = button_res->get_value_int() + 1; +#ifdef SENSORS_AND_BUTTONS +// Additional resources for sensor readings +MbedCloudClientResource *humidity_res; +MbedCloudClientResource *temperature_res; +MbedCloudClientResource *distance_res; +#endif /* SENSORS_AND_BUTTONS */ - button_res->set_value(v); +// When the device is registered, this variable will be used to access various useful information, like device ID etc. +static const ConnectorClientEndpointInfo* endpointInfo; - printf("Simulated button clicked %d times\n", v); +/** + * Button function triggered by the physical button press or by timer depending on SENSORS_AND_BUTTONS macro. + */ +void button_press() { + int v = button_res->get_value_int() + 1; + button_res->set_value(v); + printf("Button clicked %d times\n", v); } /** @@ -98,19 +128,134 @@ */ void registered(const ConnectorClientEndpointInfo *endpoint) { printf("Connected to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str()); + endpointInfo = endpoint; } +#ifdef SENSORS_AND_BUTTONS +/** + * Initialize sensors + */ +void sensors_init() { + uint8_t id; + + // Initialize sensors + hum_temp.init(NULL); + press_temp.init(NULL); + acc_gyro.init(NULL); + magnetometer.init(NULL); + range.init_sensor(VL53L0X_DEFAULT_ADDRESS); + + /// Call sensors enable routines + hum_temp.enable(); + press_temp.enable(); + //magnetometer.enable(); + acc_gyro.enable_x(); + acc_gyro.enable_g(); + + printf("\033[2J\033[20A"); + printf ("\r\n--- Sensors configuration ---\r\n\r\n"); + + hum_temp.read_id(&id); + printf("HTS221 humidity & temperature = 0x%X\r\n", id); + press_temp.read_id(&id); + printf("LPS22HB pressure & temperature = 0x%X\r\n", id); + magnetometer.read_id(&id); + printf("LIS3MDL magnetometer = 0x%X\r\n", id); + acc_gyro.read_id(&id); + printf("LSM6DSL accelerometer & gyroscope = 0x%X\r\n", id); + + printf("\n\r--- Reading sensor values ---\n\r"); ; +} + +/** + * Update sensors and report their values. + * This function is called periodically. + */ +void sensors_update() { + float value1, value2; + int32_t axes[3]; + uint32_t distance; + + printf("\r\n"); + + value1 = value2 = 0.0; + hum_temp.get_temperature(&value1); + hum_temp.get_humidity(&value2); + if (endpointInfo) { + temperature_res->set_value(value1); + humidity_res->set_value(value2); + } + printf("HTS221: [temp] %.2f C, [hum] %.2f%%\r\n", value1, value2); + + value1 = value2 = 0.0; + press_temp.get_temperature(&value1); + press_temp.get_pressure(&value2); + printf("LPS22HB: [temp] %.2f C, [press] %.2f mbar\r\n", value1, value2); + printf("Mag/Acc/Gyro readings: x, y, z\r\n"); + + magnetometer.get_m_axes(axes); + printf("LIS3MDL [mag/mgauss]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); + acc_gyro.get_x_axes(axes); + printf("LSM6DSL [acc/mg]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); + acc_gyro.get_g_axes(axes); + printf("LSM6DSL [gyro/mdps]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); + + if (range.get_distance(&distance) == VL53L0X_ERROR_NONE) { + printf("VL53L0X [mm]: %6ld\r\n", distance); + if (endpointInfo) { + distance_res->set_value((int)distance); + } + } else { + printf("VL53L0X [mm]: --\r\n"); + } + + printf("\033[8A"); +} +#endif /* SENSORS_AND_BUTTONS */ + + int main(void) { printf("Starting Simple Pelion Device Management Client example\n"); printf("Connecting to the network using Wifi...\n"); + // If the User button is pressed, then format storage. + const int PRESSED = 0; + DigitalIn *user_button = new DigitalIn(USER_BUTTON); + if (user_button->read() == PRESSED) { + printf("User button is pushed on start. Formatting the storage...\n"); + int storage_status = fs.reformat(&sd); + if (storage_status != 0) { + if (sd.erase(0, sd.size()) == 0) { + if (fs.format(&sd) == 0) { + storage_status = 0; + printf("The storage reformatted successfully.\n"); + } + } + } + if (storage_status != 0) { + printf("Failed to reformat the storage.\n"); + } + } + +#ifdef SENSORS_AND_BUTTONS + sensors_init(); +#endif /* SENSORS_AND_BUTTONS */ + // Connect to the internet (DHCP is expected to be on) net = NetworkInterface::get_default_instance(); - nsapi_error_t status = net->connect(); + nsapi_error_t net_status = -1; + for (int tries = 0; tries < 3; tries++) { + net_status = net->connect(); + if (net_status == NSAPI_ERROR_OK) { + break; + } else { + printf("[WARN] Unable to connect to network. Retrying...\n"); + } + } - if (status != NSAPI_ERROR_OK) { - printf("Connecting to the network failed %d!\n", status); + if (net_status != NSAPI_ERROR_OK) { + printf("Connecting to the network failed %d!\n", net_status); return -1; } @@ -140,6 +285,24 @@ blink_res->methods(M2MMethod::POST); blink_res->attach_post_callback(blink_callback); +#ifdef SENSORS_AND_BUTTONS + // Sensor resources + temperature_res = client.create_resource("3303/0/5700", "temperature"); + temperature_res->set_value(0); + temperature_res->methods(M2MMethod::GET); + temperature_res->observable(true); + + humidity_res = client.create_resource("3304/0/5700", "humidity"); + humidity_res->set_value(0); + humidity_res->methods(M2MMethod::GET); + humidity_res->observable(true); + + distance_res = client.create_resource("3330/0/5700", "distance"); + distance_res->set_value(0); + distance_res->methods(M2MMethod::GET); + distance_res->observable(true); +#endif /* SENSORS_AND_BUTTONS */ + printf("Initialized Pelion Client. Registering...\n"); // Callback that fires when registering is complete @@ -150,8 +313,15 @@ // Placeholder for callback to update local resource when GET comes. // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations +#ifdef SENSORS_AND_BUTTONS + button.fall(eventQueue.event(button_press)); + Ticker timer; - timer.attach(eventQueue.event(&fake_button_press), 5.0); + timer.attach(eventQueue.event(sensors_update), 3.0); +#else /* SENSORS_AND_BUTTONS */ + Ticker timer; + timer.attach(eventQueue.event(&button_press), 5.0); +#endif /* SENSORS_AND_BUTTONS */ // You can easily run the eventQueue in a separate thread if required eventQueue.dispatch_forever();