BG96_K6xF_pelion-example-frdm_Temp

Dependencies:   FXAS21002 FXOS8700Q

Overview

This document is based on https://os.mbed.com/teams/NXP/code/pelion-example-frdm/ and the code forked Daniel_Lee's(https://os.mbed.com/users/Daniel_Lee/code/BG96_K6xF_pelion-example-frdm/)BG96_K6xF_pelion-example-frdm repository and added some features. Need a WIZnet IoT Shield BG96 board and development board.

This example is known to work great on the following platforms:

/media/uploads/stkim92/pel01.png

Requirement

  1. FRDM-K64F or FRDM-K66F
  2. WIZnet IoT Shield BG96 board
  3. USIM card

Example functionality

This example showcases the following device functionality:

Read onboard FXOS8700Q accelerometer, magnetometer and temperature(on shield). And report the values as Pelion LWM2M resources (see image below). (FRDM-K66F only) Read onboard FXAS21002 gyroscope and report the values as Pelion LWM2M resources. On user button click, increment Pelion LWM2M button resource. Allow the user to change the state of the board LED from Pelion LWM2M led_state resource and PUT request.

1. Import into Compiler

/media/uploads/stkim92/pel1.png

2. Apply Update Certificate

/media/uploads/stkim92/pel03.png

3. Compile and Program

/media/uploads/stkim92/pel04.png

4. If successfully connect to cellular networks(SKTelecom) then you can get below message

Device's Result

include the mbed library with this snippet

You can hold the user button during boot to format the storage and change the device identity.

M2Mnet(BG96) Power ON



Sensors configuration:

FXOS8700Q accelerometer = 0xC7

FXOS8700Q magnetometer  = 0xC7



Connecting to the network using the default network interface...

Connected to the network successfully. IP address: 2001:2D8:65

Initializing Pelion Device Management Client...

Initialized Pelion Device Management Client. Registering...

Press the user button to increment the LwM2M resource value...

Celsius temp : 26.10 C                                                             

FXOS8700Q mag:    0.217 x,   0.420 y,   0.288 z [gauss]     

Pelion Cloud Result (1)

/media/uploads/stkim92/pel4.png

Pelion Cloud Result (2)

/media/uploads/stkim92/pel5.png

