sample_pir-lights_rgb

Dependencies:   ChainableLED

Committer:
iv123
Date:
Sun Jun 18 10:14:56 2017 +0000
Revision:
0:7a352727249b
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
iv123 0:7a352727249b 1 # Adding connectivity
iv123 0:7a352727249b 2
iv123 0:7a352727249b 3 Now that we've built our basic circuit and wrote the code to control that circuit, we can start adding connectivity to the project. Part of the ARM mbed IoT Device Platform is mbed Device Connector, a unified solution to connect devices to the internet and communicate with them regardless of *how* these devices connect to the internet. There are libraries available for a variety of connectivity methods, including Ethernet, Wi-Fi, 6LoWPAN, Thread and Cellular.
iv123 0:7a352727249b 4
iv123 0:7a352727249b 5 ## Obtaining a device certificate
iv123 0:7a352727249b 6
iv123 0:7a352727249b 7 All data that goes from the device to mbed Device Connector (and vice-versa) is end-to-end encrypted by [mbed TLS](https://tls.mbed.org). To set up secure communications we need a security certificate. We can get one from the mbed Device Connector website:
iv123 0:7a352727249b 8
iv123 0:7a352727249b 9 1. Go to the [mbed Device Connector homepage](https://connector.mbed.com) and click *Sign in to get connected*.
iv123 0:7a352727249b 10 1. If prompted for your login credentials, use your mbed developer account (the same account you use to log into the mbed Online Compiler).
iv123 0:7a352727249b 11 1. Go to *My Devices* > *Security Credentials*.
iv123 0:7a352727249b 12 1. Click *Get my security credentials*.
iv123 0:7a352727249b 13 1. Copy the contents of the gray box. This is your certificate.
iv123 0:7a352727249b 14
iv123 0:7a352727249b 15 <span class="images">![The certificate is located in the gray box](assets/lights16.png)</span>
iv123 0:7a352727249b 16
iv123 0:7a352727249b 17 1. Go back to the online compiler.
iv123 0:7a352727249b 18 1. Create a new file ``security.h`` in your application's ``source`` directory.
iv123 0:7a352727249b 19 1. Paste the certificate into this file.
iv123 0:7a352727249b 20
iv123 0:7a352727249b 21 ## Adding connectivity to the board
iv123 0:7a352727249b 22
iv123 0:7a352727249b 23 ### Ethernet
iv123 0:7a352727249b 24
iv123 0:7a352727249b 25 If you have a development board that connects over Ethernet, just plug in an Ethernet cable. We’re assuming that the network has DHCP enabled and the firewall does not block connections to *http://connector.mbed.com*.
iv123 0:7a352727249b 26
iv123 0:7a352727249b 27 ### ESP8266 Wi-Fi module
iv123 0:7a352727249b 28
iv123 0:7a352727249b 29 To wire the ESP8266 module up to your development board, look at the [ESP8266 Cookbook page](https://developer.mbed.org/users/4180_1/notebook/using-the-esp8266-with-the-mbed-lpc1768/). Broadly, this means hooking up the ESP8266's TX pin to `D0` and RX pin to `D1`.
iv123 0:7a352727249b 30
iv123 0:7a352727249b 31 <span class="notes">**Note about ESP8266 on NUCLEO boards:** On the NUCLEO boards pins `D0` and `D1` are used for serial communication with the computer. Use pins `D8` and `D2` instead.</span>
iv123 0:7a352727249b 32
iv123 0:7a352727249b 33 ### 6LoWPAN
iv123 0:7a352727249b 34
iv123 0:7a352727249b 35 First connect your 6LoWPAN gateway to an IPv6-enabled network by following the steps under 'Gateway Configuration' on [this page](https://github.com/ARMmbed/mbed-client-example-6lowpan#gateway-configuration).
iv123 0:7a352727249b 36
iv123 0:7a352727249b 37 Then attach the 6LoWPAN shield to the top of your development board.
iv123 0:7a352727249b 38
iv123 0:7a352727249b 39 ## Adding libraries with the online compiler
iv123 0:7a352727249b 40
iv123 0:7a352727249b 41 For the device and mbed Device Connector to talk we need the [mbed Client library](https://docs.mbed.com/docs/mbed-client-guide/en/latest/). This library is already included in mbed OS, and is very powerful, but can also be daunting for new users. In this example we'll use an additional library built on top of mbed Client: SimpleClient. This library is designed to easily expose variables and resources to the cloud.
iv123 0:7a352727249b 42
iv123 0:7a352727249b 43 We will also use [EasyConnect](https://github.com/ARMmbed/easy-connect) to handle connectivity.
iv123 0:7a352727249b 44
iv123 0:7a352727249b 45 To add these libraries to your project:
iv123 0:7a352727249b 46
iv123 0:7a352727249b 47 1. Go back to the online compiler.
iv123 0:7a352727249b 48 1. Right click on your program in the tree and select *Import Library* > *From URL*.
iv123 0:7a352727249b 49 1. Under *Source URL* enter: ``https://github.com/armmbed/easy-connect``.
iv123 0:7a352727249b 50 1. Do **not** tick 'Update all sub-libraries to the latest version'.
iv123 0:7a352727249b 51 1. Click *Import*.
iv123 0:7a352727249b 52 1. Again, right click on your program and select *Import Library* > *From URL*.
iv123 0:7a352727249b 53 1. Under *Source URL* enter: ``https://developer.mbed.org/teams/sandbox/code/simple-mbed-client/``.
iv123 0:7a352727249b 54 1. Click *Import*.
iv123 0:7a352727249b 55
iv123 0:7a352727249b 56 ## Adding libraries with mbed CLI
iv123 0:7a352727249b 57
iv123 0:7a352727249b 58 If you are using mbed CLI, run the following commands to add the libraries:
iv123 0:7a352727249b 59
iv123 0:7a352727249b 60 ```bash
iv123 0:7a352727249b 61 $ mbed add easy-connect
iv123 0:7a352727249b 62 $ mbed add http://developer.mbed.org/teams/sandbox/code/simple-mbed-client/
iv123 0:7a352727249b 63 ```
iv123 0:7a352727249b 64
iv123 0:7a352727249b 65 ## Updating configuration
iv123 0:7a352727249b 66
iv123 0:7a352727249b 67 We need to tell EasyConnect which connectivity method to use. Open ``mbed_app.json`` and locate the `network-interface` field. Change the `value` to the connectivity method used:
iv123 0:7a352727249b 68
iv123 0:7a352727249b 69 ```json
iv123 0:7a352727249b 70 /* mbed_app.json */
iv123 0:7a352727249b 71
iv123 0:7a352727249b 72 /* snip */
iv123 0:7a352727249b 73
iv123 0:7a352727249b 74 "network-interface":{
iv123 0:7a352727249b 75 "help": "options are ETHERNET,WIFI_ESP8266,MESH_LOWPAN_ND,MESH_THREAD",
iv123 0:7a352727249b 76 "value": "ETHERNET"
iv123 0:7a352727249b 77 },
iv123 0:7a352727249b 78 "esp8266-tx": {
iv123 0:7a352727249b 79 "help": "Pin used as TX (connects to ESP8266 RX)",
iv123 0:7a352727249b 80 "value": "D1"
iv123 0:7a352727249b 81 },
iv123 0:7a352727249b 82 "esp8266-rx": {
iv123 0:7a352727249b 83 "help": "Pin used as RX (connects to ESP8266 TX)",
iv123 0:7a352727249b 84 "value": "D0"
iv123 0:7a352727249b 85 },
iv123 0:7a352727249b 86 "esp8266-ssid": {
iv123 0:7a352727249b 87 "value": "\"SSID\""
iv123 0:7a352727249b 88 },
iv123 0:7a352727249b 89 "esp8266-password": {
iv123 0:7a352727249b 90 "value": "\"Password\""
iv123 0:7a352727249b 91 },
iv123 0:7a352727249b 92 "esp8266-debug": {
iv123 0:7a352727249b 93 "value": true
iv123 0:7a352727249b 94 }
iv123 0:7a352727249b 95 }
iv123 0:7a352727249b 96
iv123 0:7a352727249b 97 /* snip */
iv123 0:7a352727249b 98 ```
iv123 0:7a352727249b 99
iv123 0:7a352727249b 100 If you:
iv123 0:7a352727249b 101
iv123 0:7a352727249b 102 * Are using Wi-Fi: also set your Wi-Fi SSID and your password.
iv123 0:7a352727249b 103 * Used pins other than `D0`/`D1`: also change the pin names.
iv123 0:7a352727249b 104
iv123 0:7a352727249b 105 ## Writing code
iv123 0:7a352727249b 106
iv123 0:7a352727249b 107 ### Setting up a connection
iv123 0:7a352727249b 108
iv123 0:7a352727249b 109 We need to add some code to the application so it connects to the internet and sets up a connection to mbed Device Connector.
iv123 0:7a352727249b 110
iv123 0:7a352727249b 111 Replace ``main.cpp`` with:
iv123 0:7a352727249b 112
iv123 0:7a352727249b 113 ```cpp
iv123 0:7a352727249b 114 #include "mbed.h"
iv123 0:7a352727249b 115 #include "led.h" // Abstracts away the differens between the LED types
iv123 0:7a352727249b 116 #include "security.h" // Security configuration
iv123 0:7a352727249b 117 #include "easy-connect.h"
iv123 0:7a352727249b 118 #include "simple-mbed-client.h"
iv123 0:7a352727249b 119
iv123 0:7a352727249b 120 EventQueue eventQueue; // An event queue
iv123 0:7a352727249b 121 Thread eventThread; // An RTOS thread to process events in
iv123 0:7a352727249b 122
iv123 0:7a352727249b 123 SimpleMbedClient client;
iv123 0:7a352727249b 124
iv123 0:7a352727249b 125 // PIR sensor acts as an interrupt - signals us whenever it goes high (or low)
iv123 0:7a352727249b 126 InterruptIn pir(PIR_PIN); // This pin value comes out mbed_app.json
iv123 0:7a352727249b 127
iv123 0:7a352727249b 128
iv123 0:7a352727249b 129 // YOUR CODE HERE
iv123 0:7a352727249b 130 void pir_rise() { }
iv123 0:7a352727249b 131 // END OF YOUR CODE HERE
iv123 0:7a352727249b 132
iv123 0:7a352727249b 133 // Use the built-in LED as a status LED
iv123 0:7a352727249b 134 DigitalOut statusLed(LED1);
iv123 0:7a352727249b 135 int statusLedBlinkId; // Callback ID
iv123 0:7a352727249b 136 void blink_builtin_led() {
iv123 0:7a352727249b 137 statusLed = !statusLed;
iv123 0:7a352727249b 138 }
iv123 0:7a352727249b 139
iv123 0:7a352727249b 140 void registered() {
iv123 0:7a352727249b 141 // When we registered with mbed Device Connector, blink faster
iv123 0:7a352727249b 142 eventQueue.cancel(statusLedBlinkId);
iv123 0:7a352727249b 143
iv123 0:7a352727249b 144 statusLedBlinkId = eventQueue.call_every(300, &blink_builtin_led);
iv123 0:7a352727249b 145 }
iv123 0:7a352727249b 146
iv123 0:7a352727249b 147 int main(int, char**) {
iv123 0:7a352727249b 148 // Using an event queue is a very useful abstraction around many microcontroller 'problems', like dealing with ISRs
iv123 0:7a352727249b 149 // see https://developer.mbed.org/blog/entry/Simplify-your-code-with-mbed-events/
iv123 0:7a352727249b 150 eventThread.start(callback(&eventQueue, &EventQueue::dispatch_forever));
iv123 0:7a352727249b 151
iv123 0:7a352727249b 152 // Blink the built-in LED every 1000ms. After registering we'll blink every 300ms.
iv123 0:7a352727249b 153 statusLedBlinkId = eventQueue.call_every(1000, &blink_builtin_led);
iv123 0:7a352727249b 154
iv123 0:7a352727249b 155 // Disable the LED
iv123 0:7a352727249b 156 setRgbColor(0.0f, 0.0f, 0.0f);
iv123 0:7a352727249b 157
iv123 0:7a352727249b 158 // The PIR sensor uses interrupts, no need to poll
iv123 0:7a352727249b 159 pir.rise(eventQueue.event(&pir_rise));
iv123 0:7a352727249b 160
iv123 0:7a352727249b 161 NetworkInterface* network = easy_connect(true);
iv123 0:7a352727249b 162 if (!network) {
iv123 0:7a352727249b 163 printf("Connect to internet failed... See serial output.\r\n");
iv123 0:7a352727249b 164 return 1;
iv123 0:7a352727249b 165 }
iv123 0:7a352727249b 166
iv123 0:7a352727249b 167 struct MbedClientOptions options = client.get_default_options();
iv123 0:7a352727249b 168 options.DeviceType = "light-system";
iv123 0:7a352727249b 169 if (!client.setup(options, network)) {
iv123 0:7a352727249b 170 printf("Setting up mbed_client failed...\r\n");
iv123 0:7a352727249b 171 return 1;
iv123 0:7a352727249b 172 }
iv123 0:7a352727249b 173
iv123 0:7a352727249b 174 client.on_registered(eventQueue.event(&registered));
iv123 0:7a352727249b 175
iv123 0:7a352727249b 176 // We can just let the main thread end here, no need to busy-loop
iv123 0:7a352727249b 177 }
iv123 0:7a352727249b 178 ```
iv123 0:7a352727249b 179
iv123 0:7a352727249b 180 ### Program logic
iv123 0:7a352727249b 181
iv123 0:7a352727249b 182 The code sample above does not do much, except for setting up the connection. We can now define some logic for this program:
iv123 0:7a352727249b 183
iv123 0:7a352727249b 184 1. The color of the LED should be configurable.
iv123 0:7a352727249b 185 1. The period between the moment of motion detection to the moment lights go out should be configurable.
iv123 0:7a352727249b 186 1. There should be a permanent-on mode for the lights.
iv123 0:7a352727249b 187 1. We should notify mbed Device Connector whenever we detect movement.
iv123 0:7a352727249b 188
iv123 0:7a352727249b 189 We can implement these actions by defining *resources*: pieces of information the device makes available. We can read or write to them from the cloud, and the device can use a resource's value to determine the correct action to perform. We can reach a resource with a URI and access modifier (for example, only write allowed), and we can also subscribe to them, so we'll be notified when a resource changes.
iv123 0:7a352727249b 190
iv123 0:7a352727249b 191 Let's define a resource for each of our actions:
iv123 0:7a352727249b 192
iv123 0:7a352727249b 193 * `led/0/color` - the color of the LED.
iv123 0:7a352727249b 194 * `led/0/timeout` - the timeout (in seconds) after detection; lights are disabled when this period ends.
iv123 0:7a352727249b 195 * `led/0/permanent_status` - whether we should have the lights permanently on (or off).
iv123 0:7a352727249b 196 * `pir/0/count` - the number of times the PIR sensor was triggered. Read only, and should allow notifications.
iv123 0:7a352727249b 197
iv123 0:7a352727249b 198 We can use SimpleClient to define these resources and attach actions to each resource.
iv123 0:7a352727249b 199
iv123 0:7a352727249b 200 Replace the following section in ``main.cpp``:
iv123 0:7a352727249b 201
iv123 0:7a352727249b 202 ```cpp
iv123 0:7a352727249b 203 // YOUR CODE HERE
iv123 0:7a352727249b 204 void pir_rise() { }
iv123 0:7a352727249b 205 // END OF YOUR CODE HERE
iv123 0:7a352727249b 206 ```
iv123 0:7a352727249b 207
iv123 0:7a352727249b 208 with (comments inline):
iv123 0:7a352727249b 209
iv123 0:7a352727249b 210 ```cpp
iv123 0:7a352727249b 211 // Fwd declaration
iv123 0:7a352727249b 212 void putLightsOn();
iv123 0:7a352727249b 213 void colorChanged(int newColor);
iv123 0:7a352727249b 214
iv123 0:7a352727249b 215 // Variable that holds whether the light is on because the PIR sensor triggered (and timeout didn't happen yet)
iv123 0:7a352727249b 216 bool ledOnBecauseOfPir = false;
iv123 0:7a352727249b 217
iv123 0:7a352727249b 218 // Timeout based on led/0/timeout, disables the light after a set interval
iv123 0:7a352727249b 219 Timeout pirTimeout;
iv123 0:7a352727249b 220
iv123 0:7a352727249b 221 // Permanent statuses (set by led/0/permanent_status)
iv123 0:7a352727249b 222 #define STATUS_NONE 0
iv123 0:7a352727249b 223 #define STATUS_ON 1
iv123 0:7a352727249b 224 #define STATUS_OFF 2
iv123 0:7a352727249b 225
iv123 0:7a352727249b 226 // clear the lights
iv123 0:7a352727249b 227 void putLightsOff() {
iv123 0:7a352727249b 228 setRgbColor(0.0f, 0.0f, 0.0f);
iv123 0:7a352727249b 229 }
iv123 0:7a352727249b 230
iv123 0:7a352727249b 231 // Status changes
iv123 0:7a352727249b 232 void statusChanged(int newStatus) {
iv123 0:7a352727249b 233 switch (newStatus) {
iv123 0:7a352727249b 234 case STATUS_ON: // Permanently on? OK.
iv123 0:7a352727249b 235 putLightsOn();
iv123 0:7a352727249b 236 break;
iv123 0:7a352727249b 237 case STATUS_NONE: // Otherwise listen to PIR sensor
iv123 0:7a352727249b 238 case STATUS_OFF: // Or be off forever
iv123 0:7a352727249b 239 putLightsOff();
iv123 0:7a352727249b 240 break;
iv123 0:7a352727249b 241 }
iv123 0:7a352727249b 242 }
iv123 0:7a352727249b 243
iv123 0:7a352727249b 244 // Here are our resources:
iv123 0:7a352727249b 245 // We encode color in 3 bytes [R, G, B] and put it in an integer by providing the color as an hex value (default color: green)
iv123 0:7a352727249b 246 SimpleResourceInt ledColor = client.define_resource("led/0/color", 0x00ff00, &colorChanged);
iv123 0:7a352727249b 247 SimpleResourceInt ledTimeout = client.define_resource("led/0/timeout", 5);
iv123 0:7a352727249b 248 SimpleResourceInt ledStatus = client.define_resource("led/0/permanent_status", STATUS_NONE, &statusChanged);
iv123 0:7a352727249b 249 SimpleResourceInt pirCount = client.define_resource("pir/0/count", 0, M2MBase::GET_ALLOWED);
iv123 0:7a352727249b 250
iv123 0:7a352727249b 251 // As said above, color is encoded in three bytes
iv123 0:7a352727249b 252 void putLightsOn() {
iv123 0:7a352727249b 253 // parse the individual channels
iv123 0:7a352727249b 254 int redCh = ledColor >> 16 & 0xff;
iv123 0:7a352727249b 255 int greenCh = ledColor >> 8 & 0xff;
iv123 0:7a352727249b 256 int blueCh = ledColor & 0xff;
iv123 0:7a352727249b 257
iv123 0:7a352727249b 258 // our color is 0..255, but we need a float between 0..1, cast it.
iv123 0:7a352727249b 259 float red = static_cast<float>(redCh) / 255.0f;
iv123 0:7a352727249b 260 float green = static_cast<float>(greenCh) / 255.0f;
iv123 0:7a352727249b 261 float blue = static_cast<float>(blueCh) / 255.0f;
iv123 0:7a352727249b 262 setRgbColor(red, green, blue);
iv123 0:7a352727249b 263 }
iv123 0:7a352727249b 264
iv123 0:7a352727249b 265 // Color updated from the cloud,
iv123 0:7a352727249b 266 // if the LED is on because of the PIR, or if the LED is on permanently -> Set the color.
iv123 0:7a352727249b 267 void colorChanged(int newColor) {
iv123 0:7a352727249b 268 if (ledOnBecauseOfPir || ledStatus == STATUS_ON) {
iv123 0:7a352727249b 269 putLightsOn();
iv123 0:7a352727249b 270 }
iv123 0:7a352727249b 271 }
iv123 0:7a352727249b 272
iv123 0:7a352727249b 273 // Timeout (from led/0/timeout) happened after PIR sensor was triggered...
iv123 0:7a352727249b 274 void onPirTimeout() {
iv123 0:7a352727249b 275 // if we're not permanent on
iv123 0:7a352727249b 276 if (ledStatus != STATUS_ON) {
iv123 0:7a352727249b 277 // clear the lights
iv123 0:7a352727249b 278 putLightsOff();
iv123 0:7a352727249b 279
iv123 0:7a352727249b 280 ledOnBecauseOfPir = false;
iv123 0:7a352727249b 281 }
iv123 0:7a352727249b 282 }
iv123 0:7a352727249b 283
iv123 0:7a352727249b 284 // When the PIR sensor fires...
iv123 0:7a352727249b 285 void pir_rise() {
iv123 0:7a352727249b 286 // Update the resource
iv123 0:7a352727249b 287 pirCount = pirCount + 1;
iv123 0:7a352727249b 288
iv123 0:7a352727249b 289 // Permanent off? Don't put the lights on...
iv123 0:7a352727249b 290 if (ledStatus == STATUS_OFF) return;
iv123 0:7a352727249b 291
iv123 0:7a352727249b 292 // Otherwise do it!
iv123 0:7a352727249b 293 ledOnBecauseOfPir = true;
iv123 0:7a352727249b 294 putLightsOn();
iv123 0:7a352727249b 295
iv123 0:7a352727249b 296 // And attach the timeout
iv123 0:7a352727249b 297 pirTimeout.attach(eventQueue.event(&onPirTimeout), static_cast<float>(ledTimeout));
iv123 0:7a352727249b 298 }
iv123 0:7a352727249b 299 ```
iv123 0:7a352727249b 300
iv123 0:7a352727249b 301 When you compile and flash this program, you'll see that when you wave your hand in front of the PIR sensor the color of the LED changes to green, and the LED always goes off after 5 seconds.
iv123 0:7a352727249b 302
iv123 0:7a352727249b 303 When the connection to mbed Device Connector is created, the onboard LED will blink faster. We can now control this device from the cloud.
iv123 0:7a352727249b 304
iv123 0:7a352727249b 305 <span class="notes">**Note:** No connection? [Inspect the logs on the device](https://developer.mbed.org/handbook/SerialPC#host-interface-and-terminal-applications).</span>
iv123 0:7a352727249b 306