├── README.md ├── cli.md ├── compatibility.md ├── hardware-api.md ├── module-apis.md ├── tools.md ├── tutorials ├── ble-getting-started.md ├── c-to-js.md ├── communication-protocols.md ├── connect-arduino-tessel.md ├── debug-using-busblaster.md ├── diy_module_creation.md ├── gpio-interrupts.md ├── make-external-hardware-library.md ├── multi-module.md ├── raw-spi.md ├── untethered.md └── usb_messages │ ├── .gitignore │ ├── device │ ├── index.js │ └── package.json │ ├── host.js │ ├── multi_host.js │ ├── package.json │ └── readme.md └── wifi.md /README.md: -------------------------------------------------------------------------------- 1 | Tessel 1 Documentation 2 | ==== 3 | 4 | *If you are looking for Tessel 2 documentation, go to [tessel.io/docs](//tessel.io/docs).* 5 | 6 | This is Tessel. Think of it as a tiny server, or a tiny robot you can control from the internet. 7 | 8 | 9 | 10 | Tessel is programmed in JavaScript, and comes with Wifi built in. Capabilities such as sensing, and actuation can be added to Tessel with plug-and-play modules, or you can do your own wiring through the GPIO bank. 11 | 12 | Tessel was designed for web developers to work in the world of hardware for the first time. However, whether you come from a web development background or have spent the last 40 years working in controls systems, we hope that you find Tessel easy and enjoyable to use. 13 | 14 | ==== 15 | 16 | To install and get started with Tessel, launch our [First Run Experience](//tessel.io/start). 17 | 18 | ## Tessel 1 API Documentation 19 | 20 | * [Tessel 1 CLI](https://github.com/tessel/t1-docs/blob/master/cli.md) 21 | * [Tessel 1 Hardware API (LEDs, pins, ports, etc.)](https://github.com/tessel/t1-docs/blob/master/hardware-api.md) 22 | * [Modules on Tessel 1](https://github.com/tessel/t1-docs/blob/master/module-apis.md) 23 | * [Connecting Tessel 1 to Wifi](https://github.com/tessel/t1-docs/blob/master/wifi.md) 24 | * [Tessel 1 Languages and Compatibility](https://github.com/tessel/t1-docs/blob/master/compatibility.md) 25 | 26 | ## Tessel 1 Hardware Documentation 27 | 28 | * [Overview of Tessel 1's hardware](https://github.com/tessel/hardware/blob/master/tessel-hardware-overview.md) 29 | * [Powering Tessel 1](https://github.com/tessel/hardware/blob/master/powering-tessel.md) 30 | * [Adding a Wifi antenna to Tessel 1](https://github.com/tessel/hardware/blob/master/external-wifi-antenna.md) 31 | * [Tessel 1 design files](https://github.com/tessel/hardware/blob/master/design-files.md) 32 | * [Tessel Module hardware overview](https://github.com/tessel/hardware/blob/master/modules-overview.md) 33 | 34 | ## Tessel 1 Tutorials 35 | 36 | * [Communication protocols](https://github.com/tessel/t1-docs/blob/master/tutorials/communication-protocols.md) 37 | * [Making a DIY module](https://github.com/tessel/t1-docs/blob/master/tutorials/diy_module_creation.md) 38 | * [Using multiple modules](https://github.com/tessel/t1-docs/blob/master/tutorials/multi-module.md) 39 | * [Untethering Tessel](https://github.com/tessel/t1-docs/blob/master/tutorials/untethered.md) 40 | 41 | ## Modules 42 | 43 | * [Accelerometer](https://github.com/tessel/accel-mma84) 44 | * [Ambient](https://github.com/tessel/ambient-attx4) 45 | * [Audio](https://github.com/tessel/audio-vs1053b) 46 | * [Bluetooth Low Energy](https://github.com/tessel/ble-ble113a) 47 | * [Camera](https://github.com/tessel/camera-vc0706) 48 | * [Climate](https://github.com/tessel/climate-si7020) 49 | * [DIY](//tessel.io/diy) 50 | * [GPS](https://github.com/tessel/gps-a2235h) 51 | * [GPRS](https://github.com/tessel/gprs-sim900) 52 | * [Infrared](https://github.com/tessel/ir-attx4) 53 | * [MicroSD](https://github.com/tessel/sdcard) 54 | * [Relay](https://github.com/tessel/relay-mono) 55 | * [RFID](https://github.com/tessel/rfid-pn532) 56 | * [Servo](https://github.com/tessel/servo-pca9685) 57 | 58 | If there's anything you can't find, something that isn't working, or documentation that we should add, please don't hesitate to reach out to us on the [Tessel forums](//forums.tessel.io) or on the [Tessel Github repos](//github.com/tessel). 59 | 60 | Technical Machine is open source, [hardware](//github.com/tessel/hardware) and [software](//github.com/tessel/t1-firmware). We welcome your pull requests, and we encourage you to design your own modules and products based on our designs. Check out the [contribution guide](//github.com/tessel/contribution-guide) for more details. 61 | 62 | Once you've made something (building block or whole system; both are useful), please share it with the community on the [Projects Page](http://tessel.hackster.io)! 63 | 64 | We look forward to seeing what you make. 65 | 66 | Sincerely,
67 | the Technical Machine Team
68 | (Jon, Jia, Tim, Kelsey, Eric, Kevin, Ken, and Kwyn) 69 | -------------------------------------------------------------------------------- /cli.md: -------------------------------------------------------------------------------- 1 | # Tessel CLI 2 | 3 | Tessel CLI is the command line interface for the Tessel microcontroller (http://tessel.io). 4 | [[CLI source.](https://github.com/tessel/t1-cli)] 5 | 6 | * [Installation](#installation) 7 | * [Commands](#commands) 8 | * [Code Deploy Process](#deploying) 9 | * [REPL](#repl) 10 | 11 | ## Installation 12 | 13 | Node.js is a prerequisite for installing the Tessel command line. You can install it from the official website, or if you have brew installed: 14 | 15 | ```sh 16 | brew install node 17 | ``` 18 | 19 | Once Node.js is installed, run this installation script from your terminal: 20 | 21 | ```sh 22 | npm install -g http://s3.amazonaws.com/builds.tessel.io/cli/tessel-cli-current.tar.gz 23 | ``` 24 | 25 | ## Commands 26 | 27 | ##### `tessel ` 28 | ##### `tessel list` 29 | ##### `tessel logs` 30 | ##### `tessel push [options]` 31 | Push a file and its containing directory into flash memory (persists across power cycles). For more information about what files/folders are sent to Tessel, see the [deploying](#deploying) section. 32 | Options: 33 | * `-a, --args` Arguments to passin as process.argv 34 | * `-q, --quiet` [Tessel] Hide tessel deployment messages 35 | * `-m, --messages` [Tessel] Forward stdin as child process messages 36 | * `-l, --logs` [Tessel] Stay connected and print logs 37 | * `-s, --single` [Tessel] Push a single script file to Tessel 38 | * `-h, --help` Show usage for tessel push 39 | 40 | ##### `tessel run [options]` 41 | Run a script and its containing directory temporarily without writing it to flash. For more information about what files/folders are sent to Tessel, see the [deploying](#deploying) section. 42 | Options: 43 | * `-a, --args` Arguments to passin as process.argv 44 | * `-i, --interactive` Enter the REPL 45 | * `-q, --quiet` [Tessel] Hide tessel deployment messages 46 | * `-m, --messages` [Tessel] Forward stdin as child process messages 47 | * `-l, --logs` [Tessel] Stay connected and print logs 48 | * `-s, --single` [Tessel] Push a single script file to Tessel 49 | * `-u --upload-dir` Directory where uploads from process.sendfile should be saved 50 | * `-v, --version` Print tessel-node's version 51 | * `-h, --help` Show usage for tessel push 52 | 53 | ##### `tessel repl` 54 | Interactive JavaScript shell - see [REPL docs below](#repl) 55 | ##### `tessel wifi -n -p [-s ]` 56 | Connects to wifi 57 | ##### `tessel wifi -n ` 58 | Connects to a wifi network without a password 59 | ##### `tessel wifi -l` 60 | See current wifi status 61 | ##### `tessel wifi -d` 62 | Disconnect from the current network and forget its credentials 63 | ##### `tessel stop` 64 | ##### `tessel pack ` 65 | Creates a tarball of all the files that would be sent over to Tessel. This is helpful for checking what files may be too large or missing from any particular script. 66 | ##### `tessel check ` 67 | Dumps tessel binary code 68 | ##### `tessel dfu-restore [tag]` 69 | Uploads new firmware in DFU mode. 70 | No tag given: list available tags 71 | Relative or absolute filepath: push a local binary to tessel 72 | ##### `tessel blink` 73 | Run test script to make LEDs blink back and forth 74 | ##### `tessel update ` 75 | Updates tessel to the newest released firmware localed at filepath or url. 76 | ##### `tessel update [options]` 77 | Updates tessel's firmware 78 | Options: 79 | * `-l, --list` List firmware versions 80 | * `-w, --wifi` Optional version of CC3000 wifi firmware to install 81 | * `-b, --build` Optional build of the firmware version (does not update wifi) 82 | * `-f, --force` Forcibly reload firmware onto Tessel 83 | * `-d, --dfu` Apply firmware update to device in DFU mode 84 | 85 | ##### `tessel debug [script]` 86 | Runs through debug script and uploads logs 87 | ##### `tessel version` 88 | Show version of CLI 89 | ##### `tessel version --board` 90 | Show version of the connected Tessel 91 | 92 | ## Deploying 93 | When a host computer deploys code to Tessel (either via the `run` or `push` command), the host computer bundles up the entire "project directory" and sends it to the Tessel. The CLI must wrap up all the dependencies (node_modules and subfolders) before sending the project over because the Tessel has no mechanism for fetching them from the host computer once the script has initiated on Tessel. The CLI defines the root of a "project directory" as the highest level folder that contains a node_modules folder or a package.json (note: if you pass the -s flag, only a single file is sent). This means that when `tessel run` or `tessel push` is called, the CLI will traverse up the directory tree until it finds a folder that matches that criteria. It will not bundle the home folder of a filesystem because it's probably greater than the 32MB available on Tessel. 94 | 95 | If you're having trouble figuring out which files are being sent to Tessel, use the `tessel pack` command. 96 | 97 | ## REPL 98 | *Source: [tessel-repl](https://github.com/tessel/cli/blob/master/src/commands.js) or [tessel-run](https://github.com/tessel/cli/blob/master/bin/tessel-run.js) with the interactive flag set.* 99 | 100 | Tessel has a REPL, an interactive JavaScript shell. Enter the REPL by running `tessel repl`. 101 | 102 | Require tessel as usual with `var tessel = require('tessel')` 103 | 104 | Now play! Try `tessel.led[1].toggle()` to turn one of the LEDs on or off. 105 | 106 | Tessel REPL is under development; feel free to [contribute](https://github.com/tessel/contribution-guide). 107 | -------------------------------------------------------------------------------- /compatibility.md: -------------------------------------------------------------------------------- 1 | #Tessel is programmed in JavaScript. 2 | * [JavaScript](#javascript) 3 | * [Node](#node) 4 | * [CoffeeScript](#coffeescript) 5 | 6 | ##JavaScript 7 | 8 | Tessel is programmed in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), which automatically compiles to Lua when you run code on Tessel. 9 | 10 | Tessel aims for full JavaScript compatibility, with the exception of `eval()`. If you run into compilation error, please file an issue on our GitHub repo. 11 | 12 | Documentation for the JavaScript programming language can be found [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference). 13 | 14 | ##Node 15 | Tessel is currently compatible with the most common and applicable core [Node](http://nodejs.org/about/) libraries. Most non-core libraries should also work however we don't yet support libraries with binary dependencies. If your module is not working, please [file an issue](https://github.com/tessel/runtime/issues)! 16 | 17 | Node library support is prioritized by which libraries are most relevant to Tessel usage. The target Node version is latest Node master. 18 | 19 | Documentation for Node can be found [here](http://nodejs.org/api/). 20 | 21 | ### Supported and Under Development: 22 | * [buffer](http://nodejs.org/api/buffer.html) 23 | * [console](http://nodejs.org/api/console.html) 24 | - [console.dir](http://nodejs.org/api/console.html#console_console_dir_obj) not implemented yet 25 | - [console.time](http://nodejs.org/api/console.html#console_console_time_label) not implemented yet 26 | - [console.timeEnd](http://nodejs.org/api/console.html#console_console_timeend_label) not implemented yet 27 | - [console.trace](http://nodejs.org/api/console.html#console_console_trace_label) not implemented yet 28 | - [console.assert](http://nodejs.org/api/console.html#console_console_assert_expression_message) not implemented yet 29 | * [crypto](http://nodejs.org/api/crypto.html) 30 | - Most of the Node library is not yet supported. The methods that ARE implemented are: 31 | * [randomBytes](http://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) 32 | * [pseudoRandomBytes](http://nodejs.org/api/crypto.html#crypto_crypto_pseudorandombytes_size_callback) 33 | * [createHmac](http://nodejs.org/api/crypto.html#crypto_crypto_createhmac_algorithm_key) 34 | * [dgram](http://nodejs.org/api/dgram.html) 35 | - [Event:'listening'](http://nodejs.org/api/dgram.html#dgram_event_listening) not implemented yet 36 | - [Event:'close'](http://nodejs.org/api/dgram.html#dgram_event_close) not implemented yet 37 | - [Event:'error'](http://nodejs.org/api/dgram.html#dgram_event_error) not implemented yet 38 | - [socket.address](http://nodejs.org/api/dgram.html#dgram_socket_address) not implemented yet 39 | - [socket.setBroadcast](http://nodejs.org/api/dgram.html#dgram_socket_setbroadcast_flag) not implemented yet 40 | - [socket.setTTL](http://nodejs.org/api/dgram.html#dgram_socket_setttl_ttl) not implemented yet 41 | - [socket.setMulticastTTL](http://nodejs.org/api/dgram.html#dgram_socket_setmulticastttl_ttl) not implemented yet 42 | - [socket.setMulticastLoopback](http://nodejs.org/api/dgram.html#dgram_socket_setmulticastloopback_flag) not implemented yet 43 | - [socket.addMembership](http://nodejs.org/api/dgram.html#dgram_socket_addmembership_multicastaddress_multicastinterface) not implemented yet 44 | - [socket.dropMembership](http://nodejs.org/api/dgram.html#dgram_socket_dropmembership_multicastaddress_multicastinterface) not implemented yet 45 | - [socket.unref](http://nodejs.org/api/dgram.html#dgram_socket_unref) not implemented yet 46 | - [socket.ref](http://nodejs.org/api/dgram.html#dgram_socket_unref) not implemented yet 47 | * [dns](http://nodejs.org/api/dns.html) 48 | - Most of the Node library is not yet supported. The method that IS implemented is: 49 | [resolve](http://nodejs.org/api/dns.html#dns_dns_resolve_domain_rrtype_callback) 50 | * [events](http://nodejs.org/api/events.html) 51 | * [fs](http://nodejs.org/api/fs.html) — builtin 52 | - Async and sync versions of file/directory permissions/owner related functions are not yet implemented (chown, fchown, lchown, chmod, fchmod, lchmod) 53 | - Symlink related functions are not yet implemented (link, symlink, readlink, unlink) 54 | - File/Directory watching related methods not supported (watchFile, unwatchFile, watch) 55 | - Timestamp related functions not supported (utimes, futimes) 56 | * [fs](http://nodejs.org/api/fs.html) — sdcard's [fatfs](https://github.com/natevw/fatfs) instances 57 | - Note that *instances* of this "module" come from sdcard getFilesystems option (or method call) 58 | - fs.*Sync methods not implemented 59 | - [fs.rename](http://nodejs.org/api/fs.html#fs_fs_rename_oldpath_newpath_callback) not implemented yet 60 | - [fs.unlink](http://nodejs.org/api/fs.html#fs_fs_unlink_path_callback) not implemented yet 61 | - [fs.rmdir](http://nodejs.org/api/fs.html#fs_fs_rmdir_path_callback) not implemented yet 62 | - [fs.watchFile](http://nodejs.org/api/fs.html#fs_fs_watchfile_filename_options_listener) not implemented yet 63 | - [fs.unwatchFile](http://nodejs.org/api/fs.html#fs_fs_unwatchfile_filename_listener) not implemented yet 64 | - [fs.watch](http://nodejs.org/api/fs.html#fs_fs_watch_filename_options_listener) not implemented yet 65 | * [Globals](http://nodejs.org/api/globals.html) 66 | * [http](http://nodejs.org/api/http.html) / [https](http://nodejs.org/api/https.html) 67 | - [response.setTimeout](http://nodejs.org/api/http.html#http_response_settimeout_msecs_callback) not implemented yet, [#428](https://github.com/tessel/runtime/issues/428) 68 | - [sever.setTimeout](http://nodejs.org/api/http.html#http_server_settimeout_msecs_callback) not implemented yet, [#428](https://github.com/tessel/runtime/issues/428) 69 | - [server.timeout](http://nodejs.org/api/http.html#http_server_timeout) not implemented yet, [#428](https://github.com/tessel/runtime/issues/428) 70 | - [request.setTimeout](http://nodejs.org/api/http.html#http_request_settimeout_timeout_callback) not implemented well, [#428](https://github.com/tessel/runtime/issues/428) 71 | - [request.setNoDelay](http://nodejs.org/api/http.html#http_request_setnodelay_nodelay) not implemented yet, [#428](https://github.com/tessel/runtime/issues/428) 72 | - [request.setSocketKeepAlive](http://nodejs.org/api/http.html#http_request_setsocketkeepalive_enable_initialdelay) not implemented yet, [#428](https://github.com/tessel/runtime/issues/428) 73 | * [modules](http://nodejs.org/api/modules.html) 74 | * [net](http://nodejs.org/api/net.html) 75 | - Some socket options may not be possible to configure (at least on a per-connection basis) with the CC3000 drivers: 76 | - [socket.setNoDelay](http://nodejs.org/api/net.html#net_socket_setnodelay_nodelay) not implemented, [#342](https://github.com/tessel/runtime/issues/342) 77 | - [socket.setKeepAlive](http://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) not implemented, [#342](https://github.com/tessel/runtime/issues/342) 78 | - ['allowHalfOpen' socket/server option](http://nodejs.org/api/net.html#net_net_createserver_options_connectionlistener) not implemented yet, [#409](https://github.com/tessel/runtime/issues/409) 79 | - ['fd' socket option](http://nodejs.org/api/net.html#net_new_net_socket_options) not implemented 80 | - These are dependent on currently missing runtime support, [#266](https://github.com/tessel/runtime/issues/266): 81 | - [server.unref](http://nodejs.org/api/net.html#net_server_unref) not implemented yet 82 | - [server.ref](http://nodejs.org/api/net.html#net_server_ref) not implemented yet 83 | - [socket.unref](http://nodejs.org/api/net.html#net_socket_unref) not implemented yet 84 | - [socket.ref](http://nodejs.org/api/net.html#net_socket_ref) not implemented yet 85 | - These would be welcome contributions if they are needed by anyone: 86 | - [server.maxConnections](http://nodejs.org/api/net.html#net_server_maxconnections) not implemented yet, [#341](https://github.com/tessel/runtime/issues/341) 87 | - [server.getConnections](http://nodejs.org/api/net.html#net_server_getconnections_callback) not implemented yet, [#341](https://github.com/tessel/runtime/issues/341) 88 | - [socket.bufferSize](http://nodejs.org/api/net.html#net_socket_buffersize) not implemented yet, [#339](https://github.com/tessel/runtime/issues/339) 89 | - [socket.bytesRead](http://nodejs.org/api/net.html#net_socket_localport) not implemented yet, [#339](https://github.com/tessel/runtime/issues/339) 90 | - [socket.bytesWritten](http://nodejs.org/api/net.html#net_socket_byteswritten) not implemented yet, [#339](https://github.com/tessel/runtime/issues/339) 91 | * [os](http://nodejs.org/api/os.html) 92 | * [path](http://nodejs.org/api/path.html) 93 | * [process](http://nodejs.org/api/process.html) 94 | - Most of the process library is not yet supported. The methods that ARE implemented are: 95 | * [stdin](http://nodejs.org/api/process.html#process_process_stdin) 96 | * [argv](http://nodejs.org/api/process.html#process_process_argv) 97 | * [exit](http://nodejs.org/api/process.html#process_process_exit_code) 98 | * [memoryUsage](http://nodejs.org/api/process.html#process_process_memoryusage) 99 | * [nextTick](http://nodejs.org/api/process.html#process_process_nexttick_callback) 100 | * [punycode](http://nodejs.org/api/punycode.html) 101 | * [querystring](http://nodejs.org/api/querystring.html) 102 | * [smalloc](http://nodejs.org/api/smalloc.html) 103 | * [stream](http://nodejs.org/api/stream.html) 104 | * [sys](http://nodejs.org/api/sys.html) 105 | * [timers](http://nodejs.org/api/timers.html) 106 | * [tracing](http://nodejs.org/api/tracing.html) 107 | * [url](http://nodejs.org/api/url.html) 108 | * [util](http://nodejs.org/api/util.html) 109 | - [format](http://nodejs.org/api/util.html#util_util_format_format) not implemented yet 110 | - [debug](http://nodejs.org/api/util.html#util_util_debug_string) not implemented yet 111 | - [error](http://nodejs.org/api/util.html#util_util_error) not implemented yet 112 | - [puts](http://nodejs.org/api/util.html#util_util_puts) not implemented yet 113 | - [print](http://nodejs.org/api/util.html#util_util_print) not implemented yet 114 | - [log](http://nodejs.org/api/util.html#util_util_log_string) not implemented yet 115 | - [inspect](http://nodejs.org/api/util.html#util_util_inspect_object_options) not implemented yet 116 | - [isError](http://nodejs.org/api/util.html#util_util_iserror_object) not implemented yet 117 | 118 | 119 | ###Plan to support in the future: 120 | * [assert](http://nodejs.org/api/assert.html) 121 | * [Binary Dependencies](http://nodejs.org/api/addons.html) 122 | * [vm](http://nodejs.org/api/vm.html) 123 | * [child_process](http://nodejs.org/api/child_process.html) 124 | * [readline](http://nodejs.org/api/readline.html) 125 | * [repl](http://nodejs.org/api/repl.html) 126 | * [string_decoder](http://nodejs.org/api/string_decoder.html) 127 | * [tls](http://nodejs.org/api/tls.html) 128 | * [tty](http://nodejs.org/api/tty.html) 129 | * [debugger](http://nodejs.org/api/debugger.html) 130 | * [zlib](http://nodejs.org/api/zlib.html) 131 | 132 | ###No plans to support: 133 | * [cluster](https://www.npmjs.org/package/cluster) 134 | * [domain](http://nodejs.org/api/domain.html) 135 | 136 | ##CoffeeScript 137 | Tessel plans to eventually support [CoffeeScript](http://coffeescript.org/). 138 | 139 | (Tessel can currently run pre-compiled CoffeeScript into [JavaScript](#javascript).) 140 | -------------------------------------------------------------------------------- /hardware-api.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Tessel API Documentation 4 | 5 | Documentation for Tessel's hardware APIs. These are available for code running on Tessel, and is imported by `require('tessel')`. 6 | 7 | ##Contents 8 | 9 | * [Ports and LEDs (Tessel)](#tessel) 10 | * [GPIO/Pins](#pins) 11 | * [Buttons](#buttons) 12 | * [SPI](#spi) 13 | * [I2C](#i2c) 14 | * [UART](#uart) 15 | * [System](#system) 16 | 17 | 18 | ##Tessel 19 | 20 | Tessel is the root object for each of the different ports on the device. 21 | 22 | ```js 23 | var tessel = require('tessel'); // import tessel 24 | var gpio = tessel.port['GPIO']; // select the GPIO port 25 | gpio.digital[1].write(1); // turn digital pin #1 high 26 | ``` 27 | 28 | 29 | # map<Port>  tessel.port = {} 30 | A list of ports available on Tessel. Keys for this are `"A"`, `"B"`, `"C"`, `"D"`, or `"GPIO"`. 31 | 32 | # array<Pin>  tessel.led = [] 33 | An array of 4 LEDs available on the Tessel board. These are [`Pin` objects](#pins). Their board order is different than their array index order; they're in rainbow order on the board. See below: 34 | 35 | | Index | Position (from micro-USB) | Color | Name | 36 | |-------| ------------------------- | ----- | ----- | 37 | | 0 | 3rd | Green | LED1 | 38 | | 1 | 4th | Blue | LED2 | 39 | | 2 | 1st | Red | Error | 40 | | 3 | 2nd | Amber | Conn | 41 | 42 | ```js 43 | // Toggle an LED every 200ms 44 | (function blink (value) { 45 | tessel.led[1].write(value); 46 | setTimeout(blink, 200, !value); 47 | })(true) 48 | ``` 49 | 50 | ##Pins 51 | 52 | General purpose input-output (GPIO) provides access for digital and analog signal lines. Available pins are exposed through the `.pin`, `.digital`, `.analog`, and `.pwm` arrays. 53 | 54 | By default, all of the pins are pulled high if not specifically set. 55 | 56 | You may find it useful to cross-reference this section with the hardware documentation for [Pins and Ports](https://github.com/tessel/hardware/blob/master/tessel-hardware-overview.md#pins-and-ports). 57 | 58 | ###GPIO bank 59 | Tessel's GPIO bank is designed to be breadboardable, so you can interact easily with sensors and actuators beyond our pre-built modules. 60 | 61 | This example logs the value of each digital and analog pin from the GPIO bank: 62 | ```js 63 | var tessel = require('tessel'); // import tessel 64 | var gpio = tessel.port['GPIO']; // select the GPIO port 65 | gpio.digital.forEach(function (pin, i) { 66 | console.log('Value of digital pin', i, '=', pin.read()); 67 | }); 68 | gpio.analog.forEach(function (pin, i) { 69 | console.log('Value of analog pin', i, '=', pin.read() * pin.resolution, '/', pin.resolution); 70 | }); 71 | ``` 72 | 73 | **Digital pins** are either high (3.3V) or low (GND/0V). 74 | 75 | Tessel has six digital pins on the GPIO bank, and three more on each of the four module ports. 76 | 77 | This example shows the reading and writing of a digital pin: 78 | ```js 79 | var tessel = require('tessel'); // import tessel 80 | var gpio = tessel.port['GPIO']; // select the GPIO port 81 | var myPin = gpio.digital[0]; // on GPIO, can be gpio.digital[0] through 5 or gpio.pin['G3'] through ‘G6’ 82 | // Turn on the pin 83 | myPin.output(1); // setting ‘true’ has the same effect 84 | // Read the pin 85 | console.log('Reading pin:', myPin.rawRead()); 86 | // Turn off the pin 87 | myPin.output(0); // setting ‘false’ has the same effect. We could also call myPin.toggle() here. 88 | // Read the pin 89 | console.log('Reading pin:', myPin.rawRead()); 90 | ``` 91 | 92 | **Analog pins** can be any value between 0 and 1 (GND/0V and 3.3V). 93 | 94 | Tessel has six analog pins on the GPIO bank. All six can be used as inputs, but should not be used as outputs. 95 | 96 | Here is an example of reading analog values. 97 | ```js 98 | var tessel = require('tessel'); // import tessel 99 | var gpio = tessel.port['GPIO']; // select the GPIO port 100 | var myPin = gpio.analog[0]; // can read on any of gpio.analog[0-5] or gpio.pin['A1'] through A6 101 | // Read the pin 102 | console.log('Reading pin:', myPin.read()); 103 | ``` 104 | 105 | **PWM pins** are pulse-width modulated pins ([wiki link](http://en.wikipedia.org/wiki/Pulse-width_modulation)). Essentially, PWM is a digital signal that spends between 0% and 100% of its time on (this is its "duty cycle"). You can set the PWM pins to any value between 0 and 1 to approximate an analog signal. PWM is often used to control servo speeds or LED brightness. 106 | 107 | Tessel has three PWM pins: G4, G5, and G6 on the GPIO bank. 108 | 109 | If you try to read a PWM pin, you will always get back 0 or 1, depending on which part of the duty cycle your .read() call happened to hit. 110 | 111 | Here is an example of setting a PWM pin: 112 | ```js 113 | var tessel = require('tessel'); // import tessel 114 | var gpio = tessel.port['GPIO']; // select the GPIO port 115 | var myPin = gpio.pwm[0]; // can be gpio.pwm[0] through 3 or gpio.pin['G4'] through ‘G6’ 116 | // Tell the GPIO port that the frequency of its pwm pins is 980 Hz 117 | gpio.pwmFrequency(980); 118 | // Set duty cycle 119 | myPin.pwmDutyCycle(0.6); // set the pin to be on 60% of the time 120 | ``` 121 | 122 | Tessel also has a pin that will allow you to read in the length of an incoming pulse. 123 | 124 | Here is an example of reading a pulse in from an external device 125 | ```js 126 | var tessel = require('tessel'); // import tessel 127 | var gpio = tessel.port['GPIO']; // select the GPIO port 128 | var pin_input = gpio.pin['G3']; // readPulse only works on gpio.pin['G3'] 129 | // read a low pulse in (--_--) and timeout if there's no pulse within 3 seconds 130 | pin_input.readPulse('low', 3000, function (err,pulse_len) { 131 | // if there's an err object it means the SCT timed out or was already in use 132 | if (err) { 133 | console.log(err.message); 134 | return; 135 | } 136 | // Log the pulse length 137 | console.log('Pulse read length:',pulse_len,'ms'); 138 | }); 139 | ``` 140 | 141 | Note that readPulse is similar to the arduino pulseIn function. 142 | 143 | **Other pins:** For more details on addressing the other pins on the GPIO bank, see the sections on [SPI](#spi), [I2C](#i2c), and [UART](#uart). 144 | 145 | ###Module port pins 146 | 147 | You can address each of the pins in the module ports. 148 | 149 | Ports A, B, C, and D each have 3 digital pins which can be addressed in two ways: 150 | 151 | Digital pins addressed as items in an array: 152 | 153 | 154 | ```js 155 | tessel.port['A'].digital[0]; 156 | tessel.port['A'].digital[1]; 157 | tessel.port['A'].digital[2]; 158 | ``` 159 | 160 | Digital pins addressed by the silkscreen printed on Tessel: 161 | 162 | 163 | ```js 164 | tessel.port['A'].pin['G1']; // this is the same as digital[0] 165 | tessel.port['A'].pin['G2']; // this is the same as digital[1] 166 | tessel.port['A'].pin['G3']; // this is the same as digital[2] 167 | ``` 168 | 169 | For more details on addressing the other pins on the module ports, see the sections on [SPI](#spi), [I2C](#i2c), and [UART](#uart). 170 | 171 | ###Referring to Pins 172 | 173 | The table below indexes the various ways of referring to pins. 174 | 175 | Pin # is the number returned when you console.log the pin. Label is the silkscreened label. Type and index can be used together, e.g. pin #16 can be referred to as `tessel.port['A'].pin['G1']` or `tessel.port['A'].digital[0]`. 176 | 177 | | Pin # | Port | Label | Type | Index | 178 | |-------|----- | ----- | ------- | ----- | 179 | | 16 | A | G1 | Digital | 0 | 180 | | 17 | A | G2 | Digital | 1 | 181 | | 18 | A | G3 | Digital | 2 | 182 | | 19 | B | G1 | Digital | 0 | 183 | | 20 | B | G2 | Digital | 1 | 184 | | 21 | B | G3 | Digital | 2 | 185 | | 22 | C | G1 | Digital | 0 | 186 | | 23 | C | G2 | Digital | 1 | 187 | | 24 | C | G3 | Digital | 2 | 188 | | 25 | D | G1 | Digital | 0 | 189 | | 26 | D | G2 | Digital | 1 | 190 | | 27 | D | G3 | Digital | 2 | 191 | | 28 | GPIO | A1 | Analog | 0 | 192 | | 29 | GPIO | A2 | Analog | 1 | 193 | | 30 | GPIO | A3 | Analog | 2 | 194 | | 31 | GPIO | A4 | Analog | 3 | 195 | | 32 | GPIO | A5 | Analog | 4 | 196 | | 33 | GPIO | A6 | Analog | 5 | 197 | | 34 | GPIO | G1 | Digital | 0 | 198 | | 35 | GPIO | G2 | Digital | 1 | 199 | | 36 | GPIO | G3 | Digital | 2 | 200 | | 37 | GPIO | G4 | Digital | 3 | 201 | | 37 | GPIO | G4 | PWM | 0 | 202 | | 38 | GPIO | G5 | Digital | 4 | 203 | | 38 | GPIO | G5 | PWM | 1 | 204 | | 39 | GPIO | G6 | Digital | 5 | 205 | | 39 | GPIO | G6 | PWM | 2 | 206 | 207 | 208 | ###Pin API 209 | 210 | 211 | # string  port.id 212 | The unique ID of this port. On Tessel, this would be one of `"A"`, `"B"`, `"C"`, `"D"`, or `"GPIO"`. 213 | 214 | # array<number>  port.digital = [] 215 | An array of which pins are digital inputs/outputs. Has 3 pins for ports A, B, C, and D and 6 pins for the GPIO port. 216 | 217 | # array<number>  port.analog = [] 218 | An array of which pins are analog inputs. Is only available on the GPIO port. 219 | 220 | # array<number>  port.pwm = [] 221 | An array of which pins are PWM outputs (may overlap analog array). 222 | 223 | # port.pwmFrequency ( frequency ) 224 | Sets the frequency of PWM for a given port. Only the GPIO bank supports PWM pins on Tessel. 225 | 226 | # array<number>  port.pin = [] 227 | An array of all pins on the port. You can differentiate them by their `.type` and `.isPWM` attributes. 228 | 229 | # new  port.Pin ( pin ) 230 | Create and return `pin` object. 231 | 232 | # string  pin.type 233 | "digital" or "analog". 234 | 235 | # number  pin.resolution 236 | Digital pins: 1. Analog pins: ADC resolution of output pins ( e\.g\. 1023 for Tessel ). 237 | 238 | # pin.input() 239 | Set `pin` to be an input. 240 | 241 | # pin.output ( value ) 242 | Set `pin` to be an output with value `value`. Note that the Analog pins cannot be outputs. 243 | 244 | # pin.rawDirection( isOutput ) 245 | Set `pin` as input or output. 246 | 247 | # pin.write ( value ) 248 | Behaves the same as `pin.output`. Sets pin as an output with `value`. Digital pins: output is set HIGH if `value` is truthy, otherwise LOW. 249 | 250 | # pin.pwmDutyCycle ( dutyCycleFloat ) 251 | Creates a PWM signal with a duty cycle of `dutyCycleFloat`, the fraction of the PWM period in which the signal is high. Range is between [0-1] inclusive. Only works with pins with true property of `isPWM`. 252 | 253 | # pin.rawWrite ( value ) 254 | Sets the pin to `value`. Does not change the direction of the pin. 255 | 256 | # pin.read () 257 | Sets the pin as an input and reads a digital or analog `value`. For digital pins, `1` is returned if the value is HIGH, otherwise `0` if LOW. For analog pins the range is between [1-0] inclusive. 258 | 259 | # pin.readPulse ( type, timeout, callback(err, pulsetime) ) 260 | Measures the length of an input pulse. The `type` of the pulse can either be `'high'` or `'low'`. The `callback` function is passed an `err` if no pulse was read within the `timeout` (in milliseconds) or if the SCT was in use by another process. If there was an error then `pulsetime` will be set to 0, otherwise it will be set to the measured pulse length. Note that reading a pulse is only possible on GPIO pin `'G3'`. 261 | 262 | # pin.rawRead () 263 | Reads from the pin ***without** first setting the direction as an input. Only available on digital pins. 264 | 265 | # pin.pull ( mode ) 266 | Sets the pin as a pullup, pulldown, or neutral pin. Mode is one of `pullup`, `pulldown` or `none`. Passing in no argument is equivalent to `none`. 267 | 268 | # pin.mode () 269 | Returns the mode of the pin. 270 | 271 | External GPIO Interrupts can be used much like regular Node EventEmitters. There are seven external interrupts you can work with. You can read more in depth discussion about gpio interrupts in [our External GPIO Walkthrough](https://github.com/tessel/t1-docs/blob/master/tutorials/gpio-interrupts.md). 272 | 273 | # pin.on ( type, callback(time, type) ) 274 | Sets a listener for a signal edge on `pin`. `time` is the milliseconds since boot up and `type` can be one of `rise`, `fall`, `change`. The `high` and `low` level triggers cannot be used with `on` because they would fire repeatedly and wreak havoc on the runtime. 275 | 276 | # pin.once ( type, callback(time, type) ) 277 | Sets a listener for a a single event of the trigger type on the `pin`. `time` is the milliseconds since boot up and `type` can be one of `rise`, `fall`, `change`, `high`, or `fall`. 278 | 279 | # pin.removeListener ( type, listener ) 280 | Removes the `listener` callback for a given `type` of trigger (eg. 'rise' or 'high') on a pin. 281 | 282 | # pin.removeAllListeners ( type ) 283 | Removes all of the listeners for a given trigger `type` on a `pin`. 284 | 285 | ##Buttons 286 | 287 | Tessel has two buttons. The `reset` button (nearer to the edge of the board) will stop running any program that is currently executing and restart the microcontroller (erasing any memory in RAM). 288 | 289 | The `config` button will eventually be used for other purposes but is currently a simple way to get user feedback into a script: 290 | ```js 291 | var tessel = require('tessel'); 292 | 293 | tessel.button.on('press', function(time) { 294 | console.log('the button was pressed!', time); 295 | }); 296 | 297 | tessel.button.on('release', function(time) { 298 | console.log('button was released', time); 299 | }); 300 | ``` 301 | Please note that the button `press` and `release` events will use one of the seven External GPIO Interrupts (for one or both events). 302 | 303 | The buttons can also be used to put the board into DFU Mode which can be understood as the stage just prior to reprogramming the board. This is useful if the board is no longer able to communicate like typical with a host computer. To activate DFU mode, hold down the `config` button while pressing and releasing the `reset` button so that the `config` button is pressed down when the board comes out of a reset. Then release the `config button`. 304 | 305 | ##SPI 306 | 307 | A SPI channel. For details on connecting the hardware to Tessel see [the Pins and Ports section of the Hardware documentation](https://github.com/tessel/hardware/blob/master/tessel-hardware-overview.md#pins-and-ports). 308 | 309 | ```js 310 | var port = tessel.port['A']; 311 | var spi = new port.SPI({ 312 | clockSpeed: 4*1000*1000, // 4MHz 313 | cpol: 1, // polarity 314 | cpha: 0, // clock phase 315 | }); 316 | 317 | spi.transfer(new Buffer([0xde, 0xad, 0xbe, 0xef]), function (err, rx) { 318 | console.log('buffer returned by SPI slave:', rx); 319 | }); 320 | 321 | spi.transferBatch(new Buffer([0xc0, 0xd0, 0xc1, 0xd1]), {chunkSize:2}, function (err, rx) { 322 | // Equivalent to 323 | // spi.transfer(new Buffer[0xc0, 0xd0]); 324 | // spi.transfer(new Buffer[0xc1, 0xd1]); 325 | // Faster than doing separate transfers because only 1 JS call is made 326 | }); 327 | ``` 328 | 329 | 330 | # new  port.SPI ( [options] ) 331 | Creates a SPI object. Options is an object specifying any of the following: 332 | 333 | * **channel** (optional) — An optional numeric index for selecting a SPI channel. Defaults to the first (or only) SPI channel. 334 | * **clockSpeed** (default `100000`) — SPI clock speed in Hz. 335 | * **cpol** (default `0`) — Clock polarity. Options are 0 or 1, or 'low' and 'high'. 336 | * **cpha** (default `0`) — Clock phase. Options are 0 or 1, or 'first' and 'second'. 337 | * **dataMode** (default `0`) — An alternative to defining **cpol** and **cpha** explicitly, you can [use mode numbers](http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Mode_numbers). 338 | * **bitOrder** (default `"msb"`) — Bit order, most significant bit first or least. Options are 'msb' or 'lsb'. 339 | * **frameMode** (default `"normal"`) — SPI frame format. Only one format is supported at the moment, `"normal"`. 340 | * **chipSelect** (default `null`) — Pin to use as a default chip select pin. If a pin is specified, this pin is toggled in master mode whenever data is to be sent/received on the bus. 341 | * **chipSelectActive** (default `"low"`) — If a **chipSelect** pin is specified, this defines the polarity of the CS line when *active*. 342 | * **role** (default `master`) — Determines the role the SPI channel plays, either "master" or "slave". (Currently not supported.) 343 | 344 | # spi.transfer ( txbuf, callback(err, rxbuf) ) 345 | Transfers a Buffer `txbuf` to the slave and receives a response in `rxbuf`. 346 | 347 | # spi.transferBatch ( txbuf, [options], callback(err, rxbuf) ) 348 | Transfers a series of commands stored in a Buffer `txbuf` by splitting `txbuf` into chunks of a specified size. Sends each command in `txbuf` to the slave and receives a response in `rxbuf`. Options is an object specifying any of the following: 349 | 350 | * **chunkSize** (optional) — An optional value specifying the interval size. Defaults to `txbuf.length`. 351 | * **repeat** (optional) — An optional value specifying how many times the `txbuf` will be transmitted. Used for transmitting the same buffer multiple times. Defaults to 1. 352 | 353 | # spi.receive ( len, callback(err, rxbuf) ) 354 | Reads `len` bytes from a slave. Returns a buffer. 355 | 356 | # spi.send ( txbuf, callback(err) ) 357 | Sends a Buffer `txbuf` to the slave. 358 | 359 | # spi.sendBatch ( txbuf, [options], callback(err) ) 360 | Sends a series of commands stored in a Buffer `txbuf` by splitting txbuf into chunks of a specified size. Sends each command in `txbuf` to the slave. Options is an object specifying any of the following: 361 | 362 | * **chunkSize** (optional) — An optional value specifying the interval size. Defaults to `txbuf.length`. 363 | * **repeat** (optional) — An optional value specifying how many times the `txbuf` will be transmitted. Used for transmitting the same buffer multiple times. Defaults to 1. 364 | 365 | # spi.setClockSpeed ( clockspeed ) 366 | Sets the clockspeed. 367 | 368 | # spi.setDataMode ( mode ) 369 | Sets the data mode. 370 | 371 | # spi.setFrameMode ( mode ) 372 | Sets the frame mode. 373 | 374 | # spi.setRole ( role ) 375 | Sets the role. 376 | 377 | # spi.setChipSelectMode ( mode ) 378 | Sets the chip select settings. 379 | 380 | # spi.lock ( callback ) 381 | Locks SPI so that only one SPI port is communicating at a time. To read more about SPI Bus Locking, check out our discussion about the [Bus Locking and Raw Transfers API](https://github.com/tessel/t1-docs/blob/master/tutorials/raw-spi.md). 382 | 383 | 384 | ##I2C 385 | 386 | An I2C channel. For details on connecting the hardware to Tessel see [the Pins and Ports section of the Hardware documentation](https://github.com/tessel/hardware/blob/master/tessel-hardware-overview.md#pins-and-ports). 387 | 388 | ```js 389 | var port = tessel.port['A']; 390 | var slaveAddress = 0xDE; 391 | var i2c = new port.I2C(slaveAddress) 392 | i2c.transfer(new Buffer([0xde, 0xad, 0xbe, 0xef]), function (err, rx) { 393 | console.log('buffer returned by I2C slave ('+slaveAddress.toString(16)+'):', rx); 394 | }) 395 | ``` 396 | 397 | 398 | # new  port.I2C ( address, [idx] ) 399 | Creates an I2C channel for a device of a specific `address`. Multiple I2C channels can be used in parallel. 400 | 401 | # i2c.transfer ( txbuf, rxbuf_len, callback(err, rxbuf) ) 402 | Transfers a Buffer `txbuf` to the client and receives a response of length `rxbuf_len`. 403 | 404 | # i2c.receive ( rxbuf_len, callback(err, rxbuf) ) 405 | Reads `rxbuf_len` bytes from a client. 406 | 407 | # i2c.send ( txbuf, callback(err) ) 408 | Sends a Buffer `txbuf` to the client. 409 | 410 | ##UART 411 | 412 | A UART channel. For details on connecting the hardware to Tessel see [the Pins and Ports section of the Hardware documentation](https://github.com/tessel/hardware/blob/master/tessel-hardware-overview.md#pins-and-ports). 413 | 414 | ```js 415 | var port = tessel.port['A']; 416 | var uart = new port.UART({ 417 | baudrate: 115200 418 | }); 419 | 420 | uart.write('ahoy hoy\n') 421 | uart.on('data', function (data) { 422 | console.log('received:', data); 423 | }) 424 | 425 | // UART objects are streams! 426 | // pipe all incoming data to stdout: 427 | uart.pipe(process.stdout); 428 | ``` 429 | 430 | 431 | # new  port.UART ( [idx[, options]] ) 432 | implements DuplexStream 433 | Creates a UART channel. Defaults: `{"baudrate": 9600, "dataBits": 8, "parity": "none", "stopBits": 1}` 434 | 435 | # array<number>  uart.baudRates = [] 436 | An array of valid baud rates supported by the system. 437 | 438 | # uart.setBaudRate ( rate ) 439 | Sets the baud `rate` to a valid rate in `baudRates`. 440 | 441 | # uart.setDataBits ( bits ) 442 | Sets the number of data `bits` to the number 5, 6, 7, or 8. 443 | 444 | # uart.setStopBits ( bits ) 445 | Sets the number of data `bits` to the number 1 or 2. 446 | 447 | # uart.setParity ( parity ) 448 | Sets the `parity` to the value "none", "odd", or "even". 449 | 450 | # uart.write ( buf ) 451 | Writes a buffer to the UART connection. 452 | 453 | # uart → emits "data" 454 | Data that arrives over the UART channel is sent as a Node.js stream. 455 | 456 | ##System 457 | 458 | # process.sendfile ( filename, buffer ) 459 | A buffer can be sent over USB to a file named filename on a host computer's file system. You must start the script with -u and the argument of which directory to save the folder. For example, tessel run test.js -u ./recordings will save the file in the recordings directory. 460 | 461 | # tessel.deviceId () 462 | Get the Unique ID of your Tessel. 463 | -------------------------------------------------------------------------------- /module-apis.md: -------------------------------------------------------------------------------- 1 | #Modules 2 | 3 | * [Setup](#setup) 4 | * [APIs](#apis) 5 | 6 | ##Setup 7 | Tessel has four module ports, labeled A, B, C, and D. 8 | 9 | 10 | 11 | Most modules can be plugged into any port. The exceptions are that BLE and Camera cannot be plugged into Port C (they depend on an as-yet unimplemented software UART) 12 | 13 | Modules should be plugged in so that all of the electrical components are face up and all the hexagons are face down: 14 | Face up: 15 | 16 | 17 | 18 | Face down: 19 | 20 | 21 | 22 | ##APIs 23 | 24 | Documentation for each of Tessel's modules can be found on the individual modules' pages: 25 | 26 | * [Accelerometer](https://github.com/tessel/accel-mma84) 27 | * [Ambient](https://github.com/tessel/ambient-attx4) 28 | * [Audio](https://github.com/tessel/audio-vs1053b) 29 | * [Bluetooth Low Energy](https://github.com/tessel/ble-ble113a) 30 | * [Camera](https://github.com/tessel/camera-vc0706) 31 | * [Climate](https://github.com/tessel/climate-si7020) 32 | * [DIY](//tessel.io/diy) 33 | * [GPS](https://github.com/tessel/gps-a2235h) 34 | * [GPRS](https://github.com/tessel/gprs-sim900) 35 | * [Infrared](https://github.com/tessel/ir-attx4) 36 | * [MicroSD](https://github.com/tessel/sdcard) 37 | * [Relay](https://github.com/tessel/relay-mono) 38 | * [RFID](https://github.com/tessel/rfid-pn532) 39 | * [Servo](https://github.com/tessel/servo-pca9685) 40 | -------------------------------------------------------------------------------- /tools.md: -------------------------------------------------------------------------------- 1 | # Tools for Tessel 2 | 3 | A collection of tools for use with Tessel. Community-created or built by Technical Machine. Please feel free to add to this list. See the [style guide](https://github.com/tessel/style#api-formatting) for formatting. 4 | 5 | ### Contents 6 | 7 | * [Tutorials](#tutorials) 8 | * [Software tools](#software-tools) 9 | * [Hardware libraries](#hardware-libraries) 10 | * [Contributing](#contributing) 11 | 12 | 13 | ### Tutorials 14 | 15 | #### Communications 16 | 17 | # [USB message passing]( https://github.com/tessel/docs/tree/master/tutorials/usb_messages ) 18 | USB communication between Tessel and Node on your PC. 19 | 20 | # [Getting started with BLE]( https://github.com/tessel/docs/blob/master/tutorials/ble-getting-started.md ) 21 | A guide to Bluetooth Low Energy for beginners, particularly flavored for Tessel. 22 | 23 | # [External GPIO Pin Interrupts API]( https://github.com/tessel/docs/blob/master/tutorials/gpio-interrupts.md ) 24 | External interrupts are used for getting updated from other sensors or the environment that something has changed. It allows the processesor to work on other tasks until the state of a pin is altered at which point hardware processes take over and handle the interrupt. 25 | 26 | # [SPI Locks and Raw Transfers]( https://github.com/tessel/docs/blob/master/tutorials/raw-spi.md ) 27 | Tutorial on SPI communication. 28 | 29 | #### Firmware 30 | 31 | # [Expose a C function up to JS userspace]( https://github.com/tessel/docs/blob/master/tutorials/c-to-js.md ) 32 | This tutorial goes over how to expose a C function to JS where the user can interact with it via any JS function. 33 | 34 | # [Debugging Tessel]( https://github.com/tessel/docs/blob/master/tutorials/debug-using-busblaster.md ) 35 | You can debug Tessel by soldering JTAG headers to the board and using a JTAG debugger. This tutorial asummes you are using a Bus Blaster and an associated JTAG 20 -> 10 pin adapter. 36 | 37 | 38 | #### Hardware 39 | 40 | # [Powering Tessel]( https://github.com/tessel/hardware/blob/master/powering-tessel.md ) 41 | Powering Tessel through an external power source 42 | 43 | # [Adding a Wifi Antenna]( https://github.com/tessel/hardware/blob/master/external-wifi-antenna.md ) 44 | How to add a Wifi antenna to Tessel to improve Wifi reception 45 | 46 | # [Connecting Arduino and Tessel]( https://github.com/tessel/docs/blob/master/tutorials/connect-arduino-tessel.md ) 47 | This is a tutorial for how to pass data back and forth between an Arduino and a Tessel. 48 | 49 | 50 | ### Software tools 51 | 52 | #### Development tools 53 | 54 | # [tiny-router]( https://www.npmjs.org/package/tiny-router ) 55 | A simple routing library targeting embedded system where every byte counts 56 | 57 | # [tesselate]( https://www.npmjs.org/package/tesselate ) 58 | A dependency injector for tessel modules, abstracting away the need to nest multiple ‘ready’ listeners and callbacks within each other, or use promises or generators (or multiple, internal loaded flags) 59 | 60 | # [avr-isp]( https://www.npmjs.org/package/avr-isp ) 61 | Library to allow Tessel to act as an AVR In-System Programmer 62 | 63 | # [grunt-tessel]( https://www.npmjs.org/package/grunt-tessel ) 64 | Grunt tasks to aid tessel development 65 | 66 | # [mockfs]( https://github.com/Olegas/node-mockfs ) 67 | Virtual in-memory file system accessible through native FS module 68 | 69 | # [tesselbot]( https://www.npmjs.org/package/tesselbot ) 70 | A chainable tessel rebot made for building simple apps easier 71 | 72 | #### Multi-language support 73 | # [lua-tessel]( https://www.npmjs.org/package/lua-tessel ) 74 | A CLI that enables the scripting of a Tessel device in Lua 75 | 76 | # [Rust on Tessel]( https://github.com/kevinmehall/rust-tessel ) 77 | Examples of the Rust language running on Tessel 78 | 79 | #### Libraries 80 | 81 | # [cylon-tessel]( https://www.npmjs.org/package/cylon-tessel ) 82 | Cylon.js is a JavaScript framework for robotics and physical computing using Node.js 83 | 84 | # [Plotly example]( https://gist.github.com/alexander-daniel/856ccc58c4cda1707ab2 ) 85 | Tessel + Plotly streaming example 86 | 87 | # [m2x-tessel]( https://www.npmjs.org/package/m2x-tessel ) 88 | AT&T M2X API client for node.js based Tessel 89 | 90 | 91 | ### Hardware libraries 92 | 93 | Beyond the [modules](//tessel.io/modules), libraries and examples for connecting with Tessel. 94 | 95 | # [pir]( https://www.npmjs.org/package/pir ) 96 | Node/Tessel library for a PIR motion detector 97 | 98 | # [pulse sensor]( https://www.npmjs.org/package/pulsesensor ) 99 | Node/Tessel library for a pulse sensor 100 | 101 | # [tessel-ht16k33]( https://www.npmjs.com/package/backpack-ht16k33 ) 102 | Use the Adafruit HT16K33 LED Backpack with your Tessel 103 | 104 | # [tessel-button]( https://www.npmjs.org/package/tessel-button ) 105 | API to provide more feedback / options to the single tessel 'config' button 106 | 107 | # [neopixels]( https://www.npmjs.org/package/neopixels ) 108 | Library to run a strand of neopixels from Tessel 109 | 110 | # [ir-codes]( https://www.npmjs.org/package/ir-codes ) 111 | Generates signal buffers for different infrared device manufacturers 112 | 113 | 114 | ### Contributing 115 | 116 | # [Technical Machine contribution guide]( https://github.com/tessel/contribution-guide ) 117 | A thorough explanation of how the Tessel software architecture works as a whole, descriptions of the individual pieces, and the processes for contributing code 118 | 119 | # [Technical Machine style guide]( https://github.com/tessel/style ) 120 | Defines style for Technical Machine code, docs, and directories, particularly Tessel modules 121 | 122 | # [Contributing category on the Tessel forums]( https://forums.tessel.io/c/contributing ) 123 | Technical Machine & community members request comments on APIs and projects 124 | -------------------------------------------------------------------------------- /tutorials/ble-getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started with BLE + Tessel 2 | 3 | This guide is meant to be suitable for a Bluetooth novice. If you find any part of this guide hard to understand or inaccurate, let us know! We'd love to fix that. We hope that after reading this you'll understand what is and is not possible with BLE, as well as know when to properly refer to a BLE device as an iBeacon. 4 | 5 | ## Contents 6 | * [Introduction](#introduction) 7 | * [Comparison to Classic Bluetooth](#comparison-to-classic-bluetooth) 8 | * [Pairing and Bonding](#pairing-and-bonding) 9 | * [Data Model](#data-model) 10 | * [Dual Mode Devices](#dual-mode-devices) 11 | * [BLE Roles](#ble-roles) 12 | * [Central vs Peripheral](#central-vs-peripheral) 13 | * [Client vs Server](#client-vs-server) 14 | * [Beacons](#beacons) 15 | * [Generic Attribute Profiles](#generic-attribute-profiles) 16 | * [Characteristics](#characteristics) 17 | * [Services](#services) 18 | * [UUIDs](#uuids) 19 | * [Tessel's GATT Profile](#tessels-gatt-profile) 20 | * [Advertisements](#advertisements) 21 | * [Advertising packet data](#advertising-packet-data) 22 | * [Finding the right device](#finding-the-right-device) 23 | * [iBeacons](#ibeacons) 24 | * [Advertising Examples](#advertising-examples) 25 | * [Connecting](#connecting) 26 | * [Scan for Peripherals](#scan-for-peripherals) 27 | * [Security](#security) 28 | * [Encryption and Bonding](#encryption-and-bonding) 29 | * [Passkey Entry](#passkey-entry) 30 | * [Out of Band](#out-of-band) 31 | * [Connection Examples](#connection-examples) 32 | * [Transferring Data](#transferring-data) 33 | * [Service Discovery](#service-discovery) 34 | * [Updating a local GATT database](#updating-a-local-gatt-database) 35 | * [Updating a remote GATT database](#updating-a-remote-gatt-database) 36 | * [Subscribing to changes on a remote GATT database](#subscribing-to-changes-on-a-remote-gatt-database) 37 | * [Data Transfer Examples](#data-transfer-examples) 38 | * [Testing and Debugging](#testing-and-debugging) 39 | * [LightBlue](#lightblue) 40 | * [Noble](#noble) 41 | * [Links](#links) 42 | 43 | ## Introduction 44 | Bluetooth Low Energy (BLE/Bluetooth 4.0/Bluetooth Smart) is the most recent incarnation of Bluetooth technology put out by the Bluetooth SIG (the organization that maintains the specification). It is designed for applications in which transferring small amounts of data at a relatively low speed makes sense, and low power consumption is necessary. It is important to understand that BLE is not at all backwards compatible with older versions of Bluetooth. 45 | 46 | ### Comparison to Classic Bluetooth 47 | The list of reasons why Bluetooth Classic (also known as Basic Rate/Enhanced Data Rate - BR/EDR) and BLE are incompatible is extensive, but we'll try to cover some of the more fundamental differences here. This section can help you decide whether BLE is right for the application you might have in mind. 48 | 49 | #### Pairing and Bonding 50 | In Bluetooth Classic, before any data can be exchanged a few things need to happen. 51 | 52 | First, a master device needs to find a slave device to connect to. If the master has an address for a device, it can attempt to pair directly, without even scanning for devices. Bluetooth Classic devices can be either **discoverable** or **non-discoverable**, but can still be paired with while non-discoverable. So, even if the master did scan for the device and found nothing, there is still a chance the device is in range and not-discoverable, so it might as well try pairing any way. Once the two devices have paired successfully, exchanging pin codes and security keys if necessary, then they are **bonded** and can initiate a **connection**. 53 | 54 | Once the devices are bonded, any time they come within range of each other, they will automatically connect, if possible. When the connection has been made, the devices can exchange data wirelessly as needed. 55 | 56 | With the introduction of BLE, there are a number of differences to the connection process. First, in order to connect to a BLE device, the target device must be **advertising** that it is connectable. Second, a connection can be made without pairing, with pairing being left as an optional security mode. Finally, a connection does not have to be made in order to get data from a remote device. We'll see how this is possible later on. 57 | 58 | #### Data Model 59 | Bluetooth Classic is set up to stream data from one device to another. It can accomodate data rates high enough to support streaming audio. One of the most popular use cases for Bluetooth has historically been serial cable replacement, which is just a two-way communication stream, conveniently made wireless. 60 | 61 | BLE, on the other hand, exchanges data through a database located on one of the connected devices. Rather than keep an open stream of data, data is only exchanged when the database is modified, or a connected device requests a value from the database. For this reason, it doesn't really make sense to use BLE in the same way Bluetooth Classic has been used, but there are plenty of new applications involving sensors and other devices exchanging small amounts of data, which BLE was designed for. 62 | 63 | #### Dual Mode Devices 64 | There are some devices, such as cell phones and computers, which need to be able to connect to both types of devices. These devices will have Bluetooth hardware that separately supports both versions. This class of devices is referred to as **dual-mode**, contrary to a **single-mode** device, which is only compatible with same-version devices and dual-mode devices. 65 | 66 | ### BLE Roles 67 | The BLE specification allows a device to take on various roles that define the specific actions the device may be capable of. There are really two types of roles, with each device in a network fulfilling one of each type of role. The two types are **central** or **peripheral**, and **client** or **server**. 68 | 69 | #### Central vs Peripheral 70 | The central and peripheral roles describe the order of command in a BLE network. The role of the central device is similar to that of the master in Bluetooth Classic. The central device is responsible for searching for and establishing a connection with one or more peripheral devices. 71 | 72 | The role of the peripheral device is similar to that of the slave in Bluetooth Classic. The peripheral device advertises whether or not it is connectable, as well as any services it might provide. The central can use that data to decide if it should connect to the peripheral or not. 73 | 74 | #### Client vs Server 75 | The client and server roles describe the data ownership and transmission relationship in a BLE network. In a typical network, the central device will take on the role of client - requesting and sending data from and to one or more server devices. 76 | 77 | Peripheral devices will typically take on the role of server. Servers keep a database of attributes that a connected client can write to, and read or subscribe to changes from. 78 | 79 | #### Beacons 80 | A beacon is a specific implementation of a peripheral device that does not act as a server. All of the data a central device needs from a beacon is broadcast through the advertisement, so there is no need to connect to request the data. It is also important not to confuse any generic BLE beacon with iBeacons. 81 | 82 | ## Generic Attribute Profiles 83 | Generic Attribute Profiles (GATT Profiles) are used to define the hierarchical structure of the database a server uses to store the data it makes available to clients. A profile consists of **services**, each of which may contain multiple **characteristics**. The core specification has a small set of [pre-defined profiles](https://developer.bluetooth.org/gatt/profiles/Pages/ProfilesHome.aspx), however the specification does allow you to create your own. 84 | 85 | ### Characteristics 86 | A characteristic represents one data attribute that a client can access. Each characteristic can store only a single value at a time. Each characteristic can have different access permissions such as read, write, and notify. 87 | 88 | ### Services 89 | A service is used to group a category of characteristics. All characteristics must belong to a service. Usually when central devices are looking for a device to connect to, they will look to see if they support a particular service, rather than an individual characteristic. 90 | 91 | ### UUIDs 92 | Every service and every characteristic must be assigned its own Universally Unique Identifier (UUID). This UUID is how devices will look for and recognize if another device supports a particular attribute. There is a set of reserved 16-bit and 32-bit UUIDs outlined in the core specification that have a predefined or reserved use across both services and characteristics. The list of profiles linked above makes use of this reserved space. If you are looking to create your own profile, the best way to get UUIDs is through the command line tool `uuidgen` if you are on OS X or Linux, or through a simple online service like http://www.uuidgen.com/. 93 | 94 | ### Tessel's GATT Profile 95 | Below, we show a portion of the Tessel's GATT profile, which has two unique services. One service is for sharing the BLE module's firmware version, and the other is for sending and receiving data. 96 | 97 | The second service has a total of 12 characteristics which can be used generically for sandboxed design and prototyping of your own services. 98 | 99 | ```js 100 | { 101 | "services" : [ 102 | { 103 | "uuid" : "08c8c7a06cc511e3981f0800200c9a66" 104 | , "description" : "Tessel Firmware Information" 105 | , "characteristics" : [ 106 | { 107 | "uuid" : "50888c106cc511e3981f0800200c9a66" 108 | , "id" : "c_tessel_firmware_version" 109 | , "description" : "Firmware Version" 110 | , "value" : "1.0.1" 111 | } 112 | ] 113 | } 114 | , { 115 | "uuid" : "d752c5fb13804cd5b0efcac7d72cff20" 116 | , "id" : "data_transceiver" 117 | , "description" : "Data Transceiving" 118 | , "characteristics" : [ 119 | { 120 | "uuid" : "883f1e6b76f64da187eb6bdbdb617888" 121 | , "id" : "c_trans_0" 122 | , "description" : "Transceiver Value 0" 123 | , "properties" : ["read", "write", "indicate", "notify"] 124 | , "length" : "255" 125 | } 126 | . 127 | . 128 | . // The full service contains 12 generic characteristics 129 | . 130 | . 131 | , { 132 | "uuid" : "4a0efa07e1814a7fbd72094df3e97132" 133 | , "id" : "c_trans_11" 134 | , "description" : "Transceiver Value 11" 135 | , "properties" : ["read", "write", "indicate", "notify"] 136 | , "length" : "255" 137 | } 138 | ] 139 | } 140 | ] 141 | } 142 | ``` 143 | 144 | You can find a JSON version of the Tessel's entire GATT Profile, including omitted services and characteristics, [in the `ble-ble113a` library](https://github.com/tessel/ble-ble113a/blob/master/lib/profile.json). Please note that this is just a description of the GATT profile, which is actually defined in the firmware of the BLE module. Making changes to the GATT profile on the module requires creating a modified version of the firmware and uploading it to the module. A guide for doing this is coming soon. 145 | 146 | ## Advertisements 147 | In order to form a connection between two devices, the peripheral device must broadcast an advertisement for the central device to see. An advertisement packet contains the perihperal device's address, as well as a device-configurable section of data that can contain various kinds of data. A scanning central device can also request a **scan response** from a peripheral, which has the same format as an advertisement, but can contain different, additional data. Think of a scan response as a second advertisement that can be sent upon request. 148 | 149 | ### Advertising packet data 150 | The type of data an advertisement can contain is strictly defined by the core specification and a full list of available data types can be found [here](https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile). Fortunately, we have put together an [npm module called `bleadvertise`](https://www.npmjs.org/package/bleadvertise) to help you create and decode advertising data packets in a more semantic manner. Some of the more common data types to put in the advertisement are **Flags** (which is more or less mandatory), **Incomplete List of 128-bit Service UUIDs**, either **Short Local Name** or **Complete Local Name**, as well as **Manufacturer Specific Data** which is used in iBeacons. The maximum length an advertising data packet can be is 32 bytes, so this is an important consideration in designing what kinds of information to put in the advertisement and/or scan response. 151 | 152 | ### Finding the right device 153 | When a central device is looking for a specific device or specific type of device, it has a few options in terms of what to look for in an advertisement to determine whether or not to connect. The two most common pieces of advertising data that are examined are the device address, and the complete or incomplete list of supported services. Sometimes the address is not the best way to keep track of a device, because many devices use what is known as a **random address** which will change relatively frequently, and in this case, other information in the advertisement should be used to pick a device. 154 | 155 | ### iBeacons 156 | While any peripheral device can be a BLE beacon, and can beacon any data it wants to, there is now a very popular type of beacon specification created by Apple called the iBeacon. iBeacons are meant to be used for location-based applications, where high accuracy is important (i.e. inside a grocery store). The advertisement packet for an iBeacon is relatively simple consisting of a 128-bit location UUID followed by 2-Byte Major region code and 2-Byte Minor region code, marked as **Manufacturer Specific Data**. You can read more about the specification and licensing on [Apple's developer website](https://developer.apple.com/ibeacon/). 157 | 158 | ### Advertising Examples 159 | 160 | The following example will show you how to set up a Tessel with a custom advertisement. 161 | 162 | ```js 163 | var tessel = require('tessel'); 164 | var bleLib = require('ble-ble113a'); 165 | var bleadvertise = require('bleadvertise'); 166 | 167 | var packet = { 168 | flags: [0x02, 0x04], // Connectable, BLE only 169 | incompleteUUID128 : ['08c8c7a06cc511e3981f0800200c9a66'], // Tessel Firmware Version Service UUID 170 | shortName : 'Tessel' 171 | } 172 | 173 | var ad = bleadvertise.serialize(packet); 174 | 175 | var peripheral = bleLib.use(tessel.port['A'], function(){ 176 | peripheral.setAdvertisingData(ad, function(){ 177 | peripheral.startAdvertising(); 178 | console.log('Now advertising'); 179 | }); 180 | }); 181 | ``` 182 | 183 | That's it! We'll come back and add more to this later, once we learn about receiving connection events from a central device. 184 | 185 | The example for creating an iBeacon is similar, but uses slightly different data. 186 | 187 | ```js 188 | var tessel = require('tessel'); 189 | var bleLib = require('ble-ble113a'); 190 | var bleadvertise = require('bleadvertise'); 191 | 192 | var uuid = 'D9B9EC1F392543D080A91E39D4CEA95C'; // Apple's example UUID 193 | var major = '01'; 194 | var minor = '10'; 195 | 196 | var iBeaconData = new Buffer(uuid+major+minor, 'hex'); // Create data Buffer 197 | 198 | var packet = { 199 | flags: [0x04], // BLE only 200 | mfrData : iBeaconData 201 | } 202 | 203 | var ad = bleadvertise.serialize(packet); 204 | 205 | var beacon = bleLib.use(tessel.port['A'], function(){ 206 | beacon.setAdvertisingData(ad, function(){ 207 | beacon.startAdvertising(); 208 | console.log('Beaconing'); 209 | }); 210 | }); 211 | ``` 212 | Since beacons generally aren't meant to connect to other devices, this is pretty much everything you need to make a beacon. Of course, if you want to beacon something besides a static value, you'll need to make some changes, but that's the gist of it. 213 | 214 | 215 | ## Connecting 216 | Now that we understand how peripherals let central devices know they're available, let's look at how the central finds them and initiates a connection. 217 | 218 | ### Scan for Peripherals 219 | The first step in discovering advertising peripherals is with a device scan. In the scanning process, the central will listen for advertisements and report when it finds one. On most platforms, there will be scanning options that let you filter discovered peripherals by the service UUIDs in their advertisements, and also prevent reporting of duplicate devices. Once you have discovered a suitable device to connect to, just send a connect command and you're ready to start exchanging data! 220 | 221 | ### Security 222 | With BLE there are two main modes of secure data exchange - encryption and bonding, as well as three different methods for exchanging encryption keys - Just Works, Passkey Entry, and Out of Band. 223 | 224 | #### Encryption and Bonding 225 | With BLE, a connection can be encrypted with a short term key through **pairing**, and it can also be encrypted with a long term key through **bonding**. When paired, the encryption will last for the duration of the connection, and will need to be re-encrypted each time the connection is established. Through bonding, the devices will store the encryption keys, such that each time they re-connect, they will attempt to encrypt the connection. The simplest, however insecure, means of encrypting the connection is called **Just Works** and uses an exchanged passkey of 000000, so there is no required input from the user. The more secure options are **Paskey Entry** and **Out of Band**. To use Just Works pairing with a Tessel in the central role, call the `ble.startEncryption()` method after a connection has been made. 226 | 227 | #### Passkey Entry 228 | With passkey entry pairing, there is a requirement that one device be capable of displaying a passkey value (6 digits) and the other device be capable of inputting the passkey. When the passkey is displayed, it is up to the user to enter the code on the input device. Once the passkey is confirmed, the connection will be encrypted. There is no requirement that the the central or peripheral take on either display or input roles, just that both are implemented between the two devices. To enable passkey entry on a Tessel central device, call `ble.setMITMProtection(true)` as well as `ble.setIOCapabilities()` to identify the device as a display or input before scanning for devices. After connecting, once again call `ble.startEncryption()` to start the passkey process. In either central or peripheral mode, a Tessel can receive a `'passkeyDisplay'` or `'passkeyRequest'` event, and can input a displayed passkey with the `ble.enterPasskey(000000)` method. 229 | 230 | #### Out of Band 231 | Out of Band (OOB) pairing requires the use of another means of communication, besides BLE, to exchange encryption keys. A common example of an OOB exchange would be over NFC. Once the devices have exchanged keys over NFC, the data is relayed to the BLE controller, and the connection can be encrypted using the keys. This method is the most secure option BLE currently offers to prevent MITM attacks. Implementing OOB security on a Tessel is similar to passkey protection, however instead of needing to set the IO capabilities, you need to use `ble.setOOBData(data)`, where `data` is a 16-byte string. If either one of the connecting devices has OOB data set, then the other will need to have the same data set in order for the connection to be encrypted. 232 | 233 | ### Connection Examples 234 | First let's see what our code looks like on a Tessel acting as a central device that wants to connect to another Tessel acting as a peripheral. Let's assume that the peripheral is advertising the same packet from our first advertisement example above. 235 | 236 | ```js 237 | var tessel = require('tessel'); 238 | var bleLib = require('ble-ble113a'); 239 | 240 | var serviceUUID = ['08c8c7a06cc511e3981f0800200c9a66']; // UUID to filter for 241 | var central = bleLib.use(tessel.port['A'], function(){ 242 | central.startScanning(serviceUUID); // Start the scanning process 243 | central.on('discover', function(peripheral){ // Catch the discover event 244 | peripheral.connect(); // Connect to this device 245 | }); 246 | central.on('connect', function(peripheral){ // Catch the connect event 247 | console.log('Connected to', peripheral.address.toString()); 248 | }); 249 | }); 250 | ``` 251 | 252 | As you can see we have two events we can listen for that let us know when a new device has been discovered or connected to.The connect event works for both central and peripheral devices, so we can go back to our advertisement example and add a listener for a connect event. 253 | 254 | ```js 255 | var tessel = require('tessel'); 256 | var bleLib = require('ble-ble113a'); 257 | var bleadvertise = require('bleadvertise'); 258 | 259 | var packet = { 260 | flags: [0x02, 0x04], // Connectable, BLE only 261 | incompleteUUID128 : ['08c8c7a06cc511e3981f0800200c9a66'], // Tessel Firmware Version Service UUID 262 | shortName : 'Tessel' 263 | } 264 | 265 | var ad = bleadvertise.serialize(packet); 266 | 267 | var peripheral = bleLib.use(tessel.port['A'], function(){ 268 | peripheral.setAdvertisingData(ad, function(){ 269 | peripheral.startAdvertising(); 270 | console.log('Now advertising'); 271 | }); 272 | peripheral.on('connect', function(connectionId){ 273 | console.log('Connected to central device'); 274 | }); 275 | }); 276 | ``` 277 | 278 | When the connection is established the central will automatically stop scanning, and the peripheral will stop advertising. Since the central can handle connections with multiple peripherals, you can start scanning again and look for another device, if needed. 279 | 280 | 281 | ## Transferring Data 282 | Once we have established a connection, we can start transferring data back and forth between our devices. This is where the terms client and server become relevant again. For this tutorial let's assume our central will play the role of client, and the peripheral will be the server. With BLE all data is read from and written to the server's GATT database, which is that data store who's structure is defined by the GATT profile, discussed above. 283 | 284 | ### Service Discovery 285 | In order for a client to read and write characteristics on a remote server, it first needs to know which services and characteristics are available. To get this information, the client can request the server send over a list of all of its services and characteristics. Part of this service discovery includes a short 1-byte **handle** value for each characteristic. Once the client has the handle, it will use that instead of the 16-byte UUID for each exchange. This handle will be unique on different devices for characteristics with the same UUID, so it is always necessary to do a service discovery in order to get the proper handle, even if you already know the UUID. 286 | 287 | ### Updating a local GATT database 288 | Since the GATT database lives on the server, it should always have direct access to the data being exchanged. The way this is handled will vary by platform and device, but most devices that support server mode should have methods for directly updating and reading values in the GATT database. 289 | 290 | ### Updating a remote GATT database 291 | Once the client has access to the handle for the characteristic it needs to read or write to, doing so is pretty straightforward. Again, any reasonable platform should expose methods for reading/writing methods through its API. At this point it probably also important to mention that you should make sure the permissions on the characteristic you are trying to access allow your desired operation. On the Tessel, all of the Tessel-specific characteristics can be read, and all of the characteristics in the Transceiver service can be written and subscribed to, as well. 292 | 293 | ### Subscribing to changes on a remote GATT database 294 | For some applications, you don't want to periodically check if a remote value has updated, but would rather get a notification when it has, and only then read the value. BLE allows this through two similar mechanisms. A client can set up either **notifications** or **indications** on a particular characteristic, assuming the server permissions allow it. Once a client subscribes to notifications, any time the server makes a change to the subscribed characteristic, it will let the client know, along with a short preview of the data. If the entire piece of data does not fit in the notification, the client can then send a read request for the rest. An indication works the same way, except the client must send a message back to the server, acknowledging that it received the indication. 295 | 296 | ### Data Transfer Examples 297 | Let's go ahead and add to our earlier connection example, and make our two devices exchange data. First we'll set up our central as a client by adding a service discovery request, looking for the first transceiver characteristic, and then subscribe to notifications. 298 | 299 | ```js 300 | var tessel = require('tessel'); 301 | var bleLib = require('ble-ble113a'); 302 | 303 | var options = { serviceUUIDs : ['08c8c7a06cc511e3981f0800200c9a66'] }; // UUID to filter for 304 | var characteristicUUID = ['883f1e6b76f64da187eb6bdbdb617888'] // Characteristic we will write to 305 | var central = bleLib.use(tessel.port['A'], function(){ 306 | central.startScanning(options); // Start the scanning process 307 | central.on('discover', function(peripheral){ // Catch the discover event 308 | peripheral.connect(); 309 | }); 310 | central.on('connect', function(peripheral){ 311 | console.log('Connected to', peripheral.address.toString()); 312 | peripheral.discoverCharacteristics(characteristicUUID, function(err, characteristic) { 313 | if (characteristic.length){ 314 | characteristic[0].notify(true); 315 | characteristic[0].on('notification', function(data){ 316 | console.log('Got notification', data.toString()); 317 | }); 318 | } 319 | }); 320 | }); 321 | }); 322 | ``` 323 | 324 | And now we'll update our peripheral example with some corresponing server functionality. We'll need to set it up to listen for when the client subscribes to a characteristic. Once that happens, we can periodically update the value and the client should automatically receive notifications. 325 | 326 | ```js 327 | var tessel = require('tessel'); 328 | var bleLib = require('ble-ble113a'); 329 | var bleadvertise = require('bleadvertise'); 330 | 331 | var packet = { 332 | flags: [0x02, 0x04], // Connectable, BLE only 333 | incompleteUUID128 : ['08c8c7a06cc511e3981f0800200c9a66'], // Tessel Firmware Version Service UUID 334 | shortName : 'Tessel' 335 | } 336 | 337 | var ad = bleadvertise.serialize(packet); 338 | 339 | var peripheral = bleLib.use(tessel.port['B'], function(){ 340 | peripheral.setAdvertisingData(ad, function(){ 341 | peripheral.startAdvertising(); 342 | console.log('Now advertising'); 343 | }); 344 | peripheral.on('connect', function(connectionId){ 345 | console.log('Connected to central device'); 346 | }); 347 | peripheral.on( 'remoteNotification', function(connectionId, index){ // Catch when remote subscribes 348 | console.log('Notifications started'); 349 | var count = 0; 350 | setInterval(function(){ 351 | peripheral.writeLocalValue(index, new Buffer( count.toString() )); // Write to [index] transceiver value 352 | count++; 353 | }, 2000); 354 | }); 355 | }); 356 | ``` 357 | 358 | ## Testing and Debugging 359 | When working with BLE you might encounter an issue that you realize you have no way to resolve, especially if you are using a device which you cannot make any changes to. The following are some of the most helpful that we've found in working with Bluetooth. 360 | 361 | ### LightBlue 362 | LightBlue is an OS X and iOS application that allows you to see and connect to BLE devices, as well as run a service discovery, and make read/write/notify requests. This is great if you are working with a peripheral device and want to see it from the perspective of a central device. 363 | 364 | ### Noble 365 | Noble is a Node library which allows you to access the BLE capabilities of newer Mac Books as well as Linux laptops with the appropriate hardware. Noble allows you to set up your laptop as a central device, and its companion library, Bleno, allows you to set up the computer as a peripheral. 366 | 367 | ## Links 368 | * [ble-ble113a library on Github](https://github.com/tessel/ble-ble113a) 369 | * [Noble](https://github.com/sandeepmistry/noble) 370 | * [More on GATT Profiles](https://developer.bluetooth.org/TechnologyOverview/Pages/GATT.aspx) 371 | * [Advertisement data types](https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile) 372 | * [BLE Security](https://developer.bluetooth.org/TechnologyOverview/Pages/LE-Security.aspx) 373 | * [Bluetooth 4.1 Core Specification](https://www.bluetooth.org/en-us/specification/adopted-specifications) 374 | -------------------------------------------------------------------------------- /tutorials/c-to-js.md: -------------------------------------------------------------------------------- 1 | # Expose a C function up to JS userspace 2 | 3 | This tutorial goes over how to expose a C function to JS where the user can interact with it via any JS function. 4 | 5 | The function will pass this simple test case: 6 | 7 | ```js 8 | var tessel = require('tessel'); 9 | console.log("Can Tessel add?", 3 == tessel.add(1, 2)); 10 | ``` 11 | 12 | 1. Clone down the [tessel/t1-firmware](https://github.com/tessel/t1-firmware) repo. 13 | 2. Set up the firmware according to the [tessel/t1-firmware readme](https://github.com/tessel/t1-firmware/blob/master/README.md). 14 | 3. Open up `src/tessel.c`. Add these lines 15 | 16 | ```c 17 | uint32_t tessel_add(uint32_t x, uint32_t y) 18 | { 19 | return x + y; 20 | } 21 | ``` 22 | 5. Add this function to the header file. Open up `src/tessel.h` and add 23 | 24 | ```c 25 | uint32_t tessel_add(uint32_t x, uint32_t y); 26 | ``` 27 | 6. Add the Lua binding. Open up `src/hw/l_hw.c` and add 28 | 29 | ```c 30 | static int l_hw_add(lua_State* L) 31 | { 32 | uint32_t x = (uint32_t)lua_tonumber(L, ARG1); 33 | uint32_t y = (uint32_t)lua_tonumber(L, ARG1+1); 34 | lua_pushnumber(L, tessel_add(x, y)); 35 | return 1; // return 0 if the c function doesn't return a value 36 | } 37 | ``` 38 | 7. Scroll down to the bottom of `src/hw/l_hw.c` where we're defining all the JS function names in `luaL_reg regs[]` and add in the following entry: 39 | ```c 40 | {"add", l_hw_add} 41 | ``` 42 | 43 | So it should look something like: 44 | ```c 45 | luaL_reg regs[] = { 46 | {"add", l_hw_add}, 47 | // spi 48 | { "spi_initialize", l_hw_spi_initialize }, 49 | { "spi_enable", l_hw_spi_enable }, 50 | ... 51 | ``` 52 | 53 | 8. Add the JS bindings. Open up `builtin/tessel.js` and find this function: 54 | ```js 55 | this.deviceId = function(){ 56 | return hw.device_id(); 57 | }; 58 | ``` 59 | 60 | Add the following right below it 61 | ```js 62 | this.add = function(x, y){ // the "this" object is referring to the "tessel" object 63 | return hw.add(x, y); // the "add" function here corresponds with the string in the lua binding. That's how we get from C -> Lua -> JS 64 | } 65 | ``` 66 | 67 | 9. Go back to the main directory of the `firmware` repo and do a `make arm`. You should see an output like this 68 | 69 | ``` 70 | [183/183] STAMP obj/tessel-firmware.actions_depends.stamp 71 | arm-none-eabi-size out/Release/tessel-firmware.elf out/Release/tessel-boot.elf out/Release/tessel-otp.elf 72 | text data bss dec hex filename 73 | 824912 3576 24660 853148 d049c out/Release/tessel-firmware.elf 74 | 30848 2260 3232 36340 8df4 out/Release/tessel-boot.elf 75 | 6100 34272 36 40408 9dd8 out/Release/tessel-otp.elf 76 | ``` 77 | 78 | This outputs the [elf file](http://en.wikipedia.org/wiki/Executable_and_Linkable_Format) for hardware debugging. 79 | 80 | 10. Now go to `out/Release/` and do an `ls`. You should see the following 81 | 82 | ``` 83 | build.ninja tessel-cc3k-patch.bin tessel-firmware.bin.cpgz 84 | gen tessel-cc3k-patch.elf tessel-firmware.elf 85 | obj tessel-erase.bin tessel-firmware.hex 86 | tessel-boot.bin tessel-erase.elf tessel-otp.bin 87 | tessel-boot.elf tessel-firmware.bin tessel-otp.elf 88 | ``` 89 | 90 | Here's what each of those do: 91 | * `tessel-boot`: bootloader for Tessel. Also writes the Tessel version number (04) in [otp](http://en.wikipedia.org/wiki/One-time_programmable). 92 | * `tessel-cc3k-patch`: updates the firmware for the [CC3000 wifi chip](http://processors.wiki.ti.com/index.php/CC3000) on Tessel. Current version is 1.28. 93 | * `tessel-erase`: erases all JS user code on Tessel. 94 | * `tessel-firmware`: the firmware for Tessel. This was just changed this to add the '.add' function. 95 | 96 | 11. Overwrite the Tessel firmware with the new firmware you just built. In the `Release` directory: 97 | 98 | `tessel update ./tessel-firmware.bin` 99 | Don't forget that `./` before tessel-firmware. It specifies a local path. Otherwise `tessel update` will look for firmware patches on our build server. 100 | 101 | 12. Now run the test code you have for this function and it should pass. 102 | 103 | If you want to revert back to the original Tessel firmware, just run a `tessel update --force` which will force Tessel to update to the newest release version. 104 | -------------------------------------------------------------------------------- /tutorials/communication-protocols.md: -------------------------------------------------------------------------------- 1 | #Tessel Module Communication Protocols 2 | Each of the four ports on the Tessel exposes ten pins for use in creating custom modules. Two of the pins are for power (3.3V and ground) and the other eight are digital pins that can be used to communicate with your module. 3 | 4 | All eight communication pins speak in terms of simple on/off states, but only three of them (the GPIO pins) are meant to be controlled manually. The rest, when grouped in pre-defined ways, are capable of encoding complex messages by having their state rapidly toggled in accordance with various protocols. It's a lot like [Morse code](http://en.wikipedia.org/wiki/Morse_code), but for electronics. 5 | 6 | In embedded electronics, there are four common protocols and Tessel [supports them all in JavaScript](https://github.com/tessel/t1-docs/blob/master/hardware-api.md). 7 | 8 | * [GPIO](#gpio) 9 | * [SPI](#spi) 10 | * [I2C](#i2c) 11 | * [UART](#uart) 12 | 13 | This guide will provide a brief overview of the protocols and cover some of the strengths and weaknesses of each. 14 | 15 | ##Quick Reference 16 | Most of the time, you will choose your protocol based on the parts you are using when designing your module. Other things to consider are the pins you have available, as well as your communication speed requirements. The following table can be used as a quick reference for the more detailed explanations of each protocol below. 17 | 18 | | Protocol | # Pins Required | Supported Ports | Max Speed | Example Modules | 19 | |:--------: |:---------------------------------: |:-------------------------------------------: |:-------------------------------: |:---------------: | 20 | | GPIO | **1** (G1,G2 or G3) | A,B,C,D | 1kHz | [All Modules](https://tessel.io/modules) | 21 | | SPI | **3+** (MOSI, MISO, SCK + 1 GPIO pin) | A,B,C,D | 25MBit/s | | 22 | | I2C | **2** (SCL and SDA) | A,B (shared bus I2C1) C,D (shared bus I2C0) | I2C0 - 1Mbit/s I2C1 - 400kbit/s | | 23 | | UART | **2** (TX and RX) | A,B,D - hardware C - software | 8Mbit/s | | 24 | 25 | ##A Note on Level Shifting 26 | All of the diagrams and discussions below regarding communication protocols assume that the hardware modules you are communicating with operate at 3.3V, just like the Tessel. 27 | 28 | If you have a device on your custom module that operates at 5V, 1.8V, or any other non-3.3V voltage, be careful! Directly connecting components with different operating voltages can damage the Tessel and/or your device. 29 | 30 | You can use devices which operate at different voltages by employing a technique called 'level shifting'. Sparkfun has a [nice writeup on voltage dividers and level shifting][level_shifting] that can be used as a starting point. 31 | 32 | The easiest way to avoid this complication is by trying to find module components that natively work at 3.3V. 33 | 34 | 35 | ##GPIO 36 | **Pros:** Simple, Requires a single pin 37 | 38 | **Cons:** Not good for sending complex data 39 | 40 | By far the simplest form of communication is via General Purpose Input/Output (GPIO). GPIO isn't really a 'protocol'. It is a rudimentary form of communication where you manually (in code) turn a pin on and off or read its state. 41 | 42 | Each port on the Tessel exposes three GPIO pins that can serve as a digital input or output and are marked as G1, G2, and G3. 43 | 44 |

45 | 46 |

GPIO pins available on a Tessel module port: G1, G2, and G3

47 | 48 | By default, Tessel's GPIO pins are configured to be inputs. 49 | 50 | ####Input 51 | When acting as a digital input, a pin can be queried in software and will return a value indicating the current state of the pin: high (1 or true) or low (0 or false). 52 | 53 | The following code snippet is an example of querying the G1 pin on port A. 54 | 55 | ```js 56 | var tessel = require('tessel'); // Import tessel 57 | var portA = tessel.port['A']; // Select Port A 58 | var myInputPin = portA.pin['G1']; // Assign the G1 pin to a variable 59 | 60 | var pinState = myInputPin.read(); // Query the state of the pin 61 | ``` 62 | 63 | This is great for connecting things like [switches, buttons][button_post], and even [motion detectors][pir_project]. Just remember that the Tessel can only handle signals that are 3.3V or lower. 64 | 65 |

66 | 67 |

The [MicroSD Card Module][sd_module] uses a GPIO pin acting as an input to detect whether a card is inserted or not.

68 | 69 | #####Determining digital state– a note for the curious: 70 | 71 | It's pretty clear that if an input pin sees 3.3V it would be interpreted as a high state and if the pin is connected to ground it would recognize that as a low state. But what if the pin senses something in between, like 2V? 72 | 73 | Your first thought might be that a high state is anything 1.65V (halfway between 0 and 3.3) or higher, and anything lower than that would be considered the low state. However, this is not always the case. 74 | 75 | The high/low threshold is always determined by the main processor. In the case of the Tessel, that's the LPC1830. The documentation on the LPC1830 tells us that the Tessel will consider an input to be high if it is at least 70% of the Tessel's supply voltage (VDD) which is 3.3V. It also tells us that any signal that is 30% of VDD or lower is guaranteed to be read as a low state. That means anything 2.31V (referenced as VIH) or higher would be considered high, and anything .99V (referenced as VIL) or lower is guaranteed to be interpreted as a low state. 76 | 77 | What about the voltages between .99V and 2.31V? The read behavior is undefined and you are not guaranteed to get an accurate result. That's one reason why it's important to make sure that any module you connect to a Tessel input pin provides a high voltage that is between VIH and 3.3V and a low voltage between ground and VIL. 78 | 79 | [More GPIO example code and information][gpio_code_example] 80 | 81 | ####Output 82 | When acting as a digital output, a pin can be set to one of two states: high (on/1/true) or low (off/0/false). 83 | High means the main Tessel board will set that pin to be 3.3V and low means it will set it to 0V. 84 | 85 | Digital output is useful for connected hardware that understands simple on/off states. The following code snippet shows how you can set the state of the G2 pin on port B. 86 | 87 | ```js 88 | var tessel = require('tessel'); // Import tessel 89 | var portB = tessel.port['B']; // Select Port B 90 | var myOutputPin = portB.pin['G2']; // Assign the G2 pin to a variable 91 | 92 | // Set the pin state with ones and zeroes 93 | myOutputPin.output(1); // Set the pin high 94 | myOutputPin.output(0); // Set the pin low 95 | 96 | // Or use booleans 97 | myOutputPin.output(false); 98 | myOutputPin.output(true); 99 | ``` 100 | 101 | Some examples of using a GPIO pin as an output are [simple LEDs][led_example] and for turning appliances on and off with a [relay][relay_module]. 102 | 103 |

104 | 105 |

An output pin is perfect for controlling an LED. Image is licensed under the [Creative Commons Attribution-Share Alike 2.0 Generic](http://creativecommons.org/licenses/by-sa/2.0/deed.en) license.

106 | 107 | [More GPIO example code and information][gpio_code_example] 108 | 109 | ###Tessel Modules That Use The GPIO Protocol 110 | Every Tessel First party module uses the GPIO protocol in some fashion. 111 | The [MicroSD Card Module][sd_module] uses a digital input to detect state on a module. 112 | The [Accelerometer Module][accel_module] uses a digital input to detect a data interrupt from the sensor. 113 | The [Relay Module][relay_module] uses digital outputs to turn things on and off. 114 | 115 | 116 | ##SPI 117 | **Pros:** Fast, supports multiple devices on a single bus, allows two-way communication 118 | 119 | **Cons:** Requires at least 3 pins 120 | 121 | SPI stands for [Serial Peripheral Interface][spi_wikipedia]. The SPI protocol allows data to be exchanged one byte at a time between the Tessel and a module via two communication lines. 122 | This is great for transferring data like sensor readings or sending commands to a module. 123 | 124 |

125 | 126 |

SPI pins SCK, MISO, and MOSI on Port B of the Tessel

127 | 128 | The SPI protocol is known as a Master/Slave protocol, which means that there is always a single master device which controls the flow of communication with one or more slave devices. Think of the master as a traffic cop. It directs all of the connected slave devices so they know when it's their turn to communicate. 129 | 130 | When you are creating modules, the Tessel will always act as the master device, and your custom module will be a slave device. 131 | 132 | The SPI protocol requires a minimum of three signal connections and usually has four (this is in addition to the power connections). The following diagram shows the connections (arrows indicate flow of data). 133 | 134 |

135 | 136 |

The red lines constitute the shared bus connections used for talking to the slave devices. The green wire is the shared bus connection used by the slaves to talk to the master. The blue line is the chip select for signaling each slave individually.

137 | 138 | 139 | ####SCK 140 | This is the clock signal that keeps the Tessel and the module synchronized while transferring data. The two devices need to have a mutual understanding of how fast data is to be transferred between them. 141 | This is sometimes referred to as the baud or bitrate. 142 | The clock signal provides that reference signal for the devices to use when exchanging data. 143 | 144 | Without a clock signal to synchronize the devices, the devices would have no way to interpret the signal on the data lines. 145 | 146 | One bit of data is transferred with each clock cycle (see the diagram below). 147 | 148 | ####MOSI 149 | MOSI stands for **M**aster **O**ut **S**lave **I**n and is the connection used by the Tessel to send data to the module. It's on this line that the Tessel will encode its data. 150 | 151 | ####MISO 152 | MISO stands for **M**aster **I**n **S**lave **O**ut and is the connection used by the module to send data to the Tessel. 153 | 154 | ####SS or CS 155 | This line, normally referred to as the **Slave Select (SS)** or **Chip Select (CS)** line, is used by the master device to notify a specific slave device that it is about to send data. We normally call it CS, but you may see it either way in datasheets and other references. 156 | 157 | When you create a Tessel module which uses the SPI protocol, the CS connection will be handled by one of the GPIO pins (G1, G2, G3) on the Tessel port. 158 | 159 | In the SPI protocol, the SCK, MOSI, and MISO connections are shared between all of the slave devices on a given SPI bus. For example, if you connect the MicroSD Card, Camera, and nRF24 modules to the Tessel at the same time, they will all be using the same SCK, MOSI, and MISO lines from the main Tessel chip. 160 | 161 |

162 | 163 | 164 | When the Tessel needs to send data to the Camera Module, the MicroSD and nRF24 will see that data but should just ignore it. To accomplish this, the Tessel will pull the CS line that is connected to the Camera Module low and leave the CS line high for the MicroSD and nRF24 modules. This lets the camera know that it is the active module and should pay attention. 165 | 166 | The following diagram shows how the various pins in the SPI protocol are toggled to create meaningful data. In this case, the master sends the ASCII character 'S', and the slave responds with 'F'. 167 | 168 |

169 | 170 |

Timing diagram of SPI data exchange. Modified [image](https://dlnmh9ip6v2uc.cloudfront.net/assets/c/7/8/7/d/52ddb2dcce395fed638b4567.png) from Sparkfun is [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/)

171 | 172 | Remember that the master initiates all communication. When it is ready, the first thing it will do is pull the CS/SS pin low to let the slave device know that a data transmission is about to begin. 173 | The master holds this pin low for the duration of the data exchange as seen in the diagram above. 174 | 175 | With the CS/SS pin low, the master will start to toggle the clock pin (SCK) while simultaneously controlling the MOSI to represent the bits of information it wishes to send to the slave. 176 | The numbers in green on the diagram above delineate each bit in the byte being transferred. 177 | 178 | It sounds complicated, but remember that the Tessel takes care of all of this pin manipulation for you. All you have to do is write some Javascript like this code snippet, which demonstrates the use of the SPI protocol on port A. 179 | 180 | ```js 181 | var portA = tessel.port['A']; 182 | var spi = new portA.SPI({ 183 | clockSpeed: 4000000 // 4MHz 184 | }); 185 | 186 | spi.transfer(new Buffer([0xde, 0xad, 0xbe, 0xef]), function (err, rx) { 187 | console.log('buffer returned by SPI slave:', rx); 188 | }); 189 | ``` 190 | 191 | [More SPI example code and information][spi_code_example] 192 | 193 | ###Tessel Modules That Use The SPI Protocol 194 | [Ambient][ambient_index], [Audio][audio_index], [Camera][camera_index], [Micro SD][sd_index], [nRF24][nrf_index], and [Infrared][ir_index] 195 | 196 | 197 | ##I2C 198 | **Pros:** Only requires 2 pins, multiple devices on a single bus, allows two-way communication 199 | 200 | **Cons:** Devices can have address conflicts, not as fast as SPI 201 | 202 | I2C stands for [Inter-Integrated Circuit][i2c_wikipedia] and is pronounced "I squared C", "I two C" or "I-I-C". I2C is a protocol that allows one device to exchange data with one or more connected devices through the use of a single data line and clock signal. 203 | 204 |

205 | 206 |

I2C pins SCL and SDA on Port B of the Tessel

207 | 208 | I2C is a Master/Slave protocol, which means that there is always a single master device which controls the flow of communication with one or more slave devices. 209 | 210 | I2C only requires two communication connections: 211 | 212 |

213 | 214 | 215 | ####SCL 216 | This is the clock signal that keeps the Tessel and the module synchronized while transferring data. The two devices need to have a mutual understanding of how fast data is to be transferred between them. This is sometimes referred to as the baud or bitrate. The clock signal provides that reference signal for the devices to use when exchanging data. Without a clock signal to synchronize the devices, they would have no way to interpret the signal on the data lines. 217 | 218 | ####SDA 219 | This is the data line used for exchanging data between the master and slaves. Instead of having separate communication lines for the master and slave devices, they both share a single data connection. The master coordinates the usage of that connection so that only one device is "talking" at a time. 220 | 221 | Since multiple slave devices can use the same SDA line, the master needs a way to distinguish between them and talk to a single device at a time. The I2C protocol uses the concept of **device addressing** to coordinate traffic on the data line. 222 | 223 | Every single I2C device connected to the Tessel will have an internal address that cannot be the same as any other module connected to the Tessel. This address is usually determined by the device manufacturer and listed in the datasheet. Sometimes you can configure the address through device-specific tweaks defined by the manufacturer. The Tessel, as the master device, needs to know the address of each slave and will use it to notify a device when it wants to communicate with it before transferring data. 224 | 225 |

226 | 227 |

Flow of data between Tessel and multiple I2C devices.

228 | 229 | The following diagram illustrates how the SDA and SCL pins are toggled when transferring data with the I2C protocol. 230 | 231 |

232 | 233 | To begin a data transaction, the master creates what is called a start condition by pulling the SDA pin low before the SCL pin. 234 | 235 | The master then broadcasts the address of the device it wishes to communicate with by sending each bit of the 7 bit address. Notice the clock signal (SCL) is toggled for each bit. This toggling is how the slaves know when to read each bit of the address so they can determine with which device the master wants to communicate. 236 | 237 | Right after the address, the master sends a read/write bit which signals whether it will be sending data to the slave or reading data from the slave. 238 | 239 | After broadcasting the address, the master either transmits data to the slave or sends the address of a register (internal storage) on the slave from which it wishes to retrieve data. 240 | 241 | Finally, the master will issue a stop condition on the bus by pulling SCL high, followed by SDA. 242 | 243 | It's a little complicated, but the Tessel takes care of all the details for you. Using the I2C pins on port A looks like this: 244 | 245 | ```js 246 | var tessel = require('tessel'); // import tessel 247 | var portA = tessel.port['A']; // use Port A 248 | var slaveAddress = 0xDE; // This is the address of the attached module/sensor 249 | var i2c = new portA.I2C(slaveAddress) 250 | 251 | i2c.send(new Buffer([0xde, 0xad, 0xbe, 0xef]), function (err) { 252 | console.log("I'm done sending the data"); 253 | // Can also use err for error handling 254 | }) 255 | ``` 256 | 257 | [More I2C example code and information][i2c_code_example] 258 | 259 | ###Tessel Modules That Use The I2C Protocol 260 | [Accelerometer][accel_index], [Climate][climate_index], [RFID][rfid_index], and [Servo][servo_index] 261 | 262 | 263 | ##UART 264 | **Pros:** Widely supported, allows two-way communication 265 | 266 | **Cons:** Can't share communication lines, slower than SPI and I2C 267 | 268 | UART stands for [Universal Asynchronous Receiver/Transmitter][uart_wikipedia] and is really just a fancy way of referring to a serial port. It is really easy to understand as it only requires two lines: a transmission line (**TX**) and a receiving line (**RX**). The Tessel sends data to connected modules on the TX line and gets data back on the RX line. 269 | 270 |

271 | 272 |

UART pins TX and RX on Port B of the Tessel

273 | 274 | ###TX 275 | Used by the Tessel to send data to the module. 276 | 277 | ###RX 278 | Used by the module to send data to the Tessel. 279 | 280 | When using a UART, it's important to remember that the communication lines cannot be shared between modules. In fact, because of this, each Tessel port needs its own RX and TX line from the main Tessel chip (LPC1830) as seen below. 281 | 282 |

283 | 284 |

Only ports A, B, and D have dedicated UART lines from the LPC1830.

285 | 286 | Since the LPC1830 doesn't have 4 UARTs, only Ports A, B, and D have a hardware UART. A software UART can be implemented on Port C but is beyond the scope of this guide. If you need to use a UART for communication we recommend using Port A, B or D. 287 | 288 |

289 | 290 |

A UART data transmission.

291 | 292 | UART transmissions begin with a start bit where the appropriate line (TX or RX) is pulled low by the sending party. Then 5 to 8 data bits are sent. The diagram above shows a scenario where 8 bits are sent. 293 | 294 | Following the data, an optional [parity bit](http://en.wikipedia.org/wiki/Parity_bit) is sent, followed by 1 or 2 stop bits, where the sending module pulls the pin high. 295 | 296 | For this protocol to work, the sender and receiver have to agree on a few things. 297 | 298 | 1. How many data bits are sent with each packet (5 to 8)? 299 | 2. How fast should the data be sent? This is know as the baud rate. 300 | 3. Is there a parity bit after the data, and is it high or low? 301 | 4. How many stop bits will be sent at the end of each transmission? 302 | 303 | When you want to interact with a specific module via UART, the answers to these questions are found in the module's datasheet. Using that information you can configure the UART in Javascript like this: 304 | 305 | ```js 306 | var port = tessel.port['A']; 307 | var uart = new port.UART({ 308 | dataBits: 8, 309 | baudrate: 115200, 310 | parity: "none", 311 | stopBits: 1 312 | }); 313 | 314 | uart.write('Hello UART'); 315 | ``` 316 | 317 | [More example code using a UART][uart_code_example] 318 | 319 | ###Tessel Modules That Use a UART 320 | [BLE][ble_index], [Camera][camera_index], [GPS][gps_index], and [GPRS][gprs_index] 321 | 322 | 323 | 324 | 325 | [led_example]: http://start.tessel.io/blinky 326 | [relay_module]: https://tessel.io/modules#module-relay 327 | [sd_module]: https://tessel.io/modules#module-sdcard 328 | [climate_module]: https://tessel.io/modules#module-climate 329 | [ambient_module]: https://tessel.io/modules#module-ambient 330 | [accel_module]: https://tessel.io/modules#module-accelerometer 331 | [ble_module]: https://tessel.io/modules#module-ble 332 | [gps_module]: https://tessel.io/modules#module-gps 333 | [spi_wikipedia]: http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus 334 | [i2c_wikipedia]: http://en.wikipedia.org/wiki/I%C2%B2C 335 | [uart_wikipedia]: http://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter 336 | [level_shifting]: https://learn.sparkfun.com/tutorials/voltage-dividers 337 | [spi_code_example]: https://github.com/tessel/t1-docs/blob/master/hardware-api.md#spi 338 | [gpio_code_example]: https://github.com/tessel/t1-docs/blob/master/hardware-api.md#pins 339 | [i2c_code_example]: https://github.com/tessel/t1-docs/blob/master/hardware-api.md#i2c 340 | [uart_code_example]: https://github.com/tessel/t1-docs/blob/master/hardware-api.md#uart 341 | [pir_project]: https://tessel.hackster.io/ifoundthemeaningoflife/pir-a0a3f8?ref=search&ref_id=pir&offset=3 342 | [button_post]: https://tessel.hackster.io/ifoundthemeaningoflife/tessel-button-bcf822?ref=search&ref_id=button&offset=4 343 | [ambient_index]: https://github.com/tessel/ambient-attx4 344 | [audio_index]: https://github.com/tessel/audio-vs1053b 345 | [camera_index]: https://github.com/tessel/camera-vc0706 346 | [sd_index]: https://github.com/tessel/sdcard 347 | [nrf_index]: https://github.com/tessel/rf-nrf24 348 | [accel_index]: https://github.com/tessel/accel-mma84 349 | [climate_index]: https://github.com/tessel/climate-si7020 350 | [rfid_index]: https://github.com/tessel/rfid-pn532 351 | [servo_index]: https://github.com/tessel/servo-pca9685 352 | [ble_index]: https://github.com/tessel/ble-ble113a 353 | [gps_index]: https://github.com/tessel/gps-a2235h 354 | [gprs_index]: https://github.com/tessel/gprs-sim900 355 | [ir_index]: https://github.com/tessel/ir-attx4 356 | -------------------------------------------------------------------------------- /tutorials/connect-arduino-tessel.md: -------------------------------------------------------------------------------- 1 | #Arduino <-> Tessel communication 2 | 3 | This is a tutorial for how to pass data back and forth between an Arduino and a Tessel. 4 | 5 | The data is passed via a [UART](http://en.wikipedia.org/wiki/Uart) bridge. Arduino has the [SoftwareSerial](http://arduino.cc/en/Reference/SoftwareSerial) library for UART comm and Tessel has it's built in UART functions. 6 | 7 | UART works through having TX (transmit) and RX (recieve) pins. A TX of one device is hooked up to the RX of another device like this: 8 | 9 | * Tessel TX <---> Arduino RX 10 | * Tessel RX <---> Arduino TX 11 | * Tessel GND <---> Arduino GND 12 | 13 | ##Step 1: Get an Arduino 14 | 15 | The Arduino needs to operate at 3.3V. Some boards which operate at this voltage are: 16 | 17 | * [Arduino Mini](https://www.sparkfun.com/products/11114) 18 | * [Seeeduino](http://www.seeedstudio.com/depot/Seeeduino-V30-Atmega-328P-p-669.html) 19 | * [Crowduino](http://www.elecrow.com/crowduino-with-atmega-328-v11-p-338.html) 20 | 21 | Both the Seeeduino and the Crowduino can switch between 5V and 3.3V. 22 | 23 | 24 | ### Arduino Uno 25 | Arduino Unos send over signals at 5V and **this will damage Tessel**. If you are planning on using an Arduino Uno, you need to make a [5V to 3.3V level converter](https://www.sparkfun.com/products/12009) which shifts the 5V UART TX signal from the Arduino to 3.3V. 26 | 27 | The UART TX coming **from** Tessel is at max 3.3V, but this will register as a digital "high" signal so it does not need to be boosted up to 5V. 28 | 29 | ##Step 2: Hook up the Arduino to the Tessel 30 | 31 | There are 3 pins that need to be hooked up, UART TX, UART RX, and Ground. 32 | 33 | In the code example, we're going to be using Arduino's SoftwareSerial on pins 10 and 11. 34 | 35 | ![wiring an arduino to a tessel](https://s3.amazonaws.com/technicalmachine-assets/doc+pictures/arduino-tessel-wiring-uart.jpg) 36 | 37 | * Arduino Pin 10 (orange wire) <--> Tessel Port D, pin TX/G1 38 | * Arduino Pin 11 (white wire) <--> Tessel Port D, pin RX/G2 39 | * Arduino Ground (brown wire) <--> Tessel Ground 40 | 41 | ##Step 3: Program the Arduino 42 | 43 | Run this code on the Arduino 44 | 45 | ```c 46 | #include 47 | #define rxPin 10 // connect to TX of other device 48 | #define txPin 11 // connect to RX of other device 49 | 50 | SoftwareSerial tesselBridge = SoftwareSerial(rxPin, txPin); 51 | 52 | void setup() 53 | { 54 | // open serial port at 9600 baud 55 | Serial.begin(9600); 56 | Serial.println("Starting up..."); 57 | 58 | // set the data rate for the SoftwareSerial port 59 | tesselBridge.begin(9600); 60 | } 61 | 62 | void loop() // run over and over 63 | { 64 | if (tesselBridge.available()) 65 | Serial.write(tesselBridge.read()); 66 | if (Serial.available()) 67 | tesselBridge.write(Serial.read()); 68 | } 69 | ``` 70 | 71 | ##Step 4: Program Tessel 72 | 73 | Make a folder for the code: 74 | 75 | ``` 76 | mkdir arduinoBridge; 77 | cd arduinoBridge; touch uart.js; 78 | ``` 79 | 80 | Put this in the uart.js file. 81 | 82 | ```js 83 | var tessel = require('tessel'); 84 | var led1 = tessel.led[0].output(0); 85 | var led2 = tessel.led[1].output(0); 86 | var i = 0; 87 | 88 | // baudrate must match the baudrate set in the Arduino file 89 | uartBridge = tessel.port['D'].UART({baudrate: 9600}); 90 | 91 | uartBridge.on('data', function(data){ 92 | // UART data is not packetized, so you will get the data 93 | // buffer as the message is sent. This means that long 94 | // messages will be truncated as several events. 95 | 96 | var number = parseInt(data[0]) - 48; // convert hex to ascii to int 97 | console.log("got data", data, number); 98 | 99 | if (number == 1) 100 | led1.toggle(); 101 | 102 | if (number == 2) 103 | led2.toggle(); 104 | }); 105 | 106 | // every 3 seconds write some data over to the arduino 107 | setInterval(function(){ 108 | uartBridge.write("Hi there "+i+"\n"); 109 | i++; 110 | }, 3000); 111 | ``` 112 | 113 | Run the code with `tessel run uart.js`, or if you want this to be persistent through power cycles, `tessel push uart.js`. 114 | 115 | ##Step 5: Test it 116 | You should be able to go into the Arduino console and see the blue and green LEDs on Tessel change as you enter a "1" or a "2". 117 | 118 | ![terminal](https://s3.amazonaws.com/technicalmachine-assets/doc+pictures/arduino-to-tessel.jpg) 119 | -------------------------------------------------------------------------------- /tutorials/debug-using-busblaster.md: -------------------------------------------------------------------------------- 1 | # Debugging Tessel 2 | 3 | You can debug Tessel by soldering [JTAG headers](https://s3.amazonaws.com/technicalmachine-assets/doc+pictures/hardware_design_docs/TM-00-04-ports.png) to the board and using a JTAG debugger. This tutorial asummes you are using a [Bus Blaster](http://www.seeedstudio.com/depot/Bus-Blaster-v3-p-1415.html) and an associated [JTAG 20 -> 10 pin adapter](http://www.digikey.com/product-detail/en/ARM-JTAG-20-10/1188-1016-ND/3471401). 4 | 5 | ## Setup 6 | 1. Install OpenOCD. You need version >= 0.8.0. 7 | * This version is not in Ubuntu 14.04, but the [packages from Ubuntu Utopic work fine there](https://launchpad.net/ubuntu/+source/openocd) 8 | * `brew install libusb libftdi open-ocd` installs >= 0.8.0. 9 | 10 | 1. Acquire a configuration script for your Bus Blaster. Included in the firmware repo is `tools/tessel-busblaster.cfg`. 11 | 12 | 1. Plug the JTAG cable into the Bus Blaster's adapter board and the Tessel. Pin one is towards the USB port; the cable goes over the center of the board. 13 | 14 | 1. Run 15 | 16 | ``` 17 | arm-none-eabi-gdb out/Release/tessel-firmware.elf -ex 'target remote | openocd -c "gdb_port pipe;" -f tools/tessel-busblaster.cfg' 18 | ``` 19 | (adjust paths as appropriate) to launch gdb. 20 | 21 | ## GDB commands 22 | 23 | ### Basics 24 | * `c` - continue 25 | * `ctrl-c` - stop 26 | * `p expr` - print the value of the C expression `expr` 27 | * `bt` - stack backtrace 28 | * `s` - step instruction, goes into calls 29 | * `n` - next instruction, skips over calls 30 | * `fin` - run until return from function 31 | * `break function` - break at the beginning of a function (can also pass `file.c:line`) 32 | * `delete 1` - delete the first breakpoint 33 | * `tbreak` - break only once 34 | 35 | ### Hardware 36 | * `mon reset` - Reset Tessel and all on-chip peripherals (like the reset button) 37 | * `mon soft_reset_halt` - Reset the CPU only 38 | 39 | ## Other notes 40 | 41 | * Make sure your `.elf` file matches the firmware on the Tessel. Otherwise the position information will be wrong and calls will crash. 42 | * LPC1800 SPIFI Flash is functional from OpenOCD, but I don't recommend using it. Flash Tessel with the bootloader (`make arm-deploy`) before running GDB. 43 | * The ROM confuses JTAG on reset. If you `c` and then `ctrl-c`, it recovers. To debug the very beginning of execution, use 44 | 45 | ``` 46 | mon soft_reset_halt 47 | tbreak main 48 | c 49 | ``` 50 | 51 | ## Troubleshooting 52 | 53 | **OS X:** If you are getting a `libusb` error, you may need to disable some system drivers in order for OpenOCD to work. Run `kextstat | grep -i ftdi`. If any drivers are listed, you need to run either `sudo kextunload -bundle com.apple.driver.AppleUSBFTDI` and/or `sudo kextunload -bundle com.FTDI.driver.FTDIUSBSerialDriver`. For a long-term solution for configuring this, see . 54 | -------------------------------------------------------------------------------- /tutorials/diy_module_creation.md: -------------------------------------------------------------------------------- 1 | # Creating Your Own Tessel Module 2 | ## What Is a Module? 3 | 4 | >Modules should be devices with clear-cut functionality. That is to say, they should have a single, well-defined purpose or a set of closely related functions, rather than an eclectic mix of capabilities onboard. This requirement is designed to reduce complexity, cost, and power consumption and maximize reusability in hardware and software. 5 | 6 | >*[–Tessel hardware docs](https://github.com/tessel/hardware/blob/master/tessel-hardware-overview.md#module-design-philosophy)* 7 | 8 | One of the main goals of the Tessel platform is "connected hardware as easy as npm install." 9 | If you need an accelerometer, Bluetooth Low Energy connection, SIM card capability, or any of the other [14 first-party modules available][modules_page], you can literally plug, npm install, and play. 10 | 11 | There is also a growing library of community-contributed [third-party modules][third_party_modules]: npm libraries paired with some simple wiring instructions, built for specific pieces of hardware. 12 | 13 | But what if your project needs functionality that can't be provided by one of the existing first- or third-party modules? You make your own, of course. 14 | 15 | This guide will walk you through the basics of creating your own Tessel module using our new proto-module boards. 16 | 17 | ### A Quick Note of Encouragement 18 | 19 | Making your own module might seem like an overwhelming task best left to those who know things like Ohm's Law, how to solder, and why licking a 9V doesn't feel very good. But while having some electronics knowledge doesn't hurt, it's not a hard and fast prerequisite. If you know how to program, you are smart enough to figure out the basic concepts and make awesome things happen. Just trust us and read on. 20 | 21 | ## Module Design Basics 22 | 23 | Before you venture into the world of custom module creation, we need to cover some basics that will help guide you along the way. 24 | 25 | Every module created for the Tessel involves 5 parts: 26 | 27 | 1. Power 28 | 2. Communication 29 | 3. Software 30 | 4. Documentation 31 | 5. Sharing 32 | 33 | If you understand how each of these fit into the module creation process, you will be well on your way to creating your own custom module. Let's start with power. 34 | 35 | ### Power 36 | When dealing with anything in electronics, whether it be sensors, displays, buttons, or servos, you have to provide power. Everything needs a power source, and Tessel modules are no exception. In its simplest form, you can think of a power source as two connections; a positive voltage and a ground connection. These connections are provided on each Tessel port as seen in the image below. 37 | 38 |

39 | 40 |

Power connections on Tessel's Port B

41 | 42 | The main Tessel board [can be powered several ways][power_options], but regardless of how you provide power to the main board it ultimately turns that source into 3.3V. That's the native "voltage language" of the Tessel. It likes to speak 3.3V to everything if possible. 43 | 44 | One of the nice things about the proto-module is that the 3.3V and ground connections are exposed as two rails that run along each side of the module as seen below. This allows you to easily power your module components. 45 | 46 |

47 | 48 |

Proto-module power rails

49 | 50 | ### Special Considerations 51 | If all of the components on your custom module operate at 3.3V, then your power design is extremely simple. You just use the 3.3V and ground rails and connect your components accordingly (the [custom screen module](#screen_example) below is a good example). Sometimes, however, you may encounter a situation where 3.3V is not what you need, like in the case of the [servo module][servo_module]. 52 | 53 | Many servos like to operate at 5V. That's their native "voltage language" and so the 3.3V provided by the Tessel isn't ideal and, in many cases, just won't work. Servos can also draw a lot of current, which may overwhelm the Tessel's power supply. To solve this problem, you'll notice that the servo module has a DC barrel jack on it that allows you to plug in a 5V adapter to provide sufficient power to the connected servos. 54 | 55 |

56 | 57 |

DC Barrel Jack on the Servo Module

58 | 59 | From the [servo module schematic][servo_schematic], we can see that communication is accomplished with the normal I2C lines, which operate at 3.3V, but servo power is provided via schematic component J2, which is the barrel jack. 60 | 61 | This guide isn't meant to be a comprehensive power reference, but we just want to point out that if you have any components on your custom module that work outside of the 3.3V realm, you will [need to design for it][level_shifting]. To simplify your module design, we recommend using 3.3V components where possible. 62 | 63 | ### The Power Warnings 64 | Here are some items to remember when working with power in electronics. 65 | 66 | * **ALWAYS** unplug your Tessel and any external power before making or altering connections. 67 | * Don't mix voltages unless you know what you're doing. For example, if you put 5V on any of the module pins, you can ruin your Tessel. 68 | * Never connect the positive voltage directly to ground. This is called a [short circuit](http://en.wikipedia.org/wiki/Short_circuit) and can ruin components and your day. 69 | * Always exercise caution and verify that you have hooked everything up correctly before plugging in your Tessel. 70 | 71 | ## Communication 72 | 73 | Once you have decided how you are going to power your custom module, it's time to decide how the main Tessel board will talk to it. 74 | 75 | In the world of web communication, there are standards like HTTP, HTTPS, and FTP that allow different systems to talk to each other in well-defined ways. The same concept exists in the hardware world and the Tessel supports four standard communication protocols for talking to modules. 76 | 77 | * [GPIO][comm_gpio] 78 | * [SPI][comm_spi] 79 | * [I2C][comm_i2c] 80 | * [UART][comm_uart] 81 | 82 | Because the Tessel [does most of the heavy lifting][hardware_api] for all of these, you don't need to be an expert to use them in your custom module. However, if you'd like to learn a little more, we've [provided a simple overview of each](https://tessel.io/docs/communicationProtocols). 83 | 84 | ### So Which Communication Protocol Should I Use? 85 | Knowing that there are four communication options available to you, which should you use for your custom module? The good news is that this will usually be decided for you based on the type of module you are creating. For example, most [PIR sensor modules][pir_project] will set a pin high when motion is detected, which can be read with a simple digital input (GPIO). The same applies to sensors. For example, the Si7005 temperature and humidity sensor on the [Climate Module][climate_module] communicates via the [I2C protocol][comm_i2c]. Usually sensors will only support one protocol– so the decision is easy, you use that one. 86 | 87 | You will find some modules that support both SPI and I2C, and either will work just fine with the Tessel. As a general rule of thumb, we recommend you favor the SPI protocol in these scenarios as it eliminates the risk of I2C address collisions with other connected I2C modules. 88 | 89 | ## Software 90 | 91 | Once you have the power and communication all worked out and connected, it's time to start writing JavaScript to talk to your module. This is where the open-source nature of the Tessel really comes in handy. We've already used all of the possible communication protocols in [our modules][modules_page] and the [code is free to look at][tessel_github] and copy. 92 | 93 | Design an API for working with your module so that it's easy for others to integrate into their projects. As a general rule, top priority is intuitive interaction. Second priority is exposing as many features as you can. You can find a lot of great information about organizing your project and writing an API in [Making a Tessel-style Library for Third-Party Hardware][third_party_doc]. 94 | 95 | ## Documentation and Sharing 96 | 97 | Once you have a working module, it's time to share the good news with everyone so other people can build amazing things with your work. We recommend doing a few things to share it with the community as outlined below. This helps create a consistent feel across all Tessel modules, whether they are official modules or submitted by the community. 98 | 99 | ### Create A Git Repo 100 | Having your code in a git repo and available online makes it easy for others to grab your code and start using it in their projects. To help you get started we've created a template repository that you can use as a starting point. 101 | 102 | [Custom Module Git Repo Template][repo_template] 103 | 104 | ### Document It 105 | You may have just created the world's most amazing Tessel module, but how is anybody going to know about it or use it? Once you've hashed out the API and everything is working, it's important to document its use so others can easily apply your work to their projects. The best way to do this is to use the [README template][readme_template], which includes things like how to install the module, example usage, and API information. 106 | 107 | ### Publish Your Code on NPM 108 | Once your git repo is ready and you've documented your module, this step is really easy and makes your module fit the Tessel motto of "connected hardware as easy as npm install." If you've never published code to NPM before, you can get started with just four lines of code (run in a shell window). 109 | 110 | npm set init.author.name "Your Name" 111 | npm set init.author.email "you@example.com" 112 | npm set init.author.url "http://yourblog.com" 113 | 114 | npm adduser 115 | 116 | This sets up your NPM author info. Now you're ready to create your package.json file. There is one in the repo template but we suggest creating it by running npm init from within the project directory. 117 | 118 | ``` 119 | npm init 120 | ``` 121 | 122 | Edit your package.json file to include a name, version, and description. We also highly recommend adding "tessel" as a keyword so that other Tessel users can easily find your work. Most of the package.json file is self-explanatory and follows the [npm package.json standard][package_json_standard] with the exception of the **hardware** member. 123 | 124 |

125 | 126 |

**hardware** section of package.json

127 | 128 | This is a Tessel-specific item that you must add manually and is a list of files and folders in your project that you would like to exclude when code is pushed to your Tessel. 129 | 130 | Once your package.json file is complete you're ready to publish your code. Run the following command from the top level directory of your project. 131 | 132 | npm publish ./ 133 | 134 | ### Create a Project Page 135 | The [Tessel Projects page][tessel_projects] is a way to share your module directly with the Tessel community. You simply provide a few pieces of information, a picture, and can even use your README.md file from your Git repo as the contents. 136 | 137 | ### Submit Your Module 138 | We're always looking to add modules to our [third-party module list][third_party_modules] so if you'd like your custom module to be listed at [tessel.io/modules][modules_page] then fill out this form and we'd be happy to review it. 139 | 140 | [Third-Party Module Submission Form][module_submission] 141 | 142 | A great example of using this module-creation pattern can be found in [Making a Tessel-style Library for Third-Party Hardware][third_party_doc]. 143 | 144 | ## Your First Custom Module 145 | So now that we've described the pattern for making a custom module, let's walk through creating a very simple module using that pattern. The Tessel has a spare button on the main board, but maybe you'd like to add one as a module. Kelsey did [a great writeup on adding a button to the GPIO bank][orig_button_project_page] so let's use her work to take it one step further using a proto-module. 146 | 147 | ### Power 148 | You might not think of a button as needing power, and you're right, sort of. While the button itself doesn't need power to function, we can connect our button in such a way that it uses the power connections to create high and low states on a GPIO pin. 149 | 150 | GPIO pins on the Tessel will always read high/truthy with nothing connected, because internally (inside the main Tessel chip), they are pulled up to the 3.3V supply. That's our positive connection. 151 | 152 | The other power connection is ground, which we'll connect to one side of our button. It doesn't matter which side, because a button is just a momentary switch that creates and breaks a connection. You can't hook it up backward. We'll get to connecting the other side of the button in a minute. 153 | 154 | ### Communication 155 | As mentioned above, normally your communication protocol is determined by your module. In the case of a button, we use a GPIO pin because we want to read the state of the button. 156 | 157 | Each port on the Tessel has 3 pins that can serve this purpose, and you are free to pick any one you like because it doesn't matter. 158 | 159 |

160 | 161 |

GPIO pins available on a Tessel module port: G1, G2, and G3

162 | 163 | We're going to choose G1, which is what we will hook up to the other side of the button. When the button is not pressed, our input pin will read high, or true. When we press it, we are making a connection between our GPIO pin and ground, which will cause a low state to be present on the input pin. This is what the design looks like. 164 | 165 |

166 | 167 |

Schematic of button connections

168 | 169 |

170 | 171 |

Soldered together on a proto-module board.

172 | 173 | Don't let the soldering part scare you. Soldering components like this onto a proto-module is a little harder than learning to use a hot glue gun, but not a lot harder. 174 | [This tutorial from Sparkfun](https://learn.sparkfun.com/tutorials/how-to-solder---through-hole-soldering) is a great place to start learning soldering. 175 | 176 | Let's go ahead and plug our module into Port A. **Remember to never make connections while your Tessel is powered up. Always unplug it first.** 177 | 178 | ### Software 179 | With everything hooked up, it's time to write some Javascript. 180 | 181 | Actually, we're going to reuse the code from Kelsey and modify it just a bit. Since she followed the style guidelines and shared her work on NPM, we actually don't have to write the bulk of the code. She's even provided a [Quick Start guide](https://github.com/Frijol/tessel-button#quick-start-i-just-want-a-button) in her documentation, so we'll use that. 182 | 183 | 1. Install the tessel-gpio-button package. This will allow us to reuse Kelsey's work. 184 | 185 | ```npm install tessel-gpio-button``` 186 | 187 | 2. Create a file named **myButton.js** and copy her Quick Start code into it. It should look like this: 188 | ```js 189 | // examples/button.js 190 | // Count button presses 191 | 192 | var tessel = require('tessel'); 193 | var buttonLib = require('../'); 194 | var myButton = buttonLib.use(tessel.port['GPIO'].pin['G3']); 195 | 196 | var i = 0; 197 | 198 | myButton.on('ready', function () { 199 | myButton.on('press', function () { 200 | i++; 201 | console.log('Press', i); 202 | }); 203 | 204 | myButton.on('release', function () { 205 | i++; 206 | console.log('Release', i); 207 | }); 208 | }); 209 | ``` 210 | 211 | 212 | This almost works right out of the box. We just need to make two small adjustments. Do you see them? 213 | 214 | First, to include her module we won't use "require('../')." Instead we'll include the module directly with require('tessel-gpio-button'). 215 | 216 | Second, she hooked her button up to the G3 pin on the GPIO bank, but we've hooked our proto-module up to Port A and used the G1 pin. So all we have to change is the line where _myButton_ is defined. We'll change it to be: 217 | 218 | ```js 219 | var myButton = buttonLib.use(tessel.port['A'].pin['G1']); 220 | ``` 221 | 222 | Save your changes and test it out. 223 | 224 | ``` 225 | tessel run myButton.js 226 | ``` 227 | 228 | Every time you push your button it should log to the console. 229 | 230 | Congratulations! You just created your first custom module for the Tessel. 231 | 232 |

233 | 234 |

Custom button module connected to the Tessel

235 | 236 | ### Documentation and Sharing 237 | We sort of cheated for our first module; Kelsey had already created an NPM package that we could reuse, so there wasn't really anything to document or share on the software side. There is nothing wrong with that. In fact, the less code you have to write, the better. This is a great example of how taking the time to document and share your work benefits the entire community. 238 | 239 | What we can do though is create [a project page][button_project_page] showing how we took Kelsey's button to the next level in the form of a plug-in module. We created the physical module. It's a simple module, but we should document it in case someone else wants a button module like ours. 240 | 241 | [Custom Button Module Project Page][button_project_page] 242 | 243 | 244 | ## Custom Screen Module 245 | Now that you have a simple module under your belt, it's time to level up. To date, the module that people have requested the most is a screen module. Displays are tricky because they come in so many flavors. There are simple 7-segment displays, LCD displays, OLEDs, resistive touchscreens, capacitive touchscreens, and more. This is a great use case for a custom module. 246 | 247 | One of the popular screen modules in embedded projects is the Nokia 5110, because of its simple interface and low cost. Let's see how we'd create a module for it by following the same pattern as before. 248 | 249 | For this example we'll use the [Nokia 5110 breakout from Sparkfun][nokia_sparkfun], but you could also use the [Adafruit version of the screen][nokia_adafruit] or just try to snag one [on Ebay][nokia_ebay] 250 | 251 |

252 | 253 |

Nokia 5110 Graphic LCD

254 | 255 | ### Power 256 | The 5110 has a listed power supply range of 2.7V to 3.3V, which means any voltage in between (inclusive) is sufficient to power the screen. Since the Tessel ports have a 3.3V supply pin we don't have to do anything special to hook it up. All we need to do is connect the screen VCC, or positive pin, to a 3.3V rail on the proto-module and the GND on the screen to a GND rail. 257 | 258 | Because of the screen's size, we'll use one of the double-wide proto-modules this time, even though we'll only use a single port to connect everything. 259 | 260 |

261 | 262 |

Double-Wide Proto-Module

263 | 264 | ### Communication 265 | Just like in the button example, the communication protocol for the screen has already been chosen for us. The Nokia 5110 uses a slightly modified version of [SPI][comm_spi] to communicate with a parent controller, namely the Tessel in our case. 266 | 267 | In addition to the normal SPI protocol, the 5110 has an extra pin involved (**D/C**) that tells the screen whether the data we are sending via SPI is a special command or actual screen data. 268 | 269 | The D/C pin is controlled by a simple high or low signal, which is a perfect job for one of the GPIO pins. 270 | 271 | The following table shows all of the communication connections available on our screen and how we'll attach them to the Tessel port. 272 | 273 | | Nokia 5110 Pin | Proto-Module Connetion | 274 | |----------------|------------------------------------------| 275 | | SCE | G1 | 276 | | RST | Connected to 3.3V through 10K resistor | 277 | | D/C | G2 | 278 | | MOSI | MOSI | 279 | | SCLK | SCK | 280 | | LED | Connected to G3 through 330 ohm resistor | 281 | 282 | #### Design Note 283 | The Nokia 5110 has 4 connections that can utilize GPIO pins for functionality. The D/C (data/command) and SCE (chip select) pins have to be used to get data to the screen. That leaves just one GPIO pin on the port with RST and LED left unconnected. You have a few options here. 284 | 285 | 1. Wire RST to 3.3V through a 10K resistor which prevents you from resetting the screen in code. This allows you to control the backlight with the free GPIO pin. 286 | 2. Wire LED to 3.3V through a 330 ohm resistor (to limit current) which will permanently turn on the backlight. This leaves a GPIO free that can be used to reset the screen via Javascript. 287 | 3. Since we're using the double-wide, you could use a GPIO pin from the adjacent port and have use of both LED and RST 288 | 4. Connect SCE (chip select) to ground, which frees up a GPIO so you can control both LED and RST. Holding the chip select low, however, makes it so that **no other SPI device** (including other Tessel modules that use SPI e.g., the Camera module) can be connected to the Tessel on any other port. 289 | 290 | We decided to go with option 1 because there isn't really a need to reset the screen in most cases and it allows control of the backlight with a GPIO pin. This is another great thing about custom modules. You can design it however you want to fit your project needs. 291 | 292 | We hooked everything up using the [Graphic LCD Hookup Guide][screen_hookup_guide]. We recommend testing everything with a [breadboard](https://learn.sparkfun.com/tutorials/how-to-use-a-breadboard) before you solder everything in place, just to make sure it works the way you expect it to. 293 | 294 | Here is what the module looks like soldered to the double-wide proto-module. 295 | 296 |

297 | 298 |

Nokia 5110 soldered to a large proto-module board

299 | 300 | ### Software 301 | With the screen hooked up, it's time to start writing code. We'll follow the pattern found in the [Git Repo Template][repo_template] and start by creating a directory called **tessel-nokia5110** and cd into that directory. Next, we'll create **index.js** which is where we'll write our API using [the example index.js template][index_template] as a guide. 302 | 303 | Because this screen is so popular, there are lots of code examples and libraries online for interacting with it. We don't need to reinvent the wheel; we just want to control the screen with JavaScript. 304 | 305 | We took a [simple Arduino library][screen_arduino_code] for this screen and [ported it to JavaScript][screen_github]. 306 | Our API is very simple and exposes just one event and a few methods. 307 | 308 | ####Event 309 | Nokia5110.**on**('ready', callback(err, screen)) - Emitted when the screen object is first initialized 310 | 311 | ####Methods 312 | Nokia5110.**gotoXY**(x,y,[callback(err)]) - Sets the active cursor location to (x,y) 313 | 314 | Nokia5110.**character**(char, [callback(err)]) - Writes a single character to the display 315 | 316 | Nokia5110.**string**(data, [callback(err)]) - Writes a string to the display 317 | 318 | Nokia5110.**bitmap**(bitmapData, [callback(err)]) - Draws a monochrome bitmap from _bitmapData_ 319 | 320 | Nokia5110.**clear**([callback(err)]) - Clears the display 321 | 322 | Nokia5110.**setBacklight**(state) - Turns the backlight on if _state_ is truthy, off otherwise 323 | 324 | ### Documentation 325 | Now that the module is connected up and the software is working, it's time to document its use. 326 | 327 | We can't stress enough how important this is, and it really only takes a few minutes once you've defined everything. Just think of all the times you've needed a piece of code and found a beautifully documented example that had you up and running in minutes. Share that love with others when you create your own modules, no matter how trivial you think they are. 328 | 329 | In our case, we'll take the [template README.md file][readme_template] and [add some notes for getting started as well as document our API][screen_github]. 330 | 331 | We'll also create an **examples** folder to show how the module can be used. 332 | 333 | ### Sharing 334 | Now it's time to share our new creation with the world by: 335 | 336 | * Creating a [git repo and pushing the code online][screen_github] 337 | * [Publishing the module to NPM][screen_npm] 338 | * Creating a [project page][screen_project_page] for it 339 | * [Submitting][module_submission] it to the [third-party module list][third_party_modules] 340 | 341 |

342 | 343 |

Finished screen module

344 | 345 | ### Resource List 346 | To help you get started creating your own custom modules, here is a list of the resources we used to put this tutorial together. 347 | 348 | #### Power 349 | * [Powering Your Tessel][power_options] 350 | * [Level Shifting][level_shifting] 351 | 352 | #### Communication 353 | * [Tessel Module Communication Protocols][comm_protocols] 354 | 355 | #### Software 356 | * [Making a Tessel-style Library for Third-Party Hardware][third_party_doc] 357 | * [Tessel Hardware API][hardware_api] 358 | * [All first-party module code on Github][tessel_github] 359 | 360 | #### Documentation 361 | * [Git Repo Template][repo_template] 362 | * [README.md Template][readme_template] 363 | 364 | #### Sharing 365 | * [Publishing to NPM Tutorial][npm_tutorial] 366 | * [package.json Standard][package_json_standard] 367 | * [Tessel Project Page][tessel_projects] 368 | * [Third-Party Module Submission Form][module_submission] 369 | 370 | [modules_page]: https://tessel.io/modules 371 | [third_party_modules]: https://tessel.io/modules#third-party 372 | [tessel_github]: https://github.com/tessel 373 | [repo_template]: https://github.com/tessel/style/tree/master/Templates 374 | [index_template]: https://github.com/tessel/style/blob/master/Templates/index.js 375 | [package_json_standard]: https://www.npmjs.org/doc/files/package.json.html 376 | [npm_tutorial]: https://gist.github.com/coolaj86/1318304 377 | [readme_template]: https://github.com/tessel/style/blob/master/module_RM_template.md 378 | [hardware_api]: https://github.com/tessel/t1-docs/blob/master/hardware-api.md 379 | [tessel_projects]: https://tessel.io/projects 380 | [module_submission]: https://docs.google.com/forms/d/1Zod-EjAIilRrCJX0Nt6k6TrFO-oREeBWMdBmNMw9Zxc/viewform 381 | [level_shifting]: https://learn.sparkfun.com/tutorials/voltage-dividers 382 | [power_options]: https://github.com/tessel/hardware/blob/master/powering-tessel.md 383 | [servo_module]: https://tessel.io/modules#module-servo 384 | [servo_schematic]: http://design-files.tessel.io.s3.amazonaws.com/2014.06.06/Modules/Servo/TM-03-03.pdf 385 | [climate_module]: https://tessel.io/modules#module-climate 386 | [pir_project]: https://tessel.hackster.io/ifoundthemeaningoflife/pir-a0a3f8?ref=search&ref_id=pir&offset=3 387 | [button_project_page]: https://tessel.hackster.io/sidwarkd/tessel-button-diy-module-054813?ref=search&ref_id=button&offset=12 388 | [orig_button_project_page]: https://tessel.hackster.io/ifoundthemeaningoflife/tessel-button-bcf822?ref=search&ref_id=button&offset=4 389 | [comm_protocols]: https://github.com/tessel/t1-docs/blob/DIY-module/tutorials/communication-protocols.md 390 | [comm_gpio]: https://github.com/tessel/t1-docs/blob/DIY-module/tutorials/communication-protocols.md#gpio 391 | [comm_spi]: https://github.com/tessel/t1-docs/blob/DIY-module/tutorials/communication-protocols.md#spi 392 | [comm_i2c]: https://github.com/tessel/t1-docs/blob/DIY-module/tutorials/communication-protocols.md#i2c 393 | [comm_uart]: https://github.com/tessel/t1-docs/blob/DIY-module/tutorials/communication-protocols.md#uart 394 | [third_party_doc]: https://github.com/tessel/t1-docs/blob/master/tutorials/make-external-hardware-library.md 395 | [nokia_sparkfun]: https://www.sparkfun.com/products/10168 396 | [nokia_adafruit]: https://www.adafruit.com/products/338 397 | [nokia_ebay]: http://www.ebay.com/sch/i.html?_from=R40&_trksid=p2050601.m570.l1313.TR6.TRC1.A0.H0.Xnokia+5110&_nkw=nokia+5110&_sacat=0) 398 | [screen_arduino_code]: http://dlnmh9ip6v2uc.cloudfront.net/datasheets/LCD/Monochrome/Nokia_5110_Example.pde 399 | [screen_github]: https://github.com/sidwarkd/tessel-nokia5110 400 | [screen_npm]: https://www.npmjs.org/package/tessel-nokia5110 401 | [screen_hookup_guide]: https://learn.sparkfun.com/tutorials/graphic-lcd-hookup-guide 402 | [screen_project_page]: https://tessel.hackster.io/sidwarkd/tessel-nokia5110-c489c7?ref=search&ref_id=lcd&offset=0 403 | -------------------------------------------------------------------------------- /tutorials/gpio-interrupts.md: -------------------------------------------------------------------------------- 1 | #External GPIO Pin Interrupts API 2 | 3 | External interrupts are used for getting updated from other sensors or the environment that something has changed. It allows the processesor to work on other tasks until the state of a pin is altered at which point hardware processes take over and handle the interrupt. 4 | 5 | You'll notice that they were designed to work in the same manner as traditional Node EventEmitter APIs. 6 | 7 | 8 | There are five different GPIO interrupt modes to work with: 9 | 10 | - Level Triggers: 11 | * `'high'` called as soon as a pin is high (may be immediately). Can only be watched for with the `once` method. Attempt to call `on` with a level interrupt will execute the Error Routine (See Error Routine below) 12 | * `'low'` called as soon as a pin is low (may be immediately). Can only be watched for with the `once` method. Attempt to call `on` with a level interrupt will execute the Error Routine (See Error Routine below) 13 | - Edge Triggers: 14 | * `'rise'` called when the state of a pin switches from low to high. Can be used with either `on` or `once`. 15 | * `'fall'` called when the state of a pin switches from high to low. Can be used with either `on` or `once`. 16 | * `'change'` called on either `'rise'` or `'fall'` event. 17 | 18 | ## Parameters 19 | A pin emission event has the following parameters: 20 | ```.js 21 | pin.on('change', function(time, trigger)); 22 | ``` 23 | Where `time` is the number of milliseconds since Tessel booted and `trigger` is the actual trigger of the interrupt (eg. `'rise'`) which is generally only used for the `'change'` event. 24 | 25 | ## Seven maximum Interrupts 26 | There are seven maximum GPIO interrupts to be assigned. **Each interrupt can only support *either* edge triggers or level triggers. A single interrupt can support multiple modes of either type (eg. both `'rise'` and `'fall'`) . Therefore, a single pin can use either 1 or 2 interrupts.** This is important to know so the user can keep track of how many interrupts remain. 27 | 28 | The following uses a single interrupt: 29 | ```.js 30 | // Edge trigger 31 | pin.on('rise', someFunc(){}); 32 | 33 | // Edge trigger 34 | pin.on('fall', someOtherFunc(){}); 35 | ``` 36 | 37 | But the following needs two separate interrupts: 38 | ```.js 39 | // Edge trigger 40 | pin.on('fall', someFunc(){}); 41 | 42 | // Level Trigger 43 | pin.once('high', someOtherFunc(){}); 44 | ``` 45 | 46 | ## Watch for a single event: 47 | ```.js 48 | var tessel = require('tessel'); 49 | var pin = tessel.port['A'].digital[0]; 50 | 51 | // To watch for a single event continuously: 52 | pin.on('change', someFunc); 53 | 54 | // OR 55 | 56 | // To watch only once 57 | // (interrupt will be removed if this was the last callback) 58 | pin.once('change', someFunc); 59 | 60 | // time is a timestamp (in ms since startup) 61 | // trigger what triggered the interrupt (eg. 'rise'). This is really only 62 | // useful for the 'change' mode 63 | function someFunc(time, trigger) {} 64 | ``` 65 | 66 | ## Stop watching a single event: 67 | ```.js 68 | 69 | // Remove one callback. 70 | // If it's the only callback, then this interrupt mode will be disabled. 71 | pin.removeListener('change', someFunc); 72 | 73 | // OR 74 | 75 | // Remove all listeners for the pin, effectively freeing the interrupt 76 | // if this was the only mode we're listening for 77 | pin.removeAllListeners('change'); 78 | ``` 79 | 80 | ## Watch For Multiple Modes 81 | ```.js 82 | 83 | // Watch for the fall event 84 | pin.on('fall', someFunc(){}); 85 | 86 | // AND 87 | 88 | // Watch for the high event 89 | pin.once('high', someOtherFunc(){}); 90 | 91 | // The fall event is still being listened for 92 | pin.removeListener('high', someOtherFunc); 93 | ``` 94 | 95 | ## Remove All Listeners 96 | ```.js 97 | // This is guaranteed to free all the listeners on a pin and make the interrupt 98 | // available for a different use. 99 | pin.removeAllListeners(); 100 | ``` 101 | ## Removing Change Events 102 | ```.js 103 | 104 | pin.once('low', someFunc(){}); 105 | 106 | pin.on('change', someOtherFunc(){}); 107 | 108 | // Does NOT remove the `'low'` listener 109 | pin.removeAllListeners('change'); 110 | 111 | ``` 112 | ## Out of Interrupts 113 | In the case that seven interrupts have already been assigned, Tessel will check to see if there are any interrupts available and, if not, will execute the Error Routine (see Error Routine below). 114 | ```.js 115 | 116 | // Assume seven interrupts already assigned 117 | pin.on('error', function(err) { 118 | console.log('ERR': err); 119 | } 120 | pin.on('fall', function(err) {}); 121 | 122 | // Also `console.warn` "WARNING: Attempt to use more than the seven available interrupts" 123 | ``` 124 | 125 | `tessel. getRemainingInterrupts(callback)` will return the number of gpio interrupts remaining. 126 | 127 | ## Error Routine 128 | There are two reasons for a pin interrupt registration to fail: 129 | * `on` was called with a level interrupt mode 130 | * Another interrupt attempted to register after all seven interrupts were registered. 131 | 132 | In these cases, another interrupt will not be registered. If there is an `error` listener for the pin, an `error` event will be emitted. If not, an Error will be immediately thrown. 133 | -------------------------------------------------------------------------------- /tutorials/make-external-hardware-library.md: -------------------------------------------------------------------------------- 1 | # Making a Tessel-style Library for Third-Party Hardware 2 | 3 | There's a lot of existing hardware from Seeed, Adafruit, and elsewhere that can be used with Tessel. Though it's not that difficult to hack together a project based on the hardware API docs, making an npm module for the hardware is a nice way to interface cleanly with the hardware, and reuse a custom API across projects. 4 | 5 | This tutorial walks you through the process to go from a piece of hardware to a Tessel-style npm module. 6 | 7 | For this tutorial, I used a [PIR motion detector from Adafruit](http://www.adafruit.com/products/189) to make [this npm module](https://www.npmjs.org/package/pir). 8 | 9 | ## Understanding your hardware 10 | Before you start, it would be a good idea to check out Tessel's [hardware docs](https://github.com/tessel/hardware) and [hardware api docs](https://github.com/tessel/t1-docs/blob/master/hardware-api.md). These two documents will give you a good idea of Tessel's capabilities and available interfaces. 11 | As a general rule, anything that can be used with an Arduino can also be used with a Tessel. Tessel reads in a maximum of 3.3V, so if your part outputs more than that, don't fry the board! 12 | 13 | Tessel can: 14 | 15 | * Read and write digital signals (3.3V when high; 0V when low) 16 | * Write PWM signals ("duty cycles") 17 | * Read analog signals 18 | * Communicate over SPI (MISO, MOSI, and SCK) 19 | * Communicate over I2C (SDA and SLC) 20 | * Communicate over UART (TX and RX) 21 | * Provide 5V power* (if Tessel is powered over USB. Please see [Powering Tessel](https://github.com/tessel/hardware/blob/master/powering-tessel.md)) 22 | * Provide 3.3V power (a digital pin set to output(1) (high)) 23 | 24 | For the PIR sensor, I needed one 3.3V digital signal pin and 5V of power. It will typically say what you need on the manufacturer's page, straight out or on a datasheet. Adafruit typically says these things in the [description field](http://www.adafruit.com/products/189#description-anchor) of a product page, as does [Seeed](http://www.seeedstudio.com/depot/PIR-Motion-sensor-module-p-74.html). 25 | 26 | ## Setting up the repo 27 | Tessel's modules all have the same basic directory. You can see a template for Tessel modules in general on our style guide [here](https://github.com/tessel/style/tree/master/Templates). 28 | You might want to check out the PIR repo set up for development [here](https://github.com/Frijol/PIR/tree/51ce84784f09902868e67f8a6c8e0270c85eb6cb). 29 | 30 | Here are notes on some of the key files: 31 | 32 | ###index.js ([template](https://github.com/tessel/style/blob/master/Templates/index.js)) 33 | This file is the driver for the hardware. Here's the basic setup: 34 | 35 | * Require util and the event emitter, along with any other dependencies. These let you write event-driven APIs. 36 | * Make a constructor function that instantiates the hardware as an object. Its two arguments are "hardware" and a callback. The function should emit a "ready" event that returns the object when it is ready. For the PIR, it's "ready" as soon as the object is instantiated. For something more complex, e.g. the Ambient module, it's not "ready" until it verifies that it has the correct firmware version. 37 | * `hardware` specifies where the hardware is connected to Tessel. For modules, it's a port. For external hardware, this will most likely be a port and a pin (e.g. tessel.port['GPIO'].pin['A3']). You should probably also add error handling in case the wrong hardware type is passed in (e.g. just a port when you need a pin) or for specification of the wrong type of pin (you can see which pins are digital, analog and PWM in the examples [here](https://github.com/tessel/t1-docs/blob/master/hardware-api.md#pins)). You can check the [PIR code](https://github.com/Frijol/PIR/blob/master/index.js) for examples of this error handling. 38 | * `callback(err, obj)` should return an error if there are any errors connecting, or if there are no errors, should return the object as its second argument. 39 | * Functions: this is the fun part! What do you want as the API for your hardware? What's useful? What do you want to expose? 40 | For the PIR motion detector, I only have one function, which reads the pin. Most of the useful information is better exposed as events for "movement", "stillness", and "change". 41 | * use function: The standard require for a Tessel module is require('module').use(tessel.port['PORT']). The "use" function takes hardware specification and a callback, and passes them to the object constructor. 42 | * exports: Export the object function and the use function. 43 | 44 | ###package.json ([template](https://github.com/tessel/style/blob/master/Templates/package.json)) 45 | Use `npm init` to generate most of this file. 46 | 47 | Other items of note: 48 | 49 | * You do not need the `tessel` npm package as a dependency. 50 | * Add a "hardware" section. By default, Tessel pushes the entire directory so that any dependencies are included. With a "hardware" section, you can specify files and folders to ignore when pushing to embedded devices. For our modules, we list "./test" and "./examples". 51 | 52 | ###examples folder ([template](https://github.com/tessel/style/tree/master/Templates/examples)) 53 | You need at least one example. This should show basic functionality of the hardware. [Mine](https://github.com/Frijol/PIR/blob/master/examples/pir.js) waits for a ready event, then logs a message on the emission of "movement" and "stillness" events. 54 | When you require the module, refer to '../' rather than the module name. 55 | 56 | ###test folder ([template](https://github.com/tessel/style/tree/master/Templates/test)) 57 | We use the node module "tinytap" for testing. Every functionality that can be tested without physical interaction should be testable with `tessel run test/*.js`. 58 | 59 | ###README.md ([template](https://github.com/tessel/style/blob/master/module_RM_template.md)) 60 | Your readme is your documentation. For consistency with Tessel modules, check out the template. We use the node module "marktype" to make pretty, linkable API documentation. 61 | 62 | ## Connecting your hardware to Tessel 63 | 64 | Connect your hardware based on the [hardware](https://github.com/tessel/hardware/blob/master/tessel-hardware-overview.md#pins-and-ports) and [API](https://github.com/tessel/t1-docs/blob/master/hardware-api.md#pins) documentation. 65 | Instructions for establishing SPI/UART/I2C are part of the API docs. 66 | 67 | At the top of your README, write which pins should be connected to which between the Tessel and the external hardware. 68 | A picture of the setup would also be useful to include in the README. 69 | 70 | ## Establishing communication 71 | 72 | Set up something basic to make sure you can connect to the sensor. 73 | I like to start with example code: require Tessel, read the pin, see what kind of values we get. 74 | 75 | If you're working with more complex hardware, you might need to wake up the hardware with a wakeup sequence. This sort of thing will be documented in the part's datasheet. 76 | 77 | If there is existing Arduino code for the hardware, this can be a good starting point to poke around and get an understanding of how to interface with the device. 78 | 79 | ## Writing an API 80 | 81 | Once you're able to connect and get some basic functionality out of the device, start writing your API. 82 | 83 | Start with the object constructor and the `use` function in your index.js file. Make sure you can require the hardware and have it connect. 84 | 85 | Now, draft up your API. How might people want to interface with this piece of hardware? How can you make it intuitive? If you'd like feedback on a proposed API, feel free to post it to [the forums](https://forums.tessel.io). 86 | 87 | As a general rule, top priority is intuitive interaction. Second priority is exposing as much as you can. 88 | 89 | ## Writing tests 90 | 91 | Write tests as you go. 92 | 93 | * Initializing the object should callback the object, return the object, and emit the object as a ready event. 94 | * Super thorough tests check to make sure errors are emitted when they should be. 95 | 96 | ## Writing an example 97 | 98 | The example named `.js` should be a simple "is it working" example. 99 | 100 | Feel free to write other examples to show off different uses of the hardware and the API you've built! 101 | 102 | ## Writing the docs 103 | 104 | Please follow the template formatting [here](https://github.com/tessel/style/blob/master/module_RM_template.md) to write your README. 105 | 106 | Document every method, event, and property. 107 | 108 | Complete documentation is important! If you don't document a method, most people will never realize that method exists. 109 | 110 | ## Publishing 111 | Publish your module to npm! If you've never done that, [this](https://gist.github.com/coolaj86/1318304) is a good tutorial. Be sure to include 'tessel' in the keywords of your package.json so that people can find it! 112 | 113 | Other places you might want to publish as well: 114 | 115 | * [This list of tools to use with Tessel](https://github.com/tessel/t1-docs/blob/master/tools.md) 116 | * [Tessel's forums](https://forums.tessel.io/) 117 | * [The Tessel projects page](//tessel.io/projects) 118 | -------------------------------------------------------------------------------- /tutorials/multi-module.md: -------------------------------------------------------------------------------- 1 | # Multiple Modules 2 | 3 | Plug in multiple modules to your Tessel for more interactions! 4 | 5 | Put the BLE and Accelerometer Modules together for an activity tracking app, 6 | or a Climate Module and a Relay Module together to build an internet-connected thermostat. 7 | Or maybe you're getting creative with the RFID, Servo, and Ambient modules all at once. 8 | 9 | 10 | Whatever you're making, here are some tips for working with multiple modules on Tessel. 11 | 12 | ## Loading multiple modules 13 | 14 | We recommend you use the community-created npm package tesselate. 15 | This package loads all of your modules and returns them as an object when they're all ready. 16 | Check out its usage docs here. 17 | 18 | For example, if you wanted to build something involving climate and relay, with `tesselate`, it might look like this: 19 | 20 | ```js 21 | require('tesselate') ({ 22 | modules: { 23 | A: ['relay-mono', 'relay'], 24 | B: ['climate-si7020', 'climate'] 25 | } 26 | }, function (tessel, modules) { 27 | // Function called when all modules are ready 28 | var relay = modules.relay; 29 | var climate = modules.climate; 30 | // Do something with relay and climate 31 | }); 32 | ``` 33 | 34 | ### Why use tesselate? What if I don't want to? 35 | 36 | You may have noticed that each module example tells you to wait for an on('ready') event. 37 | This ensures your code doesn't run before the hardware has acknowledged that it is powered on and ready to go. 38 | 39 | However, when you use multiple modules, waiting for ready events can cause a race condition if you're not careful. 40 | 41 | You might be tempted to write something like this: 42 | 43 | ```js 44 | var tessel = require('tessel'); 45 | var relay = require('relay-mono').use(tessel.port['A']); 46 | var climate = require('climate-si7020').use(tessel.port['B']); 47 | 48 | relay.on('ready', function () { 49 | climate.on('ready', function () { 50 | // Do something with relay and climate 51 | }); 52 | }); 53 | ``` 54 | 55 | And it might work! But only if the climate module's ready event occurs after the relay module's event. 56 | 57 | This is exactly the sort of async problem Node programmers run into all the time, and **your bonus challenge** is to figure out how to make this work consistently. 58 | 59 | But if you'd rather skip the exercise, tesselate is a nifty little solution. 60 | 61 | *Now make something and post about it on the Projects Page!* 62 | -------------------------------------------------------------------------------- /tutorials/raw-spi.md: -------------------------------------------------------------------------------- 1 | ## Spi Locks and Raw Transfers 2 | 3 | For most applications, the typical spi transfer method is ideal: 4 | ```.js 5 | spi.transfer(someData, function(err, receivedData) { 6 | ... 7 | }); 8 | ``` 9 | 10 | But occasionally, a finicky piece of hardware will require very specific timing on SPI communication. Specifically, it may want to have full control over the SPI bus. 11 | 12 | Most hardware APIs don't use asynchronous JavaScript so they don't have this fun challenge. We pity them. 13 | 14 | Each module port on Tessel shares the same SPI CLK, MISO, and MOSI lines. Unique GPIOs on each port are used as chip selects so peripherals know when they are being addressed. However, some hardware may not use a chip select pin or it may have some other reason that it needs the SPI Bus to remain perfectly calm except when talking to it. 15 | 16 | For that reason, we've have a locking implementation. A SPI Lock will retain control of the SPI Bus so you can immediately transfer whatever data needs to be transfered and all requests from other ports will be queued until the lock is released. 17 | 18 | As an example, let's say we have a module on port A that needs all of it's communication to be done in a lock. We would do it like so: 19 | 20 | ```.js 21 | var tessel = require('tessel'); 22 | var spi = tessel.port['A'].SPI(); 23 | 24 | function SPITransfer(data, callback) { 25 | 26 | // Request a lock 27 | // Callback called when lock received 28 | spi.lock(function(err, lock) { 29 | 30 | // Complete the transfer (skips the entire queue) 31 | lock.rawTransfer(data, function(err, rxdata) { 32 | 33 | // Release the lock when you're done 34 | lock.release( function() { 35 | 36 | // Call the callback with return data 37 | callback(err, rxdata); 38 | }); 39 | }); 40 | }); 41 | } 42 | ``` 43 | 44 | Locks queue on top of each other as well so you can have locks waiting for locks waiting for locks. Use them wisely. 45 | -------------------------------------------------------------------------------- /tutorials/untethered.md: -------------------------------------------------------------------------------- 1 | # Running Tessel from a Battery 2 | Tessel can be unplugged from your computer and powered from alternative power sources, like a USB battery. 3 | 4 | ## Deploying Code to Tessel 5 | 6 | While Tessel is connected to the computer, you can push code into Tessel's Flash memory with the following command: 7 | 8 | ```sh 9 | tessel push script.js 10 | ``` 11 | (Try it with blinky.js from [here](http://start.tessel.io/blinky) if you just want to test it out.) 12 | 13 | Once the push command completes, you can disconnect Tessel from your computer and connect it to a different power source. 14 | 15 | *(You can read more about pushing vs running code on Tessel [here](http://start.tessel.io/usage).)* 16 | 17 | ## Powering Tessel 18 | 19 | For the simplest power solution, all you need is a USB charger of some kind: 20 | 21 | 22 | 23 | 24 | *USB battery* | *USB wall adapter* 25 | 26 | (There are various other ways to power your Tessel as well. You can read about them [here](https://github.com/tessel/hardware/blob/master/powering-tessel.md).) 27 | 28 | Once you've pushed your code to Tessel's Flash, plug in your Tessel to power. 29 | 30 | Tessel should boot up and immediately start running your code. 31 | 32 | *Make something cool? Show it off on the [Projects Page](//tessel.io/projects)!* 33 | -------------------------------------------------------------------------------- /tutorials/usb_messages/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /tutorials/usb_messages/device/index.js: -------------------------------------------------------------------------------- 1 | // Any copyright is dedicated to the Public Domain. 2 | // http://creativecommons.org/publicdomain/zero/1.0/ 3 | 4 | // The `tessel` module built-in to the Tessel firmware for access to hardware 5 | var tessel = require('tessel'); 6 | 7 | //When a message is received from the computer, this event triggers. 8 | process.on('message', function(msg) { 9 | console.log("[Tessel] Message from PC:", msg); 10 | }); 11 | 12 | var counter = 0; 13 | 14 | // Every 5 seconds... 15 | setInterval(function() { 16 | // Send a message to the computer 17 | process.send({count: counter++}); 18 | }, 5000); 19 | 20 | // Keep the event loop alive 21 | process.ref(); -------------------------------------------------------------------------------- /tutorials/usb_messages/device/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "usb_messages", 3 | "version": "0.0.0", 4 | "description": "Tessel USB communication example", 5 | "main": "host.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tessel/docs" 12 | }, 13 | "author": "Technical Machine", 14 | "license": "Public Domain", 15 | "bugs": { 16 | "url": "https://github.com/tessel/docs/issues" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tutorials/usb_messages/host.js: -------------------------------------------------------------------------------- 1 | // Any copyright is dedicated to the Public Domain. 2 | // http://creativecommons.org/publicdomain/zero/1.0/ 3 | 4 | // When we `require('tessel')` here, this is the library out of `node_modules` 5 | // for USB communication. It's not the same as the `tessel` module built into 6 | // the Tessel firmware that code on the Tessel uses for hardware access -- 7 | // that's only available to JS that executes on the Tessel itself. 8 | var tessel = require('tessel'); 9 | 10 | var script = require.resolve('./device/index.js'); 11 | 12 | var opts = { 13 | // Stop existing script, if any 14 | stop: true, 15 | // Serial number (`undefined` picks the first one) 16 | serial: process.env.TESSEL_SERIAL, 17 | }; 18 | 19 | var args = []; 20 | 21 | // `tessel.findTessel` finds a Tessel attached to this computer and connects. 22 | tessel.findTessel(opts, function(err, device) { 23 | if (err) throw err; 24 | 25 | // Once we've found a Tessel, we tell it to run our script. This works just 26 | // like `tessel run` and bundles the `device/` directory. It bundles only 27 | // `device/` and not the host code because `device/` has its own 28 | // `package.json`. 29 | device.run(script, args, {}, function () { 30 | // Connect the stdout and stderr of the process running on Tessel to 31 | // the console, so that our `console.log` messages show. 32 | device.stdout.resume(); 33 | device.stdout.pipe(process.stdout); 34 | device.stderr.resume(); 35 | device.stderr.pipe(process.stderr); 36 | 37 | var count = 0; 38 | 39 | // `device.send(msg)` sends an object to Tessel. It supports JSON 40 | // compatible objects as messages, with the addition that `Buffer`s, 41 | // `Date`s and cyclic data structures are also handled properly. 42 | setInterval(function(){ 43 | device.send({count:count++, data: {obj: 'demo'}}) 44 | }, 4000); 45 | 46 | // `device.on('message', function (msg) { ... })` receives an event 47 | // when an object is received from Tessel. 48 | device.on('message', function (m) { 49 | console.log('[PC] Message from Tessel:', m); 50 | }); 51 | 52 | // Exit cleanly on Ctrl+C. 53 | process.on('SIGINT', function() { 54 | // Try to stop the process on the Tessel 55 | device.stop(); 56 | 57 | setTimeout(function () { 58 | // But if that fails, just exit 59 | logs.info('Script aborted'); 60 | process.exit(131); 61 | }, 200); 62 | }); 63 | 64 | // When the script on Tessel exits, shut down 65 | // USB communications and exit 66 | device.once('script-stop', function (code) { 67 | device.close(function () { 68 | process.exit(code); 69 | }); 70 | }); 71 | }); 72 | }); -------------------------------------------------------------------------------- /tutorials/usb_messages/multi_host.js: -------------------------------------------------------------------------------- 1 | // Any copyright is dedicated to the Public Domain. 2 | // http://creativecommons.org/publicdomain/zero/1.0/ 3 | 4 | // This is a demo of programtically checking multiple tessels hooked 5 | // up to the same computer. 6 | 7 | // When we `require('tessel')` here, this is the library out of `node_modules` 8 | // for USB communication. It's not the same as the `tessel` module built into 9 | // the Tessel firmware that code on the Tessel uses for hardware access -- 10 | // that's only available to JS that executes on the Tessel itself. 11 | var tessel = require('tessel'); 12 | var async = require('async'); 13 | 14 | var script = require.resolve('./device/index.js'); 15 | 16 | // list all Tessels attached to this computer 17 | tessel.listDevices(function(err, devices){ 18 | if (err) throw new Error(err); 19 | 20 | // the devices object consists of the usb descriptor, 21 | // the serial number, and the version info of the Tessel 22 | 23 | var funcQueue = []; 24 | var count = 0; 25 | devices.forEach(function(device){ 26 | console.log("Found device", device.serialNumber); 27 | funcQueue.push(function(callback){ 28 | loadCode(device.serialNumber, function(){ 29 | callback(null); 30 | }); 31 | }) 32 | }) 33 | 34 | async.waterfall(funcQueue, function(err, res){ 35 | console.log('Done loading code'); 36 | }); 37 | }) 38 | 39 | 40 | function loadCode(serialNumber, next){ 41 | var opts = { 42 | // Stop existing script, if any 43 | stop: true, 44 | // Serial number 45 | serial: serialNumber, 46 | }; 47 | 48 | var args = []; 49 | 50 | // `tessel.findTessel` finds a Tessel attached to this computer and connects. 51 | tessel.findTessel(opts, function(err, device) { 52 | if (err) throw err; 53 | 54 | // Once we've found a Tessel, we tell it to run our script. This works just 55 | // like `tessel run` and bundles the `device/` directory. It bundles only 56 | // `device/` and not the host code because `device/` has its own 57 | // `package.json`. 58 | device.run(script, args, {}, function () { 59 | // Connect the stdout and stderr of the process running on Tessel to 60 | // the console, so that our `console.log` messages show. 61 | device.stdout.resume(); 62 | device.stdout.pipe(process.stdout); 63 | device.stderr.resume(); 64 | device.stderr.pipe(process.stderr); 65 | 66 | var count = 0; 67 | console.log('device initial', device.serialNumber); 68 | // `device.send(msg)` sends an object to Tessel. It supports JSON 69 | // compatible objects as messages, with the addition that `Buffer`s, 70 | // `Date`s and cyclic data structures are also handled properly. 71 | setInterval(function(){ 72 | console.log("device", device.serialNumber); 73 | device.send({count:count++, data: {obj: 'demo'}}) 74 | }, 4000); 75 | 76 | // `device.on('message', function (msg) { ... })` receives an event 77 | // when an object is received from Tessel. 78 | device.on('message', function (m) { 79 | console.log('[PC] Message from Tessel:', m); 80 | }); 81 | 82 | // Exit cleanly on Ctrl+C. 83 | process.on('SIGINT', function() { 84 | // Try to stop the process on the Tessel 85 | device.stop(); 86 | 87 | setTimeout(function () { 88 | // But if that fails, just exit 89 | logs.info('Script aborted'); 90 | process.exit(131); 91 | }, 200); 92 | }); 93 | 94 | // When the script on Tessel exits, shut down 95 | // USB communications and exit 96 | device.once('script-stop', function (code) { 97 | device.close(function () { 98 | process.exit(code); 99 | }); 100 | }); 101 | 102 | next(); 103 | 104 | }); 105 | }); 106 | } 107 | -------------------------------------------------------------------------------- /tutorials/usb_messages/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "usb_messages", 3 | "version": "0.0.0", 4 | "description": "Tessel USB communication example", 5 | "main": "host.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tessel/docs" 12 | }, 13 | "author": "Technical Machine", 14 | "license": "Public Domain", 15 | "bugs": { 16 | "url": "https://github.com/tessel/docs/issues" 17 | }, 18 | "dependencies": { 19 | "tessel": "~0.3.9", 20 | "async": "~0.9.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tutorials/usb_messages/readme.md: -------------------------------------------------------------------------------- 1 | # USB communication between Tessel and Node on your PC 2 | 3 | In addition to loading code, you can also use the USB connection to Tessel to pass data between your Tessel and Node.js on your PC. Combine your Tessel's easy access to hardware and your computer's processing power to do things neither device can do alone. 4 | 5 | Messages are JavaScript objects. It uses [structured clone](https://github.com/tcr/structured-clone), which beyond JSON, supports cyclic structures and `Buffer`, `RegExp`, and `Date` objects. 6 | 7 | We've built an example for you to expand on: 8 | 9 | ``` 10 | git clone https://github.com/tessel/docs.git 11 | cd docs/tutorials/usb_messages 12 | npm install 13 | node host.js 14 | ``` 15 | The directory structure looks like: 16 | 17 | ``` 18 | ./ 19 | /host.js -- script that runs on the computer 20 | /package.json 21 | /node_modules -- npm modules for the computer 22 | /tessel -- the Tessel host-side USB module 23 | /device -- this entire directory will be deployed to Tessel 24 | /package.json 25 | /node_modules -- all the libs that run ON Tessel go here (camera, ambient, IR, etc.) 26 | /device.js -- the main script that runs on Tessel 27 | -- other JS files for Tessel go here 28 | ``` 29 | 30 | Both Tessel and Node run JS, but you don't want all your host-side code on the Tessel. The host and device each have their own `node_modules` for npm packages. Only `devices/` is sent to the Tessel, because it has its own `package.json`. 31 | 32 | The `tessel` command line tool functionality is also exposed as a library. 33 | `host.js` uses that library to take the place of `tessel run`, and not only 34 | deploys your code to the Tessel, but also communicates with it. 35 | 36 | The Tessel code, `device/index.js`, simply demonstrates sending and receiving messages. 37 | 38 | To try this example, run `node host.js`. It sends the device-side code on the Tessel as it starts. 39 | 40 | ## Multiple Tessels on one computer 41 | **Note only works on Linux & Mac due to Windows hotplug issues** 42 | 43 | This deploys the same script to multiple Tessels and listens for output from each one. 44 | 45 | ``` 46 | git clone https://github.com/tessel/docs.git 47 | cd docs/tutorials/usb_messages 48 | npm install 49 | node multi_host.js 50 | ``` 51 | -------------------------------------------------------------------------------- /wifi.md: -------------------------------------------------------------------------------- 1 | #Connect Tessel to Wifi 2 | Tessel has Wifi built into the main board ([CC3000](http://www.ti.com/lit/ds/symlink/cc3000.pdf)). 3 | 4 | ##Connecting to a network 5 | 6 | Tessel can only connect to 802.11b/g networks using channels 1 through 11. The Wifi chip does not support 802.11n or channels 12 - 14. If you are having trouble connecting, make sure the router has b/g mode enabled and isn't using channels 12, 13, or 14. 7 | 8 | To connect to a new network, enter in your command line (without brackets) 9 | 10 | ```.sh 11 | tessel wifi -n [network name] -p [password] -s [security type*] 12 | ``` 13 | 14 | The security type flag is optional; default is wpa2. 15 | 16 | 17 | Tessel is connected to Wifi when the yellow status light is on. Tessel saves network credentials and tries to reconnect automatically on startup- the yellow light blinks, and then either goes steady (connected) or turns solid red (failed to connect). 18 | 19 | You can run `tessel wifi -l` to see connection status and the IP address of your Tessel. 20 | 21 | 22 | 23 | ##Wifi Commands 24 | ```sh 25 | tessel wifi -n -p [-s ] 26 | ``` 27 | Connects to wifi 28 | 29 | ```sh 30 | tessel wifi -n 31 | ``` 32 | Connects to a wifi network without a password 33 | 34 | ```sh 35 | tessel wifi -l 36 | ``` 37 | See current wifi status 38 | 39 | ```sh 40 | tessel wifi -d 41 | ``` 42 | Disconnect from any currently connected network and forget the credentials 43 | 44 | ##Example 45 | Here is an example of requesting a website over Tessel's Wifi connection: 46 | 47 | Save the following code in a file called wifi.js: 48 | 49 | ```js 50 | var http = require('http'); 51 | 52 | var statusCode = 200; 53 | var count = 1; 54 | 55 | setImmediate(function start () { 56 | console.log('http request #' + (count++)) 57 | http.get("http://httpstat.us/" + statusCode, function (res) { 58 | console.log('# statusCode', res.statusCode) 59 | 60 | var bufs = []; 61 | res.on('data', function (data) { 62 | bufs.push(new Buffer(data)); 63 | console.log('# received', new Buffer(data).toString()); 64 | }) 65 | res.on('close', function () { 66 | console.log('done.'); 67 | setImmediate(start); 68 | }) 69 | }).on('error', function (e) { 70 | console.log('not ok -', e.message, 'error event') 71 | setImmediate(start); 72 | }); 73 | }); 74 | ``` 75 | 76 | Run the code on your Tessel by typing this in the terminal: 77 | 78 | ```sh 79 | tessel run wifi.js 80 | ``` 81 | Watch Tessel ping the website in your console! 82 | 83 | 84 | ##Connecting to Wifi from JS 85 | Access Wifi from JS, including connection/dropping events, SmartConfig settings, WLAN settings, and finding available networks. 86 | 87 | Access through: 88 | 89 | ```js 90 | var wifi = require('wifi-cc3000'); 91 | ``` 92 | 93 | ###Methods: 94 | 95 | # wifi.connect( wifiSettings, [callback(err, res)] ) 96 | Connects to an access point. Takes in an optional callback. The `connected`, `disconnected`, and `timeout` events are emitted. Returns the wifi object. 97 | 98 | If there is already another wifi connection being initialized (from the command line, for example), this will error out immediately. 99 | 100 | `wifiSettings` is an object that consists of: 101 | 102 | ```js 103 | { ssid: // this can either be a string or a buffer 104 | , password: // this can either be a string or a buffer. Use a buffer if you need to pass in hex. 105 | , security: defaults to wpa2 106 | , timeout: defaults to 20s 107 | } 108 | ``` 109 | 110 | `res` contains the following: 111 | 112 | ```js 113 | res.ip; 114 | res.gateway; 115 | res.dns; 116 | res.ssid; 117 | res.macAddress; // not exposed yet, will add this when we add firmware support for mac address 118 | ``` 119 | 120 | # wifi.isConnected() 121 | Returns `true` if connected, `false` if not connected. 122 | 123 | # wifi.isBusy() 124 | Returns `true` if the CC3k is currently trying to connect/disconnect. Recommended to wait until the CC3k is not busy before issuing commands. After a request has been made to initiate a connection, the CC3k will be "busy" until it receives a connect or a disconnect call. However, sometimes the CC3k never gets a callback (usually more common with weak wifi strength). It's up to the user to decide whether or not to timeout and ignore the `isBusy`. 125 | 126 | # wifi.connection() 127 | Returns the details of the connection object or null if not connected. Connection object is the same as the result in `wifi.connect` 128 | 129 | # wifi.reset( [callback] ) 130 | Returns the wifi object. Does a software reset of the wifi chip. Useful for forcing a fastConnect on boot. Callback is optional. 131 | 132 | # wifi.disable( [callback] ) 133 | Returns the wifi object. Turns off the wifi chip. Saves on power. Callback is optional. 134 | 135 | # wifi.enable( callback ) 136 | Returns the wifi object. Turns on the wifi chip. 137 | 138 | # wifi.disconnect( callback ) 139 | Disconnects from the network. 140 | 141 | # wifi.isEnabled() 142 | Returns `true` if the CC3k is enabled (powered on, regardless of connection status). Returns `false` if the CC3k is powered off. 143 | 144 | ####Events 145 | 146 | # wifi.on( 'connect', callback(res) ) 147 | Event emitted on connection. `res` contains the following: 148 | 149 | ```js 150 | res.ip; 151 | res.gateway; 152 | res.dns; 153 | res.ssid; 154 | res.macAddress; // will add when its exposed in firmware 155 | ``` 156 | 157 | # wifi.on( 'disconnect', callback(err) ) 158 | Called when wifi drops. 159 | 160 | # wifi.on( 'timeout', callback(err) ) 161 | Called when the CC3k times out after the `.connect` call. 162 | 163 | # wifi.on( 'error', callback(err) ) 164 | The `error` event will be called for any of the following actions: 165 | 166 | 1. tried to disconnect while not connected 167 | 2. tried to disconnect while in the middle of trying to connect 168 | 1. tried to initialize a connection without first waiting for a timeout or a disconnect 169 | 170 | ##Debugging 171 | * Check to see if Tessel is connected to wifi with `tessel wifi -l`. If there is no IP address, you are not connected to Wifi. Try power cycling your Tessel and then run the tessel wifi connection command again. 172 | * Move closer to the router. 173 | * Make sure the router has b/g mode enabled and isn't using channels 12, 13, or 14. 174 | 175 | If you're still having trouble, please log your error on the [Wifi forums](http://forums.tessel.io/category/wifi). 176 | --------------------------------------------------------------------------------