• You Probably Don’t Need an iBeacon

    Friday, August 8, 2014

    8/8/2014– Evan Simpson

    First, a quick background on Bluetooth

    You might remember a time when the word Bluetooth was synonymous with hands-free headsets and wireless speakers. These devices gave Bluetooth a bad reputation with their poor sound quality, poor battery life, and poor interface for connecting to cell phones and computers. Since then, however, Bluetooth has come a long way, seeing huge improvements in device quality, as well as a much greater level of support in mobile and desktop operating systems.

    Back in 2010, the Bluetooth Special Interest Group (SIG) put out the 4.0 specification for Bluetooth. The goal of the new specification was to enable the creation of Bluetooth devices which operate at a low data rate, have low power consumption, and have low manufacturing costs. This was a departure from the existing specification, which had been optimized over the years for always-open, high data-rate streams. This old standard was great for applications like streaming audio, but not for others such as reading data from sensors.

    The new specification is designed for devices that only needed to connect occasionally to exchange small pieces of information, and can be put into a low power state in between exchanges. This mode of operation means big power savings for devices, to the extent that some Bluetooth 4.0 devices can be powered by a coin cell battery for months to years at a time, depending on the application. In the past few years, Bluetooth 4.0 has been rebranded as Bluetooth Smart by the SIG, but is now more colloquially known as Bluetooth Low Energy, or BLE.

    Enter Apple

    Though the specification came out over 4 years ago now, BLE has only much more recently seen mainstream adoption into connected devices. Arguably, one of the greatest contributors to BLE’s popularity has been Apple. By looking at Google search trends, we can see a surge in interest for “Bluetooth 4.0” in October of 2011, right around the time the iPhone 4S was released with support for, you guessed it, Bluetooth 4.0. In being the first big player to support the technology, Apple paved the way for other device manufacturers to support BLE, by giving them a central device to connect to. For comparison, the Android SDK didn’t have any support for BLE until late 2013 and will not have complete support for everything BLE can do until the release of Android L, and Windows Phone only began official support for BLE with this year’s 8.1 update.

    Google Search trends for “Bluetooth 4.0”

    Google Search trends for “Bluetooth 4.0”

    More recently though, Apple has released a specification for creating location based services with BLE devices, under the brand iBeacon. iBeacons have become popular enough and we get enough questions about them that it warrants clarifying what they are, how they work, and how they are different from other BLE devices.

    What is an iBeacon?

    Part of the Bluetooth 4.0 specification outlines a format for an “advertising data packet” which is a small amount of data (maximum 32 bytes) that a BLE device can publicly broadcast to any other nearby devices, without needing to connect. The primary use for the advertisement is for a device to advertise the kind of services or data it provides, information on how to connect to it, or the device’s name. However, the format specification does allow for some of the data available on the device to be broadcast as well, so other devices don’t have to make a connection in order to collect sensor data. When a BLE device is designed to put all of the data other devices might need in the advertisement, it is typically called a “beacon” - all information is out-going.

    At their most basic, iBeacons can be seen as a proprietary beacon, where they make use of the specification’s allowance for “Manufacturer Specific Data”, which can contain any arbitrary data that will fit. Apple defined their own format for a single location code to be contained in this section of an advertisement. Any other nearby BLE device (such as a smart phone) can then pick up the advertisement and parse out the location code.

    iBeacons are deceptively simple to create, because they only require a BLE radio chip (almost any BLE radio chip will do) and don’t require any application-specific software to run on the device itself. It is up to the application running on the discovering device to know what to do with the location code pre-programmed on the iBeacon. This means that any device which implements the BLE specification can function as what Apple has trademarked an iBeacon. The actual capabilities of an iBeacon are minimal, with their utility lying in the applications people create around them.

    The unfortunate side effect of the popularity of iBeacons is that they have become synonymous with BLE to many people, in much the same way that Bluetooth used to be synonymous with hands-free headsets. One thing I’ve seen all too often is products like Tile and Bean being referred to as iBeacons (although the Bean does allow you to set it up as an iBeacon, it isn’t by default). Not only has this led to a lot of confusion for people trying to get started prototyping with BLE, but it has also resulted in a sort of “bandwagon” effect, where people trying to design systems around iBeacons in order to take advantage of the brand power, but for applications where an iBeacon maybe isn’t appropriate. It means that much of what BLE is capable of is being overlooked, and that’s not to mention other means of wireless communication which might be appropriate in certain applications as well (but we can save that discussion for another time).

    So how does Technical Machine’s BLE module fit in with all of this? Our BLE module allows you full control over the advertisement data, making it easy to set up an iBeacon, or design a beacon format of your own. If you’re looking into an open alternative location service format without the licensing hurdles Apple has for iBeacons, check out AltBeacon. If you want your device to be more than a beacon, the BLE module gives you access to all of the functionality outlined in the 4.0 specification, so you can interact with any other BLE device.

    If you want to learn more about how BLE works, and how to get started making BLE connected devices, check out our Getting Started Guide.

    #iBeacon #tessel #BLE #Bluetooth #Bluetooth Low Energy #evan simpson #technical machine #data #IoT #Bluetooth Smart #Bluetooth 4.0

  • Making a Tessel-style Library for Third-Party Hardware

    Thursday, August 7, 2014

    8/7/2014– Kelsey Breseman

    Find this document on Tessel’s docs repo, where it will be kept up to date.

    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.

    I’ve so far done this with a PIR motion detector and a pulse sensor:

    This tutorial walks you through the process to go from a piece of hardware to a Tessel-style npm module.

    For this tutorial, I used a PIR motion detector from Adafruit to make this npm module.

    Understanding your hardware

    Before you start, it would be a good idea to check out Tessel’s hardware docs and hardware api docs. These two documents will give you a good idea of Tessel’s capabilities and available interfaces. 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!

    Tessel can:

    • Read and write digital signals (3.3V when high; 0V when low)
    • Write PWM signals (“duty cycles”)
    • Read analog signals
    • Communicate over SPI (MISO, MOSI, and SCK)
    • Communicate over I2C (SDA and SLC)
    • Communicate over UART (TX and RX)
    • Provide 5V power* (if Tessel is powered over USB. Please see Powering Tessel)
    • Provide 3.3V power (a digital pin set to output(1) (high))

    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 of a product page, as does Seeed.

    Setting up the repo

    Tessel’s modules all have the same basic directory. You can see a template for Tessel modules in general on our style guide here. You might want to check out the PIR repo set up for development here.

    Here are notes on some of the key files:

    index.js (template)

    This file is the driver for the hardware. Here’s the basic setup:

    • Require util and the event emitter, along with any other dependencies. These let you write event-driven APIs.
    • 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.
      • 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). You can check the PIR code for examples of this error handling.
      • 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.
    • 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? 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”.
    • 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.
    • exports: Export the object function and the use function.

    package.json (template)

    Use npm init to generate most of this file.

    Other items of note:

    • You do not need the tessel npm package as a dependency.
    • 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”.

    examples folder (template)

    You need at least one example. This should show basic functionality of the hardware. Mine waits for a ready event, then logs a message on the emission of “movement” and “stillness” events. When you require the module, refer to ’../’ rather than the module name.

    test folder (template)

    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.

    README.md (template)

    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.

    Connecting your hardware to Tessel

    Connect your hardware based on the hardware and API documentation. Instructions for establishing SPI/UART/I2C are part of the API docs.

    At the top of your README, write which pins should be connected to which between the Tessel and the external hardware. A picture of the setup would also be useful to include in the README.

    Establishing communication

    Set up something basic to make sure you can connect to the sensor. I like to start with example code: require Tessel, read the pin, see what kind of values we get.

    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.

    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.

    Writing an API

    Once you’re able to connect and get some basic functionality out of the device, start writing your API.

    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.

    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 RFC category of our forums.

    As a general rule, top priority is intuitive interaction. Second priority is exposing as much as you can.

    Writing tests

    Write tests as you go.

    • Initializing the object should callback the object, return the object, and emit the object as a ready event.
    • Super thorough tests check to make sure errors are emitted when they should be.

    Writing an example

    The example named <hardware>.js should be a simple “is it working” example.

    Feel free to write other examples to show off different uses of the hardware and the API you’ve built!

    Writing the docs

    Please follow the template formatting here to write your README.

    Document every method, event, and property.

    Complete documentation is important! If you don’t document a method, most people will never realize that method exists.

    Publishing

    Publish your module to npm! If you’ve never done that, this is a good tutorial. Be sure to include 'tessel’ in the keywords of your package.json so that people can find it!

    Other places you might want to publish as well:

    Find this document on Tessel’s docs repo, where it will be kept up to date.

    #tessel #adafruit #kelsey breseman #technical machine #seeed #pir #pulse #infrared #diy #hardware #wires

  • Tools for Tessel

    Friday, August 1, 2014

    8/1/2014– Kelsey Breseman

    Since Tessel has come out, people have been building tools and tutorials to work with the platform. Internally, we’ve been building tutorials as they become relevant, and externally, community members have published npm libraries either specifically for Tessel or to make Tessel work better with existing hardware and software.

    Throughout, I’ve been quietly collecting these links. However, I realized my list would be much more useful published– so here you go.

    I’ll be keeping it up to date on Github here. Please PR if there’s anything I’m missing!

    Contents

    Tutorials

    Communications

    # USB message passing
    USB communication between Tessel and Node on your PC.

    # Getting started with BLE
    A guide to Bluetooth Low Energy for beginners, particularly flavored for Tessel.

    # External GPIO Pin Interrupts API
    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.

    # SPI Locks and Raw Transfers
    Tutorial on SPI communication.

    Firmware

    # Expose a C function up to JS userspace
    This tutorial goes over how to expose a C function to JS where the user can interact with it via any JS function.

    # Debugging Tessel
    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.

    Hardware

    # Powering Tessel
    Powering Tessel through an external power source

    # Adding a Wifi Antenna
    How to add a Wifi antenna to Tessel to improve Wifi reception

    # Connecting Arduino and Tessel
    This is a tutorial for how to pass data back and forth between an Arduino and a Tessel.

    Software tools

    Development tools

    # tiny-router
    A simple routing library targeting embedded system where every byte counts

    # tesselate
    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)

    # avr-isp
    Library to allow Tessel to act as an AVR In-System Programmer

    # grunt-tessel
    Grunt tasks to aid tessel development

    # mockfs
    Virtual in-memory file system accessible through native FS module

    # tesselbot
    A chainable tessel rebot made for building simple apps easier

    Multi-language support

    # lua-tessel
    A CLI that enables the scripting of a Tessel device in Lua

    # Rust on Tessel
    Examples of the Rust language running on Tessel

    Libraries

    # cylon-tessel
    Cylon.js is a JavaScript framework for robotics and physical computing using Node.js

    # Plotly example
    Tessel + Plotly streaming example

    # m2x-tessel
    AT&T M2X API client for node.js based Tessel

    Hardware libraries

    Beyond the modules, libraries and examples for connecting with Tessel.

    # pir
    Node library for a PIR motion detector

    # tessel-ht16k33
    Use the Adafruit HT16K33 LED Backpack with your Tessel

    # tessel-button
    API to provide more feedback / options to the single tessel ‘config’ button

    # neopixels
    Library to run a strand of neopixels from Tessel

    # ir-codes
    Generates signal buffers for different infrared device manufacturers

    Contributing

    # Technical Machine contribution guide
    A thorough explanation of how the Tessel software architecture works as a whole, descriptions of the individual pieces, and the processes for contributing code

    # Technical Machine style guide
    Defines style for Technical Machine code, docs, and directories, particularly Tessel modules

    # RFC category on the Tessel forums
    Technical Machine & community members request comments on APIs and projects

    This document will be kept up to date here

    #tessel #kelsey breseman #tools #tessel tools #tutorial #tutorials #documentation #docs #software #firmware #hardware #contribution guide #spi #i2c #uart #avr #npm #node #module

  • USB communication between Tessel and Node on your PC

    Tuesday, July 29, 2014

    7/29/2014– Kevin Mehall

    This post is an introduction to using USB to communicate between Tessel and Node. Find updates and more examples here.

    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.

    Messages are JavaScript objects. It uses structured clone, which beyond JSON, supports cyclic structures and Buffer, RegExp, and Date objects.

    We’ve built an example for you to expand on:

    git clone https://github.com/tessel/docs.git
    cd docs/tutorial/usb_messages
    npm install
    

    The directory structure looks like:

    ./
      /host.js         -- script that runs on the computer
      /package.json
      /node_modules    -- npm modules for the computer
        /tessel        -- the Tessel host-side USB module
      /device          -- this entire directory will be deployed to Tessel
        /package.json
        /node_modules  -- all the libs that run ON Tessel go here (camera, ambient, IR, etc.)
        /device.js     -- the main script that runs on Tessel
                       -- other JS files for Tessel go here
    

    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.

    The tessel command line tool functionality is also exposed as a library. host.js uses that library to take the place of tessel run, and not only deploys your code to the Tessel, but also communicates with it.

    The Tessel code, device/index.js, simply demonstrates sending and receiving messages.

    To try this example, run node host.js. It sends the device-side code on the Tessel as it starts.


    Here’s the code that runs on the PC: host.js

    // When we `require('tessel')` here, this is the library out of `node_modules`
    // for USB communication. It's not the same as the `tessel` module built into
    // the Tessel firmware that code on the Tessel uses for hardware access --
    // that's only available to JS that executes on the Tessel itself.
    var tessel = require('tessel');
    
    var script =  require.resolve('./device/index.js');
    
    var opts = {
      // Stop existing script, if any
      stop: true,
      // Serial number (`undefined` picks the first one)
      serial: process.env.TESSEL_SERIAL,
    };
    
    var args = [];
     
    // `tessel.findTessel` finds a Tessel attached to this computer and connects.
    tessel.findTessel(opts, function(err, device) {
        if (err) throw err;
    
        // Once we've found a Tessel, we tell it to run our script. This works just
        // like `tessel run` and bundles the `device/` directory. It bundles only
        // `device/` and not the host code because `device/` has its own
        // `package.json`.
        device.run(script, args, {}, function () {
              // Connect the stdout and stderr of the process running on Tessel to
              // the console, so that our `console.log` messages show.
              device.stdout.resume();
              device.stdout.pipe(process.stdout);
              device.stderr.resume();
              device.stderr.pipe(process.stderr);
     
              var count = 0;
    
              // `device.send(msg)` sends an object to Tessel. It supports JSON
              // compatible objects as messages, with the addition that `Buffer`s,
              // `Date`s and cyclic data structures are also handled properly.
              setInterval(function(){
                device.send({count:count++, data: {obj: 'demo'}})
              }, 4000);
    
              // `device.on('message', function (msg) { ... })` receives an event
              // when an object is received from Tessel.
              device.on('message', function (m) {
                console.log('[PC] Message from Tessel:', m);
              });
     
              // Exit cleanly on Ctrl+C.
              process.on('SIGINT', function() {
                // Try to stop the process on the Tessel
                device.stop();
    
                setTimeout(function () {
                  // But if that fails, just exit
                  logs.info('Script aborted');
                  process.exit(131);
                }, 200);
              });
     
              // When the script on Tessel exits, shut down
              // USB communications and exit
              device.once('script-stop', function (code) {
                device.close(function () {
                  process.exit(code);
                });
              });
        });
    });
    

    The code that runs on Tessel is very simple: device/index.js

    // The `tessel` module built-in to the Tessel firmware for access to hardware
    var tessel = require('tessel');
    
    //When a message is received from the computer, this event triggers.
    process.on('message', function(msg) {
      console.log("[Tessel] Message from PC:", msg);
    });
    
    var counter = 0;
    
    // Every 5 seconds...
    setInterval(function() {
      // Send a message to the computer
      process.send({count: counter++});
    }, 5000);
    
    // Keep the event loop alive 
    process.ref();
    

    When a message is received from the computer, the process.on('message', function(msg) { event triggers.

    To send a message to the computer, call process.send(msg)


    Code examples in this document are placed in the public domain.

    See the code on Github here.

    #kevin mehall #docs #USB #Tessel #Technical Machine #Node #Examples #code

  • Digital Fireworks with Tessel

    Friday, July 18, 2014

    7/18/2014– Jon McKay

    Image source: Matthew Bergman

    Background Context

    Several months ago, Eran Hammer messaged me about helping him with a project he was working on for NodeConf. My only experience with Eran Hammer up to that point was watching his over-the-top presentation at Realtime Conf. I’ve since forgotten a majority of the presentation, but I do distinctly remember a dime bag containing blue rock candy, dozens of remotely controlled mortar and pestles, and several hundred pounds of dirt and edible plants in a warehouse. In short, it was weird and intriguing and made me feel vaguely like I had abused moderately-strong hallucinogens.

    Naturally, I was excited about helping with the next project, especially since I could develop it on Tessel.

    Eran was set on creating an LED fireworks display to be “set off” on July 4th. The idea was scaled down from an overhead, 15 foot wide, 10 foot long LED grid (estimated cost of $75000) to “simply” 1260 Neopixel LEDs laid out in the shape of an exploding firework.

    You can see a video of an early test or the actual display here.

    Now that we’ve finished, you can actually build a similar system yourself by installing the fireworks Node module for your computer and the neopixels Node module for Tessel.

    Technical Setup

    Eran was in charge of writing the JavaScript library to generate firework animations, and my task was to actually route those animations through Tessel and into one giant strip of Neopixels.

    Neopixel is Adafruit’s brand for addressable LED strips using a specific chip called the WS2812. They are extremely popular due to their simple programming interface and mesmerizing light displays.

    The difficult part of using Neopixels is that they are very timing constrained (so much so, in fact, that parts of the library for Arduino are written in Assembly to ensure a fast enough data throughput. Heavy timing-dependence doesn’t bode well for a JavaScript application, so I knew this project was going to be a bit of a challenge.

    We decided that most of the actually timing-based “pin-wiggling” would have to be done in the firmware layer (written in C) and we would use Tessel’s JavaScript layer to simply pass the fireworks animation from the USB hub to the firmware.

    In all, Eran’s laptop ran a Node server responsible for initiating the Tessel script and generating animations, sending those animation as a binary packet to Tessel, and Tessel was responsible for routing the buffer to the Neopixel driver.

    Each RGB LED receives 3 bytes of data (one byte for each color) and then uses a shift register to pop those bytes off before sending the rest of the animation buffer on to the next pixel. Each transmitted bit is essentially a PWM signal with a period of 1.25 microseconds. A “0” is represented by a duty cycle of 32% and a “1” is represented by a duty cycle 85% (with a ~10% error margin). At the end of an animation, the signal should be held low for at least 50 microseconds.

    Source: Adafruit

    Eran and I were initially worried that we wouldn’t be able to get a good frame rate with a single strand of 1260 pixels. A reasonable frame rate for animations is 30 frames per second. To determine the expected frame rate with Neopixels, we’d need to do a little math:

    1260 pixels * (24 bits/pixel * 1.25 microseconds/bit) + 50 microseconds = 22100 microseconds, or .0221 seconds per animation frame. In theory, that’s about 47 frames per second, but real life is always a bit slower and we weren’t sure by exactly how much.

    Implementation

    Fortunately, our LPC1830 microcontroller features a State Configurable Timer (SCT) which provides programmers with an extremely flexible interface for pin manipulation. Essentially, it allows you to define different timing states associated with different pin inputs and outputs.

    In the case of a single strand of neopixels, I could have used 4 different states. A simplified example of how it could work would be:

    • A timer for the entire period. This timer sets the output pin high at the beginning of a bit transmission which makes the PWM active.

    • A timer for the “0” duty cycle completion (at 32% as mentioned above). When this event fires, it will actually check the value of the current bit being transferred. If it’s a 0, then there is no conflict and the pin state will be pulled low. If it’s a 1, there is a conflict, and the pin will not be changed.

    • A timer for the “1” pwm completion (at 85%) will pull the pin low regardless of the value of the bit being transmitted. This is because it’s a 0, it was already pulled low and doesn’t matter, and if it’s a 1, it needs to be pulled down immediately.

    • A timer that only fires at the end of at the end of a 8 bits. This timer will call an interrupt routine to set up the next byte to be transferred.

    But in reality, I couldn’t set up the next byte after the previous one finished, because that would cause a delay between when the previous byte was sent out and the amount of time it would take to process the logic of setting up the next one. That delay in the signal would totally ruin the animation being sent to Neopixels and the colors would be all wrong (in the best case).

    In fact, what I needed was a double buffer. A double buffer would allow me to set up the next byte while the current byte is being transmitted. I implemented that functionality by adding another SCT state. I set the state of a GPIO pin either high or low depending on which buffer the SCT should be using to generate a signal, and set the next byte in the other in interrupt routines after the previous byte was sent.

    Further Work

    I ended up finishing the single strand implementation in a few hours, but wanted to take the system to the extreme. Tessel has three PWM pins connected to its GPIO port, and I wanted to enable all three of them to output animation data in parallel, effectively tripling the possible frame rate.

    One frustrating weekend, I attempted to add a four more events for the two other pins (each requires two events for the double buffer). Unfortunately, there just wasn’t enough time in the interrupt routine to service three different buffers at a time.

    1.25us/(1/180Mhz) = 225 clock cycles to update three buffers

    I found that I could update two pwm channels fairly well, but three channels took too long to update. I think my implementation could have been cleaner if I didn’t use so many structs within structs (thanks OOP).

    I ran out of time before I could try implementing the more complicated, but ever so elegant and efficient: DMA transfer. DMA effectively allows for the movement of data over physical pipes without requiring any overhead from the processor. You just tell the microcontroller the destination and source of data transfer and it all happens automagically. I wish DMA was taught in more undergraduate computer architecture classes; it’s a really cool technology.

    Using DMA would allow us to use all three PWM channels without the overhead of the interrupt routine that takes all too long to update the next byte because the hardware would handle it automatically.

    If you’re interested in contributing, this would be a super fun way to get started! As someone still getting familiar with writing firmware myself, I learned a ton about how timing, double buffers, DMA, and PWM work on a much deeper level and was able to visually see my achievement with an awesome light show.

    #jon mckay #eran hammer #fireworks #neopixels #LED #custom firmware #LED strip #LED fireworks #NodeConf #npm #node #javascript

January 2018

July 2017

February 2017

November 2016

October 2016

September 2016

August 2016

July 2016

June 2016

April 2016

March 2016

February 2016

November 2015

September 2015

August 2015

July 2015

June 2015

May 2015

March 2015

February 2015

January 2015

December 2014

November 2014

October 2014

September 2014

August 2014

July 2014

June 2014

May 2014

April 2014

March 2014

February 2014

January 2014

December 2013

November 2013

October 2013

September 2013

August 2013

July 2013