# DMA-Driven NeoPixels

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/043/667/medium800/led_pixels_Banner-DotStar.jpg?1499489877)

If you’ve used **NeoPixels** extensively you’ve likely seen&nbsp;some issues in how they interact with other code. The Arduino millis() and micros() functions **lose accuracy** , the Servo library may **stutter** , or refreshing a very long NeoPixel strip can **slow a program down**.

Sometimes you can shift a task to another part of the microcontroller, as in [this NeoPixels-and-Servos guide](../../../neopixels-and-servos/overview). That project’s code&nbsp;is specific to the **8-bit AVR microcontroller** used in “classic” Arduino-type boards…it **won’t work** on more **modern&nbsp;32-bit boards**. But the core _idea_&nbsp;—&nbsp;exploiting a microcontroller’s specific **_peripherals_** to handle a task&nbsp;—&nbsp;still applies. It’s just a different microcontroller with different peripherals.

This guide solves the problem from the **other direction** : using device peripherals to drive the NeoPixels rather than the servos. But really it’s applicable to _all kinds_ of problems, **not just servos** …any NeoPixel-heavy task involving&nbsp;accurate timekeeping or handling&nbsp;interrupts.

The code here works only on&nbsp;boards based on **SAMD21** and **SAMD51** microcontrollers,&nbsp;such as the&nbsp;Adafruit Feather M0 and M4, Grand Central, Circuit Playground Express or Arduino Zero, using these devices’&nbsp;_DMA-driven SPI_ capability. (Other boards, like the Teensy 3, may offer their own solutions…see the [NeoPixel Überguide’s “Advanced Coding” page](../../../adafruit-neopixel-uberguide/advanced-coding#third-party-libraries).)

# Setting Up

This requires installing three **&nbsp;libraries**. Two&nbsp;of these are new and experimental, so **you won’t find them** in the normal Arduino Library Manager…you’ll need to **download and install these manually** in your Documents/Arduino/Libraries folder. The third&nbsp;— Adafruit\_NeoPixel — _is_ in the Library Manager, so you can install that way (usually easier) or use the third&nbsp;link below.

[Click to download Adafruit_ZeroDMA library](https://github.com/adafruit/Adafruit_ZeroDMA/archive/master.zip)
[Click to download Adafruit_NeoPixel_ZeroDMA library](https://github.com/adafruit/Adafruit_NeoPixel_ZeroDMA/archive/master.zip)
[Click to download Adafruit_NeoPixel library](https://github.com/adafruit/Adafruit_NeoPixel/archive/master.zip)
# Using the Adafruit\_NeoPixel\_ZeroDMA Library

We’ll assume some **familiarity with the regular Adafruit\_NeoPixel library**. If you’ve never used NeoPixels before, it’s best to start with the examples included with that library.

Usage is _nearly identical_ to the regular Adafruit\_NeoPixel library…only the #include line and the object type for the strip declaration are different (but the parameters are the same):

```
#include &lt;Adafruit_NeoPixel_ZeroDMA.h&gt;

Adafruit_NeoPixel_ZeroDMA strip(60, 5, NEO_GRB);
```

All other functions (begin(), show() and so forth) are invoked&nbsp; **exactly the same** as the regular Adafruit\_NeoPixel library…so rather than repeat all that information here, just look at any existing NeoPixel example code to see how it works. Only the above two lines are different!

# No Free Lunch

There are a few “gotchas” to be aware of. One…because hardware peripherals are used, and these are a finite resource, this alternate NeoPixel library&nbsp; **only works&nbsp;with specific pins:**

\* If using the MOSI pin on these boards, the normal SPI peripheral can’t be used for other things. Occasionally SPI is used for display add-ons, SD cards and so forth. But if you’re not using any shields or FeatherWings, that pin is fair game.

\*\* DMA NeoPixels on these boards can not be used simultaneously with I2C, Serial1 or SPI. Regular GPIO in/out is OK.

Also, the&nbsp;technique used in this library requires considerably **more RAM** for the NeoPixels…a little over&nbsp; **four times** as much. Where&nbsp;the “classic” library might use 180&nbsp;bytes for 60 RGB NeoPixels, the new library consumes&nbsp;about 800 bytes&nbsp;for the same.

Keep in mind that these ARM chips are&nbsp; **3.3 Volt** devices, while NeoPixels want **5V logic**. As [explained in the NeoPixel Überguide](../../../adafruit-neopixel-uberguide/best-practices), a **logic level shifter** may be required, or you can use tricks such as a slightly lower supply voltage for the NeoPixels (e.g. 4.5V from three alkaline cells, or 3.7V from a LiPoly battery).

# The Payoff

If you can work with the above constraints — compatible board, pin number and RAM usage — your code may run noticeably faster, plus you can now use the regular Arduino Servo library,&nbsp;and&nbsp;any code that relies on the millis() or micros() functions now keeps track of time correctly.

Additionally, getPixelColor() works correctly when used in combination with setBrightness(). In the classic NeoPixel library, changing&nbsp;brightness is a “destructive” operation and the value returned by getPixelColor() is only an approximation.

# NeoMatrix Too…

There’s also a variant of the Adafruit\_NeoMatrix library that uses the same methodology:

[Click to download Adafruit_NeoMatrix_ZeroDMA library](https://github.com/adafruit/Adafruit_NeoMatrix_ZeroDMA/archive/master.zip)
NeoMatrix is already [explained in the NeoPixel Überguide](../../../adafruit-neopixel-uberguide/neomatrix-library), so we won’t cover the basics here.

Just like Adafruit\_NeoPixel\_ZeroDMA, the alternate NeoMatrix library requires just a couple changes to existing sketches&nbsp;—&nbsp;the #include line and object declaration:

```
#include &lt;Adafruit_NeoMatrix_ZeroDMA.h&gt;

Adafruit_NeoMatrix_ZeroDMA matrix(5, 8, PIN,
  NEO_MATRIX_TOP     + NEO_MATRIX_RIGHT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
  NEO_GRB);
```

Everything else works the same as the regular&nbsp;library.

The same limitations&nbsp;that apply to Adafruit\_NeoPixel\_ZeroDMA also apply to Adafruit\_NeoMatrix\_ZeroDMA: it’s specific to SAMD21 and SAMD51 (aka M0 and M4) boards, works only on certain pins, and has a considerable RAM overhead (12 bytes _per pixel_ for RGB NeoPixels, 16 bytes for RGBW pixels).

# How Does It Work?

**Magic!**

…

Okay, not really.

As the library name implies, _ **DMA** _ (_direct memory access_, the&nbsp;ability of this chip to move data directly between peripherals and memory without CPU intervention) is part of the solution. But this particular ARM chip _does not_&nbsp;support DMA to the GPIO PORT registers which set pins “high” or “low” (akin to Arduino’s digitalWrite() function).

The chip’s **SPI** peripherals (of which there are several, explained in [this guide about SERCOMs](../../../using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/overview)) _do_ support DMA. By pulling some shenanigans, we can persuade SPI to issue&nbsp;a bit pattern that **resembles NeoPixel data**. The duty cycle&nbsp;doesn’t _precisely_ match the datasheet, but it’s close enough to work. (The availability of SPI SERCOMs is why this library only works on specific pins.)

To do this, we expand every&nbsp;bit of NeoPixel color data by a factor of 3 — with a bit pattern of **_100_** to represent a NeoPixel “zero” bit, and **_110_** to represent a “one” bit. We then send this data out the SPI bus at **2.4 MHz** …with the 3:1 bit expansion, this matches the NeoPixels’ desired **800 KHz** data rate.

This 3:1 expansion explains the additional RAM use in this library. There’s the original NeoPixel color data in memory (3 or 4 bytes per pixel for RGB or RGBW), then a 3-fold bit-expanded copy to send over SPI.

![](https://cdn-learn.adafruit.com/assets/assets/000/043/674/medium800/led_pixels_bit-expansion.png?1499556286)

Geting the end-of-data latch (300 microseconds of&nbsp;a LOW logic state) proved tricky, because the SPI idle state is a HIGH logic level. Switching quickly between SPI and GPIO at the beginning and end of each transaction didn’t quite work…this would always “glitch” the first bit out and mess up the first NeoPixel’s color. Solution was to end the NeoPixel data transfer with 300 microseconds worth of zero bits (about 90 bytes worth), then set DMA to run in an endless loop. So…even when the pixels aren’t changing, data is being sent again and again regardless. This doesn’t cost us anything time-wise, there’s zero impact on program speed, because this is all handled through DMA.

- [Next Page](https://learn.adafruit.com/dma-driven-neopixels/neopxl8.md)

## Featured Products

### Adafruit METRO M0 Express - designed for CircuitPython

[Adafruit METRO M0 Express - designed for CircuitPython](https://www.adafruit.com/product/3505)
Metro is our series of microcontroller boards for use with the Arduino IDE. This new **Metro M0 Express** board looks a whole lot like our&nbsp;[original Metro 328](https://www.adafruit.com/product/2488), but with a huge upgrade. Instead of the ATmega328, this Metro...

In Stock
[Buy Now](https://www.adafruit.com/product/3505)
[Related Guides to the Product](https://learn.adafruit.com/products/3505/guides)
### Arduino Zero - 32 bit Cortex M0 Arduino with Debug Interface

[Arduino Zero - 32 bit Cortex M0 Arduino with Debug Interface](https://www.adafruit.com/product/2843)
With the new **Arduino Zero** , the more creative individual will have the potential to create one’s most imaginative and new ideas for IoT devices, wearable technologies, high tech automation, wild robotics and other not yet thinkable adventures in the world of...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/2843)
[Related Guides to the Product](https://learn.adafruit.com/products/2843/guides)
### Adafruit Feather M0 Basic Proto - ATSAMD21 Cortex M0

[Adafruit Feather M0 Basic Proto - ATSAMD21 Cortex M0](https://www.adafruit.com/product/2772)
Feather is the new development board from Adafruit, and like its namesake it is thin, light, and lets you fly! We designed Feather to be a new standard for portable microcontroller cores.

This is the&nbsp; **Feather M0 Basic Proto** ,&nbsp;it has a bunch of prototyping space...

In Stock
[Buy Now](https://www.adafruit.com/product/2772)
[Related Guides to the Product](https://learn.adafruit.com/products/2772/guides)
### Adafruit Feather M0 Adalogger

[Adafruit Feather M0 Adalogger](https://www.adafruit.com/product/2796)
Feather is the new development board from Adafruit, and like its namesake it is thin, light, and lets you fly! We designed Feather to be a new standard for portable microcontroller cores.

This is the&nbsp; **Adafruit Feather M0 Adalogger** &nbsp;- our take on an...

In Stock
[Buy Now](https://www.adafruit.com/product/2796)
[Related Guides to the Product](https://learn.adafruit.com/products/2796/guides)
### Adafruit Feather M0 WiFi - ATSAMD21 + ATWINC1500

[Adafruit Feather M0 WiFi - ATSAMD21 + ATWINC1500](https://www.adafruit.com/product/3010)
Feather is the new development board from Adafruit, and like its namesake it is thin, light, and lets you fly! We designed Feather to be a new standard for portable microcontroller cores. This is the&nbsp; **Adafruit Feather M0 WiFi&nbsp;w/ATWINC1500** - our take on an...

In Stock
[Buy Now](https://www.adafruit.com/product/3010)
[Related Guides to the Product](https://learn.adafruit.com/products/3010/guides)

## Related Guides

- [Adafruit Feather M0 Adalogger](https://learn.adafruit.com/adafruit-feather-m0-adalogger.md)
- [Adafruit Metro M0 Express](https://learn.adafruit.com/adafruit-metro-m0-express.md)
- [Neon LED Signs](https://learn.adafruit.com/led-neon-signs.md)
- [MicroPython for SAMD21](https://learn.adafruit.com/micropython-for-samd21.md)
- [CircuitPython Basics: Analog Inputs & Outputs](https://learn.adafruit.com/circuitpython-basics-analog-inputs-and-outputs.md)
- [Debugging the SAMD21 with GDB](https://learn.adafruit.com/debugging-the-samd21-with-gdb.md)
- [Welcome to CircuitPython!](https://learn.adafruit.com/welcome-to-circuitpython.md)
- [Mini Commodore PET with Charlieplexed LED Matrix](https://learn.adafruit.com/mini-commodore-pet-with-charlieplexed-led-matrix.md)
- [Adafruit DS3502 I2C Digital Potentiometer](https://learn.adafruit.com/ds3502-i2c-potentiometer.md)
- [CircuitPython Hardware: SSD1306 OLED Display](https://learn.adafruit.com/micropython-hardware-ssd1306-oled-display.md)
- [Using Servos With CircuitPython and Arduino](https://learn.adafruit.com/using-servos-with-circuitpython.md)
- [Pixie CyberWig - A Wearable WiFi LED Visualization ](https://learn.adafruit.com/wifi-pixie-cyberwig-wearable-visualization.md)
- [CircuitPython Hardware: PCA9685 DC Motor & Stepper Driver](https://learn.adafruit.com/micropython-hardware-pca9685-dc-motor-and-stepper-driver.md)
- [CircuitPython Hardware: Charlieplex LED Matrix](https://learn.adafruit.com/micropython-hardware-charlieplex-led-matrix.md)
- [Adafruit Feather M0 WiFi with ATWINC1500](https://learn.adafruit.com/adafruit-feather-m0-wifi-atwinc1500.md)
- [Talking Musical NeoPixel Clock with Infrared, BLE and Touch Controls](https://learn.adafruit.com/talking-musical-neo-pixel-clock-with-infrared-ble-and-touch-controls.md)
