├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── doc ├── README.md ├── connectivity.md ├── data-handling.md ├── local-device-setup.md ├── mesh.md ├── powering-projects.md ├── sleep-modes.md ├── system-thread.md └── workbench.md └── examples ├── README.md ├── encryption └── aes256-encryption-01.ino └── power ├── get-power-status-argon-xenon-01.ino └── get-power-status-electron-boron-01.ino /.gitignore: -------------------------------------------------------------------------------- 1 | notes.md 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Dougal Campbell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Particle Cookbook 2 | 3 | * * * 4 | 5 | _A collection of programming snippets, tips, and tricks for developing with 6 | Particle IoT devices._ 7 | 8 | ## Devices 9 | 10 | The [Particle](https://particle.io/) ecosystem of devices along with their 11 | Particle Cloud platform make it simple for hobbyists and product developers 12 | to create connected projects. Their product line currently includes: 13 | 14 | - **Wifi**: Core, Photon, Argon 15 | 16 | - **Cellular:** (2G/3G/LTE): Electron, Boron 17 | 18 | - **Mesh:** (based on IEEE 802.15.4-2006): Xenon, Argon, Boron 19 | 20 | - **Bluetooth:** RedBear Duo, RedBear Nano, Xenon, Argon, Boron 21 | 22 | _The RedBear product line is still available for sale, but it is unclear 23 | whether Particle will continue to develop or support them._ 24 | 25 | _Particle Mesh devices are capable of supporting Bluetooth 5, but the 26 | software APIs are still under development as of January 2019._ 27 | 28 | ## Development Tools 29 | 30 | Particle provides many excellent tools for developing software for their 31 | devices, including a browser-based [Web IDE](https://build.particle.io/), 32 | [Particle Workbench](https://www.particle.io/workbench) (an IDE built on 33 | Microsoft Visual Studio Code), and [Particle 34 | CLI](https://docs.particle.io/tutorials/developer-tools/cli/) (a 35 | command-line experience). 36 | 37 | Particle Workbench allows you to build and flash firmware locally, for 38 | Windows, Mac, and Linux, and Particle CLI is an excellent tool for building 39 | firmware or managing your Particle devices. 40 | 41 | You can choose to install and use Particle's Device OS toolchain directly if 42 | you wish by [setting up the environment 43 | manually](https://docs.particle.io/support/particle-tools-faq/local-build/), 44 | or by using a third-party utility like [po-util](https://po-util.com). 45 | 46 | Particle has a [detailed 47 | documentation](https://docs.particle.io/reference/device-os/firmware) of the 48 | firmware libraries, tutorials, and sample code, which covers most anything 49 | you need to know, and the [community forums](https://community.particle.io/) 50 | are a great resource when you have questions. If you have a question about 51 | how to hook up some odd sensor, or how to use a certain code library, send 52 | data to a third-party service, or just about anything really, you'll often 53 | find the answer in the forums. 54 | 55 | In fact, the forums are chock-full of great information, tips, little-known 56 | facts, pointers to other tools, etc. So full, that it can be overwhelming. 57 | Sometimes when you have a problem, you aren't even sure what to search for. 58 | And _sometimes_, you don't even know that a feature exists, because you've 59 | just never run across it before. 60 | 61 | ## Purpose 62 | 63 | This Cookbook is an attempt to address this problem by collecting and 64 | (hopefully) organizing some of these hidden gems so that you don't have to 65 | waste time searching through the forums, trying to filter out tons of 66 | unanswered questions, or long threads that touch on a topic, then spin off 67 | in another direction, or trying to piece together bits of the technically 68 | excellent firmware documentation into a code example that works for your 69 | particular, unusual use-case. 70 | 71 | ## Topics 72 | 73 | - [Data Handling](doc/data-handling.md) 74 | - [Local Mesh Device Setup](doc/local-device-setup.md) 75 | - [Mesh](doc/mesh.md) 76 | - [Particle Workbench](doc/workbench.md) 77 | - [Powering Projects](doc/powering-projects.md) 78 | - [Sleep Modes](doc/sleep-modes.md) 79 | - [System Thread](doc/system-thread.md) 80 | 81 | ## See Also: 82 | [github.com/rickkas7](https://github.com/rickkas7) Particle Technical Documentation Writer @rickkas7 has several good tutorials 83 | and example code in his Github. 84 | 85 | [Awesome Particle](https://github.com/particle-iot/awesome-particle) is a curated list of awesome things related to Particle. 86 | 87 | ## Contributions Welcome 88 | 89 | If you have suggestions, additions, corrections, complaints, or whatever, 90 | please feel free to let me know. Pull Requests welcome. For now, I'm just 91 | making this a collection of Markdown files, but I'm open to suggestions for 92 | other organizational schemes (wiki, CMS, category/tag hierarchies, ...). 93 | 94 | ## Credits 95 | 96 | The Particle Cookbook was originally created by [Dougal 97 | Campbell](@dougalcampbell). Fellow community member [Nathan 98 | Robinson](@nrobinson2000) quickly jumped in with typo fixes, formatting and 99 | organizational improvements, and the initial Github Pages implementation. 100 | And of course, this project wouldn't have happened without the invaluable 101 | information shared on the [Particle Community 102 | Forums](https://community.particle.io/) by countless other selfless 103 | contributors. Wherever possible, this Cookbook will link out to original 104 | source material, to give credit where credit is due. 105 | 106 | The original version of this project can be found at: 107 | 108 | https://github.com/dougalcampbell/particle-cookbook 109 | 110 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | ## Topics 2 | 3 | - [Data Handling](data-handling.md) 4 | - [Local Mesh Device Setup](local-device-setup.md) 5 | - [Mesh](mesh.md) 6 | - [Particle Workbench](workbench.md) 7 | - [Powering Projects](powering-projects.md) 8 | - [Sleep Modes](sleep-modes.md) 9 | - [System Thread](system-thread.md) 10 | 11 | * * * 12 | 13 | [<- Home](/particle-cookbook) 14 | -------------------------------------------------------------------------------- /doc/connectivity.md: -------------------------------------------------------------------------------- 1 | # Connectivity 2 | Connectivity is at the heart of the Particle family of devices. Whether or 3 | not you are using the Particle Cloud platform, the main advantage of these 4 | devices is their built-in, easy-to-use ability to communicate, whether by 5 | WiFi/Ethernet, Bluetooth, or Mesh protocols. 6 | 7 | Particle provides a lot of control over how devices use that connectivity, 8 | which makes this a very broad subject. 9 | 10 | 11 | ## PLACEHOLDER : TODO ## 12 | \[Editor Note: We might want to consider breaking these into separate 13 | sub-documents, like `connectivity-particle-cloud.md`, 14 | `connectivity-wifi.md`, etc.\] 15 | 16 | 17 | ## How do I control my connection to the network/cloud? 18 | A common question when working with Particle devices is "How can I prevent 19 | my device from automatically connecting to the Cloud/Wifi/Cellular when it 20 | first starts up? Not every project requires a network connection, or you 21 | might want to let your device check for certain conditions first, before 22 | it makes a connection. This behavior is controlled via the `SYSTEM_MODE` 23 | macro. There are three possible settings: `AUTOMATIC`, `SEMI_AUTOMATIC`, 24 | and `MANUAL`. 25 | 26 | `SYSTEM_MODE(AUTOMATIC)` is the default setting, which is the same as if 27 | you didn't specify a system mode at all. With this mode, your device will 28 | automatically attempt to connect to the local network and the Particle 29 | Cloud. 30 | 31 | `SYSTEM_MODE(SEMI_AUTOMATIC)` will automatically connect to the local network 32 | (WiFi, Cellular, or Mesh), but not to the Particle Cloud. You can manually 33 | connect and disconnect to the Cloud manually, if needed. 34 | 35 | `SYSTEM_MODE(MANUAL)` will not connect to anything automatically. If you need 36 | to connect to the local network or to the Cloud, you will have to manage the 37 | connection and disconnection manually. 38 | 39 | Note that this statement should be *outside* of your `setup()` and `loop()` 40 | functions. For example: 41 | 42 | /* My awesome project */ 43 | SYSTEM_MODE(SEMI_AUTOMATIC) 44 | 45 | setup() { 46 | // set up some stuff... 47 | } 48 | 49 | loop() { 50 | // do all the things... 51 | } 52 | 53 | 54 | ## Can I make my code run faster? 55 | The FreeRTOS system that underlies the Particle deviceOS is capable of using 56 | threading to manage multiple tasks at once. In deviceOS, we can use this to 57 | let the Particle networking management functions run in their own thread, 58 | instead of invisibly running as part of your user code thread. This can 59 | result in a speedup of up to about five times (depending on what other 60 | things are happening in your code). This is done with the `SYSTEM_THREAD` 61 | macro: 62 | 63 | `SYSTEM_THREAD(ENABLED)` 64 | 65 | Like `SYSTEM_MODE`, this statement should go outside of your `setup()` and 66 | `loop()` functions. 67 | 68 | Note that the use of `SYSTEM_THREAD` will cause certain other functions to 69 | behave in an asyncronous mode, will may require you to make some adjustments 70 | to your code. 71 | 72 | ## TODO: Explain async ## 73 | 74 | 75 | 76 | ## Particle Cloud 77 | 78 | ### Particle.publish() / Particle.subscribe() 79 | 80 | ### Particle.variable() 81 | 82 | ### Particle.function() 83 | 84 | ### Webhooks 85 | 86 | ### Local Cloud Server 87 | At one time, Particle maintained a project called [particle-iot/spark-server](https://github.com/particle-iot/spark-server), which let you host your own 88 | local cloud server. They have not updated the codebase since 2015. However, 89 | community member @Brewskey maintains his own fork, [Brewskey/spark-server](https://github.com/Brewskey/spark-server), 90 | which you can use. Be sure to read the docs to learn what differences there 91 | might be between the official Cloud and the local server. 92 | 93 | 94 | ## WiFi 95 | 96 | 97 | ## Cellular 98 | 99 | 100 | ## Mesh 101 | 102 | 103 | ## TCPClient 104 | 105 | 106 | ## UDP 107 | 108 | 109 | ## Serial 110 | 111 | 112 | ## ?? MQTT ?? 113 | \[Maybe include info about MQTT here? But there might be a better parent 114 | topic for it later.\] 115 | 116 | 117 | 118 | --- 119 | [<- Home](/particle-cookbook) 120 | -------------------------------------------------------------------------------- /doc/data-handling.md: -------------------------------------------------------------------------------- 1 | # Data Handling 2 | Tips on how to format and parse data. 3 | 4 | ## Generating and Parson JSON 5 | Try the [`JsonParserGeneratorRK`](https://build.particle.io/libs/JsonParserGeneratorRK/0.0.6/) library for sending or receiving JSON data. 6 | 7 | There is also the [`JsonStreamingParser`](https://build.particle.io/libs/JsonStreamingParser/1.0.5/) library, 8 | which might be useful if you need to extract data from a large JSON response. 9 | 10 | 11 | ## Avoid the `String` class and string concatenation 12 | When possible, avoid using the `String` class or string concatenation (with 13 | or without the class). The use of strings requires dynamic memory allocation, 14 | which can fragment the available memory. Instead, try to use functions like 15 | `snprintf()` with one large format string. 16 | 17 | 18 | --- 19 | [<- Home](/particle-cookbook) 20 | -------------------------------------------------------------------------------- /doc/local-device-setup.md: -------------------------------------------------------------------------------- 1 | # Setup a New Mesh Device Locally 2 | --- 3 | 4 | The usual method for setting up a new Particle device is to use the Particle 5 | mobile app (iOS or Android). With the Mesh devices (Argon, Boron, and Xenon), 6 | this involves scanning a very small barcode from a label on the device. Some 7 | people have had problems with that step, because the camera on their phone 8 | just can't focus well enough at a close enough distance to decode the bar 9 | code. 10 | 11 | Luckily, it is possible to set up a device completely from a computer, using 12 | Particle Workbench (or po-util, or whatever local toolchain you prefer) to 13 | compile a new firmware, and the Particle CLI to claim it. 14 | 15 | 16 | ## Requirements 17 | * A Particle Cloud login account 18 | * Particle CLI version 1.40.0 or higher 19 | * Particle WorkBench, po-util, or other local build toolchain 20 | * DeviceOS 0.9.0 or higher 21 | 22 | To claim a Xenon, you will need a functioning Argon or Boron. This guide will 23 | start with instructions for setting up an Argon. 24 | 25 | 26 | ## Setting up an Argon 27 | First of all, make sure you have Particle CLI 1.40.0 or higher installed. 28 | If you already have the cli installed, you can check the version by running 29 | the command `particle --version` in your terminal. If you have an older 30 | version, the method for upgrading might vary, depending on how you originally 31 | installed it. You may need to download the newest installer from the Particle 32 | web site, or run the command `particle update-cli`, or perhaps run the 33 | command `npm install -g particle-cli`. 34 | 35 | Next, your device must have DeviceOS 0.9.0 or higher installed. At the time 36 | of this writing, chances are that your device has an older version installed. 37 | If so, you will need to compile a new firmware, and flash it to the the 38 | device with DFU. 39 | 40 | ### How to tell if you need to flash new firmware 41 | Unpack your Argon, place it on the breadboard, and attach the included 42 | antenna to the connector labeled `WIFI`. Connect it to your computer's USB 43 | port (it should begin blinking blue), and run the command `particle serial 44 | identify`. If this command returns an error, then your device needs to be 45 | upgraded. On my Mac, the error is `Could not identify device: No serial 46 | port identified`. If the identify command displays your Device ID and 47 | firmware version, then you should be able to skip the following update step, 48 | and proceed to `Connect to WiFi`. 49 | 50 | 51 | ### Update your device firmware and NCP 52 | If your device is not responding to the identify command, you will need to 53 | flash a new firmware with the deviceOS upgrade included. You can [download 54 | a stock hybrid firmware 55 | image](https://github.com/particle-iot/device-os/releases/tag/v0.9.0) from 56 | the Particle github, or build your own with Workbench. 57 | 58 | In either case, you will need to put your device into DFU mode. You do this 59 | by simultaneously pressing the RESET and MODE buttons, then release the 60 | RESET button, and continue holding MODE until the light changes from 61 | flashing magenta to flashing yellow, then release MODE. The device should 62 | continue flashing yellow. 63 | 64 | In Particle Workbench, you can start a project, set it to build with 65 | deviceOS 0.9.0, and select Argon as the target device. Then choose `Run 66 | Build Task...` from the `Terminal` menu, and select "Particle: Flash 67 | application & DeviceOS (local)". It shouldn't matter much what program you 68 | use to flash, it can just be the default empty file. Once the firmware has 69 | flashed, your device should return to flashing blue. In your terminal, you 70 | should be able to run the command `particle serial identify`, and it should 71 | return your device ID and new deviceOS version. 72 | 73 | It is possible that the first attempt to flash the firmware will fail. If 74 | so, just repeat the process, and it should succeed on the second try. 75 | 76 | The Argon (Argons only, not Borons or Xenons) will also require an update to 77 | the NCP (Network CoProcessor). [Download the Argon NCP OTA 78 | firmware](https://github.com/particle-iot/argon-ncp-firmware/releases/tag/v0.0.5) 79 | .bin file, then flash it do your Argon with the command `particle flash 80 | --serial argon-ncp-firmware-0.0.5-ota.bin`. Without this update, your device 81 | will be unable to properly connect to a WiFi network. 82 | 83 | You can read more information about updating the deviceOS and NCP [in the 84 | Particle Community Forums](https://community.particle.io/t/updated-3-21-19-gen-3-known-issues/45722/3). 85 | 86 | 87 | ### Connect to WiFi 88 | If you haven't already, take note of your Device ID. If you need to, run the 89 | `particle serial identify` command again to get it. Copy it into your 90 | computer clipboard, and maybe paste it into a text editor or notepad app for 91 | reference, if needed. We will need this ID in order to claim your device and 92 | set up devices on a mesh network and the Particle Cloud. 93 | 94 | With your deviceOS and NCP up-to-date, you are now ready to connect to the 95 | Internet. Use the command `particle serial wifi`, and follow the prompts to 96 | select your network, and provide login credentials. 97 | 98 | $ particle serial wifi 99 | ? Should I scan for nearby Wi-Fi networks? Yes 100 | ? Select the Wi-Fi network with which you wish to connect your device: myNetwork 101 | ? Should I try to auto-detect the wireless security type? Yes 102 | > Detected WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP) security 103 | ? Wi-Fi Password myWifiPassword 104 | Done! Your device should now restart. 105 | 106 | Your device should change from blinking blue to blinking green, to rapid 107 | flashing green, to flashing cyan, then finally to "breathing" cyan. This 108 | indicates that your device has a connection to the Particle Cloud. 109 | 110 | ### Claim your device 111 | Now that your device is online, you can claim it into your Particle account. 112 | Run the command `particle device add `, substituting your 113 | device ID. For example (not a real device id): 114 | 115 | $ particle device add d01c3e6h01bdh3h279c226af 116 | Claiming device d01c3e6h01bdh3h279c226af 117 | Successfully claimed device d01c3e6h01bdh3h279c226af 118 | 119 | ### Rename your device (optional) 120 | With your device claimed, you can give it a name which will be easier to 121 | remember, so that you don't have to keep using the long hashed Device ID. 122 | Use the `particle device rename` command: 123 | 124 | $ particle device rename d01c3e6h01bdh3h279c226af MyArgon01 125 | Renaming device d01c3e6h01bdh3h279c226af 126 | Successfully renamed device d01c3e6h01bdh3h279c226af to: MyArgon01 127 | 128 | From this point on, you should be able to use either the name or the ID in 129 | most particle CLI commands. 130 | 131 | ### Create a Mesh network 132 | At this point, you can create a new Mesh network with your Argon as its 133 | gateway device. You will provide a name for your network and the Argon's 134 | device ID: 135 | 136 | $ particle mesh create MyMeshNetwork MyArgon01 137 | ? Enter a password for the new network [hidden] 138 | ? Confirm the password [hidden] 139 | Done! The device will be registered in the network once it is connected to the cloud. 140 | 141 | Congratulations! Your Argon should now be completely setup, and ready to 142 | use. You can flash it OTA (Over-The-Air), communicate with the Particle Cloud, 143 | and add more devices to your Mesh network. 144 | 145 | 146 | --- 147 | [<- Home](/particle-cookbook) 148 | -------------------------------------------------------------------------------- /doc/mesh.md: -------------------------------------------------------------------------------- 1 | # Mesh 2 | --- 3 | 4 | ## Sample Code: MarcoPolo 5 | 6 | Forum user [@ninjatill](https://community.particle.io/u/ninjatill/summary) 7 | created a project called `Marco Polo` to help test the 8 | range and reliability of Particle Mesh devices. A gateway node publishes 9 | "Marco" events to the mesh network. The other nodes acknowledge with a "Polo" 10 | event and their Device IDs. The gateway gathers these responses, and publishes 11 | statistics to the Particle Cloud about the number of devices who responded, 12 | their response times, and other information. 13 | 14 | This code also shows good examples of handling Cloud disconnections and 15 | conditionally selecting to use the external mesh antenna. 16 | 17 | 18 | 19 | 20 | 21 | ## Xenon D5 Stays High? (Ethernet FeatherWing) 22 | If you have a Xenon that automatically pulls pin `D5` high at startup, it's 23 | probably because you used it with an Ethernet FeatherWing in the past. When 24 | a Xenon is configured to use an Ethernet FeatherWing, it will automatically 25 | pull pin `D5` high, because this is the Ethernet chip select signal for the 26 | FeatherWing. This is a setting stored in configuration flash, so it will 27 | continue doing this, even when the Xenon is removed from the FeatherWing 28 | board. 29 | 30 | To turn this behavior off, flash code which includes: 31 | 32 | System.disableFeature(FEATURE_ETHERNET_DETECTION) 33 | 34 | This will reset the setting in configuration flash. Once this code has run 35 | once, the setting will be reset, so you only need to do it once. You can 36 | then remove that code and flash other code normally. 37 | 38 | 39 | 40 | --- 41 | [<- Home](/particle-cookbook) 42 | -------------------------------------------------------------------------------- /doc/powering-projects.md: -------------------------------------------------------------------------------- 1 | # Powering Projects 2 | --- 3 | 4 | ## Powering Boron using 12v 5 | Though the data sheet for the Boron says that the maximum `Vin` voltage for 6 | the Boron is 6.2V, you can actually directly power it on the `VUSB` pin at 7 | 12V, or even as high as 16-17V. At higher voltages, you could run into heat 8 | problems, and you may need to limit charging current to the LiPo battery to 9 | 500ma. 10 | 11 | It is still recommended that you are not powering your device by battery, to 12 | use a converter to power the device at 5V, either by the `VUSB` pin, or the 13 | USB port. Also, you probably should not connect anything to the USB port if 14 | you are supplying power on `VUSB` (though, if you supply power via the USB 15 | port, you can use the `VUSB` pin to supply 5V power to other peripherals). 16 | 17 | **NOTE:** Boron only. Other devices use a different charging circuit. I 18 | recommend only using Particle's stated maximums for each device, unless 19 | you confirm for yourself that you can safely exceed those limits. 20 | 21 | 22 | 23 | ## Power conversion for automotive projects 24 | Many automotive projects can be powered by simply using a USB converter 25 | plugged into a power port (formerly known as the cigarette lighter). But 26 | if one of those ports isn't convenient, you may want to draw power from 27 | the car battery, either directly, or indirectly through a fuse, or other car 28 | wiring. However, the power environment in an automobile can be harsh -- 29 | there are power spikes/dropouts and noise to deal with. It is recommended 30 | that you use some sort of power conditioning when powering micro-controller 31 | projects. One such device is this step-down voltage regulator, found on 32 | Amazon.com: 33 | 34 | 35 | 36 | This device can take in up to 24V, protects against over/under voltage, 37 | reverse polarization, etc, and outputs clean 5V up to 3A (there is also a 38 | 10A version). 39 | 40 | For more information, see this thread on the Arduino forums: 41 | 42 | 43 | 44 | 45 | ## Vin On Electron and Mesh devices 46 | When powering Electron or Mesh devices via their onboard LiPo connectors, 47 | be aware that the `Vin` pin will not supply any power. `Vin` will only 48 | supply voltage when `VUSB` is powered. 49 | 50 | 51 | 52 | 53 | ## Detecting Vin, Battery, and Battery Status 54 | The Electron and the Mesh devices (Argon, Boron, Xenon) can all be powered 55 | by a 3.7V LiPo battery. Often, it is useful for a device to know whether it 56 | is running on battery power or not, and what the charge status of the 57 | battery is. The Electron and Boron boards both have an advanced Power 58 | Management chip built in which can report details on the battery status, 59 | while the Argon and Xenon do not, and can only report back a simple battery 60 | voltage level. This can still be useful, as you can read that value, and 61 | have your device send alerts or shut itself down if the battery reaches a 62 | critically low level (general wisdom is don't go lower than about 3.2V). 63 | 64 | * [Example Code for Electron and Boron](/particle-cookbook/examples/power/get-power-status-electron-boron-01.ino) 65 | * [Example Code for Argon and Xenon](/particle-cookbook/examples/power/get-power-status-electron-boron-01.ino) 66 | 67 | 68 | --- 69 | [<- Home](/particle-cookbook) 70 | -------------------------------------------------------------------------------- /doc/sleep-modes.md: -------------------------------------------------------------------------------- 1 | # Sleep Modes 2 | --- 3 | 4 | ## Quick Electron/Boron Sleep Mode Advice 5 | The balance between conserving battery power and conserving cellular data can 6 | make the question of "best" sleep mode a tricky question. However, the most 7 | common use-case probably looks something like: 8 | 9 | 1. Wake up 10 | 2. Take sensor readings 11 | 3. `Particle.publish()` data 12 | 4. Go to sleep for `N` minutes 13 | 5. Repeat 14 | 15 | Generally speaking, if you are putting your device to sleep for less than 23 16 | minutes, you should use "stop mode (pin + time) with 17 | `SLEEP_NETWORK_STANDBY`". This will look something like: 18 | 19 | System.sleep(D1, RISING, sleep_sec, SLEEP_NETWORK_STANDBY); 20 | 21 | Where `D1` is a pin which can wake the device, and `sleep_sec` is how long 22 | you want to sleep (in seconds). *NOTE:* Only certain pins are valid for the 23 | wakeup interrupt, be sure to check the documentation for details. 24 | 25 | If you are putting your device to sleep for more than 23 minutes, you should 26 | probably use deep sleep: 27 | 28 | System.sleep(SLEEP_MODE_DEEP, sleep_sec); 29 | 30 | This sleep mode will turn off the cellular modem completely, which saves more power. 31 | But it also means that on wake, that the device must reestablish its connection 32 | to the cellular network, which uses extra power and an additional amount of 33 | data for the handshaking (about 6K). 34 | 35 | You may be wondering "why 23 minutes?" This actually is particular to the use 36 | of Particle SIMs in the United States (or is it all of North America?). The 37 | agreement that Particle has with its partner carriers allows for a 23 minute 38 | keep-alive period. If you use a third-party SIM, your keep-alive time may be 39 | _*much*_ lower (e.g., 30 seconds -- but check with your provider to be sure). 40 | 41 | 42 | ## Electron SLEEP_MODE_DEEP tips and examples 43 | Some information about managing the cellular modem in conjunction with the use 44 | of `SLEEP_MODE_DEEP`. 45 | 46 | 47 | 48 | ## Choosing an Electron sleep mode 49 | Excellent information and tutorial about Electron sleep modes by @rickkas7. 50 | This article summarizes the various sleep modes, and the pros and cons of each 51 | with regards to power usage and wake-up time. This will help you choose the 52 | best sleep mode to use, depending on how often your project needs to wake up 53 | and publish data. or how quickly it needs to be ready to publish after waking 54 | up from a sleep state. 55 | 56 | 57 | 58 | 59 | ## STOP Mode Sleep Without Using a Pin 60 | The syntax for using STOP Mode sleep requires a pin, and trigger mode, in 61 | addition to the sleep time. Your device will wake if either the pin is 62 | activated _or_ the time expires. But what if you you don't want to wake 63 | on a pin signal, or you don't have any pins available? You can use an 64 | empty pin list and trigger: 65 | 66 | // STOP sleep for 60 seconds, no pin monitored: 67 | // Hat tip: @ScruffR 68 | // @see https://community.particle.io/t/gen3-sleep-sleep-for-time-only/47886/6 69 | System.sleep( {}, {}, 60 ); 70 | 71 | 72 | ## Maximum Sleep Time 73 | The maximum sleep time for Mesh devices is roughly 24 days, using STOP mode. 74 | For DEEP_SLEEP or STANDBY mode, an external RealTime Clock is required. 75 | 76 | 77 | --- 78 | [<- Home](/particle-cookbook/) 79 | -------------------------------------------------------------------------------- /doc/system-thread.md: -------------------------------------------------------------------------------- 1 | # System Thread 2 | --- 3 | 4 | ## Particle publish and blocking 5 | This is a very detailed article about using `SYSTEM_THREAD(ENABLED);` (or 6 | not), and how it affects publishing and other networking, and how to 7 | properly avoid your code blocking on certain operations. 8 | 9 | 10 | 11 | ## Particle Threads Tutorial 12 | You may not even realize that the Particle Device OS is built atop FreeRTOS, 13 | a real-time operating system for embedded devices, and that FreeRTOS supports 14 | Threads, which allow you to run multiple tasks simultaneously or 15 | asynchronously. However, threads are very complex and there are lots of 16 | pitfalls. This article gives a pretty deep dive into using threads, and why 17 | you probably should avoid it, unless you really know what you're doing. 18 | 19 | 20 | 21 | --- 22 | [<- Home](/particle-cookbook) 23 | -------------------------------------------------------------------------------- /doc/workbench.md: -------------------------------------------------------------------------------- 1 | # Particle Workbench 2 | Helpful information for using Visual Studio Code and Particle Workbench. 3 | 4 | ## Getting VSCode to recognize the `retained` keyword 5 | If you are using `retained` variables to save information across power 6 | cycles or deep sleep, Intellisense in VSCode might flag the `retained` 7 | keyword as unknown, and then flag every use of those variables as undefined 8 | identifiers. 9 | 10 | This problem exists as of January 2019, in Particle Workbench alpha7. It 11 | will probably be fixed in a future release of Particle Workbench. But in 12 | the meantime, you can work around it by adding the following include to your 13 | project: 14 | 15 | #include "deepsleep_hal_impl.h" 16 | 17 | Even if you don't do this, Workbench will still be able to compile your 18 | code. The error highlighting in the editor is only because the Intellisense 19 | syntax highlighting doesn't recognize the `retained` keyword, but the 20 | compiler still does. 21 | 22 | 23 | --- 24 | [<- Home](/particle-cookbook) 25 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Code Examples 2 | 3 | *This folder will contain simple sketches that demonstrate useful snippets.* 4 | 5 | ## Suggested organization 6 | As we add examples here, create subdirectories named corresponding to the 7 | main topic that links to it, and give each file a reasonably descriptive 8 | name. If a particular piece of example code will be linked from multiple 9 | topics, do not create multiple example code files -- pick the topic that 10 | seems to be most relevant. There could be multiple sketches for any given 11 | type of example, so add a two-digit numeric suffix for each file. 12 | 13 | For example, if you are adding single piece of sample code which will be 14 | linked both from `powering-projects` and `sleep-modes`, you might create a 15 | file named `examples/sleep-modes/electron-deep-sleep-01.ino` 16 | 17 | --- 18 | [<- Home](/particle-cookbook) 19 | -------------------------------------------------------------------------------- /examples/encryption/aes256-encryption-01.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Using AES256 encryption/decryption 3 | * 4 | * @author @hirotakaster 5 | * @see https://community.particle.io/t/aes-256-options/47437 6 | */ 7 | #include "TlsTcpClient.h" 8 | #include "mbedtls/aes.h" 9 | 10 | void setup() { 11 | Serial.begin(9600); 12 | 13 | unsigned char key[32]; 14 | unsigned char iv_enc[16] = {'i', 'n', 'i', 't', 'i', 'a', 'l', 'v', 'e', 'c', 't', 'o', 'r', ' ', ' ', ' '}; 15 | unsigned char iv_dec[16] = {'i', 'n', 'i', 't', 'i', 'a', 'l', 'v', 'e', 'c', 't', 'o', 'r', ' ', ' ', ' '}; 16 | unsigned char encbuff[128]; 17 | unsigned char decbuff[128]; 18 | unsigned char str[128]; 19 | 20 | memset(str, 0, sizeof(str)); 21 | memset(encbuff, 0, sizeof(encbuff)); 22 | memset(decbuff, 0, sizeof(decbuff)); 23 | 24 | for (int i = 0; i < 32; i++) key[i] = i; 25 | strcpy((char *)str, "Some text for AES 256 bytes :)"); 26 | 27 | mbedtls_aes_context aes_ctx; 28 | 29 | mbedtls_aes_init(&aes_ctx); 30 | mbedtls_aes_setkey_enc(&aes_ctx, key, 256); 31 | mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, 128, iv_enc, str, encbuff); 32 | 33 | mbedtls_aes_setkey_dec(&aes_ctx, key, 256); 34 | mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, 128, iv_dec, encbuff, decbuff); 35 | mbedtls_aes_free(&aes_ctx); 36 | Serial.print("Dec:"); Serial.println((char *)decbuff); 37 | 38 | } 39 | 40 | void loop() { 41 | delay(1000); 42 | } 43 | -------------------------------------------------------------------------------- /examples/power/get-power-status-argon-xenon-01.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Check Power Status 3 | * 4 | * For Argon and Xenon, this script will render the current voltage level 5 | * of the battery, and whether the board is powered by USB or Battery. 6 | * 7 | * Boron requires a different technique, using its PMIC functions. 8 | * 9 | * @author @rickkas7 10 | * @see https://community.particle.io/t/argon-check-power-source/47694/3 11 | */ 12 | #include "Particle.h" 13 | 14 | SerialLogHandler logHandler; 15 | 16 | char lastMsg[128]; 17 | unsigned long lastPublish = 0; 18 | 19 | void setup() { 20 | Serial.begin(); 21 | pinMode(PWR, INPUT); 22 | pinMode(CHG, INPUT); 23 | } 24 | 25 | void loop() { 26 | float voltage = analogRead(BATT) * 0.0011224; 27 | 28 | // PWR: 0=no USB power, 1=USB powered 29 | // CHG: 0=charging, 1=not charging 30 | char buf[128]; 31 | snprintf(buf, sizeof(buf), "voltage=%.1f PWR=%d CHG=%d", voltage, digitalRead(PWR), digitalRead(CHG)); 32 | 33 | if (strcmp(buf, lastMsg) != 0 && millis() - lastPublish > 2000) { 34 | Particle.publish("battery", buf, PRIVATE); 35 | Log.info(buf); 36 | strcpy(lastMsg, buf); 37 | lastPublish = millis(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/power/get-power-status-electron-boron-01.ino: -------------------------------------------------------------------------------- 1 | #include "Particle.h" 2 | 3 | /** 4 | * Simple class to monitor for has power (USB or VIN), has a battery, and is charging 5 | * 6 | * Just instantiate one of these as a global variable and call setup() out of setup() 7 | * to initialize it. Then use the getHasPower(), getHasBattery() and getIsCharging() 8 | * methods as desired. 9 | * 10 | * @author rickkas7 11 | * @see https://community.particle.io/t/when-is-electron-powered-by-battery/20702/18 12 | */ 13 | class PowerCheck { 14 | public: 15 | 16 | PowerCheck(); 17 | virtual ~PowerCheck(); 18 | 19 | /** 20 | * You must call this out of setup() to initialize the interrupt handler! 21 | */ 22 | void setup(); 23 | 24 | /** 25 | * Returns true if the Electron has power, either a USB host (computer), USB charger, or VIN power. 26 | * 27 | * Not interrupt or timer safe; call only from the main loop as it uses I2C to query the PMIC. 28 | */ 29 | bool getHasPower(); 30 | 31 | /** 32 | * Returns true if the Electron has a battery. 33 | */ 34 | bool getHasBattery(); 35 | 36 | /** 37 | * Returns true if the Electron is currently charging (red light on) 38 | * 39 | * Not interrupt or timer safe; call only from the main loop as it uses I2C to query the PMIC. 40 | */ 41 | bool getIsCharging(); 42 | 43 | private: 44 | void interruptHandler(); 45 | 46 | PMIC pmic; 47 | volatile bool hasBattery = true; 48 | volatile unsigned long lastChange = 0; 49 | }; 50 | 51 | PowerCheck::PowerCheck() { 52 | } 53 | 54 | PowerCheck::~PowerCheck() { 55 | } 56 | 57 | void PowerCheck::setup() { 58 | // This can't be part of the constructor because it's initialized too early. 59 | // Call this from setup() instead. 60 | 61 | // BATT_INT_PC13 62 | attachInterrupt(LOW_BAT_UC, &PowerCheck::interruptHandler, this, FALLING); 63 | } 64 | 65 | bool PowerCheck::getHasPower() { 66 | // Bit 2 (mask 0x4) == PG_STAT. If non-zero, power is good 67 | // This means we're powered off USB or VIN, so we don't know for sure if there's a battery 68 | byte systemStatus = pmic.getSystemStatus(); 69 | return ((systemStatus & 0x04) != 0); 70 | } 71 | 72 | /** 73 | * Returns true if the Electron has a battery. 74 | */ 75 | bool PowerCheck::getHasBattery() { 76 | if (millis() - lastChange < 100) { 77 | // When there is no battery, the charge status goes rapidly between fast charge and 78 | // charge done, about 30 times per second. 79 | 80 | // Normally this case means we have no battery, but return hasBattery instead to take 81 | // care of the case that the state changed because the battery just became charged 82 | // or the charger was plugged in or unplugged, etc. 83 | return hasBattery; 84 | } 85 | else { 86 | // It's been more than a 100 ms. since the charge status changed, assume that there is 87 | // a battery 88 | return true; 89 | } 90 | } 91 | 92 | 93 | /** 94 | * Returns true if the Electron is currently charging (red light on) 95 | */ 96 | bool PowerCheck::getIsCharging() { 97 | if (getHasBattery()) { 98 | byte systemStatus = pmic.getSystemStatus(); 99 | 100 | // Bit 5 CHRG_STAT[1] R 101 | // Bit 4 CHRG_STAT[0] R 102 | // 00 – Not Charging, 01 – Pre-charge (> 4) & 0x3; 104 | 105 | // Return true if battery is charging if in pre-charge or fast charge mode 106 | return (chrgStat == 1 || chrgStat == 2); 107 | } 108 | else { 109 | // Does not have a battery, can't be charging. 110 | // Don't just return the charge status because it's rapidly switching 111 | // between charging and done when there is no battery. 112 | return false; 113 | } 114 | } 115 | 116 | void PowerCheck::interruptHandler() { 117 | if (millis() - lastChange < 100) { 118 | // We very recently had a change; assume there is no battey and we're rapidly switching 119 | // between fast charge and charge done 120 | hasBattery = false; 121 | } 122 | else { 123 | // Note: It's quite possible that hasBattery will be false when there is a battery; the logic 124 | // in getHasBattery() takes this into account by checking lastChange as well. 125 | hasBattery = true; 126 | } 127 | lastChange = millis(); 128 | } 129 | 130 | 131 | 132 | // Global variables 133 | PowerCheck powerCheck; 134 | unsigned long lastCheck = 0; 135 | char lastStatus[256]; 136 | 137 | void setup() { 138 | Serial.begin(9600); 139 | powerCheck.setup(); 140 | } 141 | 142 | void loop() { 143 | 144 | if (millis() - lastCheck > 2000) { 145 | lastCheck = millis(); 146 | 147 | char buffer[256]; 148 | snprintf(buffer, sizeof(buffer), "hasPower=%d hasBattery=%d isCharging=%d", 149 | powerCheck.getHasPower(), powerCheck.getHasBattery(), powerCheck.getIsCharging()); 150 | 151 | if (strcmp(lastStatus, buffer) != 0) { 152 | strcpy(lastStatus, buffer); 153 | Particle.publish("battery", buffer, PRIVATE); 154 | } 155 | } 156 | } 157 | 158 | } 159 | } 160 | } 161 | --------------------------------------------------------------------------------