├── api.md └── firmware.md /api.md: -------------------------------------------------------------------------------- 1 | RootCloud API 2 | ========== 3 | 4 | Introduction 5 | === 6 | 7 | The RootCloud API is a [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer) API. 8 | REST means a lot of things, but first and foremost it means that we use the URL in the way that it's intended: 9 | as a "Uniform Resource Locator". 10 | 11 | In this case, the unique "resource" in question is your Oak Board. 12 | Every Oak Board ("board") has a URL, which can be used to `GET` variables, `POST` a function call, or `PUT` new firmware. 13 | The variables and functions that you have written in your firmware are exposed as *subresources* within the Oak Board. 14 | 15 | All requests to the Oak Board come through our API server using TLS security. 16 | 17 | **Spark API Compatibility:** The RootCloud API has been developed as a completely new codebase in a clean room implementation, but these documents and the API structure are borrowed heavily from the [Spark](http://spark.io) project. While the RootCloud API was originally implmented as an entirely seperate API, the Spark API seemed structured in a way that would work well with the RootCloud devices, so in the interest on compatibility and standards we have built our API to be 99% compatible with the Spark API, while implementing many new features as well. 18 | 19 | **Credit:** Much credit is due to the Spark team! They have created a very logical API implementation for talking to IoT devices, and graciously open sourced their documentation and some of their tools. A huge thanks to them! 20 | 21 | 22 | ``` 23 | PROTOCOL AND HOST 24 | https://api.rootcloud.io 25 | ``` 26 | 27 | There are a number of API calls available, which are summarized here, and described in more detail below. 28 | 29 | List devices 30 | ------- 31 | 32 | List devices the currently authenticated user has access to. 33 | 34 | ``` 35 | GET /v1/devices 36 | 37 | # A typical JSON response will look like this 38 | [ 39 | { 40 | "id": "53ff6f0650723", 41 | "name": "digistump_oak", 42 | "last_app": null, 43 | "last_heard": null, 44 | "connected": false 45 | }, 46 | { 47 | "id": "53ff291839887", 48 | "name": "turtle", 49 | "last_app": null, 50 | "last_heard": 2015-02-15T20:12:51.974Z, 51 | "connected": true 52 | } 53 | ] 54 | ``` 55 | 56 | Claim board/module 57 | ------- 58 | 59 | You can claim a brand new or released board/module through a simple API call. All you need as an access token and board/module id! 60 | 61 | ``` 62 | POST /v1/devices 63 | 64 | # EXAMPLE REQUEST 65 | curl https://api.rootcloud.io/v1/devices \ 66 | -d access_token=1234 \ 67 | -d id=0123456789abcdef01234567 68 | ``` 69 | 70 | Device information 71 | ------- 72 | 73 | Get basic information about the given board, including the custom variables and functions it has exposed. 74 | 75 | ``` 76 | GET /v1/devices/{DEVICE_ID} 77 | ``` 78 | 79 | Update the board, including the display name or the firmware (either binary or source). 80 | 81 | ``` 82 | PUT /v1/devices/{DEVICE_ID} 83 | ``` 84 | 85 | Requesting a variable value 86 | ------- 87 | 88 | Request the current value of a variable exposed by the board, 89 | e.g., `GET /v1/devices/0123456789abcdef01234567/temperature` 90 | 91 | ``` 92 | GET /v1/devices/{DEVICE_ID}/{VARIABLE} 93 | ``` 94 | 95 | Calling a function 96 | ------- 97 | 98 | Call a function exposed by the board, with arguments passed in request body, 99 | e.g., `POST /v1/devices/0123456789abcdef01234567/brew` 100 | 101 | ``` 102 | POST /v1/devices/{DEVICE_ID}/{FUNCTION} 103 | ``` 104 | 105 | Open a stream of [Server-Sent Events](http://www.w3.org/TR/eventsource/) 106 | 107 | ``` 108 | GET /v1/events[/:event_name] 109 | GET /v1/devices/events[/:event_name] 110 | GET /v1/devices/{DEVICE_ID}/events[/:event_name] 111 | ``` 112 | 113 | 114 | Authentication 115 | ------- 116 | 117 | Just because you've connected your Oak Board to the internet doesn't mean anyone else should have access to it. 118 | Permissions for controlling and communciating with your Oak Board are managed with OAuth2. 119 | 120 | ```bash 121 | # You type in your terminal 122 | curl https://api.rootcloud.io/v1/devices/0123456789abcdef01234567/brew \ 123 | -d access_token=9876987698769876987698769876987698769876 124 | # Response status is 200 OK, which means 125 | # the board says, "Yes ma'am!" 126 | 127 | # Sneaky Pete tries the same thing in his terminal 128 | curl https://api.rootcloud.io/v1/devices/0123456789abcdef01234567/brew \ 129 | -d access_token=1234123412341234123412341234123412341234 130 | # Response status is 403 Forbidden, which means 131 | # the board says, "You ain't the boss of me." 132 | 133 | # LESSON: Protect your access token. 134 | ``` 135 | 136 | Your access token can be found in the RootCloud IDE by clicking the "Keys" button on the top button bar. 137 | 138 | [RootCloud IDE >](https://ide.rootcloud.io) 139 | 140 | When you connect your Oak Board to the Cloud for the first time, it will be associated with your account, 141 | and only you will have permission to control your Oak Board—using your access token. 142 | 143 | ~~If you need to transfer ownership of the board to another user, the easiest way is to simply log into the [RootCloud IDE site](https://ide.rootcloud.io), select the device from the drop down "Devices" list and click on the gear next to the drop down. Then click "Release Device". This will make it possible for the other person you are transfering the device to, to go through the normal [claiming process](/#/connect/claiming-your-board).~~ Not yet implemented 144 | 145 | In the future, you will be able to provision access to your Oak Board to other accounts 146 | and to third-party app developers; however, these features are not yet available. 147 | 148 | 149 | 150 | ### How to send your access token 151 | 152 | There are three ways to send your access token in a request. 153 | 154 | * In an HTTP Authorization header (always works) 155 | * In the URL query string (only works with GET requests) 156 | * In the request body (only works for POST & PUT when body is URL-encoded) 157 | 158 | In these docs, you'll see example calls written using a terminal program called 159 | [curl](http://curl.haxx.se/) 160 | which may already be available on your machine. 161 | 162 | Example commands will always start with `curl`. 163 | 164 | --- 165 | 166 | To send a custom header using curl, use you the `-H` flag. 167 | The access token is called a "Bearer" token and goes in the standard 168 | HTTP `Authorization` header. 169 | 170 | ``` 171 | curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" 172 | https://... 173 | ``` 174 | 175 | --- 176 | 177 | The query string is the part of the URL after a `?` question mark. 178 | To send the access token in the query string just add `access_token=38bb...`. 179 | Because your terminal thinks the question mark is special, we escape it with a backslash. 180 | 181 | ``` 182 | curl https://api.rootcloud.io/v1/devices\?access_token=38bb7b318cc6898c80317decb34525844bc9db55 183 | ``` 184 | 185 | --- 186 | 187 | The request body is how form contents are submitted on the web. 188 | Using curl, each parameter you send, including the access token is preceded by a `-d` flag. 189 | By default, if you add a `-d` flag, curl assumes that the request is a POST. 190 | If you need a different request type, you have to specifically say so with the `-X` flag, 191 | for example `-X PUT`. 192 | 193 | ``` 194 | curl -d access_token=38bb7b318cc6898c80317decb34525844bc9db55 195 | https://... 196 | ``` 197 | 198 | 199 | ### Generate a new access token 200 | 201 | ``` 202 | POST /oauth/token 203 | 204 | # Using curl in your terminal 205 | curl https://api.rootcloud.io/oauth/token \ 206 | -d grant_type=password -d username=joe@example.com -d password=SuperSecret 207 | 208 | # A typical JSON response will look like this 209 | { 210 | "access_token": "254406f79c1999af65a7df4388971354f85cfee9", 211 | "token_type": "bearer", 212 | "expires_in": 7776000 213 | } 214 | ``` 215 | 216 | When creating a new access token, you need to specify several additional pieces of info. 217 | 218 | You must give a valid client ID and password in HTTP Basic Auth. 219 | **RootCloud Change:** A client ID is not required - but one may be sent, it will be ignored. 220 | In the POST body, you need three parameters: 221 | 222 | * grant_type=password 223 | * username=YOUR_EMAIL@ADDRE.SS 224 | * password=YOUR_PASSWORD 225 | 226 | ### Configure when your token expires 227 | 228 | You can control when your access token will expire, or set it to not expire at all! 229 | There are two ways to specify how / when your token should expire. 230 | 231 | 232 | ####expires_in - Optional 233 | 234 | How many seconds should the token last for? Setting this to 0 seconds will create a token that never expires. 235 | 236 | It's generally a little safer to create short lived tokens and refresh them frequently, since it makes it harder to lose a token that has access to your devices. 237 | 238 | ``` 239 | # expires in 3600 seconds, or 1 hour 240 | "expires_in": 3600 241 | ``` 242 | 243 | ``` 244 | # Setting token lifespan using expires_in with curl in your terminal 245 | curl https://api.rootcloud.io/oauth/token \ 246 | -d grant_type=password \ 247 | -d username=joe@example.com \ 248 | -d password=SuperSecret \ 249 | -d expires_in=3600 250 | ``` 251 | 252 | 253 | ``` 254 | 255 | ``` 256 | 257 | ####expires_at - Optional 258 | 259 | At what date and time should the token expire? This should be an ISO8601 style date string, or null for never 260 | 261 | 262 | ``` 263 | # date format: YYYY-MM-DD 264 | # expires in 2020 265 | "expires_at": "2020-01-01" 266 | ``` 267 | 268 | ``` 269 | # Setting token lifespan using a date string with curl in your terminal 270 | curl https://api.rootcloud.io/oauth/token \ 271 | -d grant_type=password \ 272 | -d username=joe@example.com \ 273 | -d password=SuperSecret \ 274 | -d expires_at=2020-01-01 275 | ``` 276 | 277 | 278 | 279 | 280 | 281 | ### List all your tokens 282 | 283 | ``` 284 | GET /v1/access_tokens 285 | 286 | # Using curl in your terminal 287 | curl https://api.rootcloud.io/v1/access_tokens -u joe@example.com:SuperSecret 288 | 289 | # Example JSON response 290 | [ 291 | { 292 | "token": "b5b901e8760164e134199bc2c3dd1d228acf2d98", 293 | "expires_at": "2014-04-27T02:20:36.177Z", 294 | "client": "rootcloud" 295 | }, 296 | { 297 | "token": "ba54b6bb71a43b7612bdc7c972914604a078892b", 298 | "expires_at": "2014-04-27T06:31:08.991Z", 299 | "client": "rootcloud" 300 | } 301 | ] 302 | ``` 303 | 304 | You can list all your access tokens by passing your email address and password 305 | in an HTTP Basic Auth header to `/v1/access_tokens`. 306 | 307 | 308 | ### Deleting an access token 309 | 310 | ``` 311 | DELETE /v1/access_tokens/:token 312 | 313 | # Using curl in your terminal 314 | curl https://api.rootcloud.io/v1/access_tokens/b5b901e8760164e134199bc2c3dd1d228acf2d98 \ 315 | -u joe@example.com:SuperSecret -X DELETE 316 | 317 | # Example JSON response 318 | { 319 | "ok": true 320 | } 321 | ``` 322 | 323 | If you have a bunch of unused tokens and want to clean up, you can delete tokens. 324 | 325 | Just as for listing them, send your username and password in an HTTP Basic Auth header. 326 | 327 | 328 | Errors 329 | ------- 330 | 331 | The RootCloud uses traditional HTTP response codes to provide feedback from the board regarding the validity 332 | of the request and its success or failure. As with other HTTP resources, response codes in the 200 range 333 | indicate success; codes in the 400 range indicate failure due to the information provided; 334 | codes in the 500 range indicate failure within RootCloud's server infrastructure. 335 | 336 | ``` 337 | 200 OK - API call successfully delivered to the board and executed. 338 | 339 | 400 Bad Request - Your request is not understood by the board, 340 | or the requested subresource (variable/function) has not been exposed. 341 | 342 | 401 Unauthorized - Your access token is not valid, or you are attempting to do something you do not have permission to do. This is currently used as somewhat of a catch-all response. 343 | 344 | 403 Forbidden - Your access token is not authorized to interface with this board. 345 | 346 | 404 Not Found - The board you requested is not currently connected to the cloud. 347 | 348 | 408 Timed Out - The cloud experienced a significant delay when trying to reach the board. 349 | 350 | 500 Server errors - Fail whale. Something's wrong on our end. 351 | ``` 352 | 353 | Versioning 354 | ------- 355 | 356 | The API endpoints all start with `/v1` to represent the first official version of the RootCloud API. 357 | The existing API is stable, and we may add new endpoints with the `/v1` prefix. 358 | 359 | If in the future we make backwards-incompatible changes to the API, the new endpoints will start with 360 | something different, probably `/v2`. If we decide to deprecate any `/v1` endpoints, 361 | we'll give you lots of notice and a clear upgrade path. 362 | 363 | Basic functions 364 | ======== 365 | 366 | Controlling a board 367 | -------- 368 | 369 | To control a board, you must first define and expose *functions* in the board firmware. 370 | You then call these functions remotely using the RootCloud API. 371 | 372 | Note: If you have declared a function name longer than 12 characters it *will be truncated* to 12 characters. Example: RootCloud.function("someFunction1", ...); exposes a function called **someFunction** and *not* **someFunction1** 373 | 374 | ```cpp 375 | /* FIRMWARE */ 376 | int brew(String args) 377 | { 378 | // parse brew temperature and duration from args 379 | // ... 380 | 381 | activate_heating_element(temperature); 382 | start_water_pump(duration_seconds); 383 | 384 | // int status_code = ... 385 | return status_code; 386 | } 387 | ``` 388 | 389 | --- 390 | 391 | Let's say, as an example, you create a Oak powered coffeemaker. 392 | Within the firmware, we might expect to see something like this brew function. 393 | 394 | ```cpp 395 | /* FIRMWARE */ 396 | void setup() 397 | { 398 | RootCloud.function("brew", brew); 399 | } 400 | ``` 401 | 402 | In a normal coffeemaker, `brew` might be called when a button on the front of the coffeemaker is pressed. 403 | 404 | To make this function available through the RootCloud, simply add a `RootCloud.function` call to your `setup()`. 405 | 406 | 407 | 408 | --- 409 | 410 | This *exposes* the brew function so that it can be called through the API. When this code is present in the firmware, you can make this API call. 411 | 412 | ```bash 413 | POST /v1/devices/{DEVICE_ID}/{FUNCTION} 414 | 415 | # EXAMPLE REQUEST 416 | curl https://api.rootcloud.io/v1/devices/0123456789abcdef01234567/brew \ 417 | -d access_token=1234123412341234123412341234123412341234 \ 418 | -d "args=202,230" 419 | ``` 420 | 421 | --- 422 | 423 | The API request will be routed to the Oak Board and will run your `brew` function. The response will have a `return_value` key containing the integer returned by `brew`. 424 | 425 | ```json 426 | // EXAMPLE RESPONSE 427 | { 428 | "id": "0123456789abcdef01234567", 429 | "name": "prototype99", 430 | "connected": true, 431 | "return_value": 42 432 | } 433 | 434 | ``` 435 | 436 | All RootCloud functions take a String as the only argument and must return a 32-bit integer. 437 | The maximum length of the argument is 63 characters. 438 | 439 | 440 | Reading data from a board 441 | -------- 442 | 443 | ### Variables 444 | 445 | Imagine you have a temperature sensor attached to the A0 pin of your Oak Board 446 | and your firmware has exposed the value of the sensor as a RootCloud variable. 447 | 448 | ```cpp 449 | /* FIRMWARE */ 450 | int temperature = 0; 451 | 452 | void setup() 453 | { 454 | RootCloud.variable("temperature", &temperature, INT); 455 | pinMode(A0, INPUT); 456 | } 457 | 458 | void loop() 459 | { 460 | temperature = analogRead(A0); 461 | } 462 | ``` 463 | 464 | --- 465 | 466 | You can now make a `GET` request, even with your browser, to read the sensor at any time. 467 | The API endpoint is `/v1/devices/{DEVICE_ID}/{VARIABLE}` and as always, you have to include your access token. 468 | 469 | ```bash 470 | # EXAMPLE REQUEST IN TERMINAL 471 | # Device ID is 0123456789abcdef01234567 472 | # Your access token is 1234123412341234123412341234123412341234 473 | curl "https://api.rootcloud.io/v1/devices/0123456789abcdef01234567/temperature?access_token=1234123412341234123412341234123412341234" 474 | ``` 475 | And the response contains a `result` like this: 476 | 477 | ```json 478 | // EXAMPLE RESPONSE 479 | { 480 | "cmd": "VarReturn", 481 | "name": "temperature", 482 | "result": 42, 483 | "coreInfo": { 484 | "last_app": "", 485 | "last_heard": "2014-08-22T22:33:25.407Z", 486 | "connected": true, 487 | "deviceID": "53ff6c065075535119511687" 488 | } 489 | 490 | ``` 491 | 492 | **NOTE**: Variable names are truncated after the 12th character: `temperature_sensor` is accessible as `temperature_` 493 | 494 | ### Events 495 | 496 | #### Registering a callback 497 | 498 | In the RootCloud IDE, you will be able to register a URL on your own server 499 | to which we will POST each time one of your Oak Boards publishes a certain event. *This feature is still in progress, and will be released by the time the Kickstarter's ship.* 500 | 501 | #### Archived event data - RootCloud Data Explorer 502 | 503 | A feature unique to the RootCloud API is the ability to specify that an event should be archived, and later retrieve that archived data. 504 | 505 | Archived data from your devices can be explored and filtered with the RootCloud Data Explorer: https://data.rootcloud.io The RootCloud Data Explorer provides filtering and drill down capabilities and presents the corresponding REST API URL for the current filter set in use. 506 | 507 | You can also access archived data directly from the REST API: 508 | 509 | --- 510 | 511 | Fetch all archived events (optionally matching the event_name), public and private, published by devices one owns: 512 | 513 | ``` 514 | GET /v1/devices/data[/:event_name] 515 | 516 | # EXAMPLE 517 | curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" 518 | https://api.rootcloud.io/v1/devices/data/temperature 519 | ``` 520 | 521 | --- 522 | 523 | Fetch all archived events (optionally matching the event_name), public and private, published by a specific device: 524 | 525 | ``` 526 | GET /v1/devices/:device_id/data[/:event_name] 527 | 528 | # EXAMPLE 529 | curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" 530 | https://api.rootcloud.io/v1/devices/55ff70064939494339432586/data/temperature 531 | ``` 532 | 533 | --- 534 | 535 | Filter the fetching of archived events (optionally matching the event_name) by a start and or end date: 536 | 537 | ``` 538 | GET /v1/devices/data[/:event_name] 539 | or 540 | GET /v1/devices/:device_id/data[/:event_name] 541 | 542 | # EXAMPLE 543 | curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" 544 | https://api.rootcloud.io/v1/devices/data/temperature?start=2015-04-19T12:59:23Z&end=2015-04-21T00:00:00Z 545 | ``` 546 | 547 | #### Subscribing to events 548 | 549 | You can make an API call that will open a stream of 550 | [Server-Sent Events](http://www.w3.org/TR/eventsource/) (SSEs). 551 | You will make one API call that opens a connection to the RootCloud. 552 | That connection will stay open, unlike normal HTTP calls which end quickly. 553 | Very little data will come to you across the connection unless your Oak Board publishes an event, 554 | at which point you will be immediately notified. 555 | 556 | To subscribe to an event stream, make a GET request to one of the following endpoints. 557 | This will open a Server-Sent Events (SSE) stream, i.e., a TCP socket that stays open. 558 | In each case, the event name filter in the URI is optional. When specifying an event name filter, 559 | published events will be limited to those events with names that begin with the specified string. 560 | For example, specifying an event name filter of 'temp' will return events with names 'temp' and 561 | 'temperature'. 562 | 563 | SSE resources: 564 | 565 | * http://dev.w3.org/html5/eventsource/ 566 | * https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events 567 | * http://www.html5rocks.com/en/tutorials/eventsource/basics/ 568 | 569 | --- 570 | 571 | Subscribe to the firehose of public events, plus private events published by devices one owns: 572 | 573 | ``` 574 | GET /v1/events[/:event_name] 575 | 576 | # EXAMPLE 577 | curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" 578 | https://api.rootcloud.io/v1/events/temperature 579 | ``` 580 | 581 | --- 582 | 583 | Subscribe to all events, public and private, published by devices one owns: 584 | 585 | ``` 586 | GET /v1/devices/events[/:event_name] 587 | 588 | # EXAMPLE 589 | curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" 590 | https://api.rootcloud.io/v1/devices/events/temperature 591 | ``` 592 | 593 | --- 594 | 595 | Subscribe to events from one specific device. 596 | If the API user owns the device, then she will receive all events, 597 | public and private, published by that device. 598 | If the API user does not own the device she will only receive public events. 599 | 600 | ``` 601 | GET /v1/devices/:device_id/events[/:event_name] 602 | 603 | # EXAMPLE 604 | curl -H "Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55" 605 | https://api.rootcloud.io/v1/devices/55ff70064939494339432586/events/temperature 606 | ``` 607 | 608 | #### Publishing events 609 | 610 | You can publish events to your devices using the publish event endpoint. 611 | 612 | 613 | ``` 614 | POST /v1/devices/events 615 | 616 | # EXAMPLE 617 | curl https://api.rootcloud.io/v1/devices/events \ 618 | -d access_token=1234123412341234123412341234123412341234 \ 619 | -d "name=myevent" \ 620 | -d "data=Hello World" \ 621 | -d "private=true" \ 622 | -d "ttl=0" \ 623 | -d "archive=true" 624 | ``` 625 | 626 | "data", "private", "ttl", and "archive" are all optional. You can also send these with the RootCloud CLI: 627 | 628 | ``` 629 | # grab the rootcloud-cli here - Not yet available 630 | rootcloud publish test "Hello World" 631 | ``` 632 | 633 | 634 | Verifying and Flashing new firmware 635 | --------- 636 | 637 | All your Oak firmware coding can happen entirely in the RootCloud IDE. 638 | However, if you prefer to use your own text editor or IDE, you can! 639 | It just means that instead of hitting the "Flash" or "Verify" buttons, you'll make API calls that reference a file. 640 | 641 | 642 | ### Flash a board with source code 643 | 644 | If you have written a source code file that defines `setup()` and `loop()` functions, 645 | you can flash it to your Oak Board with an HTTP PUT request. 646 | 647 | ``` 648 | # HTTP REQUEST DEFINITION 649 | PUT /v1/devices/{DEVICE_ID} 650 | Content-Type: multipart/form-data 651 | 652 | Send the source code file as "file" in request body. 653 | ``` 654 | 655 | --- 656 | 657 | The API request should be encoded as `multipart/form-data` with a `file` field populated. 658 | Your filename does not matter. In particular, the extension can be .c, .cpp, .ino, or anything else your prefer. 659 | 660 | This API request will submit your firmware to be compiled into a binary, after which, 661 | if compilation was successful, the binary will be flashed to your board wirelessly. 662 | 663 | ```bash 664 | # EXAMPLE REQUEST IN TERMINAL 665 | # Flash a board with a file called "my-firmware-app.cpp" 666 | curl -X PUT -F file=@my-firmware-app.cpp \ 667 | "https://api.rootcloud.io/v1/devices/0123456789abcdef01234567?access_token=1234123412341234123412341234123412341234" 668 | ``` 669 | 670 | --- 671 | 672 | There are three possible response formats: 673 | 674 | * A successful response, in which both compilation and flashing succeed. 675 | * A failure due to compilation errors. 676 | * A failure due to inability to transmit the binary to the board. 677 | 678 | 679 | ```js 680 | // EXAMPLE SUCCESSFUL RESPONSE 681 | { 682 | "ok": true, 683 | "firmware_binary_id": "12345" 684 | } 685 | ``` 686 | 687 | ```js 688 | // EXAMPLE COMPILE FAILURE RESPONSE 689 | { 690 | "ok": false, 691 | "errors": ["Compile error"], 692 | "output": ".... lots of debug output from the compiler..." 693 | } 694 | ``` 695 | 696 | ```js 697 | // EXAMPLE FLASH FAILURE RESPONSE 698 | { 699 | "ok": false, 700 | "firmware_binary_id": "1234567", 701 | "errors": ["Device is not connected."] 702 | } 703 | ``` 704 | 705 | ### Flash a board with a pre-compiled binary 706 | 707 | If you want to compile the firmware yourself and send a binary instead of a source file, you can do that too! 708 | Just add `file_type=binary` to the request body, and we will skip the compilation stage altogether. 709 | The response format will look like those shown above. 710 | 711 | ```bash 712 | # EXAMPLE REQUEST IN TERMINAL TO FLASH A BINARY 713 | curl -X PUT -F file=@my-firmware-app.bin -F file_type=binary \ 714 | "https://api.rootcloud.io/v1/devices/0123456789abcdef01234567?access_token=1234123412341234123412341234123412341234" 715 | ``` 716 | -------------------------------------------------------------------------------- /firmware.md: -------------------------------------------------------------------------------- 1 | Oak Firmware 2 | ========== 3 | 4 | Introduction 5 | === 6 | 7 | **Spark Firmware Compatibility:** The Oak Firmware has been developed as a completely new codebase in a clean room implementation, but for compatibility many of the functions are similar to those used by the [Spark](http://spark.io) project. Many of these functions work differently then they do with a Spark device, but have similar parameters, returns, and uses - these differences are noted where they will affect the end user. 8 | 9 | **Credit:** Much credit is due to the Spark team! They have created a great platform and graciously open sourced their documentation and some of their tools. A huge thanks to them! 10 | 11 | Cloud Functions 12 | ===== 13 | 14 | ### RootCloud.variable() 15 | 16 | Expose a *variable* through the RootCloud so that it can be called with `GET /v1/devices/{DEVICE_ID}/{VARIABLE}`. 17 | 18 | ```C++ 19 | // EXAMPLE USAGE 20 | int analogvalue = 0; 21 | double tempC = 0; 22 | char *message = "my name is oak"; 23 | 24 | void setup() 25 | { 26 | // variable name max length is 12 characters long 27 | RootCloud.variable("analogvalue", &analogvalue, INT); 28 | RootCloud.variable("temp", &tempC, DOUBLE); 29 | RootCloud.variable("mess", message, STRING); 30 | pinMode(A0, INPUT); 31 | } 32 | 33 | void loop() 34 | { 35 | // Read the analog value of the sensor (TMP36) 36 | analogvalue = analogRead(A0); 37 | //Convert the reading into degree celcius 38 | tempC = (((analogvalue * 3.3)/4095) - 0.5) * 100; 39 | delay(200); 40 | } 41 | ``` 42 | Currently, up to 10 RootCloud variables may be defined and each variable name is limited to a max of 12 characters. 43 | 44 | There are three supported data types: 45 | 46 | * `INT` 47 | * `DOUBLE` 48 | * `STRING` (maximum string size is 622 bytes) 49 | 50 | 51 | 52 | 53 | ```json 54 | # EXAMPLE REQUEST IN TERMINAL 55 | # Device ID is 0123456789abcdef 56 | # Your access token is 123412341234 57 | curl "https://api.RootCloud.io/v1/devices/0123456789abcdef/analogvalue?access_token=123412341234" 58 | curl "https://api.RootCloud.io/v1/devices/0123456789abcdef/temp?access_token=123412341234" 59 | curl "https://api.RootCloud.io/v1/devices/0123456789abcdef/mess?access_token=123412341234" 60 | 61 | # In return you'll get something like this: 62 | 960 63 | 27.44322344322344 64 | my name is oak 65 | 66 | ``` 67 | 68 | ### RootCloud.function() 69 | 70 | Expose a *function* through the RootCloud so that it can be called with `POST device/{FUNCTION}`. 71 | 72 | ```cpp 73 | // SYNTAX TO REGISTER A ROOTCLOUD FUNCTION 74 | RootCloud.function("funcKey", funcName); 75 | // ^ 76 | // | 77 | // (max of 12 characters long) 78 | ``` 79 | 80 | Currently the application supports the creation of up to 4 different RootCloud functions. 81 | 82 | In order to register a RootCloud function, the user provides the `funcKey`, which is the string name used to make a POST request and a `funcName`, which is the actual name of the function that gets called in the RootCloud app. The RootCloud function can return any integer; `-1` is commonly used for a failed function call. 83 | 84 | The length of the `funcKey` is limited to a max of 12 characters. If you declare a function name longer than 12 characters it will be truncated to 12 characters. 85 | 86 | Example: RootCloud.function("someFunction1", ...); exposes a function called someFunction and not someFunction1 87 | 88 | A RootCloud function is set up to take one argument of the [String](/firmware/#language-syntax-string-class) datatype. This argument length is limited to a max of 63 characters. 89 | 90 | ```cpp 91 | // EXAMPLE USAGE 92 | int brewCoffee(String command); 93 | 94 | void setup() 95 | { 96 | // register the RootCloud function 97 | RootCloud.function("brew", brewCoffee); 98 | } 99 | 100 | void loop() 101 | { 102 | // this loops forever 103 | } 104 | 105 | // this function automagically gets called upon a matching POST request 106 | int brewCoffee(String command) 107 | { 108 | // look for the matching argument "coffee" <-- max of 64 characters long 109 | if(command == "coffee") 110 | { 111 | // some example functions you might have 112 | //activateWaterHeater(); 113 | //activateWaterPump(); 114 | return 1; 115 | } 116 | else return -1; 117 | } 118 | ``` 119 | 120 | ```json 121 | COMPLEMENTARY API CALL 122 | POST /v1/devices/{DEVICE_ID}/{FUNCTION} 123 | 124 | # EXAMPLE REQUEST 125 | curl https://api.RootCloud.io/v1/devices/0123456789abcdef/brew \ 126 | -d access_token=123412341234 \ 127 | -d "args=coffee" 128 | ``` 129 | 130 | The API request will be routed to the board and will run your brew function. The response will have a return_value key containing the integer returned by brew. 131 | 132 | ### RootCloud.publish() 133 | 134 | Publish an *event* through the RootCloud that will be forwarded to all registered callbacks, subscribed streams of Server-Sent Events, and boards listening via `RootCloud.subscribe()`. 135 | 136 | This feature allows the board to generate an event based on a condition. For example, you could connect a motion sensor to the board and have the board generate an event whenever motion is detected. 137 | 138 | RootCloud events have the following properties: 139 | 140 | * name (1–63 ASCII characters) 141 | * public/private (default public) 142 | * ttl (time to live, 0–16777215 seconds, default 0) **RootCloud Change:** Because RootCloud has implemented persistent events the TTL default has been set to 0, so that the default behavior is consistent with the RootCloud API, as they have not yet implemented persistance. 143 | * optional data (up to 63 bytes) 144 | # archive (true or false, 0 or 1) **RootCloud Change:** The Spark API does not have the ability to archive data. RootCloud allows you to specificy that an event should be archived, data points from that event will then be accessible via the RootCloud Data Explorer and API calls. See the Event section of the API readme for more info. 145 | 146 | Anyone may subscribe to public events; think of them like tweets. 147 | Only the owner of the device will be able to subscribe to private events. 148 | Only the owner of the device will be able to view archived data (for now?). 149 | 150 | Some events are reserved for officially curated data originating from the RootCloud. 151 | 152 | **RootCloud Change:** When a server-events stream is first opened, or a board first subscribes all previously published persistant (TTL > 0) events matching the subscription context that have not expired will be sent. 153 | 154 | --- 155 | 156 | Publish a public event with the given name, no data, and the default TTL of 0 seconds. 157 | 158 | ```C++ 159 | // SYNTAX 160 | RootCloud.publish(const char *eventName); 161 | RootCloud.publish(String eventName); 162 | 163 | // EXAMPLE USAGE 164 | RootCloud.publish("motion-detected"); 165 | ``` 166 | 167 | --- 168 | 169 | Publish a public event with the given name and data, with the default TTL of 0 seconds. 170 | 171 | ```C++ 172 | // SYNTAX 173 | RootCloud.publish(const char *eventName, const char *data); 174 | RootCloud.publish(String eventName, String data); 175 | 176 | // EXAMPLE USAGE 177 | RootCloud.publish("temperature", "19 F"); 178 | ``` 179 | 180 | --- 181 | 182 | Publish a public event with the given name, data, and TTL. 183 | 184 | ```C++ 185 | // SYNTAX 186 | RootCloud.publish(const char *eventName, const char *data, int ttl); 187 | RootCloud.publish(String eventName, String data, int ttl); 188 | 189 | // EXAMPLE USAGE 190 | RootCloud.publish("lake-depth/1", "28m", 21600); 191 | ``` 192 | 193 | --- 194 | 195 | Publish a private event with the given name, data, and TTL. 196 | In order to publish a private event, you must pass at least four parameters. 197 | 198 | ```C++ 199 | // SYNTAX 200 | RootCloud.publish(const char *eventName, const char *data, int ttl, PRIVATE); 201 | RootCloud.publish(String eventName, String data, int ttl, PRIVATE); 202 | 203 | // EXAMPLE USAGE 204 | RootCloud.publish("front-door-unlocked", NULL, 60, PRIVATE); 205 | ``` 206 | 207 | Publish an event with the given name, data, TTL, PUBLIC/PRIVATE state, and archive it. 208 | In order to publish an event and have it archived, you must pass all five parameters. 209 | 210 | ```C++ 211 | // SYNTAX 212 | RootCloud.publish(const char *eventName, const char *data, int ttl, [PRIVATE,PUBLIC], bool archive); 213 | RootCloud.publish(String eventName, String data, int ttl, [PRIVATE,PUBLIC], bool archive); 214 | 215 | // EXAMPLE USAGE 216 | RootCloud.publish("front-door-unlocked", NULL, 60, PRIVATE, true); 217 | RootCloud.publish("front-door-unlocked", NULL, 0, PUBLIC, true); 218 | ``` 219 | 220 | 221 | ```json 222 | COMPLEMENTARY API CALL 223 | GET /v1/events/{EVENT_NAME} 224 | 225 | # EXAMPLE REQUEST 226 | curl -H "Authorization: Bearer {ACCESS_TOKEN_GOES_HERE}" \ 227 | https://api.RootCloud.io/v1/events/motion-detected 228 | 229 | # Will return a stream that echoes text when your event is published 230 | event: motion-detected 231 | data: {"data":"23:23:44","ttl":"60","published_at":"2014-05-28T19:20:34.638Z","boardid":"0123456789abcdef"} 232 | ``` 233 | 234 | ### RootCloud.subscribe() 235 | 236 | Subscribe to events published by boards. 237 | 238 | This allows boards to talk to each other very easily. For example, one board could publish events when a motion sensor is triggered and another could subscribe to these events and respond by sounding an alarm. 239 | 240 | ```cpp 241 | int i = 0; 242 | 243 | void myHandler(const char *event, const char *data) 244 | { 245 | i++; 246 | Serial.print(i); 247 | Serial.print(event); 248 | Serial.print(", data: "); 249 | if (data) 250 | Serial.println(data); 251 | else 252 | Serial.println("NULL"); 253 | } 254 | 255 | void setup() 256 | { 257 | RootCloud.subscribe("temperature", myHandler); 258 | //Serial.begin(9600); 259 | //begin does not do anything for Serial which uses the cloud 260 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 261 | } 262 | ``` 263 | 264 | To use `RootCloud.subscribe()`, define a handler function and register it in `setup()`. 265 | 266 | 267 | --- 268 | 269 | You can listen to events published only by your own boards by adding a `MY_DEVICES` constant. 270 | 271 | ```cpp 272 | // only events from my boards 273 | RootCloud.subscribe("the_event_prefix", theHandler, MY_DEVICES); 274 | ``` 275 | 276 | --- 277 | 278 | You are also able to subscribe to events from a single board by specifying the Device's ID. 279 | 280 | ```cpp 281 | // Subscribe to events published from one board 282 | RootCloud.subscribe("motion/front-door", motionHandler, "55ff70064989495339432587"); 283 | ``` 284 | 285 | --- 286 | 287 | A subscription works like a prefix filter. If you subscribe to "foo", you will receive any event whose name begins with "foo", including "foo", "fool", "foobar", and "food/indian/sweet-curry-beans". 288 | 289 | Received events will be passed to a handler function similar to `RootCloud.function()`. 290 | A _subscription handler_ (like `myHandler` above) must return `void` and take two arguments, both of which are C strings (`const char *`). 291 | 292 | - The first argument is the full name of the published event. 293 | - The second argument (which may be NULL) is any data that came along with the event. 294 | 295 | `RootCloud.subscribe()` returns a `bool` indicating success. 296 | 297 | NOTE: A board can register up to 4 event handlers. This means you can call `RootCloud.subscribe()` a maximum of 4 times; after that it will return `false`. 298 | 299 | ### RootCloud.connect() 300 | 301 | `RootCloud.connect()` connects the board to the Cloud. This will automatically activate the Wi-Fi radio and attempt to connect to a Wi-Fi network if the board is not already connected to a network. 302 | 303 | ```cpp 304 | void setup() {} 305 | 306 | void loop() { 307 | if (RootCloud.connected() == false) { 308 | RootCloud.connect(); 309 | } 310 | } 311 | ``` 312 | 313 | After you call `RootCloud.connect()`, your loop will not be called again until the board finishes connecting to the RootCloud. Typically, you can expect a delay of approximately one second. 314 | 315 | In most cases, you do not need to call `RootCloud.connect()`; it is called automatically when the board turns on. Typically you only need to call `RootCloud.connect()` after disconnecting with [`RootCloud.disconnect()`](#rootcloud-disconnect) or when you change the [system mode](#advanced-system-modes). 316 | 317 | 318 | ### RootCloud.disconnect() 319 | 320 | `RootCloud.disconnect()` disconnects the board from the RootCloud. 321 | 322 | ```C++ 323 | int counter = 10000; 324 | 325 | void doConnectedWork() { 326 | digitalWrite(D7, HIGH); 327 | Serial.println("Working online"); 328 | } 329 | 330 | void doOfflineWork() { 331 | digitalWrite(D7, LOW); 332 | Serial.println("Working offline"); 333 | } 334 | 335 | bool needConnection() { 336 | --counter; 337 | if (0 == counter) 338 | counter = 10000; 339 | return (2000 > counter); 340 | } 341 | 342 | void setup() { 343 | pinMode(D7, OUTPUT); 344 | //Serial.begin(9600); 345 | //begin does not do anything for Serial which uses the cloud 346 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 347 | } 348 | 349 | void loop() { 350 | if (needConnection()) { 351 | if (!RootCloud.connected()) 352 | RootCloud.connect(); 353 | doConnectedWork(); 354 | } else { 355 | if (RootCloud.connected()) 356 | RootCloud.disconnect(); 357 | doOfflineWork(); 358 | } 359 | } 360 | ``` 361 | 362 | While this function will disconnect from the RootCloud, it will keep the connection to the Wi-Fi network. If you would like to completely deactivate the Wi-Fi module, use [`WiFi.off()`](#wifi-off). 363 | 364 | NOTE: When the board is disconnected, many features are not possible, including over-the-air updates, reading RootCloud.variables, and calling RootCloud.functions. 365 | 366 | *If you disconnect from the RootCloud, you will NOT BE ABLE to flash new firmware over the air. A power cycle will allow the upload to occur.* 367 | 368 | ### RootCloud.connected() 369 | 370 | Returns `true` when connected to the RootCloud, and `false` when disconnected from the RootCloud. 371 | 372 | ```C++ 373 | // SYNTAX 374 | RootCloud.connected(); 375 | 376 | RETURNS 377 | boolean (true or false) 378 | 379 | // EXAMPLE USAGE 380 | void setup() { 381 | //Serial.begin(9600); 382 | //begin does not do anything for Serial which uses the cloud 383 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 384 | } 385 | 386 | void loop() { 387 | if (RootCloud.connected()) { 388 | Serial.println("Connected!"); 389 | } 390 | delay(1000); 391 | } 392 | ``` 393 | 394 | ### RootCloud.process() 395 | 396 | `RootCloud.process()` allows the board to handle Wi-Fi processes, if it's not called frequently, the connection to the RootCloud may be lost, but it will be called automatically in most cases. 397 | 398 | ```cpp 399 | void setup() { 400 | //Serial.begin(9600); 401 | //begin does not do anything for Serial which uses the cloud 402 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 403 | } 404 | 405 | void loop() { 406 | while (1) { 407 | RootCloud.process(); 408 | redundantLoop(); 409 | } 410 | } 411 | 412 | void redundantLoop() { 413 | Serial.println("Well that was unnecessary."); 414 | } 415 | ``` 416 | 417 | `RootCloud.process()` is a blocking call, and blocks for a few milliseconds. `RootCloud.process()` is called automatically after every `loop()` and during delays. Typically you will not need to call `RootCloud.process()` unless you block in some other way and need to maintain the connection to the RootCloud. 418 | 419 | 420 | 421 | ### RootCloud.deviceID() 422 | 423 | `RootCloud.deviceID()` provides an easy way to extract the device ID of your board. It returns a [String object](#data-types-string-object) of the device ID, which is used frequently to identify your board. 424 | 425 | ```cpp 426 | // EXAMPLE USAGE 427 | 428 | void setup() 429 | { 430 | // Upload this from the RootCloud IDE 431 | //Serial.begin(9600); 432 | //begin does not do anything for Serial which uses the cloud 433 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 434 | 435 | String myID = RootCloud.deviceID(); 436 | // Prints out the device ID in the RootCloud IDE debug window 437 | Serial.println(myID); 438 | } 439 | 440 | void loop() {} 441 | ``` 442 | 443 | ### RootCloud.sleep() 444 | 445 | `RootCloud.sleep()` can be used to dramatically improve the battery life of a project by temporarily deactivating the Wi-Fi module, which is by far the biggest power draw. 446 | 447 | ```C++ 448 | // SYNTAX 449 | RootCloud.sleep(int seconds); 450 | ``` 451 | 452 | ```C++ 453 | // EXAMPLE USAGE: Put the Wi-Fi module in standby (low power) for 5 seconds 454 | RootCloud.sleep(5); 455 | ``` 456 | `RootCloud.sleep(int seconds)` does NOT stop the execution of user code (non-blocking call). User code will continue running while the Wi-Fi module is in standby mode. During sleep, WiFi.status() will return WIFI_OFF. Once sleep time has expired and the Wi-FI module attempts reconnection, WiFi.status() will return value WIFI_CONNECTING and WIFI_ON. 457 | 458 | `RootCloud.sleep(SLEEP_MODE_DEEP, int seconds)` can be used to put the entire board into a *deep sleep* mode. In this particular mode, the board shuts down the Wi-Fi radio and puts the microcontroller in a stand-by mode. When the board awakens from deep sleep, it will reset the board and run all user code from the beginning with no values being maintained in memory from before the deep sleep. As such, it is recommended that deep sleep be called only after all user code has completed. The Standby mode is used to achieve the lowest power consumption. After entering Standby mode, the SRAM and register contents are lost except for registers in the backup domain. 459 | 460 | ```C++ 461 | // SYNTAX 462 | RootCloud.sleep(SLEEP_MODE_DEEP, int seconds); 463 | ``` 464 | 465 | ```C++ 466 | // EXAMPLE USAGE: Put the board into deep sleep for 60 seconds 467 | RootCloud.sleep(SLEEP_MODE_DEEP,60); 468 | ``` 469 | The board will automatically *wake up* and reestablish the WiFi connection after the specified number of seconds. 470 | 471 | In *standard sleep mode*, the board's current consumption is in the range of: **30mA** 472 | 473 | In *deep sleep mode*, the board's current consumption is around: **20 μA** 474 | 475 | ### RootCloud.syncTime() 476 | 477 | Synchronize the time with the RootCloud. 478 | This happens automatically when the board connects to the Cloud. 479 | However, if your board runs continuously for a long time, 480 | you may want to synchronize once per day or so. 481 | 482 | ```C++ 483 | #define ONE_DAY_MILLIS (24 * 60 * 60 * 1000) 484 | unsigned long lastSync = millis(); 485 | 486 | void loop() { 487 | if (millis() - lastSync > ONE_DAY_MILLIS) { 488 | // Request time synchronization from the RootCloud 489 | RootCloud.syncTime(); 490 | lastSync = millis(); 491 | } 492 | } 493 | ``` 494 | 495 | 496 | 497 | WiFi 498 | ===== 499 | 500 | ### WiFi.on() 501 | 502 | `WiFi.on()` turns on the Wi-Fi module. Useful when you've turned it off, and you changed your mind. 503 | 504 | Note that `WiFi.on()` does not need to be called unless you have changed the [system mode](#advanced-system-modes) or you have previously turned the Wi-Fi module off. 505 | 506 | ### WiFi.off() 507 | 508 | `WiFi.off()` turns off the Wi-Fi module. Useful for saving power, since most of the power draw of the board is the Wi-Fi module. 509 | 510 | ### WiFi.connect() 511 | 512 | Attempts to connect to the Wi-Fi network. If there are no credentials stored, this will enter listening mode. If there are credentials stored, this will try the available credentials until connection is successful. When this function returns, the device may not have an IP address on the LAN; use `WiFi.ready()` to determine the connection status. 513 | 514 | ### WiFi.disconnect() 515 | 516 | Disconnects from the Wi-Fi network, but leaves the Wi-Fi module on. 517 | 518 | ### WiFi.connecting() 519 | 520 | This function will return `true` once the board is attempting to connect using stored Wi-Fi credentials, and will return `false` once the board has successfully connected to the Wi-Fi network. 521 | 522 | ### WiFi.ready() 523 | 524 | This function will return `true` once the board is connected to the network and has been assigned an IP address, which means that it's ready to open TCP sockets and send UDP datagrams. Otherwise it will return `false`. 525 | 526 | ### WiFi.listen() 527 | 528 | This will enter listening mode, which opens a Serial connection to get Wi-Fi credentials over USB, and also listens for credentials over Smart Config. 529 | 530 | ### WiFi.listening() 531 | 532 | This will return `true` once `WiFi.listen()` has been called and will return `false` once the board has been given some Wi-Fi credentials to try, either over USB or Smart Config. 533 | 534 | ### WiFi.setCredentials() 535 | 536 | Allows the user to set credentials for the Wi-Fi network from within the code. These credentials will replace the current defaults and the board will automatically attempt to connect to this network in the future. 537 | 538 | ```cpp 539 | // Connects to an unsecured network. 540 | WiFi.setCredentials(SSID); 541 | WiFi.setCredentials("My_Router_Is_Big"); 542 | 543 | // Connects to a network secured with WPA2 credentials. 544 | WiFi.setCredentials(SSID, PASSWORD); 545 | WiFi.setCredentials("My_Router", "mypasswordishuge"); 546 | 547 | // Connects to a network with a specified authentication procedure. 548 | // Options are WPA2, WPA, or WEP. 549 | WiFi.setCredentials(SSID, PASSWORD, AUTH); 550 | WiFi.setCredentials("My_Router", "wepistheworst", WEP); 551 | ``` 552 | 553 | ### WiFi.clearCredentials() 554 | 555 | This will clear all saved credentials from memory. This will return `true` on success and `false` if there is an error. 556 | 557 | ### WiFi.hasCredentials() 558 | 559 | Will return `true` if there are Wi-Fi credentials stored in memory. 560 | 561 | ### WiFi.macAddress() 562 | 563 | `WiFi.macAddress()` returns the MAC address of the device. 564 | 565 | ```cpp 566 | 567 | byte mac[6]; 568 | 569 | void setup() { 570 | //Serial.begin(9600); 571 | //begin does not do anything for Serial which uses the cloud 572 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 573 | 574 | WiFi.macAddress(mac); 575 | 576 | Serial.print(mac[5],HEX); 577 | Serial.print(":"); 578 | Serial.print(mac[4],HEX); 579 | Serial.print(":"); 580 | Serial.print(mac[3],HEX); 581 | Serial.print(":"); 582 | Serial.print(mac[2],HEX); 583 | Serial.print(":"); 584 | Serial.print(mac[1],HEX); 585 | Serial.print(":"); 586 | Serial.println(mac[0],HEX); 587 | } 588 | 589 | void loop() {} 590 | ``` 591 | 592 | ### WiFi.SSID() 593 | 594 | `WiFi.SSID()` returns the SSID of the network the board is currently connected to as a `char*`. 595 | 596 | ### WiFi.ping() 597 | 598 | `WiFi.ping()` allows you to ping an IP address and returns the number of packets received as an `int`. It takes two forms: 599 | 600 | `WiFi.ping(IPAddress remoteIP)` takes an `IPAddress` and pings that address. 601 | 602 | `WiFi.ping(IPAddress remoteIP, uint8_t nTries)` and pings that address a specified number of times. 603 | 604 | ### WiFi.localIP() 605 | 606 | `WiFi.localIP()` returns the local IP address assigned to the board as an `IPAddress`. 607 | 608 | ```cpp 609 | 610 | void setup() { 611 | //Serial.begin(9600); 612 | //begin does not do anything for Serial which uses the cloud 613 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 614 | 615 | // Prints out the local IP over Serial. 616 | Serial.println(WiFi.localIP()); 617 | } 618 | ``` 619 | 620 | ### WiFi.subnetMask() 621 | 622 | `WiFi.subnetMask()` returns the subnet mask of the network as an `IPAddress`. 623 | 624 | ```cpp 625 | 626 | void setup() { 627 | //Serial.begin(9600); 628 | //begin does not do anything for Serial which uses the cloud 629 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 630 | 631 | // Prints out the subnet mask over Serial. 632 | Serial.println(WiFi.subnetMask()); 633 | } 634 | ``` 635 | 636 | ### WiFi.gatewayIP() 637 | 638 | `WiFi.gatewayIP()` returns the gateway IP address of the network as an `IPAddress`. 639 | 640 | ```cpp 641 | 642 | void setup() { 643 | //Serial.begin(9600); 644 | //begin does not do anything for Serial which uses the cloud 645 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 646 | 647 | // Prints out the gateway IP over Serial. 648 | Serial.println(WiFi.gatewayIP()); 649 | } 650 | ``` 651 | 652 | Input/Output 653 | ===== 654 | 655 | Setup 656 | ----- 657 | 658 | ### pinMode() 659 | 660 | `pinMode()` configures the specified pin to behave either as an input (with or without an internal weak pull-up or pull-down resistor), or an output. 661 | 662 | ```C++ 663 | // SYNTAX 664 | pinMode(pin,mode); 665 | ``` 666 | 667 | `pinMode()` takes two arguments, `pin`: the number of the pin whose mode you wish to set and `mode`: `INPUT, INPUT_PULLUP, INPUT_PULLDOWN or OUTPUT.` 668 | 669 | `pinMode()` does not return anything. 670 | 671 | ```C++ 672 | // EXAMPLE USAGE 673 | int button = D0; // button is connected to D0 674 | int LED = D1; // LED is connected to D1 675 | 676 | void setup() 677 | { 678 | pinMode(LED, OUTPUT); // sets pin as output 679 | pinMode(button, INPUT_PULLDOWN); // sets pin as input 680 | } 681 | 682 | void loop() 683 | { 684 | // blink the LED as long as the button is pressed 685 | while(digitalRead(button) == HIGH) { 686 | digitalWrite(LED, HIGH); // sets the LED on 687 | delay(200); // waits for 200mS 688 | digitalWrite(LED, LOW); // sets the LED off 689 | delay(200); // waits for 200mS 690 | } 691 | } 692 | ``` 693 | 694 | I/O 695 | ------ 696 | 697 | ### digitalWrite() 698 | 699 | Write a `HIGH` or a `LOW` value to a digital pin. 700 | 701 | ```C++ 702 | // SYNTAX 703 | digitalWrite(pin, value); 704 | ``` 705 | 706 | If the pin has been configured as an `OUTPUT` with `pinMode()` or if previously used with `analogWrite()`, its voltage will be set to the corresponding value: 3.3V for HIGH, 0V (ground) for LOW. 707 | 708 | `digitalWrite()` takes two arguments, `pin`: the number of the pin whose value you wish to set and `value`: `HIGH` or `LOW`. 709 | 710 | `digitalWrite()` does not return anything. 711 | 712 | ```C++ 713 | // EXAMPLE USAGE 714 | int LED = D1; // LED connected to D1 715 | 716 | void setup() 717 | { 718 | pinMode(LED, OUTPUT); // sets pin as output 719 | } 720 | 721 | void loop() 722 | { 723 | digitalWrite(LED, HIGH); // sets the LED on 724 | delay(200); // waits for 200mS 725 | digitalWrite(LED, LOW); // sets the LED off 726 | delay(200); // waits for 200mS 727 | } 728 | ``` 729 | 730 | ### digitalRead() 731 | 732 | Reads the value from a specified digital `pin`, either `HIGH` or `LOW`. 733 | 734 | ```C++ 735 | // SYNTAX 736 | digitalRead(pin); 737 | ``` 738 | 739 | `digitalRead()` takes one argument, `pin`: the number of the digital pin you want to read. 740 | 741 | `digitalRead()` returns `HIGH` or `LOW`. 742 | 743 | ```C++ 744 | // EXAMPLE USAGE 745 | int button = D0; // button is connected to D0 746 | int LED = D1; // LED is connected to D1 747 | int val = 0; // variable to store the read value 748 | 749 | void setup() 750 | { 751 | pinMode(LED, OUTPUT); // sets pin as output 752 | pinMode(button, INPUT_PULLDOWN); // sets pin as input 753 | } 754 | 755 | void loop() 756 | { 757 | val = digitalRead(button); // read the input pin 758 | digitalWrite(LED, val); // sets the LED to the button's value 759 | } 760 | 761 | ``` 762 | 763 | ### analogWrite() 764 | 765 | Writes an analog value (PWM wave) to a pin. Can be used to light a LED at varying brightnesses or drive a motor at various speeds. After a call to analogWrite(), the pin will generate a steady square wave of the specified duty cycle until the next call to analogWrite() (or a call to digitalRead() or digitalWrite() on the same pin). The frequency of the PWM signal is approximately 500 Hz. 766 | 767 | On the Oak, this function works on all digital pins. Only 6 pins can use the PWM function at one time. 768 | 769 | The analogWrite function has nothing to do with the analog pins or the analogRead function. 770 | 771 | ```C++ 772 | // SYNTAX 773 | analogWrite(pin, value); 774 | ``` 775 | 776 | `analogWrite()` takes two arguments, `pin`: the number of the pin whose value you wish to set and `value`: the duty cycle: between 0 (always off) and 255 (always on). NOTE: `pinMode(pin, OUTPUT);` is required before calling `analogWrite(pin, value);` or else the `pin` will not be initialized as a PWM output and set to the desired duty cycle. 777 | 778 | `analogWrite()` does not return anything. 779 | 780 | ```C++ 781 | // EXAMPLE USAGE 782 | int ledPin = D1; // LED connected to digital pin D1 783 | int analogPin = A0; // potentiometer connected to analog pin A0 784 | int val = 0; // variable to store the read value 785 | 786 | void setup() 787 | { 788 | pinMode(ledPin, OUTPUT); // sets the pin as output 789 | } 790 | 791 | void loop() 792 | { 793 | val = analogRead(analogPin); // read the input pin 794 | analogWrite(ledPin, val/4); // analogRead values go from 0 to 1023, 795 | // analogWrite values from 0 to 255. 796 | delay(10); 797 | } 798 | ``` 799 | 800 | ### analogRead() 801 | 802 | Reads the value from the specified analog pin. The Oak one channel (A0) with a 10-bit resolution. This means that it will map input voltages between 0 and 3.3 volts into integer values between 0 and 1023. This yields a resolution between readings of: 3.3 volts / 1023 units or, 0.0032 volts (3.2 mV) per unit. 803 | 804 | ```C++ 805 | // SYNTAX 806 | analogRead(pin); 807 | ``` 808 | /4 809 | `analogRead()` takes one argument `pin`: the number of the analog input pin to read from ('A0 to A7'.) 810 | 811 | `analogRead()` returns an integer value ranging from 0 to 1023. 812 | 813 | ```C++ 814 | // EXAMPLE USAGE 815 | int ledPin = D1; // LED connected to digital pin D1 816 | int analogPin = A0; // potentiometer connected to analog pin A0 817 | int val = 0; // variable to store the read value 818 | 819 | void setup() 820 | { 821 | pinMode(ledPin, OUTPUT); // sets the pin as output 822 | } 823 | 824 | void loop() 825 | { 826 | val = analogRead(analogPin); // read the input pin 827 | analogWrite(ledPin, val/4); // analogRead values go from 0 to 1023, analogWrite values from 0 to 255 828 | delay(10); 829 | } 830 | ``` 831 | 832 | Advanced I/O 833 | ------ 834 | 835 | ### shiftOut() 836 | 837 | Shifts out a byte of data one bit at a time on a specified pin. Starts from either the most (i.e. the leftmost) or least (rightmost) significant bit. Each bit is written in turn to a data pin, after which a clock pin is pulsed (taken high, then low) to indicate that the bit is available. 838 | Note: if you're interfacing with a device that's clocked by rising edges, you'll need to make sure that the clock pin is low before the call to shiftOut(), e.g. with a call to digitalWrite(clockPin, LOW). 839 | This is a software implementation; see also the SPI function, which provides a hardware implementation that is faster but works only on specific pins. 840 | 841 | 842 | ```C++ 843 | // SYNTAX 844 | shiftOut(dataPin, clockPin, bitOrder, value) 845 | ``` 846 | 847 | `shiftOut()` takes four arguments, 'dataPin': the pin on which to output each bit, `clockPin`: the pin to toggle once the dataPin has been set to the correct value, `bitOrder`: which order to shift out the bits; either MSBFIRST or LSBFIRST (Most Significant Bit First, or, Least Significant Bit First) and `value`: the data (byte) to shift out. 848 | 849 | `shiftOut()` does not return anything. 850 | 851 | ```C++ 852 | // EXAMPLE USAGE 853 | 854 | // Use digital pins D0 for data and D1 for clock 855 | int dataPin = D0; 856 | int clock = D1; 857 | 858 | uint8_t data = 50; 859 | 860 | setup() { 861 | // Set data and clock pins as OUTPUT pins before using shiftOut() 862 | pinMode(dataPin, OUTPUT); 863 | pinMode(clock, OUTPUT); 864 | 865 | // shift out data using MSB first 866 | shiftOut(dataPin, clock, MSBFIRST, data); 867 | 868 | // Or do this for LSBFIRST serial 869 | shiftOut(dataPin, clock, LSBFIRST, data); 870 | } 871 | 872 | loop() { 873 | // nothing to do 874 | } 875 | ``` 876 | 877 | ### shiftIn() 878 | 879 | Shifts in a byte of data one bit at a time. Starts from either the most (i.e. the leftmost) or least (rightmost) significant bit. For each bit, the clock pin is pulled high, the next bit is read from the data line, and then the clock pin is taken low. 880 | Note: if you're interfacing with a device that's clocked by rising edges, you'll need to make sure that the clock pin is low before the call to shiftOut(), e.g. with a call to digitalWrite(clockPin, LOW). 881 | This is a software implementation; see also the SPI function, which provides a hardware implementation that is faster but works only on specific pins. 882 | 883 | 884 | ```C++ 885 | // SYNTAX 886 | shiftIn(dataPin, clockPin, bitOrder) 887 | ``` 888 | 889 | `shiftIn()` takes three arguments, 'dataPin': the pin on which to input each bit, `clockPin`: the pin to toggle to signal a read from dataPin, `bitOrder`: which order to shift in the bits; either MSBFIRST or LSBFIRST (Most Significant Bit First, or, Least Significant Bit First). 890 | 891 | `shiftIn()` returns the byte value read. 892 | 893 | 894 | ```C++ 895 | // EXAMPLE USAGE 896 | 897 | // Use digital pins D0 for data and D1 for clock 898 | int dataPin = D0; 899 | int clock = D1; 900 | 901 | uint8_t data; 902 | 903 | setup() { 904 | // Set data as INPUT and clock pin as OUTPUT before using shiftIn() 905 | pinMode(dataPin, INPUT); 906 | pinMode(clock, OUTPUT); 907 | 908 | // shift in data using MSB first 909 | data = shiftIn(dataPin, clock, MSBFIRST); 910 | 911 | // Or do this for LSBFIRST serial 912 | data = shiftIn(dataPin, clock, LSBFIRST); 913 | } 914 | 915 | loop() { 916 | // nothing to do 917 | } 918 | ``` 919 | 920 | 921 | Communication 922 | === 923 | 924 | Serial 925 | ----- 926 | 927 | Used for communication between the board and a computer or other devices. The board has one virtual and one physical serial channel: 928 | 929 | `Serial:` This channel communicates through the RootCloud and sends to/receives from the Debug Terminal in the RootCloud IDE. This will also be implemented with a helper application to allow it to show up as a virtual COM port on a Windows/OS X/Linux computer. 930 | 931 | `Serial1:` This channel is available via the board's TX and RX pins. 932 | 933 | To use the TX/RX (Serial1) pins to communicate with your personal computer, you will need an additional USB-to-serial adapter. To use them to communicate with an external TTL serial device, connect the TX pin to your device's RX pin, the RX to your device's TX pin, and the ground of your board to your device's ground. 934 | 935 | **NOTE:** Please take into account that the voltage levels on these pins runs at 0V to 3.3V and should not be connected directly to a computer's RS232 serial port which operates at +/- 12V and can damage the board. 936 | 937 | ### begin() 938 | 939 | Sets the data rate in bits per second (baud) for serial data transmission. For communicating with the computer, use one of these rates: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200. You can, however, specify other rates - for example, to communicate over pins TX and RX with a component that requires a particular baud rate. 940 | 941 | ```C++ 942 | // SYNTAX 943 | Serial.begin(speed); // serial via cloud 944 | Serial1.begin(speed); // serial via TX and RX pins 945 | ``` 946 | `speed`: parameter that specifies the baud rate *(long)* 947 | 948 | `begin()` does not return anything 949 | 950 | ```C++ 951 | // EXAMPLE USAGE 952 | void setup() 953 | { 954 | //Serial.begin(9600); 955 | //begin does not do anything for Serial which uses the cloud 956 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 957 | 958 | Serial1.begin(9600); // open serial over TX and RX pins 959 | 960 | Serial.println("Hello Computer"); 961 | Serial1.println("Hello Serial 1"); 962 | } 963 | 964 | void loop() {} 965 | ``` 966 | 967 | ### end() 968 | 969 | Disables serial communication, allowing the RX and TX pins to be used for general input and output. To re-enable serial communication, call `Serial1.begin()`. 970 | 971 | ```C++ 972 | // SYNTAX 973 | Serial1.end(); 974 | ``` 975 | 976 | ### available() 977 | 978 | Get the number of bytes (characters) available for reading from the serial port. This is data that's already arrived and stored in the serial receive buffer (which holds 64 bytes). 979 | 980 | ```C++ 981 | // EXAMPLE USAGE 982 | void setup() 983 | { 984 | //Serial.begin(9600); 985 | //begin does not do anything for Serial which uses the cloud 986 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 987 | Serial1.begin(9600); 988 | 989 | } 990 | 991 | void loop() 992 | { 993 | // read from port 0, send to port 1: 994 | if (Serial.available()) 995 | { 996 | int inByte = Serial.read(); 997 | Serial1.write(inByte); 998 | } 999 | // read from port 1, send to port 0: 1000 | if (Serial1.available()) 1001 | { 1002 | int inByte = Serial1.read(); 1003 | Serial.write(inByte); 1004 | } 1005 | } 1006 | ``` 1007 | 1008 | ### peek() 1009 | 1010 | Returns the next byte (character) of incoming serial data without removing it from the internal serial buffer. That is, successive calls to peek() will return the same character, as will the next call to `read()`. 1011 | 1012 | ```C++ 1013 | // SYNTAX 1014 | Serial.peek(); 1015 | Serial1.peek(); 1016 | ``` 1017 | `peek()` returns the first byte of incoming serial data available (or `-1` if no data is available) - *int* 1018 | 1019 | ### write() 1020 | 1021 | Writes binary data to the serial port. This data is sent as a byte or series of bytes; to send the characters representing the digits of a number use the `print()` function instead. 1022 | 1023 | ```C++ 1024 | // SYNTAX 1025 | Serial.write(val); 1026 | Serial.write(str); 1027 | Serial.write(buf, len); 1028 | ``` 1029 | 1030 | *Parameters:* 1031 | 1032 | - `val`: a value to send as a single byte 1033 | - `str`: a string to send as a series of bytes 1034 | - `buf`: an array to send as a series of bytes 1035 | - `len`: the length of the buffer 1036 | 1037 | `write()` will return the number of bytes written, though reading that number is optional. 1038 | 1039 | ```C++ 1040 | // EXAMPLE USAGE 1041 | void setup() 1042 | { 1043 | //Serial.begin(9600); 1044 | //begin does not do anything for Serial which uses the cloud 1045 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 1046 | } 1047 | 1048 | void loop() 1049 | { 1050 | Serial.write(45); // send a byte with the value 45 1051 | 1052 | int bytesSent = Serial.write(“hello”); //send the string “hello” and return the length of the string. 1053 | } 1054 | ``` 1055 | 1056 | ### read() 1057 | 1058 | Reads incoming serial data. 1059 | 1060 | ```C++ 1061 | // SYNTAX 1062 | Serial.read(); 1063 | Serial1.read(); 1064 | ``` 1065 | `read()` returns the first byte of incoming serial data available (or -1 if no data is available) - *int* 1066 | 1067 | ```C++ 1068 | // EXAMPLE USAGE 1069 | int incomingByte = 0; // for incoming serial data 1070 | 1071 | void setup() { 1072 | //Serial.begin(9600); 1073 | //begin does not do anything for Serial which uses the cloud 1074 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands // opens serial port, sets data rate to 9600 bps 1075 | } 1076 | 1077 | void loop() { 1078 | // send data only when you receive data: 1079 | if (Serial.available() > 0) { 1080 | // read the incoming byte: 1081 | incomingByte = Serial.read(); 1082 | 1083 | // say what you got: 1084 | Serial.print("I received: "); 1085 | Serial.println(incomingByte, DEC); 1086 | } 1087 | } 1088 | ``` 1089 | ### print() 1090 | 1091 | Prints data to the serial port as human-readable ASCII text. This command can take many forms. Numbers are printed using an ASCII character for each digit. Floats are similarly printed as ASCII digits, defaulting to two decimal places. Bytes are sent as a single character. Characters and strings are sent as is. For example: 1092 | 1093 | - Serial.print(78) gives "78" 1094 | - Serial.print(1.23456) gives "1.23" 1095 | - Serial.print('N') gives "N" 1096 | - Serial.print("Hello world.") gives "Hello world." 1097 | 1098 | An optional second parameter specifies the base (format) to use; permitted values are BIN (binary, or base 2), OCT (octal, or base 8), DEC (decimal, or base 10), HEX (hexadecimal, or base 16). For floating point numbers, this parameter specifies the number of decimal places to use. For example: 1099 | 1100 | - Serial.print(78, BIN) gives "1001110" 1101 | - Serial.print(78, OCT) gives "116" 1102 | - Serial.print(78, DEC) gives "78" 1103 | - Serial.print(78, HEX) gives "4E" 1104 | - Serial.println(1.23456, 0) gives "1" 1105 | - Serial.println(1.23456, 2) gives "1.23" 1106 | - Serial.println(1.23456, 4) gives "1.2346" 1107 | 1108 | ### println() 1109 | 1110 | Prints data to the serial port as human-readable ASCII text followed by a carriage return character (ASCII 13, or '\r') and a newline character (ASCII 10, or '\n'). This command takes the same forms as `Serial.print()`. 1111 | 1112 | ```C++ 1113 | // SYNTAX 1114 | Serial.println(val); 1115 | Serial.println(val, format); 1116 | ``` 1117 | 1118 | *Parameters:* 1119 | 1120 | - `val`: the value to print - any data type 1121 | - `format`: specifies the number base (for integral data types) or number of decimal places (for floating point types) 1122 | 1123 | `println()` returns the number of bytes written, though reading that number is optional - `size_t (long)` 1124 | 1125 | ```C++ 1126 | EXAMPLE 1127 | //reads an analog input on analog in A0, prints the value out. 1128 | 1129 | int analogValue = 0; // variable to hold the analog value 1130 | 1131 | void setup() 1132 | { 1133 | //Serial.begin(9600); 1134 | //begin does not do anything for Serial which uses the cloud 1135 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 1136 | } 1137 | 1138 | void loop() { 1139 | // read the analog input on pin A0: 1140 | analogValue = analogRead(A0); 1141 | 1142 | // print it out in many formats: 1143 | Serial.println(analogValue); // print as an ASCII-encoded decimal 1144 | Serial.println(analogValue, DEC); // print as an ASCII-encoded decimal 1145 | Serial.println(analogValue, HEX); // print as an ASCII-encoded hexadecimal 1146 | Serial.println(analogValue, OCT); // print as an ASCII-encoded octal 1147 | Serial.println(analogValue, BIN); // print as an ASCII-encoded binary 1148 | 1149 | // delay 10 milliseconds before the next reading: 1150 | delay(10); 1151 | } 1152 | ``` 1153 | 1154 | ### flush() 1155 | 1156 | Waits for the transmission of outgoing serial data to complete. 1157 | 1158 | ```C++ 1159 | // SYNTAX 1160 | Serial.flush(); 1161 | Serial1.flush(); 1162 | ``` 1163 | 1164 | `flush()` neither takes a parameter nor returns anything 1165 | 1166 | SPI 1167 | ---- 1168 | This library allows you to communicate with SPI devices, with the Oak as the master device. 1169 | 1170 | ### begin() 1171 | 1172 | Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low, and SS high. 1173 | 1174 | Note that once the pin is configured, you can't use it anymore as a general I/O, unless you call the SPI.end() method on the same pin. 1175 | 1176 | ```C++ 1177 | // SYNTAX 1178 | SPI.begin(); 1179 | ``` 1180 | 1181 | ### end() 1182 | 1183 | Disables the SPI bus (leaving pin modes unchanged). 1184 | 1185 | ```C++ 1186 | // SYNTAX 1187 | SPI.end(); 1188 | ``` 1189 | 1190 | ### setBitOrder() 1191 | 1192 | Sets the order of the bits shifted out of and into the SPI bus, either LSBFIRST (least-significant bit first) or MSBFIRST (most-significant bit first). 1193 | 1194 | ```C++ 1195 | // SYNTAX 1196 | SPI.setBitOrder(order); 1197 | ``` 1198 | 1199 | Where, the parameter `order` can either be `LSBFIRST` or `MSBFIRST`. 1200 | 1201 | ### setClockDivider() 1202 | 1203 | Sets the SPI clock divider relative to the system clock. The available dividers are 2, 4, 8, 16, 32, 64, 128 or 256. The default setting is SPI_CLOCK_DIV4, which sets the SPI clock to one-quarter the frequency of the system clock. 1204 | 1205 | ```C++ 1206 | // SYNTAX 1207 | SPI.setClockDivider(divider) ; 1208 | ``` 1209 | Where the parameter, `divider` can be: 1210 | 1211 | - `SPI_CLOCK_DIV2` 1212 | - `SPI_CLOCK_DIV4` 1213 | - `SPI_CLOCK_DIV8` 1214 | - `SPI_CLOCK_DIV16` 1215 | - `SPI_CLOCK_DIV32` 1216 | - `SPI_CLOCK_DIV64` 1217 | - `SPI_CLOCK_DIV128` 1218 | - `SPI_CLOCK_DIV256` 1219 | 1220 | ### setDataMode() 1221 | 1222 | Sets the SPI data mode: that is, clock polarity and phase. See the [Wikipedia article on SPI](http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus) for details. 1223 | 1224 | ```C++ 1225 | // SYNTAX 1226 | SPI.setDataMode(mode) ; 1227 | ``` 1228 | Where the parameter, `mode` can be: 1229 | 1230 | - `SPI_MODE0` 1231 | - `SPI_MODE1` 1232 | - `SPI_MODE2` 1233 | - `SPI_MODE3` 1234 | 1235 | ### transfer() 1236 | 1237 | Transfers one byte over the SPI bus, both sending and receiving. 1238 | 1239 | ```C++ 1240 | // SYNTAX 1241 | SPI.transfer(val); 1242 | ``` 1243 | Where the parameter `val`, can is the byte to send out over the SPI bus. 1244 | 1245 | Wire 1246 | ---- 1247 | 1248 | This library allows you to communicate with I2C / TWI devices. On the Oak, D0 is the Serial Data Line (SDA) and D2 is the Serial Clock (SCL). Both of these pins runs at 3.3V logic. 1249 | Connect a pull-up resistor(1.5K to 10K) on SDA line. Connect a pull-up resistor(1.5K to 10K) on SCL line. 1250 | 1251 | ### setSpeed() 1252 | 1253 | Sets the I2C clock speed. This is an optional call (not from the original Arduino specs.) and must be called once before calling begin(). The default I2C clock speed is 100KHz. 1254 | 1255 | ```C++ 1256 | // SYNTAX 1257 | Wire.setSpeed(clockSpeed); 1258 | Wire.begin(); 1259 | ``` 1260 | 1261 | Parameters: 1262 | 1263 | - `clockSpeed`: CLOCK_SPEED_100KHZ, CLOCK_SPEED_400KHZ or user specified speeds. 1264 | 1265 | ### stretchClock() 1266 | 1267 | Enables or Disables I2C clock stretching. This is an optional call (not from the original Arduino specs.) and must be called once before calling begin(). The default I2C stretch mode is disabled. 1268 | 1269 | ```C++ 1270 | // SYNTAX 1271 | Wire.stretchClock(stretch); 1272 | Wire.begin(); 1273 | ``` 1274 | 1275 | Parameters: 1276 | 1277 | - `stretch`: boolean. true will enable clock stretching. false will disable clock stretching. 1278 | 1279 | 1280 | ### begin() 1281 | 1282 | Initiate the Wire library and join the I2C bus as a master or slave. This should normally be called only once. 1283 | 1284 | ```C++ 1285 | // SYNTAX 1286 | Wire.begin(); 1287 | Wire.begin(address); 1288 | ``` 1289 | 1290 | Parameters: `address`: the 7-bit slave address (optional); if not specified, join the bus as a master. 1291 | 1292 | ### requestFrom() 1293 | 1294 | Used by the master to request bytes from a slave device. The bytes may then be retrieved with the `available()` and `read()` functions. 1295 | 1296 | If true, requestFrom() sends a stop message after the request, releasing the I2C bus. 1297 | 1298 | If false, requestFrom() sends a restart message after the request. The bus will not be released, which prevents another master device from requesting between messages. This allows one master device to send multiple requests while in control. 1299 | 1300 | The default value is true. 1301 | 1302 | ```C++ 1303 | // SYNTAX 1304 | Wire.requestFrom(address, quantity); 1305 | Wire.requestFrom(address, quantity, stop) ; 1306 | ``` 1307 | 1308 | Parameters: 1309 | 1310 | - `address`: the 7-bit address of the device to request bytes from 1311 | - `quantity`: the number of bytes to request 1312 | - `stop`: boolean. true will send a stop message after the request, releasing the bus. false will continually send a restart after the request, keeping the connection active. 1313 | 1314 | Returns: `byte` : the number of bytes returned from the slave device. 1315 | 1316 | ### beginTransmission() 1317 | 1318 | Begin a transmission to the I2C slave device with the given address. Subsequently, queue bytes for transmission with the `write()` function and transmit them by calling `endTransmission()`. 1319 | 1320 | ```C++ 1321 | // SYNTAX 1322 | Wire.beginTransmission(address); 1323 | ``` 1324 | 1325 | Parameters: `address`: the 7-bit address of the device to transmit to. 1326 | 1327 | ### endTransmission() 1328 | 1329 | Ends a transmission to a slave device that was begun by `beginTransmission()` and transmits the bytes that were queued by `write()`. 1330 | 1331 | If true, `endTransmission()` sends a stop message after transmission, releasing the I2C bus. 1332 | 1333 | If false, `endTransmission()` sends a restart message after transmission. The bus will not be released, which prevents another master device from transmitting between messages. This allows one master device to send multiple transmissions while in control. 1334 | 1335 | The default value is true. 1336 | 1337 | ```C++ 1338 | Wire.endTransmission(); 1339 | Wire.endTransmission(stop); 1340 | ``` 1341 | 1342 | Parameters: `stop` : boolean. 1343 | `true` will send a stop message, releasing the bus after transmission. `false` will send a restart, keeping the connection active. 1344 | 1345 | Returns: `byte`, which indicates the status of the transmission: 1346 | 1347 | - 0: success 1348 | - 1: data too long to fit in transmit buffer 1349 | - 2: received NACK on transmit of address 1350 | - 3: received NACK on transmit of data 1351 | - 4: other error 1352 | 1353 | ### write() 1354 | 1355 | Writes data from a slave device in response to a request from a master, or queues bytes for transmission from a master to slave device (in-between calls to `beginTransmission()` and `endTransmission()`). 1356 | 1357 | ```C++ 1358 | // Syntax 1359 | Wire.write(value); 1360 | Wire.write(string); 1361 | Wire.write(data, length); 1362 | ``` 1363 | Parameters: 1364 | 1365 | - `value`: a value to send as a single byte 1366 | - `string`: a string to send as a series of bytes 1367 | - `data`: an array of data to send as bytes 1368 | - `length`: the number of bytes to transmit 1369 | 1370 | Returns: `byte` 1371 | 1372 | `write()` will return the number of bytes written, though reading that number is optional. 1373 | 1374 | ```C++ 1375 | // EXAMPLE USAGE 1376 | 1377 | void setup() 1378 | { 1379 | Wire.begin(); // join i2c bus as master 1380 | } 1381 | 1382 | byte x = 0; 1383 | 1384 | void loop() 1385 | { 1386 | Wire.beginTransmission(4); // transmit to slave device #4 1387 | Wire.write("x is "); // sends five bytes 1388 | Wire.write(x); // sends one byte 1389 | Wire.endTransmission(); // stop transmitting 1390 | 1391 | x++; 1392 | delay(500); 1393 | } 1394 | ``` 1395 | 1396 | ### available() 1397 | 1398 | Returns the number of bytes available for retrieval with `read()`. This should be called on a master device after a call to `requestFrom()` or on a slave inside the `onReceive()` handler. 1399 | 1400 | ```C++ 1401 | Wire.available(); 1402 | ``` 1403 | 1404 | Returns: The number of bytes available for reading. 1405 | 1406 | ### read() 1407 | 1408 | Reads a byte that was transmitted from a slave device to a master after a call to `requestFrom()` or was transmitted from a master to a slave. `read()` inherits from the `Stream` utility class. 1409 | 1410 | ```C++ 1411 | Wire.read() ; 1412 | ``` 1413 | 1414 | Returns: The next byte received 1415 | 1416 | ```C++ 1417 | // EXAMPLE USAGE 1418 | 1419 | void setup() 1420 | { 1421 | Wire.begin(); // join i2c bus as master 1422 | //Serial.begin(9600); 1423 | //begin does not do anything for Serial which uses the cloud 1424 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands // start serial for output 1425 | } 1426 | 1427 | void loop() 1428 | { 1429 | Wire.requestFrom(2, 6); // request 6 bytes from slave device #2 1430 | 1431 | while(Wire.available()) // slave may send less than requested 1432 | { 1433 | char c = Wire.read(); // receive a byte as character 1434 | Serial.print(c); // print the character 1435 | } 1436 | 1437 | delay(500); 1438 | } 1439 | ``` 1440 | 1441 | IPAddress 1442 | ----- 1443 | ### IPAddress 1444 | 1445 | Creates an IP address that can be used with TCPServer, TCPClient, and UDP objects. 1446 | 1447 | ```C++ 1448 | // EXAMPLE USAGE 1449 | IPAddress localIP; 1450 | IPAddress server(8,8,8,8); 1451 | IPAddress IPfromInt( 167772162UL ); // 10.0.0.2 as 10*256^3+0*256^2+0*256+2 1452 | uint8_t server[] = { 10, 0, 0, 2}; 1453 | IPAddress IPfromBytes( server ); 1454 | ``` 1455 | 1456 | The IPAddress also allows for comparisons. 1457 | 1458 | ```C++ 1459 | if (IPfromInt == IPfromBytes) 1460 | { 1461 | Serial.println("Same IP addresses"); 1462 | } 1463 | ``` 1464 | 1465 | You can also use indexing the get or change individual bytes in the IP address. 1466 | 1467 | ```C++ 1468 | // PING ALL HOSTS ON YOUR SUBNET EXCEPT YOURSELF 1469 | IPAddress localIP = WiFi.localIP(); 1470 | uint8_t myLastAddrByte = localIP[3]; 1471 | for(uint8_t ipRange=1; ipRange<255; ipRange++) 1472 | { 1473 | if (ipRange != myLastAddrByte) 1474 | { 1475 | localIP[3] = ipRange; 1476 | WiFi.ping(localIP); 1477 | } 1478 | } 1479 | ``` 1480 | 1481 | You can also assign to an IPAddress from an array of uint8's or a 32-bit unsigned integer. 1482 | 1483 | ```C++ 1484 | IPAddress IPfromInt; // 10.0.0.2 as 10*256^3+0*256^2+0*256+2 1485 | IPfromInt = 167772162UL; 1486 | uint8_t server[] = { 10, 0, 0, 2}; 1487 | IPAddress IPfromBytes; 1488 | IPfromBytes = server; 1489 | ``` 1490 | 1491 | Finally IPAddress can be used directly with print. 1492 | 1493 | ```C++ 1494 | // PRINT THE BOARD'S IP ADDRESS IN 1495 | // THE FORMAT 192.168.0.10 1496 | IPAddress myIP = WiFi.localIP(); 1497 | Serial.println(myIP); // prints the board's IP address 1498 | ``` 1499 | 1500 | TCPServer 1501 | ----- 1502 | ### TCPServer 1503 | 1504 | Create a server that listens for incoming connections on the specified port. 1505 | 1506 | ```C++ 1507 | // SYNTAX 1508 | TCPServer server = TCPServer(port); 1509 | ``` 1510 | 1511 | Parameters: `port`: the port to listen on (`int`) 1512 | 1513 | ```C++ 1514 | // EXAMPLE USAGE 1515 | 1516 | // telnet defaults to port 23 1517 | TCPServer server = TCPServer(23); 1518 | TCPClient client; 1519 | 1520 | void setup() 1521 | { 1522 | // start listening for clients 1523 | server.begin(); 1524 | 1525 | //Serial.begin(9600); 1526 | //begin does not do anything for Serial which uses the cloud 1527 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 1528 | 1529 | Serial.println(WiFi.localIP()); 1530 | Serial.println(WiFi.subnetMask()); 1531 | Serial.println(WiFi.gatewayIP()); 1532 | Serial.println(WiFi.SSID()); 1533 | } 1534 | 1535 | void loop() 1536 | { 1537 | if (client.connected()) { 1538 | // echo all available bytes back to the client 1539 | while (client.available()) { 1540 | server.write(client.read()); 1541 | } 1542 | } else { 1543 | // if no client is yet connected, check for a new connection 1544 | client = server.available(); 1545 | } 1546 | } 1547 | ``` 1548 | 1549 | ### begin() 1550 | 1551 | Tells the server to begin listening for incoming connections. 1552 | 1553 | ```C++ 1554 | // SYNTAX 1555 | server.begin(); 1556 | ``` 1557 | 1558 | ### available() 1559 | 1560 | Gets a client that is connected to the server and has data available for reading. The connection persists when the returned client object goes out of scope; you can close it by calling `client.stop()`. 1561 | 1562 | `available()` inherits from the `Stream` utility class. 1563 | 1564 | ### write() 1565 | 1566 | Write data to all the clients connected to a server. This data is sent as a byte or series of bytes. 1567 | 1568 | ```C++ 1569 | // Syntax 1570 | server.write(val); 1571 | server.write(buf, len); 1572 | ``` 1573 | 1574 | Parameters: 1575 | 1576 | - `val`: a value to send as a single byte (byte or char) 1577 | - `buf`: an array to send as a series of bytes (byte or char) 1578 | - `len`: the length of the buffer 1579 | 1580 | Returns: `byte`: `write()` returns the number of bytes written. It is not necessary to read this. 1581 | 1582 | ### print() 1583 | 1584 | Print data to all the clients connected to a server. Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3'). 1585 | 1586 | ```C++ 1587 | // Syntax 1588 | server.print(data); 1589 | server.print(data, BASE) ; 1590 | ``` 1591 | 1592 | Parameters: 1593 | 1594 | - `data`: the data to print (char, byte, int, long, or string) 1595 | - `BASE`(optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16). 1596 | 1597 | Returns: `byte`: `print()` will return the number of bytes written, though reading that number is optional 1598 | 1599 | ### println() 1600 | 1601 | Print data, followed by a newline, to all the clients connected to a server. Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3'). 1602 | 1603 | ```C++ 1604 | // Syntax 1605 | 1606 | server.println(); 1607 | server.println(data); 1608 | server.println(data, BASE) ; 1609 | ``` 1610 | 1611 | Parameters: 1612 | 1613 | - `data` (optional): the data to print (char, byte, int, long, or string) 1614 | - `BASE` (optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16). 1615 | 1616 | TCPClient 1617 | ----- 1618 | 1619 | ### TCPClient 1620 | 1621 | Creates a client which can connect to a specified internet IP address and port (defined in the `client.connect()` function). 1622 | 1623 | ```C++ 1624 | // SYNTAX 1625 | TCPClient client; 1626 | ``` 1627 | 1628 | ```C++ 1629 | // EXAMPLE USAGE 1630 | 1631 | TCPClient client; 1632 | byte server[] = { 74, 125, 224, 72 }; // Google 1633 | void setup() 1634 | { 1635 | //Serial.begin(9600); 1636 | //begin does not do anything for Serial which uses the cloud 1637 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 1638 | 1639 | Serial.println("connecting..."); 1640 | 1641 | if (client.connect(server, 80)) 1642 | { 1643 | Serial.println("connected"); 1644 | client.println("GET /search?q=unicorn HTTP/1.0"); 1645 | client.println("Host: www.google.com"); 1646 | client.println("Content-Length: 0"); 1647 | client.println(); 1648 | } 1649 | else 1650 | { 1651 | Serial.println("connection failed"); 1652 | } 1653 | } 1654 | 1655 | void loop() 1656 | { 1657 | if (client.available()) 1658 | { 1659 | char c = client.read(); 1660 | Serial.print(c); 1661 | } 1662 | 1663 | if (!client.connected()) 1664 | { 1665 | Serial.println(); 1666 | Serial.println("disconnecting."); 1667 | client.stop(); 1668 | for(;;); 1669 | } 1670 | } 1671 | ``` 1672 | 1673 | ### connected() 1674 | 1675 | Whether or not the client is connected. Note that a client is considered connected if the connection has been closed but there is still unread data. 1676 | 1677 | ```C++ 1678 | // SYNTAX 1679 | client.connected(); 1680 | ``` 1681 | 1682 | Returns true if the client is connected, false if not. 1683 | 1684 | ### connect() 1685 | 1686 | Connects to a specified IP address and port. The return value indicates success or failure. Also supports DNS lookups when using a domain name. 1687 | 1688 | ```C++ 1689 | // SYNTAX 1690 | 1691 | client.connect(); 1692 | client.connect(ip, port); 1693 | client.connect(URL, port); 1694 | ``` 1695 | 1696 | Parameters: 1697 | 1698 | - `ip`: the IP address that the client will connect to (array of 4 bytes) 1699 | - `URL`: the domain name the client will connect to (string, ex.:"RootCloud.io") 1700 | - `port`: the port that the client will connect to (`int`) 1701 | 1702 | Returns true if the connection succeeds, false if not. 1703 | 1704 | ### write() 1705 | 1706 | Write data to the server the client is connected to. This data is sent as a byte or series of bytes. 1707 | 1708 | ```C++ 1709 | // SYNTAX 1710 | client.write(val); 1711 | client.write(buf, len); 1712 | ``` 1713 | 1714 | Parameters: 1715 | 1716 | - `val`: a value to send as a single byte (byte or char) 1717 | - `buf`: an array to send as a series of bytes (byte or char) 1718 | - `len`: the length of the buffer 1719 | 1720 | Returns: `byte`: `write()` returns the number of bytes written. It is not necessary to read this value. 1721 | 1722 | ### print() 1723 | 1724 | Print data to the server that a client is connected to. Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3'). 1725 | 1726 | ```C++ 1727 | // Syntax 1728 | client.print(data); 1729 | client.print(data, BASE) ; 1730 | ``` 1731 | 1732 | Parameters: 1733 | 1734 | - `data`: the data to print (char, byte, int, long, or string) 1735 | - `BASE`(optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16). 1736 | 1737 | Returns: `byte`: `print()` will return the number of bytes written, though reading that number is optional 1738 | 1739 | ### println() 1740 | 1741 | Print data, followed by a carriage return and newline, to the server a client is connected to. Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three characters '1', '2', '3'). 1742 | 1743 | ```C++ 1744 | // Syntax 1745 | 1746 | client.println(); 1747 | client.println(data); 1748 | client.println(data, BASE) ; 1749 | ``` 1750 | 1751 | Parameters: 1752 | 1753 | - `data` (optional): the data to print (char, byte, int, long, or string) 1754 | - `BASE` (optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16). 1755 | 1756 | ### available() 1757 | 1758 | Returns the number of bytes available for reading (that is, the amount of data that has been written to the client by the server it is connected to). 1759 | 1760 | ```C++ 1761 | // SYNTAX 1762 | client.available(); 1763 | ``` 1764 | 1765 | Returns the number of bytes available. 1766 | 1767 | ### read() 1768 | Read the next byte received from the server the client is connected to (after the last call to `read()`). 1769 | 1770 | ```C++ 1771 | // SYNTAX 1772 | client.read(); 1773 | ``` 1774 | 1775 | Returns the next byte (or character), or -1 if none is available. 1776 | 1777 | ### flush() 1778 | 1779 | Discard any bytes that have been written to the client but not yet read. 1780 | 1781 | ```C++ 1782 | // SYNTAX 1783 | client.flush(); 1784 | ``` 1785 | 1786 | ### stop() 1787 | 1788 | Disconnect from the server. 1789 | 1790 | ```C++ 1791 | // SYNTAX 1792 | client.stop(); 1793 | ``` 1794 | 1795 | 1796 | UDP 1797 | ----- 1798 | 1799 | This class enables UDP messages to be sent and received. 1800 | 1801 | The UDP protocol implementation has known issues that will require extra consideration when programming with it. Please refer to the Known Issues category of the Community for details. The are also numerous working examples and workarounds in the searchable Community topics. 1802 | 1803 | 1804 | 1805 | 1806 | ### begin() 1807 | 1808 | Initializes the UDP library and network settings. 1809 | 1810 | ```cpp 1811 | // EXAMPLE USAGE 1812 | 1813 | // UDP Port used for two way communication 1814 | unsigned int localPort = 8888; 1815 | 1816 | // An UDP instance to let us send and receive packets over UDP 1817 | UDP Udp; 1818 | 1819 | void setup() { 1820 | // start the UDP 1821 | Udp.begin(localPort); 1822 | 1823 | // Print your device IP Address via serial 1824 | //Serial.begin(9600); 1825 | //begin does not do anything for Serial which uses the cloud 1826 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 1827 | Serial.println(WiFi.localIP()); 1828 | } 1829 | 1830 | void loop() { 1831 | // Check if data has been received 1832 | if (Udp.parsePacket() > 0) { 1833 | 1834 | // Read first char of data received 1835 | char c = Udp.read(); 1836 | 1837 | // Ignore other chars 1838 | Udp.flush(); 1839 | 1840 | // Store sender ip and port 1841 | IPAddress ipAddress = Udp.remoteIP(); 1842 | int port = Udp.remotePort(); 1843 | 1844 | // Echo back data to sender 1845 | Udp.beginPacket(ipAddress, port); 1846 | Udp.write(c); 1847 | Udp.endPacket(); 1848 | } 1849 | } 1850 | ``` 1851 | 1852 | ### available() 1853 | 1854 | Get the number of bytes (characters) available for reading from the buffer. This is data that's already arrived. 1855 | 1856 | This function can only be successfully called after `UDP.parsePacket()`. 1857 | 1858 | `available()` inherits from the `Stream` utility class. 1859 | 1860 | ```cpp 1861 | // SYNTAX 1862 | UDP.available() 1863 | ``` 1864 | 1865 | Returns the number of bytes available to read. 1866 | 1867 | ### beginPacket() 1868 | 1869 | Starts a connection to write UDP data to the remote connection. 1870 | 1871 | ```cpp 1872 | // SYNTAX 1873 | UDP.beginPacket(remoteIP, remotePort); 1874 | ``` 1875 | 1876 | Parameters: 1877 | 1878 | - `remoteIP`: the IP address of the remote connection (4 bytes) 1879 | - `remotePort`: the port of the remote connection (int) 1880 | 1881 | It returns nothing. 1882 | 1883 | ### endPacket() 1884 | 1885 | Called after writing UDP data to the remote connection. 1886 | 1887 | ```cpp 1888 | // SYNTAX 1889 | UDP.endPacket(); 1890 | ``` 1891 | 1892 | Parameters: NONE 1893 | 1894 | ### write() 1895 | 1896 | Writes UDP data to the remote connection. Must be wrapped between `beginPacket()` and `endPacket()`. `beginPacket()` initializes the packet of data, it is not sent until `endPacket()` is called. 1897 | 1898 | ```cpp 1899 | // SYNTAX 1900 | UDP.write(message); 1901 | UDP.write(buffer, size); 1902 | ``` 1903 | 1904 | Parameters: 1905 | 1906 | - `message`: the outgoing message (char) 1907 | - `buffer`: an array to send as a series of bytes (byte or char) 1908 | - `size`: the length of the buffer 1909 | 1910 | Returns: 1911 | 1912 | - `byte`: returns the number of characters sent. This does not have to be read 1913 | 1914 | 1915 | ### parsePacket() 1916 | 1917 | Checks for the presence of a UDP packet, and reports the size. `parsePacket()` must be called before reading the buffer with `UDP.read()`. 1918 | 1919 | ```cpp 1920 | // SYNTAX 1921 | UDP.parsePacket(); 1922 | ``` 1923 | 1924 | Parameters: NONE 1925 | 1926 | Returns: 1927 | 1928 | - `int`: the size of a received UDP packet 1929 | 1930 | ### read() 1931 | 1932 | Reads UDP data from the specified buffer. If no arguments are given, it will return the next character in the buffer. 1933 | 1934 | This function can only be successfully called after `UDP.parsePacket()`. 1935 | 1936 | ```cpp 1937 | // SYNTAX 1938 | UDP.read(); 1939 | UDP.read(packetBuffer, MaxSize); 1940 | ``` 1941 | Parameters: 1942 | 1943 | - `packetBuffer`: buffer to hold incoming packets (char) 1944 | - `MaxSize`: maximum size of the buffer (int) 1945 | 1946 | Returns: 1947 | 1948 | - `char`: returns the characters in the buffer 1949 | 1950 | 1951 | ### stop() 1952 | 1953 | Disconnect from the server. Release any resource being used during the UDP session. 1954 | 1955 | ```cpp 1956 | // SYNTAX 1957 | UDP.stop(); 1958 | ``` 1959 | Parameters: NONE 1960 | 1961 | ### remoteIP() 1962 | 1963 | Returns the IP address of sender of the packet parsed by `UDP.parsePacket()`. 1964 | 1965 | ```cpp 1966 | // SYNTAX 1967 | UDP.remoteIP(); 1968 | ``` 1969 | Parameters: NONE 1970 | 1971 | Returns: 1972 | 1973 | - 4 bytes : the IP address of the sender of the packet parsed by `UDP.parsePacket()`. 1974 | 1975 | 1976 | ### remotePort() 1977 | 1978 | Returns the port from which the UDP packet was sent. The packet is the one most recently processed by UDP.parsePacket()`. 1979 | 1980 | ```cpp 1981 | // SYNTAX 1982 | UDP.remotePort(); 1983 | ``` 1984 | Parameters: NONE 1985 | 1986 | Returns: 1987 | 1988 | - `int`: the port from which the packet parsed by `UDP.parsePacket()` was sent. 1989 | 1990 | Libraries 1991 | ===== 1992 | 1993 | Time 1994 | --- 1995 | 1996 | The board synchronizes time with the RootCloud during the handshake. 1997 | From then, the time is continually updated on the board. 1998 | This reduces the need for external libraries to manage dates and times. 1999 | 2000 | 2001 | ### hour() 2002 | 2003 | Retrieve the hour for the current or given time. 2004 | Integer is returned without a leading zero. 2005 | 2006 | ```cpp 2007 | // Print the hour for the current time 2008 | Serial.print(Time.hour()); 2009 | 2010 | // Print the hour for the given time, in this case: 4 2011 | Serial.print(Time.hour(1400647897)); 2012 | ``` 2013 | 2014 | Optional parameters: Integer (Unix timestamp) 2015 | 2016 | Returns: Integer 0-23 2017 | 2018 | 2019 | ### hourFormat12() 2020 | 2021 | Retrieve the hour in 12-hour format for the current or given time. 2022 | Integer is returned without a leading zero. 2023 | 2024 | ```cpp 2025 | // Print the hour in 12-hour format for the current time 2026 | Serial.print(Time.hourFormat12()); 2027 | 2028 | // Print the hour in 12-hour format for the given time, in this case: 15 2029 | Serial.print(Time.hourFormat12(1400684400)); 2030 | ``` 2031 | 2032 | Optional parameters: Integer (Unix timestamp) 2033 | 2034 | Returns: Integer 1-12 2035 | 2036 | 2037 | ### isAM() 2038 | 2039 | Returns true if the current or given time is AM. 2040 | 2041 | ```cpp 2042 | // Print true or false depending on whether the current time is AM 2043 | Serial.print(Time.isAM()); 2044 | 2045 | // Print whether the given time is AM, in this case: true 2046 | Serial.print(Time.isAM(1400647897)); 2047 | ``` 2048 | 2049 | Optional parameters: Integer (Unix timestamp) 2050 | 2051 | Returns: Unsigned 8-bit integer: 0 = false, 1 = true 2052 | 2053 | 2054 | ### isPM() 2055 | 2056 | Returns true if the current or given time is PM. 2057 | 2058 | ```cpp 2059 | // Print true or false depending on whether the current time is PM 2060 | Serial.print(Time.isPM()); 2061 | 2062 | // Print whether the given time is PM, in this case: false 2063 | Serial.print(Time.isPM(1400647897)); 2064 | ``` 2065 | 2066 | Optional parameters: Integer (Unix timestamp) 2067 | 2068 | Returns: Unsigned 8-bit integer: 0 = false, 1 = true 2069 | 2070 | 2071 | ### minute() 2072 | 2073 | Retrieve the minute for the current or given time. 2074 | Integer is returned without a leading zero. 2075 | 2076 | ```cpp 2077 | // Print the minute for the current time 2078 | Serial.print(Time.minute()); 2079 | 2080 | // Print the minute for the given time, in this case: 51 2081 | Serial.print(Time.minute(1400647897)); 2082 | ``` 2083 | 2084 | Optional parameters: Integer (Unix timestamp) 2085 | 2086 | Returns: Integer 0-59 2087 | 2088 | 2089 | ### second() 2090 | 2091 | Retrieve the seconds for the current or given time. 2092 | Integer is returned without a leading zero. 2093 | 2094 | ```cpp 2095 | // Print the second for the current time 2096 | Serial.print(Time.second()); 2097 | 2098 | // Print the second for the given time, in this case: 51 2099 | Serial.print(Time.second(1400647897)); 2100 | ``` 2101 | 2102 | Optional parameters: Integer (Unix timestamp) 2103 | 2104 | Returns: Integer 0-59 2105 | 2106 | 2107 | ### day() 2108 | 2109 | Retrieve the day for the current or given time. 2110 | Integer is returned without a leading zero. 2111 | 2112 | ```cpp 2113 | // Print the day for the current time 2114 | Serial.print(Time.day()); 2115 | 2116 | // Print the minute for the given time, in this case: 21 2117 | Serial.print(Time.day(1400647897)); 2118 | ``` 2119 | 2120 | Optional parameters: Integer (Unix timestamp) 2121 | 2122 | Returns: Integer 1-31 2123 | 2124 | 2125 | ### weekday() 2126 | 2127 | Retrieve the weekday for the current or given time. 2128 | 2129 | - 1 = Sunday 2130 | - 2 = Monday 2131 | - 3 = Tuesday 2132 | - 4 = Wednesday 2133 | - 5 = Thursday 2134 | - 6 = Friday 2135 | - 7 = Saturday 2136 | 2137 | ```cpp 2138 | // Print the weekday number for the current time 2139 | Serial.print(Time.weekday()); 2140 | 2141 | // Print the weekday for the given time, in this case: 4 2142 | Serial.print(Time.weekday(1400647897)); 2143 | ``` 2144 | 2145 | Optional parameters: Integer (Unix timestamp) 2146 | 2147 | Returns: Integer 1-7 2148 | 2149 | 2150 | ### month() 2151 | 2152 | Retrieve the month for the current or given time. 2153 | Integer is returned without a leading zero. 2154 | 2155 | ```cpp 2156 | // Print the month number for the current time 2157 | Serial.print(Time.month()); 2158 | 2159 | // Print the month for the given time, in this case: 5 2160 | Serial.print(Time.month(1400647897)); 2161 | ``` 2162 | 2163 | Optional parameters: Integer (Unix timestamp) 2164 | 2165 | Returns: Integer 1-12 2166 | 2167 | 2168 | ### year() 2169 | 2170 | Retrieve the 4-digit year for the current or given time. 2171 | 2172 | ```cpp 2173 | // Print the current year 2174 | Serial.print(Time.year()); 2175 | 2176 | // Print the year for the given time, in this case: 2014 2177 | Serial.print(Time.year(1400647897)); 2178 | ``` 2179 | 2180 | Optional parameters: Integer (Unix timestamp) 2181 | 2182 | Returns: Integer 2183 | 2184 | 2185 | ### now() 2186 | 2187 | Retrieve the current time as seconds since January 1, 1970 (commonly known as "Unix time" or "epoch time") 2188 | 2189 | ```cpp 2190 | // Print the current Unix timestamp 2191 | Serial.print(Time.now()); // 1400647897 2192 | ``` 2193 | 2194 | Returns: Integer 2195 | 2196 | 2197 | ### zone() 2198 | 2199 | Set the time zone offset (+/-) from UTC. 2200 | The board will remember this offset until reboot. 2201 | 2202 | *NOTE*: This function does not observe daylight savings time. 2203 | 2204 | ```cpp 2205 | // Set time zone to Eastern USA daylight saving time 2206 | Time.zone(-4); 2207 | ``` 2208 | 2209 | Parameters: floating point offset from UTC in hours, from -12.0 to 13.0 2210 | 2211 | 2212 | ### setTime() 2213 | 2214 | Set the board's time to the given timestamp. 2215 | 2216 | *NOTE*: This will override the time set by the RootCloud. 2217 | If the cloud connection drops, the reconnection handshake will set the time again 2218 | 2219 | Also see: [`RootCloud.syncTime()`](#rootcloud-synctime) 2220 | 2221 | ```cpp 2222 | // Set the time to 2014-10-11 13:37:42 2223 | Time.setTime(1413034662); 2224 | ``` 2225 | 2226 | Parameters: Unix timestamp (integer) 2227 | 2228 | 2229 | ### timeStr() 2230 | 2231 | Return string representation for the given time. 2232 | ```cpp 2233 | Serial.print(Time.timeStr()); // Wed May 21 01:08:47 2014 2234 | ``` 2235 | 2236 | Returns: String 2237 | 2238 | System 2239 | --- 2240 | 2241 | ### reset() 2242 | 2243 | Resets the device, just like hitting the reset button or powering down and back up. 2244 | 2245 | ```C++ 2246 | uint32_t lastReset = 0; 2247 | 2248 | void setup() { 2249 | lastReset = millis(); 2250 | } 2251 | 2252 | void loop() { 2253 | // Reset after 5 minutes of operation 2254 | // ================================== 2255 | if (millis() - lastReset > 5*60000UL) { 2256 | System.reset(); 2257 | } 2258 | } 2259 | ``` 2260 | 2261 | 2262 | Other functions 2263 | ===== 2264 | 2265 | Note that most of the functions in newlib described at https://sourceware.org/newlib/libc.html are available for use in addition to the functions outlined below. 2266 | 2267 | Time 2268 | --- 2269 | 2270 | ### millis() 2271 | 2272 | Returns the number of milliseconds since the board began running the current program. This number will overflow (go back to zero), after approximately 49 days. 2273 | 2274 | `unsigned long time = millis();` 2275 | 2276 | ```C++ 2277 | // EXAMPLE USAGE 2278 | unsigned long time; 2279 | 2280 | void setup() 2281 | { 2282 | //Serial.begin(9600); 2283 | //begin does not do anything for Serial which uses the cloud 2284 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 2285 | } 2286 | void loop() 2287 | { 2288 | Serial.print("Time: "); 2289 | time = millis(); 2290 | //prints time since program started 2291 | Serial.println(time); 2292 | // wait a second so as not to send massive amounts of data 2293 | delay(1000); 2294 | } 2295 | ``` 2296 | **Note:** 2297 | The parameter for millis is an unsigned long, errors may be generated if a programmer tries to do math with other datatypes such as ints. 2298 | 2299 | ### micros() 2300 | 2301 | Returns the number of microseconds since the board began running the current program. This number will overflow (go back to zero), after approximately 59.65 seconds. 2302 | 2303 | `unsigned long time = micros();` 2304 | 2305 | ```C++ 2306 | // EXAMPLE USAGE 2307 | unsigned long time; 2308 | 2309 | void setup() 2310 | { 2311 | //Serial.begin(9600); 2312 | //begin does not do anything for Serial which uses the cloud 2313 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 2314 | } 2315 | void loop() 2316 | { 2317 | Serial.print("Time: "); 2318 | time = micros(); 2319 | //prints time since program started 2320 | Serial.println(time); 2321 | // wait a second so as not to send massive amounts of data 2322 | delay(1000); 2323 | } 2324 | ``` 2325 | 2326 | ### delay() 2327 | 2328 | Pauses the program for the amount of time (in miliseconds) specified as parameter. (There are 1000 milliseconds in a second.) 2329 | 2330 | ```C++ 2331 | SYNTAX 2332 | delay(ms); 2333 | ``` 2334 | 2335 | `ms` is the number of milliseconds to pause *(unsigned long)* 2336 | 2337 | ```C++ 2338 | // EXAMPLE USAGE 2339 | int ledPin = D1; // LED connected to digital pin D1 2340 | 2341 | void setup() 2342 | { 2343 | pinMode(ledPin, OUTPUT); // sets the digital pin as output 2344 | } 2345 | 2346 | void loop() 2347 | { 2348 | digitalWrite(ledPin, HIGH); // sets the LED on 2349 | delay(1000); // waits for a second 2350 | digitalWrite(ledPin, LOW); // sets the LED off 2351 | delay(1000); // waits for a second 2352 | } 2353 | ``` 2354 | **NOTE:** 2355 | the parameter for millis is an unsigned long, errors may be generated if a programmer tries to do math with other datatypes such as ints. 2356 | 2357 | ### delayMicroseconds() 2358 | 2359 | Pauses the program for the amount of time (in microseconds) specified as parameter. There are a thousand microseconds in a millisecond, and a million microseconds in a second. 2360 | 2361 | ```C++ 2362 | SYNTAX 2363 | delayMicroseconds(us); 2364 | ``` 2365 | `us` is the number of microseconds to pause *(unsigned int)* 2366 | 2367 | ```C++ 2368 | // EXAMPLE USAGE 2369 | int outPin = D1; // digital pin D1 2370 | 2371 | void setup() 2372 | { 2373 | pinMode(outPin, OUTPUT); // sets the digital pin as output 2374 | } 2375 | 2376 | void loop() 2377 | { 2378 | digitalWrite(outPin, HIGH); // sets the pin on 2379 | delayMicroseconds(50); // pauses for 50 microseconds 2380 | digitalWrite(outPin, LOW); // sets the pin off 2381 | delayMicroseconds(50); // pauses for 50 microseconds 2382 | } 2383 | ``` 2384 | 2385 | Interrupts 2386 | --- 2387 | 2388 | ### attachInterrupt() 2389 | 2390 | Specifies a function to call when an external interrupt occurs. Replaces any previous function that was attached to the interrupt. 2391 | 2392 | ```C++ 2393 | // EXAMPLE USAGE 2394 | void blink(void); 2395 | int ledPin = D1; 2396 | volatile int state = LOW; 2397 | 2398 | void setup() 2399 | { 2400 | pinMode(ledPin, OUTPUT); 2401 | attachInterrupt(D0, blink, CHANGE); 2402 | } 2403 | 2404 | void loop() 2405 | { 2406 | digitalWrite(ledPin, state); 2407 | } 2408 | 2409 | void blink() 2410 | { 2411 | state = !state; 2412 | } 2413 | ``` 2414 | 2415 | The Oak currently supports external interrupts on all digital I/O pins. 2416 | 2417 | `attachInterrupt(pin, function, mode);` 2418 | 2419 | *Parameters:* 2420 | 2421 | - `pin`: the pin number 2422 | - `function`: the function to call when the interrupt occurs; this function must take no parameters and return nothing. This function is sometimes referred to as an *interrupt service routine* (ISR). 2423 | - `mode`: defines when the interrupt should be triggered. Four constants are predefined as valid values: 2424 | - CHANGE to trigger the interrupt whenever the pin changes value, 2425 | - RISING to trigger when the pin goes from low to high, 2426 | - FALLING for when the pin goes from high to low. 2427 | 2428 | The function does not return anything. 2429 | 2430 | **NOTE:** 2431 | Inside the attached function, `delay()` won't work and the value returned by `millis()` will not increment. Serial data received while in the function may be lost. You should declare as `volatile` any variables that you modify within the attached function. 2432 | 2433 | *Using Interrupts:* 2434 | Interrupts are useful for making things happen automatically in microcontroller programs, and can help solve timing problems. Good tasks for using an interrupt may include reading a rotary encoder, or monitoring user input. 2435 | 2436 | If you wanted to insure that a program always caught the pulses from a rotary encoder, so that it never misses a pulse, it would make it very tricky to write a program to do anything else, because the program would need to constantly poll the sensor lines for the encoder, in order to catch pulses when they occurred. Other sensors have a similar interface dynamic too, such as trying to read a sound sensor that is trying to catch a click, or an infrared slot sensor (photo-interrupter) trying to catch a coin drop. In all of these situations, using an interrupt can free the microcontroller to get some other work done while not missing the input. 2437 | 2438 | 2439 | ### detatchInterrupt() 2440 | 2441 | Turns off the given interrupt. 2442 | 2443 | `detachInterrupt(pin);` 2444 | 2445 | `pin` is the pin number of the interrupt to disable. 2446 | 2447 | 2448 | ### interrupts() 2449 | 2450 | Re-enables interrupts (after they've been disabled by `noInterrupts()`). Interrupts allow certain important tasks to happen in the background and are enabled by default. Some functions will not work while interrupts are disabled, and incoming communication may be ignored. Interrupts can slightly disrupt the timing of code, however, and may be disabled for particularly critical sections of code. 2451 | 2452 | ```C++ 2453 | // EXAMPLE USAGE 2454 | void setup() {} 2455 | 2456 | void loop() 2457 | { 2458 | noInterrupts(); // disable interrupts 2459 | // 2460 | // put critical, time-sensitive code here 2461 | // 2462 | interrupts(); // enable interrupts 2463 | // 2464 | // other code here 2465 | // 2466 | } 2467 | ``` 2468 | 2469 | `interrupts()` neither accepts a parameter nor returns anything. 2470 | 2471 | ### noInterrupts() 2472 | 2473 | Disables interrupts (you can re-enable them with `interrupts()`). Interrupts allow certain important tasks to happen in the background and are enabled by default. Some functions will not work while interrupts are disabled, and incoming communication may be ignored. Interrupts can slightly disrupt the timing of code, however, and may be disabled for particularly critical sections of code. 2474 | 2475 | `noInterrupts()` neither accepts a parameter nor returns anything. 2476 | 2477 | 2478 | Math 2479 | --- 2480 | 2481 | Note that in addition to functions outlined below all of the newlib math functions described at [sourceware.org](https://sourceware.org/newlib/libm.html) are also available for use by simply including the math.h header file thus: 2482 | 2483 | `#include "math.h"` 2484 | 2485 | ### min() 2486 | 2487 | Calculates the minimum of two numbers. 2488 | 2489 | `min(x, y)` 2490 | 2491 | `x` is the first number, any data type 2492 | `y` is the second number, any data type 2493 | 2494 | The functions returns the smaller of the two numbers. 2495 | 2496 | ```C++ 2497 | // EXAMPLE USAGE 2498 | sensVal = min(sensVal, 100); // assigns sensVal to the smaller of sensVal or 100 2499 | // ensuring that it never gets above 100. 2500 | ``` 2501 | 2502 | **NOTE:** 2503 | Perhaps counter-intuitively, max() is often used to constrain the lower end of a variable's range, while min() is used to constrain the upper end of the range. 2504 | 2505 | **WARNING:** 2506 | Because of the way the min() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results 2507 | 2508 | ```C++ 2509 | min(a++, 100); // avoid this - yields incorrect results 2510 | 2511 | a++; 2512 | min(a, 100); // use this instead - keep other math outside the function 2513 | ``` 2514 | 2515 | ### max() 2516 | 2517 | Calculates the maximum of two numbers. 2518 | 2519 | `max(x, y)` 2520 | 2521 | `x` is the first number, any data type 2522 | `y` is the second number, any data type 2523 | 2524 | The functions returns the larger of the two numbers. 2525 | 2526 | ```C++ 2527 | // EXAMPLE USAGE 2528 | sensVal = max(senVal, 20); // assigns sensVal to the larger of sensVal or 20 2529 | // (effectively ensuring that it is at least 20) 2530 | ``` 2531 | 2532 | **NOTE:** 2533 | Perhaps counter-intuitively, max() is often used to constrain the lower end of a variable's range, while min() is used to constrain the upper end of the range. 2534 | 2535 | **WARNING:** 2536 | Because of the way the max() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results 2537 | 2538 | ```C++ 2539 | max(a--, 0); // avoid this - yields incorrect results 2540 | 2541 | a--; // use this instead - 2542 | max(a, 0); // keep other math outside the function 2543 | ``` 2544 | 2545 | ### abs() 2546 | 2547 | Computes the absolute value of a number. 2548 | 2549 | `abs(x);` 2550 | 2551 | where `x` is the number 2552 | 2553 | The function returns `x` if `x` is greater than or equal to `0` 2554 | and returns `-x` if `x` is less than `0`. 2555 | 2556 | **WARNING:** 2557 | Because of the way the abs() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results. 2558 | 2559 | ```C++ 2560 | abs(a++); // avoid this - yields incorrect results 2561 | 2562 | a++; // use this instead - 2563 | abs(a); // keep other math outside the function 2564 | ``` 2565 | 2566 | ### constrain() 2567 | 2568 | Constrains a number to be within a range. 2569 | 2570 | `constrain(x, a, b);` 2571 | 2572 | `x` is the number to constrain, all data types 2573 | `a` is the lower end of the range, all data types 2574 | `b` is the upper end of the range, all data types 2575 | 2576 | The function will return: 2577 | `x`: if x is between `a` and `b` 2578 | `a`: if `x` is less than `a` 2579 | `b`: if `x` is greater than `b` 2580 | 2581 | ```C++ 2582 | // EXAMPLE USAGE 2583 | sensVal = constrain(sensVal, 10, 150); 2584 | // limits range of sensor values to between 10 and 150 2585 | ``` 2586 | 2587 | ### map() 2588 | 2589 | Re-maps a number from one range to another. That is, a value of fromLow would get mapped to `toLow`, a `value` of `fromHigh` to `toHigh`, values in-between to values in-between, etc. 2590 | 2591 | `map(value, fromLow, fromHigh, toLow, toHigh);` 2592 | 2593 | Does not constrain values to within the range, because out-of-range values are sometimes intended and useful. The `constrain()` function may be used either before or after this function, if limits to the ranges are desired. 2594 | 2595 | Note that the "lower bounds" of either range may be larger or smaller than the "upper bounds" so the `map()` function may be used to reverse a range of numbers, for example 2596 | 2597 | `y = map(x, 1, 50, 50, 1);` 2598 | 2599 | The function also handles negative numbers well, so that this example 2600 | 2601 | `y = map(x, 1, 50, 50, -100);` 2602 | 2603 | is also valid and works well. 2604 | 2605 | The `map()` function uses integer math so will not generate fractions, when the math might indicate that it should do so. Fractional remainders are truncated, and are not rounded or averaged. 2606 | 2607 | *Parameters:* 2608 | 2609 | - `value`: the number to map 2610 | - `fromLow`: the lower bound of the value's current range 2611 | - `fromHigh`: the upper bound of the value's current range 2612 | - `toLow`: the lower bound of the value's target range 2613 | - `toHigh`: the upper bound of the value's target range 2614 | 2615 | The function returns the mapped value 2616 | 2617 | ```C++ 2618 | // EXAMPLE USAGE 2619 | // Map an analog value to 8 bits (0 to 255) 2620 | void setup() {} 2621 | 2622 | void loop() 2623 | { 2624 | int val = analogRead(0); 2625 | val = map(val, 0, 4095, 0, 255); 2626 | analogWrite(9, val); 2627 | } 2628 | ``` 2629 | 2630 | *Appendix:* 2631 | For the mathematically inclined, here's the whole function 2632 | 2633 | ```C++ 2634 | long map(long x, long in_min, long in_max, long out_min, long out_max) 2635 | { 2636 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 2637 | } 2638 | ``` 2639 | 2640 | ### pow() 2641 | 2642 | Calculates the value of a number raised to a power. `pow()` can be used to raise a number to a fractional power. This is useful for generating exponential mapping of values or curves. 2643 | 2644 | `pow(base, exponent);` 2645 | 2646 | `base` is the number *(float)* 2647 | `exponent` is the power to which the base is raised *(float)* 2648 | 2649 | The function returns the result of the exponentiation *(double)* 2650 | 2651 | EXAMPLE **TBD** 2652 | 2653 | ### sqrt() 2654 | 2655 | Calculates the square root of a number. 2656 | 2657 | `sqrt(x)` 2658 | 2659 | `x` is the number, any data type 2660 | 2661 | The function returns the number's square root *(double)* 2662 | 2663 | ## Random Numbers 2664 | 2665 | The firmware incorporates a pseudo-random number generator. 2666 | 2667 | ### random() 2668 | 2669 | Retrieves the next random value, restricted to a given range. 2670 | 2671 | `random(max);` 2672 | 2673 | Parameters 2674 | 2675 | - `max` - the upper limit of the random number to retrieve. 2676 | 2677 | Returns: a random value between 0 and up to, but not including `max`. 2678 | 2679 | ```c++ 2680 | int r = random(10); 2681 | // r is >= 0 and < 10 2682 | // The smallest value returned is 0 2683 | // The largest value returned is 9 2684 | ``` 2685 | 2686 | NB: When `max` is 0, the result is always 0. 2687 | 2688 | --- 2689 | 2690 | `random(min,max);` 2691 | 2692 | Parameters: 2693 | 2694 | - `min` - the lower limit (inclusive) of the random number to retrieve. 2695 | - `max` - the upper limit (exclusive) of the random number to retrieve. 2696 | 2697 | Returns: a random value from `min` and up to, but not including `max`. 2698 | 2699 | 2700 | ```c++ 2701 | int r = random(10, 100); 2702 | // r is >= 10 and < 100 2703 | // The smallest value returned is 10 2704 | // The largest value returned is 99 2705 | ``` 2706 | 2707 | NB: If `min` is greater or equal to `max`, the result is always 0. 2708 | 2709 | ### randomSeed() 2710 | 2711 | `randomSeed(newSeed);` 2712 | 2713 | Parameters: 2714 | 2715 | - `newSeed` - the new random seed 2716 | 2717 | The pseudorandom numbers produced by the firmware are derived from a single value - the random seed. 2718 | The value of this seed fully determines the sequence of random numbers produced by successive 2719 | calls to `random()`. Using the same seed on two separate runs will produce 2720 | the same sequence of random numbers, and in contrast, using different seeds 2721 | will produce a different sequence of random numbers. 2722 | 2723 | On startup, the default random seed is [set by the system](http://www.cplusplus.com/reference/cstdlib/srand/) to 1. 2724 | Unless the seed is modified, the same sequence of random numbers would be produced each time 2725 | the system starts. 2726 | 2727 | Fortunately, when the board connects to the cloud, it receives a very randomized seed value, 2728 | which is used as the random seed. So you can be sure the random numbers produced 2729 | will be different each time your program is run. 2730 | 2731 | 2732 | *** Disable random seed from the cloud *** 2733 | 2734 | When the board receives a new random seed from the cloud, it's passed to this function: 2735 | 2736 | ``` 2737 | void random_seed_from_cloud(unsigned int seed); 2738 | ``` 2739 | 2740 | The system implementation of this function calls `randomSeed()` to set 2741 | the new seed value. If you don't wish to use random seed values from the cloud, 2742 | you can take control of the ransom seeds set by adding this code to your app: 2743 | 2744 | ```cpp 2745 | void random_seed_from_cloud(unsigned int seed) { 2746 | // don't do anything with this. Continue with existing seed. 2747 | } 2748 | ``` 2749 | 2750 | In the example, the seed is simply ignored, so the system will continue using 2751 | whatever seed was previously set. In this case, the random seed will not be set 2752 | from the cloud, and setting the seed is left to up you. 2753 | 2754 | 2755 | EEPROM 2756 | ---- 2757 | 2758 | The EEPROM emulator allocates 256 bytes of the boards's built-in flash memory to act as EEPROM. The EEPROM functions can be used to store small amounts of data in flash that will persist even after the board resets after a deep sleep. 2759 | 2760 | 2761 | ### read() 2762 | Read a byte of data from the emulated EEPROM. 2763 | 2764 | `read(address)` 2765 | 2766 | `address` is the address (int) of the EERPOM location (0-99) to read 2767 | 2768 | ```C++ 2769 | // EXAMPLE USAGE 2770 | // Read the value of the second byte of EEPROM 2771 | int addr = 1; 2772 | uint8_t value = EEPROM.read(addr); 2773 | ``` 2774 | 2775 | ### write() 2776 | Write a byte of data to the emulated EEPROM. 2777 | 2778 | `write(address, value)` 2779 | 2780 | `address` is the address (int) of the EERPOM location (0-99) to write to 2781 | `value` is the byte data (uint8_t) to write 2782 | 2783 | ```C++ 2784 | // EXAMPLE USAGE 2785 | // Write a byte value to the second byte of EEPROM 2786 | int addr = 1; 2787 | uint8_t val = 0x45; 2788 | EEPROM.write(addr, val); 2789 | ``` 2790 | 2791 | Language Syntax 2792 | ===== 2793 | The following documentation is based on the Arduino reference which can be found [here.](http://arduino.cc/en/Reference/HomePage) 2794 | 2795 | Structure 2796 | --- 2797 | ### setup() 2798 | The setup() function is called when an application starts. Use it to initialize variables, pin modes, start using libraries, etc. The setup function will only run once, after each powerup or reset of the board. 2799 | 2800 | ```cpp 2801 | // EXAMPLE USAGE 2802 | int button = D0; 2803 | int LED = D1; 2804 | //setup initializes D0 as input and D1 as output 2805 | void setup() 2806 | { 2807 | pinMode(button, INPUT_PULLDOWN); 2808 | pinMode(LED, OUTPUT); 2809 | } 2810 | 2811 | void loop() 2812 | { 2813 | // ... 2814 | } 2815 | ``` 2816 | 2817 | ### loop() 2818 | After creating a setup() function, which initializes and sets the initial values, the loop() function does precisely what its name suggests, and loops consecutively, allowing your program to change and respond. Use it to actively control the board. 2819 | 2820 | ```C++ 2821 | EXAMPLE USAGE 2822 | int button = D0; 2823 | int LED = D1; 2824 | //setup initializes D0 as input and D1 as output 2825 | void setup() 2826 | { 2827 | pinMode(button, INPUT_PULLDOWN); 2828 | pinMode(LED, OUTPUT); 2829 | } 2830 | 2831 | //loops to check if button was pressed, 2832 | //if it was, then it turns ON the LED, 2833 | //else the LED remains OFF 2834 | void loop() 2835 | { 2836 | if (digitalRead(button) == HIGH) 2837 | digitalWrite(LED,HIGH); 2838 | else 2839 | digitalWrite(LED,LOW); 2840 | } 2841 | ``` 2842 | 2843 | Control structures 2844 | --- 2845 | 2846 | ### if 2847 | 2848 | `if`, which is used in conjunction with a comparison operator, tests whether a certain condition has been reached, such as an input being above a certain number. 2849 | 2850 | ```C++ 2851 | SYNTAX 2852 | if (someVariable > 50) 2853 | { 2854 | // do something here 2855 | } 2856 | ``` 2857 | The program tests to see if someVariable is greater than 50. If it is, the program takes a particular action. Put another way, if the statement in parentheses is true, the statements inside the brackets are run. If not, the program skips over the code. 2858 | 2859 | The brackets may be omitted after an *if* statement. If this is done, the next line (defined by the semicolon) becomes the only conditional statement. 2860 | 2861 | ```C++ 2862 | if (x > 120) digitalWrite(LEDpin, HIGH); 2863 | 2864 | if (x > 120) 2865 | digitalWrite(LEDpin, HIGH); 2866 | 2867 | if (x > 120){ digitalWrite(LEDpin, HIGH); } 2868 | 2869 | if (x > 120) 2870 | { 2871 | digitalWrite(LEDpin1, HIGH); 2872 | digitalWrite(LEDpin2, HIGH); 2873 | } // all are correct 2874 | ``` 2875 | The statements being evaluated inside the parentheses require the use of one or more operators: 2876 | 2877 | ### Comparison Operators 2878 | 2879 | ```C++ 2880 | x == y (x is equal to y) 2881 | x != y (x is not equal to y) 2882 | x < y (x is less than y) 2883 | x > y (x is greater than y) 2884 | x <= y (x is less than or equal to y) 2885 | x >= y (x is greater than or equal to y) 2886 | ``` 2887 | 2888 | **WARNING:** 2889 | Beware of accidentally using the single equal sign (e.g. `if (x = 10)` ). The single equal sign is the assignment operator, and sets x to 10 (puts the value 10 into the variable x). Instead use the double equal sign (e.g. `if (x == 10)` ), which is the comparison operator, and tests whether x is equal to 10 or not. The latter statement is only true if x equals 10, but the former statement will always be true. 2890 | 2891 | This is because C evaluates the statement `if (x=10)` as follows: 10 is assigned to x (remember that the single equal sign is the assignment operator), so x now contains 10. Then the 'if' conditional evaluates 10, which always evaluates to TRUE, since any non-zero number evaluates to TRUE. Consequently, `if (x = 10)` will always evaluate to TRUE, which is not the desired result when using an 'if' statement. Additionally, the variable x will be set to 10, which is also not a desired action. 2892 | 2893 | `if` can also be part of a branching control structure using the `if...else`] construction. 2894 | 2895 | ### if...else 2896 | 2897 | *if/else* allows greater control over the flow of code than the basic *if* statement, by allowing multiple tests to be grouped together. For example, an analog input could be tested and one action taken if the input was less than 500, and another action taken if the input was 500 or greater. The code would look like this: 2898 | 2899 | ```C++ 2900 | SYNTAX 2901 | if (pinFiveInput < 500) 2902 | { 2903 | // action A 2904 | } 2905 | else 2906 | { 2907 | // action B 2908 | } 2909 | ``` 2910 | `else` can proceed another `if` test, so that multiple, mutually exclusive tests can be run at the same time. 2911 | 2912 | Each test will proceed to the next one until a true test is encountered. When a true test is found, its associated block of code is run, and the program then skips to the line following the entire if/else construction. If no test proves to be true, the default else block is executed, if one is present, and sets the default behavior. 2913 | 2914 | Note that an *else if* block may be used with or without a terminating *else* block and vice versa. An unlimited number of such else if branches is allowed. 2915 | 2916 | ```C++ 2917 | if (pinFiveInput < 500) 2918 | { 2919 | // do Thing A 2920 | } 2921 | else if (pinFiveInput >= 1000) 2922 | { 2923 | // do Thing B 2924 | } 2925 | else 2926 | { 2927 | // do Thing C 2928 | } 2929 | ``` 2930 | 2931 | Another way to express branching, mutually exclusive tests, is with the [`switch case`](#/firmware/control-structures-switch-case) statement. 2932 | 2933 | ### for 2934 | 2935 | The `for` statement is used to repeat a block of statements enclosed in curly braces. An increment counter is usually used to increment and terminate the loop. The `for` statement is useful for any repetitive operation, and is often used in combination with arrays to operate on collections of data/pins. 2936 | 2937 | There are three parts to the for loop header: 2938 | 2939 | ```C++ 2940 | SYNTAX 2941 | for (initialization; condition; increment) 2942 | { 2943 | //statement(s); 2944 | } 2945 | ``` 2946 | The *initialization* happens first and exactly once. Each time through the loop, the *condition* is tested; if it's true, the statement block, and the *increment* is executed, then the condition is tested again. When the *condition* becomes false, the loop ends. 2947 | 2948 | ```C++ 2949 | // EXAMPLE USAGE 2950 | // slowy make the LED glow brighter 2951 | int ledPin = D1; // LED in series with 470 ohm resistor on pin D1 2952 | 2953 | void setup() 2954 | { 2955 | // set ledPin as an output 2956 | pinMode(ledPin,OUTPUT); 2957 | } 2958 | 2959 | void loop() 2960 | { 2961 | for (int i=0; i <= 255; i++){ 2962 | analogWrite(ledPin, i); 2963 | delay(10); 2964 | } 2965 | } 2966 | ``` 2967 | The C `for` loop is much more flexible than for loops found in some other computer languages, including BASIC. Any or all of the three header elements may be omitted, although the semicolons are required. Also the statements for initialization, condition, and increment can be any valid C statements with unrelated variables, and use any C datatypes including floats. These types of unusual for statements may provide solutions to some rare programming problems. 2968 | 2969 | For example, using a multiplication in the increment line will generate a logarithmic progression: 2970 | 2971 | ```C++ 2972 | for(int x = 2; x < 100; x = x * 1.5) 2973 | { 2974 | Serial.print(x); 2975 | } 2976 | //Generates: 2,3,4,6,9,13,19,28,42,63,94 2977 | ``` 2978 | Another example, fade an LED up and down with one for loop: 2979 | 2980 | ```C++ 2981 | // slowy make the LED glow brighter 2982 | int ledPin = D1; // LED in series with 470 ohm resistor on pin D1 2983 | 2984 | void setup() 2985 | { 2986 | // set ledPin as an output 2987 | pinMode(ledPin,OUTPUT); 2988 | } 2989 | 2990 | void loop() 2991 | { 2992 | int x = 1; 2993 | for (int i = 0; i > -1; i = i + x) 2994 | { 2995 | analogWrite(ledPin, i); 2996 | if (i == 255) x = -1; // switch direction at peak 2997 | delay(10); 2998 | } 2999 | } 3000 | ``` 3001 | 3002 | ### switch case 3003 | 3004 | Like `if` statements, `switch`...`case` controls the flow of programs by allowing programmers to specify different code that should be executed in various conditions. In particular, a switch statement compares the value of a variable to the values specified in case statements. When a case statement is found whose value matches that of the variable, the code in that case statement is run. 3005 | 3006 | The `break` keyword exits the switch statement, and is typically used at the end of each case. Without a break statement, the switch statement will continue executing the following expressions ("falling-through") until a break, or the end of the switch statement is reached. 3007 | 3008 | ```C++ 3009 | SYNTAX 3010 | switch (var) 3011 | { 3012 | case label: 3013 | // statements 3014 | break; 3015 | case label: 3016 | // statements 3017 | break; 3018 | default: 3019 | // statements 3020 | } 3021 | ``` 3022 | `var` is the variable whose value to compare to the various cases 3023 | `label` is a value to compare the variable to 3024 | 3025 | ```C++ 3026 | // EXAMPLE USAGE 3027 | switch (var) 3028 | { 3029 | case 1: 3030 | // do something when var equals 1 3031 | break; 3032 | case 2: 3033 | // do something when var equals 2 3034 | break; 3035 | default: 3036 | // if nothing else matches, do the 3037 | // default (which is optional) 3038 | } 3039 | ``` 3040 | 3041 | ### while 3042 | 3043 | `while` loops will loop continuously, and infinitely, until the expression inside the parenthesis, () becomes false. Something must change the tested variable, or the `while` loop will never exit. This could be in your code, such as an incremented variable, or an external condition, such as testing a sensor. 3044 | 3045 | ```C++ 3046 | SYNTAX 3047 | while(expression) 3048 | { 3049 | // statement(s) 3050 | } 3051 | ``` 3052 | `expression` is a (boolean) C statement that evaluates to true or false. 3053 | 3054 | ```C++ 3055 | // EXAMPLE USAGE 3056 | var = 0; 3057 | while(var < 200) 3058 | { 3059 | // do something repetitive 200 times 3060 | var++; 3061 | } 3062 | ``` 3063 | 3064 | ### do... while 3065 | 3066 | The `do` loop works in the same manner as the `while` loop, with the exception that the condition is tested at the end of the loop, so the do loop will *always* run at least once. 3067 | 3068 | ```C++ 3069 | SYNTAX 3070 | do 3071 | { 3072 | // statement block 3073 | } while (test condition); 3074 | ``` 3075 | 3076 | ```C++ 3077 | // EXAMPLE USAGE 3078 | do 3079 | { 3080 | delay(50); // wait for sensors to stabilize 3081 | x = readSensors(); // check the sensors 3082 | 3083 | } while (x < 100); 3084 | ``` 3085 | 3086 | ### break 3087 | 3088 | `break` is used to exit from a `do`, `for`, or `while` loop, bypassing the normal loop condition. It is also used to exit from a `switch` statement. 3089 | 3090 | ```C++ 3091 | // EXAMPLE USAGE 3092 | for (int x = 0; x < 255; x++) 3093 | { 3094 | digitalWrite(ledPin, x); 3095 | sens = analogRead(sensorPin); 3096 | if (sens > threshold) 3097 | { 3098 | x = 0; 3099 | break; // exit for() loop on sensor detect 3100 | } 3101 | delay(50); 3102 | } 3103 | ``` 3104 | 3105 | ### continue 3106 | 3107 | The continue statement skips the rest of the current iteration of a loop (`do`, `for`, or `while`). It continues by checking the conditional expression of the loop, and proceeding with any subsequent iterations. 3108 | 3109 | ```C++ 3110 | // EXAMPLE USAGE 3111 | for (x = 0; x < 255; x++) 3112 | { 3113 | if (x > 40 && x < 120) continue; // create jump in values 3114 | 3115 | digitalWrite(PWMpin, x); 3116 | delay(50); 3117 | } 3118 | ``` 3119 | 3120 | ### return 3121 | 3122 | Terminate a function and return a value from a function to the calling function, if desired. 3123 | 3124 | ```C++ 3125 | EXAMPLE 3126 | // A function to compare a sensor input to a threshold 3127 | int checkSensor() 3128 | { 3129 | if (analogRead(0) > 400) return 1; 3130 | else return 0; 3131 | } 3132 | ``` 3133 | The return keyword is handy to test a section of code without having to "comment out" large sections of possibly buggy code. 3134 | 3135 | ```C++ 3136 | void loop() 3137 | { 3138 | // brilliant code idea to test here 3139 | 3140 | return; 3141 | 3142 | // the rest of a dysfunctional sketch here 3143 | // this code will never be executed 3144 | } 3145 | ``` 3146 | 3147 | ### goto 3148 | 3149 | Transfers program flow to a labeled point in the program 3150 | 3151 | ```C++ 3152 | USAGE 3153 | label: 3154 | 3155 | goto label; // sends program flow to the label 3156 | ``` 3157 | 3158 | **TIP:** 3159 | The use of `goto` is discouraged in C programming, and some authors of C programming books claim that the `goto` statement is never necessary, but used judiciously, it can simplify certain programs. The reason that many programmers frown upon the use of `goto` is that with the unrestrained use of `goto` statements, it is easy to create a program with undefined program flow, which can never be debugged. 3160 | 3161 | With that said, there are instances where a `goto` statement can come in handy, and simplify coding. One of these situations is to break out of deeply nested `for` loops, or `if` logic blocks, on a certain condition. 3162 | 3163 | ```C++ 3164 | // EXAMPLE USAGE 3165 | for(byte r = 0; r < 255; r++) { 3166 | for(byte g = 255; g > -1; g--) { 3167 | for(byte b = 0; b < 255; b++) { 3168 | if (analogRead(0) > 250) { 3169 | goto bailout; 3170 | } 3171 | // more statements ... 3172 | } 3173 | } 3174 | } 3175 | bailout: 3176 | // Code execution jumps here from 3177 | // goto bailout; statement 3178 | ``` 3179 | 3180 | Further syntax 3181 | --- 3182 | 3183 | ### ; (semicolon) 3184 | 3185 | Used to end a statement. 3186 | 3187 | `int a = 13;` 3188 | 3189 | **Tip:** 3190 | Forgetting to end a line in a semicolon will result in a compiler error. The error text may be obvious, and refer to a missing semicolon, or it may not. If an impenetrable or seemingly illogical compiler error comes up, one of the first things to check is a missing semicolon, in the immediate vicinity, preceding the line at which the compiler complained. 3191 | 3192 | ### {} (curly braces) 3193 | 3194 | Curly braces (also referred to as just "braces" or as "curly brackets") are a major part of the C programming language. They are used in several different constructs, outlined below, and this can sometimes be confusing for beginners. 3195 | 3196 | ```C++ 3197 | //The main uses of curly braces 3198 | 3199 | //Functions 3200 | void myfunction(datatype argument){ 3201 | statements(s) 3202 | } 3203 | 3204 | //Loops 3205 | while (boolean expression) 3206 | { 3207 | statement(s) 3208 | } 3209 | 3210 | do 3211 | { 3212 | statement(s) 3213 | } while (boolean expression); 3214 | 3215 | for (initialisation; termination condition; incrementing expr) 3216 | { 3217 | statement(s) 3218 | } 3219 | 3220 | //Conditional statements 3221 | if (boolean expression) 3222 | { 3223 | statement(s) 3224 | } 3225 | 3226 | else if (boolean expression) 3227 | { 3228 | statement(s) 3229 | } 3230 | else 3231 | { 3232 | statement(s) 3233 | } 3234 | 3235 | ``` 3236 | 3237 | An opening curly brace "{" must always be followed by a closing curly brace "}". This is a condition that is often referred to as the braces being balanced. 3238 | 3239 | Beginning programmers, and programmers coming to C from the BASIC language often find using braces confusing or daunting. After all, the same curly braces replace the RETURN statement in a subroutine (function), the ENDIF statement in a conditional and the NEXT statement in a FOR loop. 3240 | 3241 | Because the use of the curly brace is so varied, it is good programming practice to type the closing brace immediately after typing the opening brace when inserting a construct which requires curly braces. Then insert some carriage returns between your braces and begin inserting statements. Your braces, and your attitude, will never become unbalanced. 3242 | 3243 | Unbalanced braces can often lead to cryptic, impenetrable compiler errors that can sometimes be hard to track down in a large program. Because of their varied usages, braces are also incredibly important to the syntax of a program and moving a brace one or two lines will often dramatically affect the meaning of a program. 3244 | 3245 | 3246 | ### // (single line comment) 3247 | ### /\* \*/ (multi-line comment) 3248 | 3249 | Comments are lines in the program that are used to inform yourself or others about the way the program works. They are ignored by the compiler, and not exported to the processor, so they don't take up any space on the board. 3250 | 3251 | Comments only purpose are to help you understand (or remember) how your program works or to inform others how your program works. There are two different ways of marking a line as a comment: 3252 | 3253 | ```C++ 3254 | // EXAMPLE USAGE 3255 | x = 5; // This is a single line comment. Anything after the slashes is a comment 3256 | // to the end of the line 3257 | 3258 | /* this is multiline comment - use it to comment out whole blocks of code 3259 | 3260 | if (gwb == 0) { // single line comment is OK inside a multiline comment 3261 | x = 3; /* but not another multiline comment - this is invalid */ 3262 | } 3263 | // don't forget the "closing" comment - they have to be balanced! 3264 | */ 3265 | ``` 3266 | 3267 | **TIP:** 3268 | When experimenting with code, "commenting out" parts of your program is a convenient way to remove lines that may be buggy. This leaves the lines in the code, but turns them into comments, so the compiler just ignores them. This can be especially useful when trying to locate a problem, or when a program refuses to compile and the compiler error is cryptic or unhelpful. 3269 | 3270 | 3271 | ### #define 3272 | 3273 | `#define` is a useful C component that allows the programmer to give a name to a constant value before the program is compiled. Defined constants don't take up any program memory space on the chip. The compiler will replace references to these constants with the defined value at compile time. 3274 | 3275 | `#define constantName value` 3276 | Note that the # is necessary. 3277 | 3278 | This can have some unwanted side effects though, if for example, a constant name that had been `#defined` is included in some other constant or variable name. In that case the text would be replaced by the #defined number (or text). 3279 | 3280 | ```C++ 3281 | // EXAMPLE USAGE 3282 | #define ledPin 3 3283 | // The compiler will replace any mention of ledPin with the value 3 at compile time. 3284 | ``` 3285 | 3286 | In general, the [const]() keyword is preferred for defining constants and should be used instead of #define. 3287 | 3288 | **TIP:** 3289 | There is no semicolon after the #define statement. If you include one, the compiler will throw cryptic errors further down the page. 3290 | 3291 | `#define ledPin 3; // this is an error` 3292 | 3293 | Similarly, including an equal sign after the #define statement will also generate a cryptic compiler error further down the page. 3294 | 3295 | `#define ledPin = 3 // this is also an error` 3296 | 3297 | ### #include 3298 | 3299 | `#include` is used to include outside libraries in your application code. This gives the programmer access to a large group of standard C libraries (groups of pre-made functions), and also libraries written especially for board. 3300 | 3301 | Note that #include, similar to #define, has no semicolon terminator, and the compiler will yield cryptic error messages if you add one. 3302 | 3303 | Arithmetic operators 3304 | --- 3305 | 3306 | ### = (assignment operator) 3307 | 3308 | Stores the value to the right of the equal sign in the variable to the left of the equal sign. 3309 | 3310 | The single equal sign in the C programming language is called the assignment operator. It has a different meaning than in algebra class where it indicated an equation or equality. The assignment operator tells the microcontroller to evaluate whatever value or expression is on the right side of the equal sign, and store it in the variable to the left of the equal sign. 3311 | 3312 | ```C++ 3313 | // EXAMPLE USAGE 3314 | int sensVal; // declare an integer variable named sensVal 3315 | senVal = analogRead(A0); // store the (digitized) input voltage at analog pin A0 in SensVal 3316 | ``` 3317 | **TIP:** 3318 | The variable on the left side of the assignment operator ( = sign ) needs to be able to hold the value stored in it. If it is not large enough to hold a value, the value stored in the variable will be incorrect. 3319 | 3320 | Don't confuse the assignment operator `=` (single equal sign) with the comparison operator `==` (double equal signs), which evaluates whether two expressions are equal. 3321 | 3322 | ### + - * / (additon subtraction multiplication division) 3323 | 3324 | These operators return the sum, difference, product, or quotient (respectively) of the two operands. The operation is conducted using the data type of the operands, so, for example,`9 / 4` gives 2 since 9 and 4 are ints. This also means that the operation can overflow if the result is larger than that which can be stored in the data type (e.g. adding 1 to an int with the value 2,147,483,647 gives -2,147,483,648). If the operands are of different types, the "larger" type is used for the calculation. 3325 | 3326 | If one of the numbers (operands) are of the type float or of type double, floating point math will be used for the calculation. 3327 | 3328 | ```C++ 3329 | // EXAMPLE USAGES 3330 | y = y + 3; 3331 | x = x - 7; 3332 | i = j * 6; 3333 | r = r / 5; 3334 | ``` 3335 | 3336 | ```C++ 3337 | // SYNTAX 3338 | result = value1 + value2; 3339 | result = value1 - value2; 3340 | result = value1 * value2; 3341 | result = value1 / value2; 3342 | ``` 3343 | `value1` and `value2` can be any variable or constant. 3344 | 3345 | **TIPS:** 3346 | 3347 | - Know that integer constants default to int, so some constant calculations may overflow (e.g. 50 * 50,000,000 will yield a negative result). 3348 | - Choose variable sizes that are large enough to hold the largest results from your calculations 3349 | - Know at what point your variable will "roll over" and also what happens in the other direction e.g. (0 - 1) OR (0 + 2147483648) 3350 | - For math that requires fractions, use float variables, but be aware of their drawbacks: large size, slow computation speeds 3351 | - Use the cast operator e.g. (int)myFloat to convert one variable type to another on the fly. 3352 | 3353 | ### % (modulo) 3354 | 3355 | Calculates the remainder when one integer is divided by another. It is useful for keeping a variable within a particular range (e.g. the size of an array). It is defined so that `a % b == a - ((a / b) * b)`. 3356 | 3357 | `result = dividend % divisor` 3358 | 3359 | `dividend` is the number to be divided and 3360 | `divisor` is the number to divide by. 3361 | 3362 | `result` is the remainder 3363 | 3364 | The remainder function can have unexpected behavoir when some of the opperands are negative. If the dividend is negative, then the result will be the smallest negative equivalency class. In other words, when `a` is negative, `(a % b) == (a mod b) - b` where (a mod b) follows the standard mathematical definition of mod. When the divisor is negative, the result is the same as it would be if it was positive. 3365 | 3366 | ```C++ 3367 | // EXAMPLE USAGES 3368 | x = 9 % 5; // x now contains 4 3369 | x = 5 % 5; // x now contains 0 3370 | x = 4 % 5; // x now contains 4 3371 | x = 7 % 5; // x now contains 2 3372 | x = -7 % 5; // x now contains -2 3373 | x = 7 % -5; // x now contains 2 3374 | x = -7 % -5; // x now contains -2 3375 | ``` 3376 | 3377 | ```C++ 3378 | EXAMPLE CODE 3379 | //update one value in an array each time through a loop 3380 | 3381 | int values[10]; 3382 | int i = 0; 3383 | 3384 | void setup() {} 3385 | 3386 | void loop() 3387 | { 3388 | values[i] = analogRead(A0); 3389 | i = (i + 1) % 10; // modulo operator rolls over variable 3390 | } 3391 | ``` 3392 | 3393 | **TIP:** 3394 | The modulo operator does not work on floats. For floats, an equivalent expression to `a % b` is `a - (b * ((int)(a / b)))` 3395 | 3396 | Boolean operators 3397 | --- 3398 | 3399 | These can be used inside the condition of an if statement. 3400 | 3401 | ### && (and) 3402 | 3403 | True only if both operands are true, e.g. 3404 | 3405 | ```C++ 3406 | if (digitalRead(D2) == HIGH && digitalRead(D3) == HIGH) 3407 | { 3408 | // read two switches 3409 | // ... 3410 | } 3411 | //is true only if both inputs are high. 3412 | ``` 3413 | 3414 | ### || (or) 3415 | 3416 | True if either operand is true, e.g. 3417 | 3418 | ```C++ 3419 | if (x > 0 || y > 0) 3420 | { 3421 | // ... 3422 | } 3423 | //is true if either x or y is greater than 0. 3424 | ``` 3425 | 3426 | ### ! (not) 3427 | 3428 | True if the operand is false, e.g. 3429 | 3430 | ```C++ 3431 | if (!x) 3432 | { 3433 | // ... 3434 | } 3435 | //is true if x is false (i.e. if x equals 0). 3436 | ``` 3437 | 3438 | **WARNING:** 3439 | Make sure you don't mistake the boolean AND operator, && (double ampersand) for the bitwise AND operator & (single ampersand). They are entirely different beasts. 3440 | 3441 | Similarly, do not confuse the boolean || (double pipe) operator with the bitwise OR operator | (single pipe). 3442 | 3443 | The bitwise not ~ (tilde) looks much different than the boolean not ! (exclamation point or "bang" as the programmers say) but you still have to be sure which one you want where. 3444 | 3445 | `if (a >= 10 && a <= 20){} // true if a is between 10 and 20` 3446 | 3447 | Bitwise operators 3448 | --- 3449 | 3450 | ### & (bitwise and) 3451 | 3452 | The bitwise AND operator in C++ is a single ampersand, &, used between two other integer expressions. Bitwise AND operates on each bit position of the surrounding expressions independently, according to this rule: if both input bits are 1, the resulting output is 1, otherwise the output is 0. Another way of expressing this is: 3453 | 3454 | ``` 3455 | 0 0 1 1 operand1 3456 | 0 1 0 1 operand2 3457 | ---------- 3458 | 0 0 0 1 (operand1 & operand2) - returned result 3459 | ``` 3460 | 3461 | ```C++ 3462 | // EXAMPLE USAGE 3463 | int a = 92; // in binary: 0000000001011100 3464 | int b = 101; // in binary: 0000000001100101 3465 | int c = a & b; // result: 0000000001000100, or 68 in decimal. 3466 | ``` 3467 | One of the most common uses of bitwise AND is to select a particular bit (or bits) from an integer value, often called masking. 3468 | 3469 | ### | (bitwise or) 3470 | 3471 | The bitwise OR operator in C++ is the vertical bar symbol, |. Like the & operator, | operates independently each bit in its two surrounding integer expressions, but what it does is different (of course). The bitwise OR of two bits is 1 if either or both of the input bits is 1, otherwise it is 0. In other words: 3472 | 3473 | ``` 3474 | 0 0 1 1 operand1 3475 | 0 1 0 1 operand2 3476 | ---------- 3477 | 0 1 1 1 (operand1 | operand2) - returned result 3478 | ``` 3479 | ```C++ 3480 | // EXAMPLE USAGE 3481 | int a = 92; // in binary: 0000000001011100 3482 | int b = 101; // in binary: 0000000001100101 3483 | int c = a | b; // result: 0000000001111101, or 125 in decimal. 3484 | ``` 3485 | 3486 | ### ^ (bitwise xor) 3487 | 3488 | There is a somewhat unusual operator in C++ called bitwise EXCLUSIVE OR, also known as bitwise XOR. (In English this is usually pronounced "eks-or".) The bitwise XOR operator is written using the caret symbol ^. This operator is very similar to the bitwise OR operator |, only it evaluates to 0 for a given bit position when both of the input bits for that position are 1: 3489 | 3490 | ``` 3491 | 0 0 1 1 operand1 3492 | 0 1 0 1 operand2 3493 | ---------- 3494 | 0 1 1 0 (operand1 ^ operand2) - returned result 3495 | ``` 3496 | Another way to look at bitwise XOR is that each bit in the result is a 1 if the input bits are different, or 0 if they are the same. 3497 | 3498 | ```C++ 3499 | // EXAMPLE USAGE 3500 | int x = 12; // binary: 1100 3501 | int y = 10; // binary: 1010 3502 | int z = x ^ y; // binary: 0110, or decimal 6 3503 | ``` 3504 | 3505 | The ^ operator is often used to toggle (i.e. change from 0 to 1, or 1 to 0) some of the bits in an integer expression. In a bitwise OR operation if there is a 1 in the mask bit, that bit is inverted; if there is a 0, the bit is not inverted and stays the same. 3506 | 3507 | 3508 | ### ~ (bitwise not) 3509 | 3510 | The bitwise NOT operator in C++ is the tilde character ~. Unlike & and |, the bitwise NOT operator is applied to a single operand to its right. Bitwise NOT changes each bit to its opposite: 0 becomes 1, and 1 becomes 0. For example: 3511 | 3512 | ``` 3513 | 0 1 operand1 3514 | ---------- 3515 | 1 0 ~ operand1 3516 | 3517 | int a = 103; // binary: 0000000001100111 3518 | int b = ~a; // binary: 1111111110011000 = -104 3519 | ``` 3520 | You might be surprised to see a negative number like -104 as the result of this operation. This is because the highest bit in an int variable is the so-called sign bit. If the highest bit is 1, the number is interpreted as negative. This encoding of positive and negative numbers is referred to as two's complement. For more information, see the Wikipedia article on [two's complement.](http://en.wikipedia.org/wiki/Twos_complement) 3521 | 3522 | As an aside, it is interesting to note that for any integer x, ~x is the same as -x-1. 3523 | 3524 | At times, the sign bit in a signed integer expression can cause some unwanted surprises. 3525 | 3526 | ### << (bitwise left shift), >> (bitwise right shift) 3527 | 3528 | There are two bit shift operators in C++: the left shift operator << and the right shift operator >>. These operators cause the bits in the left operand to be shifted left or right by the number of positions specified by the right operand. 3529 | 3530 | More on bitwise math may be found [here.](http://www.arduino.cc/playground/Code/BitMath) 3531 | 3532 | ``` 3533 | variable << number_of_bits 3534 | variable >> number_of_bits 3535 | ``` 3536 | 3537 | `variable` can be `byte`, `int`, `long` 3538 | `number_of_bits` and integer <= 32 3539 | 3540 | ```C++ 3541 | // EXAMPLE USAGE 3542 | int a = 5; // binary: 0000000000000101 3543 | int b = a << 3; // binary: 0000000000101000, or 40 in decimal 3544 | int c = b >> 3; // binary: 0000000000000101, or back to 5 like we started with 3545 | ``` 3546 | When you shift a value x by y bits (x << y), the leftmost y bits in x are lost, literally shifted out of existence: 3547 | 3548 | ```C++ 3549 | int a = 5; // binary: 0000000000000101 3550 | int b = a << 14; // binary: 0100000000000000 - the first 1 in 101 was discarded 3551 | ``` 3552 | If you are certain that none of the ones in a value are being shifted into oblivion, a simple way to think of the left-shift operator is that it multiplies the left operand by 2 raised to the right operand power. For example, to generate powers of 2, the following expressions can be employed: 3553 | 3554 | ``` 3555 | 1 << 0 == 1 3556 | 1 << 1 == 2 3557 | 1 << 2 == 4 3558 | 1 << 3 == 8 3559 | ... 3560 | 1 << 8 == 256 3561 | 1 << 9 == 512 3562 | 1 << 10 == 1024 3563 | ... 3564 | ``` 3565 | When you shift x right by y bits (x >> y), and the highest bit in x is a 1, the behavior depends on the exact data type of x. If x is of type int, the highest bit is the sign bit, determining whether x is negative or not, as we have discussed above. In that case, the sign bit is copied into lower bits, for esoteric historical reasons: 3566 | 3567 | ```C++ 3568 | int x = -16; // binary: 1111111111110000 3569 | int y = x >> 3; // binary: 1111111111111110 3570 | ``` 3571 | This behavior, called sign extension, is often not the behavior you want. Instead, you may wish zeros to be shifted in from the left. It turns out that the right shift rules are different for unsigned int expressions, so you can use a typecast to suppress ones being copied from the left: 3572 | 3573 | ```C++ 3574 | int x = -16; // binary: 1111111111110000 3575 | int y = (unsigned int)x >> 3; // binary: 0001111111111110 3576 | ``` 3577 | 3578 | If you are careful to avoid sign extension, you can use the right-shift operator >> as a way to divide by powers of 2. For example: 3579 | 3580 | ```C++ 3581 | int x = 1000; 3582 | int y = x >> 3; // integer division of 1000 by 8, causing y = 125 3583 | ``` 3584 | Compound operators 3585 | --- 3586 | 3587 | ### ++ (increment), -- (decrement) 3588 | 3589 | Increment or decrement a variable 3590 | 3591 | ```C++ 3592 | SYNTAX 3593 | x++; // increment x by one and returns the old value of x 3594 | ++x; // increment x by one and returns the new value of x 3595 | 3596 | x-- ; // decrement x by one and returns the old value of x 3597 | --x ; // decrement x by one and returns the new value of x 3598 | ``` 3599 | 3600 | where `x` is an integer or long (possibly unsigned) 3601 | 3602 | ```C++ 3603 | // EXAMPLE USAGE 3604 | x = 2; 3605 | y = ++x; // x now contains 3, y contains 3 3606 | y = x--; // x contains 2 again, y still contains 3 3607 | ``` 3608 | 3609 | ### compound arithmetic 3610 | 3611 | - += (compound addition) 3612 | - -= (compound subtraction) 3613 | - *= (compound multiplication) 3614 | - /= (compound division) 3615 | 3616 | Perform a mathematical operation on a variable with another constant or variable. The += (et al) operators are just a convenient shorthand for the expanded syntax. 3617 | 3618 | ```C++ 3619 | SYNTAX 3620 | x += y; // equivalent to the expression x = x + y; 3621 | x -= y; // equivalent to the expression x = x - y; 3622 | x *= y; // equivalent to the expression x = x * y; 3623 | x /= y; // equivalent to the expression x = x / y; 3624 | ``` 3625 | 3626 | `x` can be any variable type 3627 | `y` can be any variable type or constant 3628 | 3629 | ```C++ 3630 | // EXAMPLE USAGE 3631 | x = 2; 3632 | x += 4; // x now contains 6 3633 | x -= 3; // x now contains 3 3634 | x *= 10; // x now contains 30 3635 | x /= 2; // x now contains 15 3636 | ``` 3637 | 3638 | ### &= (compound bitwise and) 3639 | 3640 | The compound bitwise AND operator (&=) is often used with a variable and a constant to force particular bits in a variable to the LOW state (to 0). This is often referred to in programming guides as "clearing" or "resetting" bits. 3641 | 3642 | `x &= y; // equivalent to x = x & y;` 3643 | 3644 | `x` can be a char, int or long variable 3645 | `y` can be an integer constant, char, int, or long 3646 | 3647 | ``` 3648 | 0 0 1 1 operand1 3649 | 0 1 0 1 operand2 3650 | ---------- 3651 | 0 0 0 1 (operand1 & operand2) - returned result 3652 | ``` 3653 | Bits that are "bitwise ANDed" with 0 are cleared to 0 so, if myByte is a byte variable, 3654 | `myByte & B00000000 = 0;` 3655 | 3656 | Bits that are "bitwise ANDed" with 1 are unchanged so, 3657 | `myByte & B11111111 = myByte;` 3658 | 3659 | **Note:** because we are dealing with bits in a bitwise operator - it is convenient to use the binary formatter with constants. The numbers are still the same value in other representations, they are just not as easy to understand. Also, B00000000 is shown for clarity, but zero in any number format is zero (hmmm something philosophical there?) 3660 | 3661 | Consequently - to clear (set to zero) bits 0 & 1 of a variable, while leaving the rest of the variable unchanged, use the compound bitwise AND operator (&=) with the constant B11111100 3662 | 3663 | ``` 3664 | 1 0 1 0 1 0 1 0 variable 3665 | 1 1 1 1 1 1 0 0 mask 3666 | ---------------------- 3667 | 1 0 1 0 1 0 0 0 3668 | 3669 | variable unchanged 3670 | bits cleared 3671 | ``` 3672 | Here is the same representation with the variable's bits replaced with the symbol x 3673 | 3674 | ``` 3675 | x x x x x x x x variable 3676 | 1 1 1 1 1 1 0 0 mask 3677 | ---------------------- 3678 | x x x x x x 0 0 3679 | 3680 | variable unchanged 3681 | bits cleared 3682 | ``` 3683 | 3684 | So if: 3685 | `myByte = 10101010;` 3686 | `myByte &= B1111100 == B10101000;` 3687 | 3688 | 3689 | ### |= (compound bitwise or) 3690 | 3691 | The compound bitwise OR operator (|=) is often used with a variable and a constant to "set" (set to 1) particular bits in a variable. 3692 | 3693 | ```C++ 3694 | SYNTAX 3695 | x |= y; // equivalent to x = x | y; 3696 | ``` 3697 | `x` can be a char, int or long variable 3698 | `y` can be an integer constant or char, int or long 3699 | 3700 | ``` 3701 | 0 0 1 1 operand1 3702 | 0 1 0 1 operand2 3703 | ---------- 3704 | 0 1 1 1 (operand1 | operand2) - returned result 3705 | ``` 3706 | Bits that are "bitwise ORed" with 0 are unchanged, so if myByte is a byte variable, 3707 | `myByte | B00000000 = myByte;` 3708 | 3709 | Bits that are "bitwise ORed" with 1 are set to 1 so: 3710 | `myByte | B11111111 = B11111111;` 3711 | 3712 | Consequently - to set bits 0 & 1 of a variable, while leaving the rest of the variable unchanged, use the compound bitwise OR operator (|=) with the constant B00000011 3713 | 3714 | ``` 3715 | 1 0 1 0 1 0 1 0 variable 3716 | 0 0 0 0 0 0 1 1 mask 3717 | ---------------------- 3718 | 1 0 1 0 1 0 1 1 3719 | 3720 | variable unchanged 3721 | bits set 3722 | ``` 3723 | Here is the same representation with the variables bits replaced with the symbol x 3724 | ``` 3725 | x x x x x x x x variable 3726 | 0 0 0 0 0 0 1 1 mask 3727 | ---------------------- 3728 | x x x x x x 1 1 3729 | 3730 | variable unchanged 3731 | bits set 3732 | ``` 3733 | So if: 3734 | `myByte = B10101010;` 3735 | `myByte |= B00000011 == B10101011;` 3736 | 3737 | 3738 | 3739 | String Class 3740 | ---- 3741 | 3742 | The String class allows you to use and manipulate strings of text in more complex ways than character arrays do. You can concatenate Strings, append to them, search for and replace substrings, and more. It takes more memory than a simple character array, but it is also more useful. 3743 | 3744 | For reference, character arrays are referred to as strings with a small s, and instances of the String class are referred to as Strings with a capital S. Note that constant strings, specified in "double quotes" are treated as char arrays, not instances of the String class. 3745 | 3746 | ### String() 3747 | 3748 | Constructs an instance of the String class. There are multiple versions that construct Strings from different data types (i.e. format them as sequences of characters), including: 3749 | 3750 | * a constant string of characters, in double quotes (i.e. a char array) 3751 | * a single constant character, in single quotes 3752 | * another instance of the String object 3753 | * a constant integer or long integer 3754 | * a constant integer or long integer, using a specified base 3755 | * an integer or long integer variable 3756 | * an integer or long integer variable, using a specified base 3757 | 3758 | Constructing a String from a number results in a string that contains the ASCII representation of that number. The default is base ten, so 3759 | 3760 | `String thisString = String(13)` 3761 | gives you the String "13". You can use other bases, however. For example, 3762 | `String thisString = String(13, HEX)` 3763 | gives you the String "D", which is the hexadecimal representation of the decimal value 13. Or if you prefer binary, 3764 | `String thisString = String(13, BIN)` 3765 | gives you the String "1101", which is the binary representation of 13. 3766 | 3767 | ``` 3768 | SYNTAX: 3769 | 3770 | String(val) 3771 | String(val, base) 3772 | ``` 3773 | 3774 | Parameters: 3775 | 3776 | * val: a variable to format as a String - string, char, byte, int, long, unsigned int, unsigned long 3777 | * base (optional) - the base in which to format an integral value 3778 | 3779 | Returns: an instance of the String class 3780 | 3781 | ```cpp 3782 | // EXAMPLES 3783 | String stringOne = "Hello String"; // using a constant String 3784 | String stringOne = String('a'); // converting a constant char into a String 3785 | String stringTwo = String("This is a string"); // converting a constant string into a String object 3786 | String stringOne = String(stringTwo + " with more"); // concatenating two strings 3787 | String stringOne = String(13); // using a constant integer 3788 | String stringOne = String(analogRead(0), DEC); // using an int and a base 3789 | String stringOne = String(45, HEX); // using an int and a base (hexadecimal) 3790 | String stringOne = String(255, BIN); // using an int and a base (binary) 3791 | String stringOne = String(millis(), DEC); // using a long and a base 3792 | ``` 3793 | 3794 | ### charAt() 3795 | 3796 | Access a particular character of the String. 3797 | 3798 | ``` 3799 | SYNTAX: 3800 | 3801 | string.charAt(n) 3802 | ``` 3803 | Parameters: 3804 | 3805 | * `string`: a variable of type String 3806 | * `n`: the character to access 3807 | 3808 | Returns: the n'th character of the String 3809 | 3810 | 3811 | ### compareTo() 3812 | 3813 | Compares two Strings, testing whether one comes before or after the other, or whether they're equal. The strings are compared character by character, using the ASCII values of the characters. That means, for example, that 'a' comes before 'b' but after 'A'. Numbers come before letters. 3814 | 3815 | 3816 | ``` 3817 | SYNTAX: 3818 | 3819 | string.compareTo(string2) 3820 | ``` 3821 | 3822 | Parameters: 3823 | 3824 | * string: a variable of type String 3825 | * string2: another variable of type String 3826 | 3827 | Returns: 3828 | 3829 | * a negative number: if string comes before string2 3830 | * 0: if string equals string2 3831 | * a positive number: if string comes after string2 3832 | 3833 | ### concat() 3834 | 3835 | Combines, or *concatenates* two strings into one string. The second string is appended to the first, and the result is placed in the original string. 3836 | 3837 | ``` 3838 | SYNTAX: 3839 | 3840 | string.concat(string2) 3841 | ``` 3842 | 3843 | Parameters: 3844 | 3845 | * string, string2: variables of type String 3846 | 3847 | Returns: None 3848 | 3849 | ### endsWith() 3850 | 3851 | Tests whether or not a String ends with the characters of another String. 3852 | 3853 | ``` 3854 | SYNTAX: 3855 | 3856 | string.endsWith(string2) 3857 | ``` 3858 | 3859 | Parameters: 3860 | 3861 | * string: a variable of type String 3862 | * string2: another variable of type String 3863 | 3864 | Returns: 3865 | 3866 | * true: if string ends with the characters of string2 3867 | * false: otherwise 3868 | 3869 | 3870 | ### equals() 3871 | 3872 | Compares two strings for equality. The comparison is case-sensitive, meaning the String "hello" is not equal to the String "HELLO". 3873 | 3874 | ``` 3875 | SYNTAX: 3876 | 3877 | string.equals(string2) 3878 | ``` 3879 | Parameters: 3880 | 3881 | * string, string2: variables of type String 3882 | 3883 | Returns: 3884 | 3885 | * true: if string equals string2 3886 | * false: otherwise 3887 | 3888 | ### equalsIgnoreCase() 3889 | 3890 | Compares two strings for equality. The comparison is not case-sensitive, meaning the String("hello") is equal to the String("HELLO"). 3891 | 3892 | ``` 3893 | SYNTAX: 3894 | 3895 | string.equalsIgnoreCase(string2) 3896 | ``` 3897 | Parameters: 3898 | 3899 | * string, string2: variables of type String 3900 | 3901 | Returns: 3902 | 3903 | * true: if string equals string2 (ignoring case) 3904 | * false: otherwise 3905 | 3906 | ### getBytes() 3907 | 3908 | Copies the string's characters to the supplied buffer. 3909 | 3910 | ``` 3911 | SYNTAX: 3912 | 3913 | string.getBytes(buf, len) 3914 | ``` 3915 | Parameters: 3916 | 3917 | * string: a variable of type String 3918 | * buf: the buffer to copy the characters into (byte []) 3919 | * len: the size of the buffer (unsigned int) 3920 | 3921 | Returns: None 3922 | 3923 | ### indexOf() 3924 | 3925 | Locates a character or String within another String. By default, searches from the beginning of the String, but can also start from a given index, allowing for the locating of all instances of the character or String. 3926 | 3927 | ``` 3928 | SYNTAX: 3929 | 3930 | string.indexOf(val) 3931 | string.indexOf(val, from) 3932 | ``` 3933 | 3934 | Parameters: 3935 | 3936 | * string: a variable of type String 3937 | * val: the value to search for - char or String 3938 | * from: the index to start the search from 3939 | 3940 | Returns: The index of val within the String, or -1 if not found. 3941 | 3942 | ### lastIndexOf() 3943 | 3944 | Locates a character or String within another String. By default, searches from the end of the String, but can also work backwards from a given index, allowing for the locating of all instances of the character or String. 3945 | 3946 | ```SYNTAX: 3947 | 3948 | string.lastIndexOf(val) 3949 | string.lastIndexOf(val, from) 3950 | ``` 3951 | 3952 | Parameters: 3953 | 3954 | * string: a variable of type String 3955 | * val: the value to search for - char or String 3956 | * from: the index to work backwards from 3957 | 3958 | Returns: The index of val within the String, or -1 if not found. 3959 | 3960 | ### length() 3961 | 3962 | Returns the length of the String, in characters. (Note that this doesn't include a trailing null character.) 3963 | 3964 | ``` 3965 | SYNTAX: 3966 | 3967 | string.length() 3968 | ``` 3969 | 3970 | Parameters: 3971 | 3972 | * string: a variable of type String 3973 | 3974 | Returns: The length of the String in characters. 3975 | 3976 | ### replace() 3977 | 3978 | The String `replace()` function allows you to replace all instances of a given character with another character. You can also use replace to replace substrings of a string with a different substring. 3979 | 3980 | ``` 3981 | SYNTAX: 3982 | 3983 | string.replace(substring1, substring2) 3984 | ``` 3985 | 3986 | Parameters: 3987 | 3988 | * string: the string which will be modified - a variable of type String 3989 | * substring1: searched for - another variable of type String (single or multi-character), char or const char (single character only) 3990 | * substring2: replaced with - another variable of type String (signle or multi-character), char or const char (single character only) 3991 | 3992 | Returns: None 3993 | 3994 | ### reserve() 3995 | 3996 | The String reserve() function allows you to allocate a buffer in memory for manipulating strings. 3997 | 3998 | ``` 3999 | SYNTAX: 4000 | 4001 | string.reserve(size) 4002 | ``` 4003 | Parameters: 4004 | 4005 | * size: unsigned int declaring the number of bytes in memory to save for string manipulation 4006 | 4007 | Returns: None 4008 | 4009 | ```cpp 4010 | //EXAMPLE 4011 | 4012 | String myString; 4013 | 4014 | void setup() { 4015 | // initialize serial and wait for port to open: 4016 | //Serial.begin(9600); 4017 | //begin does not do anything for Serial which uses the cloud 4018 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 4019 | while (!Serial) { 4020 | ; // wait for serial port to connect. Needed for Leonardo only 4021 | } 4022 | 4023 | myString.reserve(26); 4024 | myString = "i="; 4025 | myString += "1234"; 4026 | myString += ", is that ok?"; 4027 | 4028 | // print the String: 4029 | Serial.println(myString); 4030 | } 4031 | 4032 | void loop() { 4033 | // nothing to do here 4034 | } 4035 | ``` 4036 | 4037 | ### setCharAt() 4038 | 4039 | Sets a character of the String. Has no effect on indices outside the existing length of the String. 4040 | 4041 | ``` 4042 | SYNTAX: 4043 | 4044 | string.setCharAt(index, c) 4045 | ``` 4046 | Parameters: 4047 | 4048 | * string: a variable of type String 4049 | * index: the index to set the character at 4050 | * c: the character to store to the given location 4051 | 4052 | Returns: None 4053 | 4054 | ### startsWith() 4055 | 4056 | Tests whether or not a String starts with the characters of another String. 4057 | 4058 | ``` 4059 | SYNTAX: 4060 | 4061 | string.startsWith(string2) 4062 | ``` 4063 | 4064 | Parameters: 4065 | 4066 | * string, string2: variable2 of type String 4067 | 4068 | Returns: 4069 | 4070 | * true: if string starts with the characters of string2 4071 | * false: otherwise 4072 | 4073 | 4074 | ### substring() 4075 | 4076 | Get a substring of a String. The starting index is inclusive (the corresponding character is included in the substring), but the optional ending index is exclusive (the corresponding character is not included in the substring). If the ending index is omitted, the substring continues to the end of the String. 4077 | 4078 | ``` 4079 | SYNTAX: 4080 | 4081 | string.substring(from) 4082 | string.substring(from, to) 4083 | ``` 4084 | 4085 | Parameters: 4086 | 4087 | * string: a variable of type String 4088 | * from: the index to start the substring at 4089 | * to (optional): the index to end the substring before 4090 | 4091 | Returns: the substring 4092 | 4093 | ### toCharArray() 4094 | 4095 | Copies the string's characters to the supplied buffer. 4096 | 4097 | ``` 4098 | SYNTAX: 4099 | 4100 | string.toCharArray(buf, len) 4101 | ``` 4102 | Parameters: 4103 | 4104 | * string: a variable of type String 4105 | * buf: the buffer to copy the characters into (char []) 4106 | * len: the size of the buffer (unsigned int) 4107 | 4108 | Returns: None 4109 | 4110 | ### toInt() 4111 | 4112 | Converts a valid String to an integer. The input string should start with an integral number. If the string contains non-integral numbers, the function will stop performing the conversion. 4113 | 4114 | ``` 4115 | SYNTAX: 4116 | 4117 | string.toInt() 4118 | ``` 4119 | 4120 | Parameters: 4121 | 4122 | * string: a variable of type String 4123 | 4124 | Returns: long (If no valid conversion could be performed because the string doesn't start with a integral number, a zero is returned.) 4125 | 4126 | ### toLowerCase() 4127 | 4128 | Get a lower-case version of a String. `toLowerCase()` modifies the string in place. 4129 | 4130 | ``` 4131 | SYNTAX: 4132 | 4133 | string.toLowerCase() 4134 | ``` 4135 | 4136 | Parameters: 4137 | 4138 | * string: a variable of type String 4139 | 4140 | Returns: None 4141 | 4142 | ### toUpperCase() 4143 | 4144 | Get an upper-case version of a String. `toUpperCase()` modifies the string in place. 4145 | 4146 | ``` 4147 | SYNTAX: 4148 | 4149 | string.toUpperCase() 4150 | ``` 4151 | 4152 | Parameters: 4153 | 4154 | * string: a variable of type String 4155 | 4156 | Returns: None 4157 | 4158 | ### trim() 4159 | 4160 | Get a version of the String with any leading and trailing whitespace removed. 4161 | 4162 | ``` 4163 | SYNTAX: 4164 | 4165 | string.trim() 4166 | ``` 4167 | 4168 | Parameters: 4169 | 4170 | * string: a variable of type String 4171 | 4172 | Returns: None 4173 | 4174 | 4175 | Variables 4176 | ===== 4177 | 4178 | Constants 4179 | ---- 4180 | 4181 | ### HIGH | LOW 4182 | 4183 | When reading or writing to a digital pin there are only two possible values a pin can take/be-set-to: HIGH and LOW. 4184 | 4185 | `HIGH` 4186 | 4187 | The meaning of `HIGH` (in reference to a pin) is somewhat different depending on whether a pin is set to an `INPUT` or `OUTPUT`. When a pin is configured as an INPUT with pinMode, and read with digitalRead, the microcontroller will report HIGH if a voltage of 3 volts or more is present at the pin. 4188 | 4189 | A pin may also be configured as an `INPUT` with `pinMode`, and subsequently made `HIGH` with `digitalWrite`, this will set the internal 40K pullup resistors, which will steer the input pin to a `HIGH` reading unless it is pulled LOW by external circuitry. This is how INPUT_PULLUP works as well 4190 | 4191 | When a pin is configured to `OUTPUT` with `pinMode`, and set to `HIGH` with `digitalWrite`, the pin is at 3.3 volts. In this state it can source current, e.g. light an LED that is connected through a series resistor to ground, or to another pin configured as an output, and set to `LOW.` 4192 | 4193 | `LOW` 4194 | 4195 | The meaning of `LOW` also has a different meaning depending on whether a pin is set to `INPUT` or `OUTPUT`. When a pin is configured as an `INPUT` with `pinMode`, and read with `digitalRead`, the microcontroller will report `LOW` if a voltage of 1.5 volts or less is present at the pin. 4196 | 4197 | When a pin is configured to `OUTPUT` with `pinMode`, and set to `LOW` with digitalWrite, the pin is at 0 volts. In this state it can sink current, e.g. light an LED that is connected through a series resistor to, +3.3 volts, or to another pin configured as an output, and set to `HIGH.` 4198 | 4199 | ### INPUT, OUTPUT, INPUT_PULLUP, INPUT_PULLDOWN 4200 | 4201 | Digital pins can be used as INPUT, INPUT_PULLUP, INPUT_PULLDOWN or OUTPUT. Changing a pin with `pinMode()` changes the electrical behavior of the pin. 4202 | 4203 | Pins Configured as `INPUT` 4204 | 4205 | The board's pins configured as `INPUT` with `pinMode()`` are said to be in a high-impedance state. Pins configured as `INPUT` make extremely small demands on the circuit that they are sampling, equivalent to a series resistor of 100 Megohms in front of the pin. This makes them useful for reading a sensor, but not powering an LED. 4206 | 4207 | If you have your pin configured as an `INPUT`, you will want the pin to have a reference to ground, often accomplished with a pull-down resistor (a resistor going to ground). 4208 | 4209 | Pins Configured as `INPUT_PULLUP` or `INPUT_PULLDOWN` 4210 | 4211 | The Oak microcontroller has internal pull-up resistors (resistors that connect to power internally) and pull-down resistors (resistors that connect to ground internally) that you can access. If you prefer to use these instead of external resistors, you can use these argument in `pinMode()`. 4212 | 4213 | Pins Configured as `OUTPUT` 4214 | 4215 | Pins configured as `OUTPUT` with `pinMode()`` are said to be in a low-impedance state. This means that they can provide a substantial amount of current to other circuits. Oak pins can source (provide positive current) or sink (provide negative current) up to 12 mA (milliamps) of current to other devices/circuits. This makes them useful for powering LED's but useless for reading sensors. Pins configured as outputs can also be damaged or destroyed if short circuited to either ground or 3.3 volt power rails. The amount of current provided by the pin is also not enough to power most relays or motors, and some interface circuitry will be required. 4216 | 4217 | ### true | false 4218 | 4219 | There are two constants used to represent truth and falsity in the Arduino language: true, and false. 4220 | 4221 | `false` 4222 | 4223 | `false` is the easier of the two to define. false is defined as 0 (zero). 4224 | 4225 | `true` 4226 | 4227 | `true` is often said to be defined as 1, which is correct, but true has a wider definition. Any integer which is non-zero is true, in a Boolean sense. So -1, 2 and -200 are all defined as true, too, in a Boolean sense. 4228 | 4229 | Note that the true and false constants are typed in lowercase unlike `HIGH, LOW, INPUT, & OUTPUT.` 4230 | 4231 | 4232 | Data Types 4233 | ---- 4234 | 4235 | **Note:** The board uses a 32-bit based microcontroller and hence the datatype lengths are different from a standard 8-bit system (for eg. Arduino Uno). 4236 | 4237 | ### void 4238 | 4239 | The `void` keyword is used only in function declarations. It indicates that the function is expected to return no information to the function from which it was called. 4240 | 4241 | ```cpp 4242 | 4243 | //EXAMPLE 4244 | // actions are performed in the functions "setup" and "loop" 4245 | // but no information is reported to the larger program 4246 | 4247 | void setup() 4248 | { 4249 | // ... 4250 | } 4251 | 4252 | void loop() 4253 | { 4254 | // ... 4255 | } 4256 | ``` 4257 | 4258 | ### boolean 4259 | 4260 | A `boolean` holds one of two values, `true` or `false`. (Each boolean variable occupies one byte of memory.) 4261 | 4262 | ```cpp 4263 | //EXAMPLE 4264 | 4265 | int LEDpin = D0; // LED on D0 4266 | int switchPin = A0; // momentary switch on A0, other side connected to ground 4267 | 4268 | boolean running = false; 4269 | 4270 | void setup() 4271 | { 4272 | pinMode(LEDpin, OUTPUT); 4273 | pinMode(switchPin, INPUT_PULLUP); 4274 | } 4275 | 4276 | void loop() 4277 | { 4278 | if (digitalRead(switchPin) == LOW) 4279 | { // switch is pressed - pullup keeps pin high normally 4280 | delay(100); // delay to debounce switch 4281 | running = !running; // toggle running variable 4282 | digitalWrite(LEDpin, running) // indicate via LED 4283 | } 4284 | } 4285 | 4286 | ``` 4287 | 4288 | ### char 4289 | 4290 | A data type that takes up 1 byte of memory that stores a character value. Character literals are written in single quotes, like this: 'A' (for multiple characters - strings - use double quotes: "ABC"). 4291 | Characters are stored as numbers however. You can see the specific encoding in the ASCII chart. This means that it is possible to do arithmetic on characters, in which the ASCII value of the character is used (e.g. 'A' + 1 has the value 66, since the ASCII value of the capital letter A is 65). See Serial.println reference for more on how characters are translated to numbers. 4292 | The char datatype is a signed type, meaning that it encodes numbers from -128 to 127. For an unsigned, one-byte (8 bit) data type, use the `byte` data type. 4293 | 4294 | ```cpp 4295 | //EXAMPLE 4296 | 4297 | char myChar = 'A'; 4298 | char myChar = 65; // both are equivalent 4299 | ``` 4300 | 4301 | ### unsigned char 4302 | 4303 | An unsigned data type that occupies 1 byte of memory. Same as the `byte` datatype. 4304 | The unsigned char datatype encodes numbers from 0 to 255. 4305 | For consistency of Arduino programming style, the `byte` data type is to be preferred. 4306 | 4307 | ```cpp 4308 | //EXAMPLE 4309 | 4310 | unsigned char myChar = 240; 4311 | ``` 4312 | 4313 | ### byte 4314 | 4315 | A byte stores an 8-bit unsigned number, from 0 to 255. 4316 | 4317 | ```cpp 4318 | //EXAMPLE 4319 | 4320 | byte b = 0x11; 4321 | ``` 4322 | 4323 | ### int 4324 | 4325 | Integers are your primary data-type for number storage. On the board, an int stores a 32-bit (4-byte) value. This yields a range of -2,147,483,648 to 2,147,483,647 (minimum value of -2^31 and a maximum value of (2^31) - 1). 4326 | int's store negative numbers with a technique called 2's complement math. The highest bit, sometimes referred to as the "sign" bit, flags the number as a negative number. The rest of the bits are inverted and 1 is added. 4327 | 4328 | Other variations: 4329 | 4330 | * `int32_t` : 32 bit signed integer 4331 | * `int16_t` : 16 bit signed integer 4332 | * `int8_t` : 8 bit signed integer 4333 | 4334 | ### unsigned int 4335 | 4336 | The board stores a 4 byte (32-bit) value, ranging from 0 to 4,294,967,295 (2^32 - 1). 4337 | The difference between unsigned ints and (signed) ints, lies in the way the highest bit, sometimes referred to as the "sign" bit, is interpreted. 4338 | 4339 | Other variations: 4340 | 4341 | * `uint32_t` : 32 bit unsigned integer 4342 | * `uint16_t` : 16 bit unsigned integer 4343 | * `uint8_t` : 8 bit unsigned integer 4344 | 4345 | ### word 4346 | 4347 | `word` stores a 32-bit unsigned number, from 0 to 4,294,967,295. 4348 | 4349 | ### long 4350 | 4351 | Long variables are extended size variables for number storage, and store 32 bits (4 bytes), from -2,147,483,648 to 2,147,483,647. 4352 | 4353 | ### unsigned long 4354 | 4355 | Unsigned long variables are extended size variables for number storage, and store 32 bits (4 bytes). Unlike standard longs unsigned longs won't store negative numbers, making their range from 0 to 4,294,967,295 (2^32 - 1). 4356 | 4357 | ### short 4358 | 4359 | A short is a 16-bit data-type. This yields a range of -32,768 to 32,767 (minimum value of -2^15 and a maximum value of (2^15) - 1). 4360 | 4361 | ### float 4362 | 4363 | Datatype for floating-point numbers, a number that has a decimal point. Floating-point numbers are often used to approximate analog and continuous values because they have greater resolution than integers. Floating-point numbers can be as large as 3.4028235E+38 and as low as -3.4028235E+38. They are stored as 32 bits (4 bytes) of information. 4364 | 4365 | Floating point numbers are not exact, and may yield strange results when compared. For example 6.0 / 3.0 may not equal 2.0. You should instead check that the absolute value of the difference between the numbers is less than some small number. 4366 | Floating point math is also much slower than integer math in performing calculations, so should be avoided if, for example, a loop has to run at top speed for a critical timing function. Programmers often go to some lengths to convert floating point calculations to integer math to increase speed. 4367 | 4368 | ### double 4369 | 4370 | Double precision floating point number. On the board, doubles have 8-byte (64 bit) precision. 4371 | 4372 | ### string - char array 4373 | 4374 | A string can be made out of an array of type `char` and null-terminated. 4375 | 4376 | ```cpp 4377 | // EXAMPLES 4378 | 4379 | char Str1[15]; 4380 | char Str2[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'}; 4381 | char Str3[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o', '\0'}; 4382 | char Str4[ ] = "arduino"; 4383 | char Str5[8] = "arduino"; 4384 | char Str6[15] = "arduino"; 4385 | ``` 4386 | 4387 | Possibilities for declaring strings: 4388 | 4389 | * Declare an array of chars without initializing it as in Str1 4390 | * Declare an array of chars (with one extra char) and the compiler will add the required null character, as in Str2 4391 | * Explicitly add the null character, Str3 4392 | * Initialize with a string constant in quotation marks; the compiler will size the array to fit the string constant and a terminating null character, Str4 4393 | * Initialize the array with an explicit size and string constant, Str5 4394 | * Initialize the array, leaving extra space for a larger string, Str6 4395 | 4396 | *Null termination:* 4397 | Generally, strings are terminated with a null character (ASCII code 0). This allows functions (like Serial.print()) to tell where the end of a string is. Otherwise, they would continue reading subsequent bytes of memory that aren't actually part of the string. 4398 | This means that your string needs to have space for one more character than the text you want it to contain. That is why Str2 and Str5 need to be eight characters, even though "arduino" is only seven - the last position is automatically filled with a null character. Str4 will be automatically sized to eight characters, one for the extra null. In Str3, we've explicitly included the null character (written '\0') ourselves. 4399 | Note that it's possible to have a string without a final null character (e.g. if you had specified the length of Str2 as seven instead of eight). This will break most functions that use strings, so you shouldn't do it intentionally. If you notice something behaving strangely (operating on characters not in the string), however, this could be the problem. 4400 | 4401 | *Single quotes or double quotes?* 4402 | Strings are always defined inside double quotes ("Abc") and characters are always defined inside single quotes('A'). 4403 | 4404 | Wrapping long strings 4405 | 4406 | ```cpp 4407 | //You can wrap long strings like this: 4408 | char myString[] = "This is the first line" 4409 | " this is the second line" 4410 | " etcetera"; 4411 | ``` 4412 | 4413 | *Arrays of strings:* 4414 | It is often convenient, when working with large amounts of text, such as a project with an LCD display, to setup an array of strings. Because strings themselves are arrays, this is in actually an example of a two-dimensional array. 4415 | In the code below, the asterisk after the datatype char "char*" indicates that this is an array of "pointers". All array names are actually pointers, so this is required to make an array of arrays. Pointers are one of the more esoteric parts of C for beginners to understand, but it isn't necessary to understand pointers in detail to use them effectively here. 4416 | 4417 | 4418 | ```cpp 4419 | //EXAMPLE 4420 | 4421 | char* myStrings[] = {"This is string 1", "This is string 2", 4422 | "This is string 3", "This is string 4", "This is string 5", 4423 | "This is string 6"}; 4424 | 4425 | void setup(){ 4426 | //Serial.begin(9600); 4427 | //begin does not do anything for Serial which uses the cloud 4428 | //(but does for Serial1 which uses the TX/RX pins), it is only implemented to compatability with Serial commands 4429 | } 4430 | 4431 | void loop(){ 4432 | for (int i = 0; i < 6; i++) { 4433 | Serial.println(myStrings[i]); 4434 | delay(500); 4435 | } 4436 | } 4437 | 4438 | ``` 4439 | 4440 | ### String - object 4441 | 4442 | More info can be found [here.](/#/firmware/language-syntax-string-class) 4443 | 4444 | ### array 4445 | 4446 | An array is a collection of variables that are accessed with an index number. 4447 | 4448 | *Creating (Declaring) an Array:* 4449 | All of the methods below are valid ways to create (declare) an array. 4450 | 4451 | ```cpp 4452 | int myInts[6]; 4453 | int myPins[] = {2, 4, 8, 3, 6}; 4454 | int mySensVals[6] = {2, 4, -8, 3, 2}; 4455 | char message[6] = "hello"; 4456 | ``` 4457 | 4458 | You can declare an array without initializing it as in myInts. 4459 | 4460 | In myPins we declare an array without explicitly choosing a size. The compiler counts the elements and creates an array of the appropriate size. 4461 | Finally you can both initialize and size your array, as in mySensVals. Note that when declaring an array of type char, one more element than your initialization is required, to hold the required null character. 4462 | 4463 | *Accessing an Array:* 4464 | Arrays are zero indexed, that is, referring to the array initialization above, the first element of the array is at index 0, hence 4465 | 4466 | `mySensVals[0] == 2, mySensVals[1] == 4`, and so forth. 4467 | It also means that in an array with ten elements, index nine is the last element. Hence: 4468 | ```cpp 4469 | int myArray[10] = {9,3,2,4,3,2,7,8,9,11}; 4470 | // myArray[9] contains 11 4471 | // myArray[10] is invalid and contains random information (other memory address) 4472 | ``` 4473 | 4474 | For this reason you should be careful in accessing arrays. Accessing past the end of an array (using an index number greater than your declared array size - 1) is reading from memory that is in use for other purposes. Reading from these locations is probably not going to do much except yield invalid data. Writing to random memory locations is definitely a bad idea and can often lead to unhappy results such as crashes or program malfunction. This can also be a difficult bug to track down. 4475 | Unlike BASIC or JAVA, the C compiler does no checking to see if array access is within legal bounds of the array size that you have declared. 4476 | 4477 | *To assign a value to an array:* 4478 | `mySensVals[0] = 10;` 4479 | 4480 | *To retrieve a value from an array:* 4481 | `x = mySensVals[4];` 4482 | 4483 | *Arrays and FOR Loops:* 4484 | Arrays are often manipulated inside `for` loops, where the loop counter is used as the index for each array element. To print the elements of an array over the serial port, you could do something like the following code example. Take special note to a MACRO called `arraySize()` which is used to determine the number of elements in `myPins`. In this case, arraySize() returns 5, which causes our `for` loop to terminate after 5 iterations. Also note that `arraySize()` will not return the correct answer if passed a pointer to an array. 4485 | 4486 | ```cpp 4487 | int myPins[] = {2, 4, 8, 3, 6}; 4488 | for (int i = 0; i < arraySize(myPins); i++) { 4489 | Serial.println(myPins[i]); 4490 | } 4491 | ``` 4492 | --------------------------------------------------------------------------------