Committer:
screamer
Date:
Mon Mar 25 17:18:30 2019 +0000
Revision:
1:42d51cf7cebe
Parent:
0:a9d53048f0b6
Child:
2:fba2c7066355
Add support for FXOS8700Q onboard sensor and report it to Pelion

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:a9d53048f0b6 1 // ----------------------------------------------------------------------------
screamer 0:a9d53048f0b6 2 // Copyright 2016-2018 ARM Ltd.
screamer 0:a9d53048f0b6 3 //
screamer 0:a9d53048f0b6 4 // SPDX-License-Identifier: Apache-2.0
screamer 0:a9d53048f0b6 5 //
screamer 0:a9d53048f0b6 6 // Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:a9d53048f0b6 7 // you may not use this file except in compliance with the License.
screamer 0:a9d53048f0b6 8 // You may obtain a copy of the License at
screamer 0:a9d53048f0b6 9 //
screamer 0:a9d53048f0b6 10 // http://www.apache.org/licenses/LICENSE-2.0
screamer 0:a9d53048f0b6 11 //
screamer 0:a9d53048f0b6 12 // Unless required by applicable law or agreed to in writing, software
screamer 0:a9d53048f0b6 13 // distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:a9d53048f0b6 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:a9d53048f0b6 15 // See the License for the specific language governing permissions and
screamer 0:a9d53048f0b6 16 // limitations under the License.
screamer 0:a9d53048f0b6 17 // ----------------------------------------------------------------------------
screamer 0:a9d53048f0b6 18 #ifndef MBED_TEST_MODE
screamer 0:a9d53048f0b6 19
screamer 0:a9d53048f0b6 20 #include "mbed.h"
screamer 0:a9d53048f0b6 21 #include "simple-mbed-cloud-client.h"
screamer 0:a9d53048f0b6 22 #include "FATFileSystem.h"
screamer 0:a9d53048f0b6 23 #include "LittleFileSystem.h"
screamer 1:42d51cf7cebe 24 #include "FXOS8700Q.h"
screamer 1:42d51cf7cebe 25
screamer 1:42d51cf7cebe 26 I2C sen_i2c(PTE25, PTE24);
screamer 1:42d51cf7cebe 27 FXOS8700QAccelerometer sen_acc(sen_i2c, FXOS8700CQ_SLAVE_ADDR1); // Configured for the FRDM-K64F with onboard sensors
screamer 1:42d51cf7cebe 28 FXOS8700QMagnetometer sen_mag(sen_i2c, FXOS8700CQ_SLAVE_ADDR1);
screamer 1:42d51cf7cebe 29
screamer 1:42d51cf7cebe 30 #define SENSORS_POLL_INTERVAL 1.0
screamer 1:42d51cf7cebe 31 #define SEND_ALL_SENSORS
screamer 0:a9d53048f0b6 32
screamer 0:a9d53048f0b6 33 // Default network interface object. Don't forget to change the WiFi SSID/password in mbed_app.json if you're using WiFi.
screamer 0:a9d53048f0b6 34 NetworkInterface *net = NetworkInterface::get_default_instance();
screamer 0:a9d53048f0b6 35
screamer 0:a9d53048f0b6 36 // Default block device available on the target board
screamer 0:a9d53048f0b6 37 BlockDevice *bd = BlockDevice::get_default_instance();
screamer 0:a9d53048f0b6 38
screamer 0:a9d53048f0b6 39 #if COMPONENT_SD || COMPONENT_NUSD
screamer 0:a9d53048f0b6 40 // Use FATFileSystem for SD card type blockdevices
screamer 0:a9d53048f0b6 41 FATFileSystem fs("fs", bd);
screamer 0:a9d53048f0b6 42 #else
screamer 0:a9d53048f0b6 43 // Use LittleFileSystem for non-SD block devices to enable wear leveling and other functions
screamer 0:a9d53048f0b6 44 LittleFileSystem fs("fs", bd);
screamer 0:a9d53048f0b6 45 #endif
screamer 0:a9d53048f0b6 46
screamer 0:a9d53048f0b6 47 #if USE_BUTTON == 1
screamer 0:a9d53048f0b6 48 InterruptIn button(BUTTON1);
screamer 0:a9d53048f0b6 49 #endif /* USE_BUTTON */
screamer 0:a9d53048f0b6 50
screamer 0:a9d53048f0b6 51 // Default LED to use for PUT/POST example
screamer 0:a9d53048f0b6 52 DigitalOut led(LED1);
screamer 0:a9d53048f0b6 53
screamer 0:a9d53048f0b6 54 // Declaring pointers for access to Pelion Device Management Client resources outside of main()
screamer 0:a9d53048f0b6 55 MbedCloudClientResource *button_res;
screamer 0:a9d53048f0b6 56 MbedCloudClientResource *led_res;
screamer 0:a9d53048f0b6 57 MbedCloudClientResource *post_res;
screamer 1:42d51cf7cebe 58 #ifdef SEND_ALL_SENSORS
screamer 1:42d51cf7cebe 59 MbedCloudClientResource *res_magnometer_x;
screamer 1:42d51cf7cebe 60 MbedCloudClientResource *res_magnometer_y;
screamer 1:42d51cf7cebe 61 MbedCloudClientResource *res_magnometer_z;
screamer 1:42d51cf7cebe 62 MbedCloudClientResource *res_accelerometer_x;
screamer 1:42d51cf7cebe 63 MbedCloudClientResource *res_accelerometer_y;
screamer 1:42d51cf7cebe 64 MbedCloudClientResource *res_accelerometer_z;
screamer 1:42d51cf7cebe 65 #endif /* SEND_ALL_SENSORS */
screamer 0:a9d53048f0b6 66
screamer 0:a9d53048f0b6 67 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
screamer 0:a9d53048f0b6 68 // 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
screamer 0:a9d53048f0b6 69 EventQueue eventQueue;
screamer 0:a9d53048f0b6 70
screamer 1:42d51cf7cebe 71 // When the device is registered, this variable will be used to access various useful information, like device ID etc.
screamer 1:42d51cf7cebe 72 static const ConnectorClientEndpointInfo* endpointInfo;
screamer 1:42d51cf7cebe 73
screamer 0:a9d53048f0b6 74 /**
screamer 0:a9d53048f0b6 75 * PUT handler - sets the value of the built-in LED
screamer 0:a9d53048f0b6 76 * @param resource The resource that triggered the callback
screamer 0:a9d53048f0b6 77 * @param newValue Updated value for the resource
screamer 0:a9d53048f0b6 78 */
screamer 0:a9d53048f0b6 79 void put_callback(MbedCloudClientResource *resource, m2m::String newValue) {
screamer 0:a9d53048f0b6 80 printf("PUT received. New value: %s\n", newValue.c_str());
screamer 0:a9d53048f0b6 81 led = atoi(newValue.c_str());
screamer 0:a9d53048f0b6 82 }
screamer 0:a9d53048f0b6 83
screamer 0:a9d53048f0b6 84 /**
screamer 0:a9d53048f0b6 85 * POST handler - prints the content of the payload
screamer 0:a9d53048f0b6 86 * @param resource The resource that triggered the callback
screamer 0:a9d53048f0b6 87 * @param buffer If a body was passed to the POST function, this contains the data.
screamer 0:a9d53048f0b6 88 * Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
screamer 0:a9d53048f0b6 89 * @param size Size of the body
screamer 0:a9d53048f0b6 90 */
screamer 0:a9d53048f0b6 91 void post_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
screamer 0:a9d53048f0b6 92 printf("POST received (length %u). Payload: ", size);
screamer 0:a9d53048f0b6 93 for (size_t ix = 0; ix < size; ix++) {
screamer 0:a9d53048f0b6 94 printf("%02x ", buffer[ix]);
screamer 0:a9d53048f0b6 95 }
screamer 0:a9d53048f0b6 96 printf("\n");
screamer 0:a9d53048f0b6 97 }
screamer 0:a9d53048f0b6 98
screamer 0:a9d53048f0b6 99 /**
screamer 0:a9d53048f0b6 100 * Button handler
screamer 0:a9d53048f0b6 101 * This function will be triggered either by a physical button press or by a ticker every 5 seconds (see below)
screamer 0:a9d53048f0b6 102 */
screamer 0:a9d53048f0b6 103 void button_press() {
screamer 0:a9d53048f0b6 104 int v = button_res->get_value_int() + 1;
screamer 0:a9d53048f0b6 105 button_res->set_value(v);
screamer 0:a9d53048f0b6 106 printf("Button clicked %d times\n", v);
screamer 0:a9d53048f0b6 107 }
screamer 0:a9d53048f0b6 108
screamer 0:a9d53048f0b6 109 /**
screamer 0:a9d53048f0b6 110 * Notification callback handler
screamer 0:a9d53048f0b6 111 * @param resource The resource that triggered the callback
screamer 0:a9d53048f0b6 112 * @param status The delivery status of the notification
screamer 0:a9d53048f0b6 113 */
screamer 0:a9d53048f0b6 114 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
screamer 0:a9d53048f0b6 115 printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
screamer 0:a9d53048f0b6 116 }
screamer 0:a9d53048f0b6 117
screamer 0:a9d53048f0b6 118 /**
screamer 0:a9d53048f0b6 119 * Registration callback handler
screamer 0:a9d53048f0b6 120 * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
screamer 0:a9d53048f0b6 121 */
screamer 0:a9d53048f0b6 122 void registered(const ConnectorClientEndpointInfo *endpoint) {
screamer 0:a9d53048f0b6 123 printf("Registered to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
screamer 0:a9d53048f0b6 124 }
screamer 0:a9d53048f0b6 125
screamer 1:42d51cf7cebe 126 /**
screamer 1:42d51cf7cebe 127 * Initialize sensors
screamer 1:42d51cf7cebe 128 */
screamer 1:42d51cf7cebe 129 void sensors_init() {
screamer 1:42d51cf7cebe 130 printf ("\nSensors configuration:\n");
screamer 1:42d51cf7cebe 131
screamer 1:42d51cf7cebe 132 sen_acc.enable();
screamer 1:42d51cf7cebe 133 sen_mag.enable();
screamer 1:42d51cf7cebe 134
screamer 1:42d51cf7cebe 135 printf("FXOS8700Q accelerometer = 0x%X\n", sen_acc.whoAmI());
screamer 1:42d51cf7cebe 136 printf("FXOS8700Q magnetometer = 0x%X\n", sen_mag.whoAmI());
screamer 1:42d51cf7cebe 137
screamer 1:42d51cf7cebe 138 printf("\n"); ;
screamer 1:42d51cf7cebe 139 }
screamer 1:42d51cf7cebe 140
screamer 1:42d51cf7cebe 141 /**
screamer 1:42d51cf7cebe 142 * Update sensors and report their values.
screamer 1:42d51cf7cebe 143 * This function is called periodically.
screamer 1:42d51cf7cebe 144 */
screamer 1:42d51cf7cebe 145 void sensors_update() {
screamer 1:42d51cf7cebe 146 motion_data_counts_t acc_raw, mag_raw;
screamer 1:42d51cf7cebe 147
screamer 1:42d51cf7cebe 148 printf(" \n");
screamer 1:42d51cf7cebe 149
screamer 1:42d51cf7cebe 150 sen_acc.getAxis(acc_raw);
screamer 1:42d51cf7cebe 151 sen_mag.getAxis(mag_raw);
screamer 1:42d51cf7cebe 152
screamer 1:42d51cf7cebe 153 printf("FXOS8700Q mag: %7ld x, %7ld y, %7ld z [mgauss] \n", mag_raw.x, mag_raw.y, mag_raw.z);
screamer 1:42d51cf7cebe 154 printf("FXOS8700Q acc: %7ld x, %7ld y, %7ld z [mg] \n", acc_raw.x, acc_raw.y, acc_raw.z);
screamer 1:42d51cf7cebe 155
screamer 1:42d51cf7cebe 156 printf("\r\033[3A");
screamer 1:42d51cf7cebe 157
screamer 1:42d51cf7cebe 158 if (endpointInfo) {
screamer 1:42d51cf7cebe 159 #ifdef SEND_ALL_SENSORS
screamer 1:42d51cf7cebe 160 res_magnometer_x->set_value((int)mag_raw.x);
screamer 1:42d51cf7cebe 161 res_magnometer_y->set_value((int)mag_raw.y);
screamer 1:42d51cf7cebe 162 res_magnometer_z->set_value((int)mag_raw.z);
screamer 1:42d51cf7cebe 163 res_accelerometer_x->set_value((int)acc_raw.x);
screamer 1:42d51cf7cebe 164 res_accelerometer_y->set_value((int)acc_raw.y);
screamer 1:42d51cf7cebe 165 res_accelerometer_z->set_value((int)acc_raw.z);
screamer 1:42d51cf7cebe 166 #endif /* SEND_ALL_SENSORS */
screamer 1:42d51cf7cebe 167 }
screamer 1:42d51cf7cebe 168 }
screamer 1:42d51cf7cebe 169
screamer 0:a9d53048f0b6 170 int main(void) {
screamer 0:a9d53048f0b6 171 printf("\nStarting Simple Pelion Device Management Client example\n");
screamer 0:a9d53048f0b6 172
screamer 0:a9d53048f0b6 173 #if USE_BUTTON == 1
screamer 0:a9d53048f0b6 174 // If the User button is pressed ons start, then format storage.
screamer 0:a9d53048f0b6 175 if (button.read() == MBED_CONF_APP_BUTTON_PRESSED_STATE) {
screamer 0:a9d53048f0b6 176 printf("User button is pushed on start. Formatting the storage...\n");
screamer 0:a9d53048f0b6 177 int storage_status = StorageHelper::format(&fs, bd);
screamer 0:a9d53048f0b6 178 if (storage_status != 0) {
screamer 0:a9d53048f0b6 179 printf("ERROR: Failed to reformat the storage (%d).\n", storage_status);
screamer 0:a9d53048f0b6 180 }
screamer 0:a9d53048f0b6 181 } else {
screamer 0:a9d53048f0b6 182 printf("You can hold the user button during boot to format the storage and change the device identity.\n");
screamer 0:a9d53048f0b6 183 }
screamer 0:a9d53048f0b6 184 #endif /* USE_BUTTON */
screamer 0:a9d53048f0b6 185
screamer 1:42d51cf7cebe 186 sensors_init();
screamer 1:42d51cf7cebe 187
screamer 0:a9d53048f0b6 188 // Connect to the Internet (DHCP is expected to be on)
screamer 0:a9d53048f0b6 189 printf("Connecting to the network using the default network interface...\n");
screamer 0:a9d53048f0b6 190 net = NetworkInterface::get_default_instance();
screamer 0:a9d53048f0b6 191
screamer 0:a9d53048f0b6 192 nsapi_error_t net_status = NSAPI_ERROR_NO_CONNECTION;
screamer 0:a9d53048f0b6 193 while ((net_status = net->connect()) != NSAPI_ERROR_OK) {
screamer 0:a9d53048f0b6 194 printf("Unable to connect to network (%d). Retrying...\n", net_status);
screamer 0:a9d53048f0b6 195 }
screamer 0:a9d53048f0b6 196
screamer 0:a9d53048f0b6 197 printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
screamer 0:a9d53048f0b6 198
screamer 0:a9d53048f0b6 199 printf("Initializing Pelion Device Management Client...\n");
screamer 0:a9d53048f0b6 200
screamer 0:a9d53048f0b6 201 // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
screamer 0:a9d53048f0b6 202 SimpleMbedCloudClient client(net, bd, &fs);
screamer 0:a9d53048f0b6 203 int client_status = client.init();
screamer 0:a9d53048f0b6 204 if (client_status != 0) {
screamer 0:a9d53048f0b6 205 printf("Pelion Client initialization failed (%d)\n", client_status);
screamer 0:a9d53048f0b6 206 return -1;
screamer 0:a9d53048f0b6 207 }
screamer 0:a9d53048f0b6 208
screamer 0:a9d53048f0b6 209 // Creating resources, which can be written or read from the cloud
screamer 0:a9d53048f0b6 210 button_res = client.create_resource("3200/0/5501", "button_count");
screamer 0:a9d53048f0b6 211 button_res->set_value(0);
screamer 0:a9d53048f0b6 212 button_res->methods(M2MMethod::GET);
screamer 0:a9d53048f0b6 213 button_res->observable(true);
screamer 0:a9d53048f0b6 214 button_res->attach_notification_callback(button_callback);
screamer 0:a9d53048f0b6 215
screamer 0:a9d53048f0b6 216 led_res = client.create_resource("3201/0/5853", "led_state");
screamer 0:a9d53048f0b6 217 led_res->set_value(led.read());
screamer 0:a9d53048f0b6 218 led_res->methods(M2MMethod::GET | M2MMethod::PUT);
screamer 0:a9d53048f0b6 219 led_res->attach_put_callback(put_callback);
screamer 0:a9d53048f0b6 220
screamer 0:a9d53048f0b6 221 post_res = client.create_resource("3300/0/5605", "execute_function");
screamer 0:a9d53048f0b6 222 post_res->methods(M2MMethod::POST);
screamer 0:a9d53048f0b6 223 post_res->attach_post_callback(post_callback);
screamer 0:a9d53048f0b6 224
screamer 0:a9d53048f0b6 225 printf("Initialized Pelion Device Management Client. Registering...\n");
screamer 0:a9d53048f0b6 226
screamer 0:a9d53048f0b6 227 // Callback that fires when registering is complete
screamer 0:a9d53048f0b6 228 client.on_registered(&registered);
screamer 0:a9d53048f0b6 229
screamer 0:a9d53048f0b6 230 // Register with Pelion DM
screamer 0:a9d53048f0b6 231 client.register_and_connect();
screamer 0:a9d53048f0b6 232
screamer 0:a9d53048f0b6 233 // The button fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
screamer 0:a9d53048f0b6 234 button.fall(eventQueue.event(&button_press));
screamer 0:a9d53048f0b6 235 printf("Press the user button to increment the LwM2M resource value...\n");
screamer 1:42d51cf7cebe 236
screamer 0:a9d53048f0b6 237 // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
screamer 0:a9d53048f0b6 238 Ticker timer;
screamer 1:42d51cf7cebe 239 timer.attach(eventQueue.event(&sensors_update), SENSORS_POLL_INTERVAL);
screamer 0:a9d53048f0b6 240
screamer 0:a9d53048f0b6 241 // You can easily run the eventQueue in a separate thread if required
screamer 0:a9d53048f0b6 242 eventQueue.dispatch_forever();
screamer 0:a9d53048f0b6 243 }
screamer 0:a9d53048f0b6 244
screamer 0:a9d53048f0b6 245 #endif /* MBED_TEST_MODE */