Documentation update, base sketch for proto sensor

main
Jurij Podgoršek 2024-08-20 14:02:45 +02:00
parent d483002ea1
commit fcbd4058e8
172 changed files with 176140 additions and 15 deletions

2
.gitignore vendored 100644
View File

@ -0,0 +1,2 @@
.venv
.pio

View File

@ -6,21 +6,47 @@ Ryuzo Fukohara dancing and triggering / modulating sounds and projections by Sim
We plan to plant 5-6 sensors on Ryuzota, the IMU signals will be converted
into midi for Borut in Simon.
** Microcontrollers
*** LilyGo ESP32-S3
https://www.lilygo.cc/products/t7-s3
[[file:doc/t7-s3_v1.1_pinmap.jpg][Pinout]]
Sometimes doesn't want to flash; hold BOOT button and click RESET to enter flash mode.
[[file:lib/OSC/SLIPEncodedSerial.cpp][cnmat/OSC SlipEncodedSerial]] needed a modification; constructor argument typecast to ~HWCDC~.
Should be compiled with ~-DARDUINO_USB_CDC_ON_BOOT=1~ to enable USB CDC.
*** Olimex ESP32-S2-DevKit-Lipo-USB microcontroller
For (testing / development)
https://www.olimex.com/Products/IoT/ESP32-S2/ESP32-S2-DevKit-Lipo-USB/open-source-hardware
[[file:doc/ESP32-S2-DevKitLiPo-GPIO.png][Pinout]]
** Sensor (Adafruit BNO055)
[[file:lib/Adafruit_BNO055-1.6.3/Adafruit_BNO055.cpp::57][Operating modes]]
[[file:doc/BST_BNO055_DS000_12.pdf][Datasheet]]
** Materials
[[file:./dokumentacija.jpg]]
[[file:./dokumentacija.jpg][raw documentation]]
** list
- 8 senzorjev MPU 9250 (9DOF)
- +8 senzorjev MPU 9250 (9-DOF)+ (wrong models sent, MPU-6500 or similar, returned)
https://www.ebay.com/itm/153559516252
5.88$ * 8 + 3.49$ (posiljka) = 47.89$ * 1.22 davek = 58.43$ (+ carina nekaj?)
- 8 krmilnikov esp32
- +8 krmilnikov esp32+
https://www.olimex.com/Products/IoT/ESP32-C3/ESP32-C3-DevKit-Lipo/open-source-hardware
6€ * 8 = 48€ * 1.22 davek = 58.56€ (+ shipping = ? - iz bulgarije)
- 16 baterij
https://www.olimex.com/Products/Power/Lipo-battery/BATTERY-LIPO1400mAh/
5.95€ * 8 = 47.6€ * 1.22 davek = 58.07€ (+ shipping skupaj z zgornjim)
- 14x Li-Po battery 3.7V 800mAh
https://www.tinytronics.nl/en/power/batteries/li-po/li-po-accu-3.7v-800mah
6.75€ * 14
- 10x Adafruit BNO055 9-DOF sensors
https://learn.adafruit.com/adafruit-bno055-absolute-orientation-sensor/overview
- 8x LilyGo ESP32-S3 microcontrollers
https://www.lilygo.cc/products/t7-s3
[[file:doc/t7-s3_v1.1_pinmap.jpg][Pinout]]
We also need some velcro tape to make sensors easily mountable and
protoboards to hold it all together.

View File

@ -0,0 +1,46 @@
{
"build": {
"arduino":{
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi",
"partitions": "default_16MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_MODE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [
[
"0X303A",
"0x1001"
]
],
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": [
"wifi",
"bluetooth"
],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "LILYGO T3-S3",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"url": "https://www.aliexpress.us/item/3256804591247074.html",
"vendor": "LILYGO"
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

8
flash.sh 100755
View File

@ -0,0 +1,8 @@
#!/bin/bash
source .venv/bin/activate
env=${1:-main}
port=${2:-/dev/ttyUSB0}
pio run --target=upload -e "$env" --upload-port "$port"

5
guix-shell.sh 100755
View File

@ -0,0 +1,5 @@
#!/usr/bin/env sh
guix shell --container --network --emulate-fhs --share=$HOME/.platformio python-platformio coreutils bash nss-certs less gcc-toolchain glibc vim sudo
#guix shell --container --network -s i686-linux --emulate-fhs --share=$HOME/.platformio python-virtualenv coreutils bash nss-certs less gcc-toolchain glibc python
#guix shell --container --network -s i686-linux --emulate-fhs --share=$HOME/.platformio python-virtualenv coreutils bash nss-certs less gcc-toolchain python

4
init.sh 100755
View File

@ -0,0 +1,4 @@
#!/bin/sh
python3 -m venv .venv
pip3 install -r requirements.txt

View File

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

View File

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

View File

@ -0,0 +1,29 @@
name: Arduino Library CI
on: [pull_request, push, repository_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py main_platforms
- name: doxygen
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit NeoPixel Library"
run: bash ci/doxy_gen_and_deploy.sh

View File

@ -0,0 +1,4 @@
# Our handy .gitignore for automation ease
Doxyfile*
doxygen_sqlite3.db
html

View File

@ -0,0 +1 @@
{"type": "library", "name": "Adafruit NeoPixel", "version": "1.12.3", "spec": {"owner": "adafruit", "id": 28, "name": "Adafruit NeoPixel", "requirements": null, "uri": null}}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,412 @@
/*!
* @file Adafruit_NeoPixel.h
*
* This is part of Adafruit's NeoPixel library for the Arduino platform,
* allowing a broad range of microcontroller boards (most AVR boards,
* many ARM devices, ESP8266 and ESP32, among others) to control Adafruit
* NeoPixels, FLORA RGB Smart Pixels and compatible devices -- WS2811,
* WS2812, WS2812B, SK6812, etc.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing products
* from Adafruit!
*
* Written by Phil "Paint Your Dragon" Burgess for Adafruit Industries,
* with contributions by PJRC, Michael Miller and other members of the
* open source community.
*
* This file is part of the Adafruit_NeoPixel library.
*
* Adafruit_NeoPixel is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Adafruit_NeoPixel is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with NeoPixel. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#ifndef ADAFRUIT_NEOPIXEL_H
#define ADAFRUIT_NEOPIXEL_H
#ifdef ARDUINO
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#include <pins_arduino.h>
#endif
#ifdef USE_TINYUSB // For Serial when selecting TinyUSB
#include <Adafruit_TinyUSB.h>
#endif
#endif
#ifdef TARGET_LPC1768
#include <Arduino.h>
#endif
#if defined(ARDUINO_ARCH_RP2040)
#include <stdlib.h>
#include "hardware/pio.h"
#include "hardware/clocks.h"
#include "rp2040_pio.h"
#endif
// The order of primary colors in the NeoPixel data stream can vary among
// device types, manufacturers and even different revisions of the same
// item. The third parameter to the Adafruit_NeoPixel constructor encodes
// the per-pixel byte offsets of the red, green and blue primaries (plus
// white, if present) in the data stream -- the following #defines provide
// an easier-to-use named version for each permutation. e.g. NEO_GRB
// indicates a NeoPixel-compatible device expecting three bytes per pixel,
// with the first byte transmitted containing the green value, second
// containing red and third containing blue. The in-memory representation
// of a chain of NeoPixels is the same as the data-stream order; no
// re-ordering of bytes is required when issuing data to the chain.
// Most of these values won't exist in real-world devices, but it's done
// this way so we're ready for it (also, if using the WS2811 driver IC,
// one might have their pixels set up in any weird permutation).
// Bits 5,4 of this value are the offset (0-3) from the first byte of a
// pixel to the location of the red color byte. Bits 3,2 are the green
// offset and 1,0 are the blue offset. If it is an RGBW-type device
// (supporting a white primary in addition to R,G,B), bits 7,6 are the
// offset to the white byte...otherwise, bits 7,6 are set to the same value
// as 5,4 (red) to indicate an RGB (not RGBW) device.
// i.e. binary representation:
// 0bWWRRGGBB for RGBW devices
// 0bRRRRGGBB for RGB
// RGB NeoPixel permutations; white and red offsets are always same
// Offset: W R G B
#define NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2)) ///< Transmit as R,G,B
#define NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1)) ///< Transmit as R,B,G
#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2)) ///< Transmit as G,R,B
#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1)) ///< Transmit as G,B,R
#define NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0)) ///< Transmit as B,R,G
#define NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0)) ///< Transmit as B,G,R
// RGBW NeoPixel permutations; all 4 offsets are distinct
// Offset: W R G B
#define NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3)) ///< Transmit as W,R,G,B
#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2)) ///< Transmit as W,R,B,G
#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3)) ///< Transmit as W,G,R,B
#define NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2)) ///< Transmit as W,G,B,R
#define NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1)) ///< Transmit as W,B,R,G
#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1)) ///< Transmit as W,B,G,R
#define NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3)) ///< Transmit as R,W,G,B
#define NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2)) ///< Transmit as R,W,B,G
#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3)) ///< Transmit as R,G,W,B
#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2)) ///< Transmit as R,G,B,W
#define NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1)) ///< Transmit as R,B,W,G
#define NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1)) ///< Transmit as R,B,G,W
#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3)) ///< Transmit as G,W,R,B
#define NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2)) ///< Transmit as G,W,B,R
#define NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3)) ///< Transmit as G,R,W,B
#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2)) ///< Transmit as G,R,B,W
#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1)) ///< Transmit as G,B,W,R
#define NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1)) ///< Transmit as G,B,R,W
#define NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0)) ///< Transmit as B,W,R,G
#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0)) ///< Transmit as B,W,G,R
#define NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0)) ///< Transmit as B,R,W,G
#define NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0)) ///< Transmit as B,R,G,W
#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0)) ///< Transmit as B,G,W,R
#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0)) ///< Transmit as B,G,R,W
// Add NEO_KHZ400 to the color order value to indicate a 400 KHz device.
// All but the earliest v1 NeoPixels expect an 800 KHz data stream, this is
// the default if unspecified. Because flash space is very limited on ATtiny
// devices (e.g. Trinket, Gemma), v1 NeoPixels aren't handled by default on
// those chips, though it can be enabled by removing the ifndef/endif below,
// but code will be bigger. Conversely, can disable the NEO_KHZ400 line on
// other MCUs to remove v1 support and save a little space.
#define NEO_KHZ800 0x0000 ///< 800 KHz data transmission
#ifndef __AVR_ATtiny85__
#define NEO_KHZ400 0x0100 ///< 400 KHz data transmission
#endif
// If 400 KHz support is enabled, the third parameter to the constructor
// requires a 16-bit value (in order to select 400 vs 800 KHz speed).
// If only 800 KHz is enabled (as is default on ATtiny), an 8-bit value
// is sufficient to encode pixel color order, saving some space.
#ifdef NEO_KHZ400
typedef uint16_t neoPixelType; ///< 3rd arg to Adafruit_NeoPixel constructor
#else
typedef uint8_t neoPixelType; ///< 3rd arg to Adafruit_NeoPixel constructor
#endif
// These two tables are declared outside the Adafruit_NeoPixel class
// because some boards may require oldschool compilers that don't
// handle the C++11 constexpr keyword.
/* A PROGMEM (flash mem) table containing 8-bit unsigned sine wave (0-255).
Copy & paste this snippet into a Python REPL to regenerate:
import math
for x in range(256):
print("{:3},".format(int((math.sin(x/128.0*math.pi)+1.0)*127.5+0.5))),
if x&15 == 15: print
*/
static const uint8_t PROGMEM _NeoPixelSineTable[256] = {
128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170,
173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211,
213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240,
241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254,
254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251,
250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 238, 237, 235, 234, 232,
230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198,
196, 193, 190, 188, 185, 182, 179, 176, 173, 170, 167, 165, 162, 158, 155,
152, 149, 146, 143, 140, 137, 134, 131, 128, 124, 121, 118, 115, 112, 109,
106, 103, 100, 97, 93, 90, 88, 85, 82, 79, 76, 73, 70, 67, 65,
62, 59, 57, 54, 52, 49, 47, 44, 42, 40, 37, 35, 33, 31, 29,
27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 9, 7, 6,
5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11,
12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37,
40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121,
124};
/* Similar to above, but for an 8-bit gamma-correction table.
Copy & paste this snippet into a Python REPL to regenerate:
import math
gamma=2.6
for x in range(256):
print("{:3},".format(int(math.pow((x)/255.0,gamma)*255.0+0.5))),
if x&15 == 15: print
*/
static const uint8_t PROGMEM _NeoPixelGammaTable[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3,
3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17,
17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35,
36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, 80, 81,
82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96, 97, 99, 100, 102,
103, 105, 106, 108, 109, 111, 112, 114, 115, 117, 119, 120, 122, 124, 125,
127, 129, 130, 132, 134, 136, 137, 139, 141, 143, 145, 146, 148, 150, 152,
154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182,
184, 186, 188, 191, 193, 195, 197, 199, 202, 204, 206, 209, 211, 213, 215,
218, 220, 223, 225, 227, 230, 232, 235, 237, 240, 242, 245, 247, 250, 252,
255};
/*!
@brief Class that stores state and functions for interacting with
Adafruit NeoPixels and compatible devices.
*/
class Adafruit_NeoPixel {
public:
// Constructor: number of LEDs, pin number, LED type
Adafruit_NeoPixel(uint16_t n, int16_t pin = 6,
neoPixelType type = NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel(void);
~Adafruit_NeoPixel();
void begin(void);
void show(void);
void setPin(int16_t p);
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
void setPixelColor(uint16_t n, uint32_t c);
void fill(uint32_t c = 0, uint16_t first = 0, uint16_t count = 0);
void setBrightness(uint8_t);
void clear(void);
void updateLength(uint16_t n);
void updateType(neoPixelType t);
/*!
@brief Check whether a call to show() will start sending data
immediately or will 'block' for a required interval. NeoPixels
require a short quiet time (about 300 microseconds) after the
last bit is received before the data 'latches' and new data can
start being received. Usually one's sketch is implicitly using
this time to generate a new frame of animation...but if it
finishes very quickly, this function could be used to see if
there's some idle time available for some low-priority
concurrent task.
@return 1 or true if show() will start sending immediately, 0 or false
if show() would block (meaning some idle time is available).
*/
bool canShow(void) {
// It's normal and possible for endTime to exceed micros() if the
// 32-bit clock counter has rolled over (about every 70 minutes).
// Since both are uint32_t, a negative delta correctly maps back to
// positive space, and it would seem like the subtraction below would
// suffice. But a problem arises if code invokes show() very
// infrequently...the micros() counter may roll over MULTIPLE times in
// that interval, the delta calculation is no longer correct and the
// next update may stall for a very long time. The check below resets
// the latch counter if a rollover has occurred. This can cause an
// extra delay of up to 300 microseconds in the rare case where a
// show() call happens precisely around the rollover, but that's
// neither likely nor especially harmful, vs. other code that might
// stall for 30+ minutes, or having to document and frequently remind
// and/or provide tech support explaining an unintuitive need for
// show() calls at least once an hour.
uint32_t now = micros();
if (endTime > now) {
endTime = now;
}
return (now - endTime) >= 300L;
}
/*!
@brief Get a pointer directly to the NeoPixel data buffer in RAM.
Pixel data is stored in a device-native format (a la the NEO_*
constants) and is not translated here. Applications that access
this buffer will need to be aware of the specific data format
and handle colors appropriately.
@return Pointer to NeoPixel buffer (uint8_t* array).
@note This is for high-performance applications where calling
setPixelColor() on every single pixel would be too slow (e.g.
POV or light-painting projects). There is no bounds checking
on the array, creating tremendous potential for mayhem if one
writes past the ends of the buffer. Great power, great
responsibility and all that.
*/
uint8_t *getPixels(void) const { return pixels; };
uint8_t getBrightness(void) const;
/*!
@brief Retrieve the pin number used for NeoPixel data output.
@return Arduino pin number (-1 if not set).
*/
int16_t getPin(void) const { return pin; };
/*!
@brief Return the number of pixels in an Adafruit_NeoPixel strip object.
@return Pixel count (0 if not set).
*/
uint16_t numPixels(void) const { return numLEDs; }
uint32_t getPixelColor(uint16_t n) const;
/*!
@brief An 8-bit integer sine wave function, not directly compatible
with standard trigonometric units like radians or degrees.
@param x Input angle, 0-255; 256 would loop back to zero, completing
the circle (equivalent to 360 degrees or 2 pi radians).
One can therefore use an unsigned 8-bit variable and simply
add or subtract, allowing it to overflow/underflow and it
still does the expected contiguous thing.
@return Sine result, 0 to 255, or -128 to +127 if type-converted to
a signed int8_t, but you'll most likely want unsigned as this
output is often used for pixel brightness in animation effects.
*/
static uint8_t sine8(uint8_t x) {
return pgm_read_byte(&_NeoPixelSineTable[x]); // 0-255 in, 0-255 out
}
/*!
@brief An 8-bit gamma-correction function for basic pixel brightness
adjustment. Makes color transitions appear more perceptially
correct.
@param x Input brightness, 0 (minimum or off/black) to 255 (maximum).
@return Gamma-adjusted brightness, can then be passed to one of the
setPixelColor() functions. This uses a fixed gamma correction
exponent of 2.6, which seems reasonably okay for average
NeoPixels in average tasks. If you need finer control you'll
need to provide your own gamma-correction function instead.
*/
static uint8_t gamma8(uint8_t x) {
return pgm_read_byte(&_NeoPixelGammaTable[x]); // 0-255 in, 0-255 out
}
/*!
@brief Convert separate red, green and blue values into a single
"packed" 32-bit RGB color.
@param r Red brightness, 0 to 255.
@param g Green brightness, 0 to 255.
@param b Blue brightness, 0 to 255.
@return 32-bit packed RGB value, which can then be assigned to a
variable for later use or passed to the setPixelColor()
function. Packed RGB format is predictable, regardless of
LED strand color order.
*/
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
/*!
@brief Convert separate red, green, blue and white values into a
single "packed" 32-bit WRGB color.
@param r Red brightness, 0 to 255.
@param g Green brightness, 0 to 255.
@param b Blue brightness, 0 to 255.
@param w White brightness, 0 to 255.
@return 32-bit packed WRGB value, which can then be assigned to a
variable for later use or passed to the setPixelColor()
function. Packed WRGB format is predictable, regardless of
LED strand color order.
*/
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
static uint32_t ColorHSV(uint16_t hue, uint8_t sat = 255, uint8_t val = 255);
/*!
@brief A gamma-correction function for 32-bit packed RGB or WRGB
colors. Makes color transitions appear more perceptially
correct.
@param x 32-bit packed RGB or WRGB color.
@return Gamma-adjusted packed color, can then be passed in one of the
setPixelColor() functions. Like gamma8(), this uses a fixed
gamma correction exponent of 2.6, which seems reasonably okay
for average NeoPixels in average tasks. If you need finer
control you'll need to provide your own gamma-correction
function instead.
*/
static uint32_t gamma32(uint32_t x);
void rainbow(uint16_t first_hue = 0, int8_t reps = 1,
uint8_t saturation = 255, uint8_t brightness = 255,
bool gammify = true);
static neoPixelType str2order(const char *v);
private:
#if defined(ARDUINO_ARCH_RP2040)
void rp2040Init(uint8_t pin, bool is800KHz);
void rp2040Show(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz);
#endif
protected:
#ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled...
bool is800KHz; ///< true if 800 KHz pixels
#endif
bool begun; ///< true if begin() previously called
uint16_t numLEDs; ///< Number of RGB LEDs in strip
uint16_t numBytes; ///< Size of 'pixels' buffer below
int16_t pin; ///< Output pin number (-1 if not yet set)
uint8_t brightness; ///< Strip brightness 0-255 (stored as +1)
uint8_t *pixels; ///< Holds LED color values (3 or 4 bytes each)
uint8_t rOffset; ///< Red index within each 3- or 4-byte pixel
uint8_t gOffset; ///< Index of green byte
uint8_t bOffset; ///< Index of blue byte
uint8_t wOffset; ///< Index of white (==rOffset if no white)
uint32_t endTime; ///< Latch timing reference
#ifdef __AVR__
volatile uint8_t *port; ///< Output PORT register
uint8_t pinMask; ///< Output PORT bitmask
#endif
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) || defined(ARDUINO_ARCH_CH32)
GPIO_TypeDef *gpioPort; ///< Output GPIO PORT
uint32_t gpioPin; ///< Output GPIO PIN
#endif
#if defined(ARDUINO_ARCH_RP2040)
PIO pio = pio0;
int sm = 0;
bool init = true;
#endif
};
#endif // ADAFRUIT_NEOPIXEL_H

View File

@ -0,0 +1,13 @@
# Contribution Guidelines
This library is the culmination of the expertise of many members of the open source community who have dedicated their time and hard work. The best way to ask for help or propose a new idea is to [create a new issue](https://github.com/adafruit/Adafruit_NeoPixel/issues/new) while creating a Pull Request with your code changes allows you to share your own innovations with the rest of the community.
The following are some guidelines to observe when creating issues or PRs:
- Be friendly; it is important that we can all enjoy a safe space as we are all working on the same project and it is okay for people to have different ideas
- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); it helps us help you when we can read your code! On that note also refrain from pasting more than 30 lines of code in a post, instead [create a gist](https://gist.github.com/) if you need to share large snippets
- Use reasonable titles; refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile:
- Be detailed; refrain from mentioning code problems without sharing your source code and always give information regarding your board and version of the library

View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -0,0 +1,158 @@
# Adafruit NeoPixel Library [![Build Status](https://github.com/adafruit/Adafruit_NeoPixel/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_NeoPixel/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_NeoPixel/html/index.html)
Arduino library for controlling single-wire-based LED pixels and strip such as the [Adafruit 60 LED/meter Digital LED strip][strip], the [Adafruit FLORA RGB Smart Pixel][flora], the [Adafruit Breadboard-friendly RGB Smart Pixel][pixel], the [Adafruit NeoPixel Stick][stick], and the [Adafruit NeoPixel Shield][shield].
After downloading, rename folder to 'Adafruit_NeoPixel' and install in Arduino Libraries folder. Restart Arduino IDE, then open File->Sketchbook->Library->Adafruit_NeoPixel->strandtest sketch.
Compatibility notes: Port A is not supported on any AVR processors at this time
[flora]: http://adafruit.com/products/1060
[strip]: http://adafruit.com/products/1138
[pixel]: http://adafruit.com/products/1312
[stick]: http://adafruit.com/products/1426
[shield]: http://adafruit.com/products/1430
---
## Installation
### First Method
![image](https://user-images.githubusercontent.com/36513474/68967967-3e37f480-0803-11ea-91d9-601848c306ee.png)
1. In the Arduino IDE, navigate to Sketch > Include Library > Manage Libraries
1. Then the Library Manager will open and you will find a list of libraries that are already installed or ready for installation.
1. Then search for Neopixel strip using the search bar.
1. Click on the text area and then select the specific version and install it.
### Second Method
1. Navigate to the [Releases page](https://github.com/adafruit/Adafruit_NeoPixel/releases).
1. Download the latest release.
1. Extract the zip file
1. In the Arduino IDE, navigate to Sketch > Include Library > Add .ZIP Library
## Features
- ### Simple to use
Controlling NeoPixels “from scratch” is quite a challenge, so we provide a library letting you focus on the fun and interesting bits.
- ### Give back
The library is free; you dont have to pay for anything. Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
- ### Supported Chipsets
We have included code for the following chips - sometimes these break for exciting reasons that we can't control in which case please open an issue!
- AVR ATmega and ATtiny (any 8-bit) - 8 MHz, 12 MHz and 16 MHz
- Teensy 3.x and LC
- Arduino Due
- Arduino 101
- ATSAMD21 (Arduino Zero/M0 and other SAMD21 boards) @ 48 MHz
- ATSAMD51 @ 120 MHz
- Adafruit STM32 Feather @ 120 MHz
- ESP8266 any speed
- ESP32 any speed
- Nordic nRF52 (Adafruit Feather nRF52), nRF51 (micro:bit)
- Infineon XMC1100 BootKit @ 32 MHz
- Infineon XMC1100 2Go @ 32 MHz
- Infineon XMC1300 BootKit @ 32 MHz
- Infineon XMC4700 RelaxKit, XMC4800 RelaxKit, XMC4800 IoT Amazon FreeRTOS Kit @ 144 MHz
Check forks for other architectures not listed here!
- ### GNU Lesser General Public License
Adafruit_NeoPixel is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
## Functions
- begin()
- updateLength()
- updateType()
- show()
- delay_ns()
- setPin()
- setPixelColor()
- fill()
- ColorHSV()
- getPixelColor()
- setBrightness()
- getBrightness()
- clear()
- gamma32()
## Examples
There are many examples implemented in this library. One of the examples is below. You can find other examples [here](https://github.com/adafruit/Adafruit_NeoPixel/tree/master/examples)
### Simple
```Cpp
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 6
#define NUMPIXELS 16
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
pixels.begin();
}
void loop() {
pixels.clear();
for(int i=0; i<NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(0, 150, 0));
pixels.show();
delay(DELAYVAL);
}
}
```
## Contributing
If you want to contribute to this project:
- Report bugs and errors
- Ask for enhancements
- Create issues and pull requests
- Tell others about this library
- Contribute new protocols
Please read [CONTRIBUTING.md](https://github.com/adafruit/Adafruit_NeoPixel/blob/master/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
### Roadmap
The PRIME DIRECTIVE is to maintain backward compatibility with existing Arduino sketches -- many are hosted elsewhere and don't track changes here, some are in print and can never be changed!
Please don't reformat code for the sake of reformatting code. The resulting large "visual diff" makes it impossible to untangle actual bug fixes from merely rearranged lines. Also, don't bother with PRs for timing adjustments "to better match the datasheet," because the datasheet isn't really true to begin with.
Things I'd Like To Do But There's No Official Timeline So Please Don't Count On Any Of This Ever Being Canonical:
- 400 KHz support can be removed, turns out it was never actually necessary; even the earliest NeoPixels can ingest 800 KHz data. Of course the #defines should remain so old sketches still compile, but both can be set to 0 and would have no effect on anything.
- For the show() function (with all the delicate pixel timing stuff), break out each architecture into separate source files rather than the current unmaintainable tangle of #ifdef statements!
- Please don't use updateLength() or updateType() in new code. They should not have been implemented this way (use the C++ 'new' operator with the regular constructor instead) and are only sticking around because of the Prime Directive. setPin() is OK for now though, it's a trick we can use to 'recycle' pixel memory across multiple strips.
- In the M0 and M4 code, use the hardware systick counter for bit timing rather than hand-tweaked NOPs (a temporary kludge at the time because I wasn't reading systick correctly). (As of 1.4.2, systick is used on M4 devices and it appears to be overclock-compatible. Not for M0 yet, which is why this item is still here.)
- As currently written, brightness scaling is still a "destructive" operation -- pixel values are altered in RAM and the original value as set can't be accurately read back, only approximated, which has been confusing and frustrating to users. It was done this way at the time because NeoPixel timing is strict, AVR microcontrollers (all we had at the time) are limited, and assembly language is hard. All the 32-bit architectures should have no problem handling nondestructive brightness scaling -- calculating each byte immediately before it's sent out the wire, maintaining the original set value in RAM -- the work just hasn't been done. There's a fair chance even the AVR code could manage it with some intense focus. (The DotStar library achieves nondestructive brightness scaling because it doesn't have to manage data timing so carefully...every architecture, even ATtiny, just takes whatever cycles it needs for the multiply/shift operations.)
## Credits
This library is written by Phil "Paint Your Dragon" Burgess for Adafruit Industries, with contributions by PJRC, Michael Miller and other members of the open source community.
## License
Adafruit_NeoPixel is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Adafruit_NeoPixel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-3.0.en.html) for more details.
You should have received a copy of the GNU Lesser General Public License along with NeoPixel. If not, see [this](https://www.gnu.org/licenses/)

View File

@ -0,0 +1,224 @@
// Implements the RMT peripheral on Espressif SoCs
// Copyright (c) 2020 Lucian Copeland for Adafruit Industries
/* Uses code from Espressif RGB LED Strip demo and drivers
* Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined(ESP32)
#include <Arduino.h>
#if defined(ESP_IDF_VERSION)
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
#define HAS_ESP_IDF_4
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#define HAS_ESP_IDF_5
#endif
#endif
#ifdef HAS_ESP_IDF_5
void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
rmt_data_t led_data[numBytes * 8];
if (!rmtInit(pin, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 10000000)) {
log_e("Failed to init RMT TX mode on pin %d", pin);
return;
}
int i=0;
for (int b=0; b < numBytes; b++) {
for (int bit=0; bit<8; bit++){
if ( pixels[b] & (1<<(7-bit)) ) {
led_data[i].level0 = 1;
led_data[i].duration0 = 8;
led_data[i].level1 = 0;
led_data[i].duration1 = 4;
} else {
led_data[i].level0 = 1;
led_data[i].duration0 = 4;
led_data[i].level1 = 0;
led_data[i].duration1 = 8;
}
i++;
}
}
//pinMode(pin, OUTPUT); // don't do this, will cause the rmt to disable!
rmtWrite(pin, led_data, numBytes * 8, RMT_WAIT_FOR_EVER);
}
#else
#include "driver/rmt.h"
// This code is adapted from the ESP-IDF v3.4 RMT "led_strip" example, altered
// to work with the Arduino version of the ESP-IDF (3.2)
#define WS2812_T0H_NS (400)
#define WS2812_T0L_NS (850)
#define WS2812_T1H_NS (800)
#define WS2812_T1L_NS (450)
#define WS2811_T0H_NS (500)
#define WS2811_T0L_NS (2000)
#define WS2811_T1H_NS (1200)
#define WS2811_T1L_NS (1300)
static uint32_t t0h_ticks = 0;
static uint32_t t1h_ticks = 0;
static uint32_t t0l_ticks = 0;
static uint32_t t1l_ticks = 0;
// Limit the number of RMT channels available for the Neopixels. Defaults to all
// channels (8 on ESP32, 4 on ESP32-S2 and S3). Redefining this value will free
// any channels with a higher number for other uses, such as IR send-and-recieve
// libraries. Redefine as 1 to restrict Neopixels to only a single channel.
#define ADAFRUIT_RMT_CHANNEL_MAX RMT_CHANNEL_MAX
#define RMT_LL_HW_BASE (&RMT)
bool rmt_reserved_channels[ADAFRUIT_RMT_CHANNEL_MAX];
static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
size_t wanted_num, size_t *translated_size, size_t *item_num)
{
if (src == NULL || dest == NULL) {
*translated_size = 0;
*item_num = 0;
return;
}
const rmt_item32_t bit0 = {{{ t0h_ticks, 1, t0l_ticks, 0 }}}; //Logical 0
const rmt_item32_t bit1 = {{{ t1h_ticks, 1, t1l_ticks, 0 }}}; //Logical 1
size_t size = 0;
size_t num = 0;
uint8_t *psrc = (uint8_t *)src;
rmt_item32_t *pdest = dest;
while (size < src_size && num < wanted_num) {
for (int i = 0; i < 8; i++) {
// MSB first
if (*psrc & (1 << (7 - i))) {
pdest->val = bit1.val;
} else {
pdest->val = bit0.val;
}
num++;
pdest++;
}
size++;
psrc++;
}
*translated_size = size;
*item_num = num;
}
void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
// Reserve channel
rmt_channel_t channel = ADAFRUIT_RMT_CHANNEL_MAX;
for (size_t i = 0; i < ADAFRUIT_RMT_CHANNEL_MAX; i++) {
if (!rmt_reserved_channels[i]) {
rmt_reserved_channels[i] = true;
channel = i;
break;
}
}
if (channel == ADAFRUIT_RMT_CHANNEL_MAX) {
// Ran out of channels!
return;
}
#if defined(HAS_ESP_IDF_4)
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(pin, channel);
config.clk_div = 2;
#else
// Match default TX config from ESP-IDF version 3.4
rmt_config_t config = {
.rmt_mode = RMT_MODE_TX,
.channel = channel,
.gpio_num = pin,
.clk_div = 2,
.mem_block_num = 1,
.tx_config = {
.carrier_freq_hz = 38000,
.carrier_level = RMT_CARRIER_LEVEL_HIGH,
.idle_level = RMT_IDLE_LEVEL_LOW,
.carrier_duty_percent = 33,
.carrier_en = false,
.loop_en = false,
.idle_output_en = true,
}
};
#endif
rmt_config(&config);
rmt_driver_install(config.channel, 0, 0);
// Convert NS timings to ticks
uint32_t counter_clk_hz = 0;
#if defined(HAS_ESP_IDF_4)
rmt_get_counter_clock(channel, &counter_clk_hz);
#else
// this emulates the rmt_get_counter_clock() function from ESP-IDF 3.4
if (RMT_LL_HW_BASE->conf_ch[config.channel].conf1.ref_always_on == RMT_BASECLK_REF) {
uint32_t div_cnt = RMT_LL_HW_BASE->conf_ch[config.channel].conf0.div_cnt;
uint32_t div = div_cnt == 0 ? 256 : div_cnt;
counter_clk_hz = REF_CLK_FREQ / (div);
} else {
uint32_t div_cnt = RMT_LL_HW_BASE->conf_ch[config.channel].conf0.div_cnt;
uint32_t div = div_cnt == 0 ? 256 : div_cnt;
counter_clk_hz = APB_CLK_FREQ / (div);
}
#endif
// NS to tick converter
float ratio = (float)counter_clk_hz / 1e9;
if (is800KHz) {
t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
} else {
t0h_ticks = (uint32_t)(ratio * WS2811_T0H_NS);
t0l_ticks = (uint32_t)(ratio * WS2811_T0L_NS);
t1h_ticks = (uint32_t)(ratio * WS2811_T1H_NS);
t1l_ticks = (uint32_t)(ratio * WS2811_T1L_NS);
}
// Initialize automatic timing translator
rmt_translator_init(config.channel, ws2812_rmt_adapter);
// Write and wait to finish
rmt_write_sample(config.channel, pixels, (size_t)numBytes, true);
rmt_wait_tx_done(config.channel, pdMS_TO_TICKS(100));
// Free channel again
rmt_driver_uninstall(config.channel);
rmt_reserved_channels[channel] = false;
gpio_set_direction(pin, GPIO_MODE_OUTPUT);
}
#endif // ifndef IDF5
#endif // ifdef(ESP32)

View File

@ -0,0 +1,86 @@
// This is a mash-up of the Due show() code + insights from Michael Miller's
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
#if defined(ESP8266)
#include <Arduino.h>
#ifdef ESP8266
#include <eagle_soc.h>
#endif
static uint32_t _getCycleCount(void) __attribute__((always_inline));
static inline uint32_t _getCycleCount(void) {
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
#ifdef ESP8266
IRAM_ATTR void espShow(
uint8_t pin, uint8_t *pixels, uint32_t numBytes, __attribute__((unused)) boolean is800KHz) {
#else
void espShow(
uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
#endif
#define CYCLES_800_T0H (F_CPU / 2500001) // 0.4us
#define CYCLES_800_T1H (F_CPU / 1250001) // 0.8us
#define CYCLES_800 (F_CPU / 800001) // 1.25us per bit
#define CYCLES_400_T0H (F_CPU / 2000000) // 0.5uS
#define CYCLES_400_T1H (F_CPU / 833333) // 1.2us
#define CYCLES_400 (F_CPU / 400000) // 2.5us per bit
uint8_t *p, *end, pix, mask;
uint32_t t, time0, time1, period, c, startTime;
#ifdef ESP8266
uint32_t pinMask;
pinMask = _BV(pin);
#endif
p = pixels;
end = p + numBytes;
pix = *p++;
mask = 0x80;
startTime = 0;
#ifdef NEO_KHZ400
if(is800KHz) {
#endif
time0 = CYCLES_800_T0H;
time1 = CYCLES_800_T1H;
period = CYCLES_800;
#ifdef NEO_KHZ400
} else { // 400 KHz bitstream
time0 = CYCLES_400_T0H;
time1 = CYCLES_400_T1H;
period = CYCLES_400;
}
#endif
for(t = time0;; t = time0) {
if(pix & mask) t = time1; // Bit high duration
while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
#ifdef ESP8266
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
#else
gpio_set_level(pin, HIGH);
#endif
startTime = c; // Save start time
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
#ifdef ESP8266
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
#else
gpio_set_level(pin, LOW);
#endif
if(!(mask >>= 1)) { // Next bit/byte
if(p >= end) break;
pix = *p++;
mask = 0x80;
}
}
while((_getCycleCount() - startTime) < period); // Wait for last bit
}
#endif // ESP8266

View File

@ -0,0 +1,177 @@
// NeoPixel test program showing use of the WHITE channel for RGBW
// pixels only (won't look correct on regular RGB NeoPixel strips).
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN 6
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 60
// NeoPixel brightness, 0 (min) to 255 (max)
#define BRIGHTNESS 50 // Set BRIGHTNESS to about 1/5 (max = 255)
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(BRIGHTNESS);
}
void loop() {
// Fill along the length of the strip in various colors...
colorWipe(strip.Color(255, 0, 0) , 50); // Red
colorWipe(strip.Color( 0, 255, 0) , 50); // Green
colorWipe(strip.Color( 0, 0, 255) , 50); // Blue
colorWipe(strip.Color( 0, 0, 0, 255), 50); // True white (not RGB white)
whiteOverRainbow(75, 5);
pulseWhite(5);
rainbowFade2White(3, 3, 1);
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void whiteOverRainbow(int whiteSpeed, int whiteLength) {
if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;
int head = whiteLength - 1;
int tail = 0;
int loops = 3;
int loopNum = 0;
uint32_t lastTime = millis();
uint32_t firstPixelHue = 0;
for(;;) { // Repeat forever (or until a 'break' or 'return')
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
if(((i >= tail) && (i <= head)) || // If between head & tail...
((tail > head) && ((i >= tail) || (i <= head)))) {
strip.setPixelColor(i, strip.Color(0, 0, 0, 255)); // Set white
} else { // else set rainbow
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
}
strip.show(); // Update strip with new contents
// There's no delay here, it just runs full-tilt until the timer and
// counter combination below runs out.
firstPixelHue += 40; // Advance just a little along the color wheel
if((millis() - lastTime) > whiteSpeed) { // Time to update head/tail?
if(++head >= strip.numPixels()) { // Advance head, wrap around
head = 0;
if(++loopNum >= loops) return;
}
if(++tail >= strip.numPixels()) { // Advance tail, wrap around
tail = 0;
}
lastTime = millis(); // Save time of last movement
}
}
}
void pulseWhite(uint8_t wait) {
for(int j=0; j<256; j++) { // Ramp up from 0 to 255
// Fill entire strip with white at gamma-corrected brightness level 'j':
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
delay(wait);
}
for(int j=255; j>=0; j--) { // Ramp down from 255 to 0
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
delay(wait);
}
}
void rainbowFade2White(int wait, int rainbowLoops, int whiteLoops) {
int fadeVal=0, fadeMax=100;
// Hue of first pixel runs 'rainbowLoops' complete loops through the color
// wheel. Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to rainbowLoops*65536, using steps of 256 so we
// advance around the wheel at a decent clip.
for(uint32_t firstPixelHue = 0; firstPixelHue < rainbowLoops*65536;
firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
uint32_t pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the three-argument variant, though the
// second value (saturation) is a constant 255.
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue, 255,
255 * fadeVal / fadeMax)));
}
strip.show();
delay(wait);
if(firstPixelHue < 65536) { // First loop,
if(fadeVal < fadeMax) fadeVal++; // fade in
} else if(firstPixelHue >= ((rainbowLoops-1) * 65536)) { // Last loop,
if(fadeVal > 0) fadeVal--; // fade out
} else {
fadeVal = fadeMax; // Interim loop, make sure fade is at max
}
}
for(int k=0; k<whiteLoops; k++) {
for(int j=0; j<256; j++) { // Ramp up 0 to 255
// Fill entire strip with white at gamma-corrected brightness level 'j':
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
}
delay(1000); // Pause 1 second
for(int j=255; j>=0; j--) { // Ramp down 255 to 0
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
}
}
delay(500); // Pause 1/2 second
}

View File

@ -0,0 +1,231 @@
/****************************************************************************
* This example is based on StrandtestBLE example and adapts it to use
* the new ArduinoBLE library.
*
* https://github.com/arduino-libraries/ArduinoBLE
*
* Supported boards:
* Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
*
* You can use a generic BLE central app, like LightBlue (iOS and Android) or
* nRF Connect (Android), to interact with the services and characteristics
* created in this sketch.
*
* This example code is in the public domain.
*
*/
#include <Adafruit_NeoPixel.h>
#define PIN 15 // Pin where NeoPixels are connected
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(64, PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
uint8_t rgb_values[3];
#include <ArduinoBLE.h>
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
void setup()
{
Serial.begin(115200);
Serial.println("Hello World!");
// custom services and characteristics can be added as well
// begin initialization
if (!BLE.begin())
{
Serial.println("starting BLE failed!");
while (1)
;
}
Serial.print("Peripheral address: ");
Serial.println(BLE.address());
// set advertised local name and service UUID:
BLE.setLocalName("LED");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
pinMode(PIN, OUTPUT);
digitalWrite(PIN, LOW);
}
void loop()
{
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central)
{
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected())
{
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written())
{
switch (switchCharacteristic.value())
{
case 'a':
colorWipe(strip.Color(255, 0, 0), 20); // Red
break;
case 'b':
colorWipe(strip.Color(0, 255, 0), 20); // Green
break;
case 'c':
colorWipe(strip.Color(0, 0, 255), 20); // Blue
break;
case 'd':
theaterChase(strip.Color(255, 0, 0), 20); // Red
break;
case 'e':
theaterChase(strip.Color(0, 255, 0), 20); // Green
break;
case 'f':
theaterChase(strip.Color(255, 0, 255), 20); // Cyan
break;
case 'g':
rainbow(10);
break;
case 'h':
theaterChaseRainbow(20);
break;
}
}
}
}
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait)
{
for (int i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait)
{
for (int a = 0; a < 10; a++)
{ // Repeat 10 times...
for (int b = 0; b < 3; b++)
{ // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for (int c = b; c < strip.numPixels(); c += 3)
{
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait)
{
// Hue of first pixel runs 5 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
// means we'll make 5*65536/256 = 1280 passes through this outer loop:
for (long firstPixelHue = 0; firstPixelHue < 5 * 65536; firstPixelHue += 256)
{
for (int i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the single-argument hue variant. The result
// is passed through strip.gamma32() to provide 'truer' colors
// before assigning to each pixel:
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait)
{
int firstPixelHue = 0; // First pixel starts at red (hue 0)
for (int a = 0; a < 30; a++)
{ // Repeat 30 times...
for (int b = 0; b < 3; b++)
{ // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for (int c = b; c < strip.numPixels(); c += 3)
{
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int hue = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}

View File

@ -0,0 +1,239 @@
/****************************************************************************
* This example is based on StrandtestArduinoBLE example to make use of
* callbacks features of the ArduinoBLE library.
*
* https://github.com/arduino-libraries/ArduinoBLE
*
* Supported boards:
* Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
*
* You can use a generic BLE central app, like LightBlue (iOS and Android) or
* nRF Connect (Android), to interact with the services and characteristics
* created in this sketch.
*
* This example code is in the public domain.
*
*/
#include <Adafruit_NeoPixel.h>
#define PIN 15 // Pin where NeoPixels are connected
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(64, PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
uint8_t rgb_values[3];
#include <ArduinoBLE.h>
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
void setup()
{
Serial.begin(115200);
Serial.println("Hello World!");
// custom services and characteristics can be added as well
// begin initialization
if (!BLE.begin())
{
Serial.println("starting BLE failed!");
while (1)
;
}
Serial.print("Peripheral address: ");
Serial.println(BLE.address());
// set advertised local name and service UUID:
BLE.setLocalName("LEDCallback");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
// add service
BLE.addService(ledService);
// assign event handlers for connected, disconnected to peripheral
BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
// assign event handlers for characteristic
switchCharacteristic.setEventHandler(BLEWritten, switchCharacteristicWritten);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
pinMode(PIN, OUTPUT);
digitalWrite(PIN, LOW);
}
void loop()
{
// poll for BLE events
BLE.poll();
}
void blePeripheralConnectHandler(BLEDevice central)
{
// central connected event handler
Serial.print("Connected event, central: ");
Serial.println(central.address());
}
void blePeripheralDisconnectHandler(BLEDevice central)
{
// central disconnected event handler
Serial.print("Disconnected event, central: ");
Serial.println(central.address());
}
void switchCharacteristicWritten(BLEDevice central, BLECharacteristic characteristic)
{
// central wrote new value to characteristic, update LED
Serial.print("Characteristic event, written: ");
switch (switchCharacteristic.value())
{
case 'a':
colorWipe(strip.Color(255, 0, 0), 20); // Red
break;
case 'b':
colorWipe(strip.Color(0, 255, 0), 20); // Green
break;
case 'c':
colorWipe(strip.Color(0, 0, 255), 20); // Blue
break;
case 'd':
theaterChase(strip.Color(255, 0, 0), 20); // Red
break;
case 'e':
theaterChase(strip.Color(0, 255, 0), 20); // Green
break;
case 'f':
theaterChase(strip.Color(255, 0, 255), 20); // Cyan
break;
case 'g':
rainbow(10);
break;
case 'h':
theaterChaseRainbow(20);
break;
}
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait)
{
for (int i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait)
{
for (int a = 0; a < 10; a++)
{ // Repeat 10 times...
for (int b = 0; b < 3; b++)
{ // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for (int c = b; c < strip.numPixels(); c += 3)
{
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait)
{
// Hue of first pixel runs 5 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
// means we'll make 5*65536/256 = 1280 passes through this outer loop:
for (long firstPixelHue = 0; firstPixelHue < 5 * 65536; firstPixelHue += 256)
{
for (int i = 0; i < strip.numPixels(); i++)
{ // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the single-argument hue variant. The result
// is passed through strip.gamma32() to provide 'truer' colors
// before assigning to each pixel:
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait)
{
int firstPixelHue = 0; // First pixel starts at red (hue 0)
for (int a = 0; a < 30; a++)
{ // Repeat 30 times...
for (int b = 0; b < 3; b++)
{ // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for (int c = b; c < strip.numPixels(); c += 3)
{
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int hue = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}

View File

@ -0,0 +1,133 @@
#include "BLESerial.h"
// #define BLE_SERIAL_DEBUG
BLESerial* BLESerial::_instance = NULL;
BLESerial::BLESerial(unsigned char req, unsigned char rdy, unsigned char rst) :
BLEPeripheral(req, rdy, rst)
{
this->_txCount = 0;
this->_rxHead = this->_rxTail = 0;
this->_flushed = 0;
BLESerial::_instance = this;
addAttribute(this->_uartService);
addAttribute(this->_uartNameDescriptor);
setAdvertisedServiceUuid(this->_uartService.uuid());
addAttribute(this->_rxCharacteristic);
addAttribute(this->_rxNameDescriptor);
this->_rxCharacteristic.setEventHandler(BLEWritten, BLESerial::_received);
addAttribute(this->_txCharacteristic);
addAttribute(this->_txNameDescriptor);
}
void BLESerial::begin(...) {
BLEPeripheral::begin();
#ifdef BLE_SERIAL_DEBUG
Serial.println(F("BLESerial::begin()"));
#endif
}
void BLESerial::poll() {
if (millis() < this->_flushed + 100) {
BLEPeripheral::poll();
} else {
flush();
}
}
void BLESerial::end() {
this->_rxCharacteristic.setEventHandler(BLEWritten, NULL);
this->_rxHead = this->_rxTail = 0;
flush();
BLEPeripheral::disconnect();
}
int BLESerial::available(void) {
BLEPeripheral::poll();
int retval = (this->_rxHead - this->_rxTail + sizeof(this->_rxBuffer)) % sizeof(this->_rxBuffer);
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::available() = "));
Serial.println(retval);
#endif
return retval;
}
int BLESerial::peek(void) {
BLEPeripheral::poll();
if (this->_rxTail == this->_rxHead) return -1;
uint8_t byte = this->_rxBuffer[this->_rxTail];
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::peek() = "));
Serial.print((char) byte);
Serial.print(F(" 0x"));
Serial.println(byte, HEX);
#endif
return byte;
}
int BLESerial::read(void) {
BLEPeripheral::poll();
if (this->_rxTail == this->_rxHead) return -1;
this->_rxTail = (this->_rxTail + 1) % sizeof(this->_rxBuffer);
uint8_t byte = this->_rxBuffer[this->_rxTail];
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::read() = "));
Serial.print((char) byte);
Serial.print(F(" 0x"));
Serial.println(byte, HEX);
#endif
return byte;
}
void BLESerial::flush(void) {
if (this->_txCount == 0) return;
this->_txCharacteristic.setValue(this->_txBuffer, this->_txCount);
this->_flushed = millis();
this->_txCount = 0;
BLEPeripheral::poll();
#ifdef BLE_SERIAL_DEBUG
Serial.println(F("BLESerial::flush()"));
#endif
}
size_t BLESerial::write(uint8_t byte) {
BLEPeripheral::poll();
if (this->_txCharacteristic.subscribed() == false) return 0;
this->_txBuffer[this->_txCount++] = byte;
if (this->_txCount == sizeof(this->_txBuffer)) flush();
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::write("));
Serial.print((char) byte);
Serial.print(F(" 0x"));
Serial.print(byte, HEX);
Serial.println(F(") = 1"));
#endif
return 1;
}
BLESerial::operator bool() {
bool retval = BLEPeripheral::connected();
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::operator bool() = "));
Serial.println(retval);
#endif
return retval;
}
void BLESerial::_received(const uint8_t* data, size_t size) {
for (int i = 0; i < size; i++) {
this->_rxHead = (this->_rxHead + 1) % sizeof(this->_rxBuffer);
this->_rxBuffer[this->_rxHead] = data[i];
}
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::received("));
for (int i = 0; i < size; i++) Serial.print((char) data[i]);
Serial.println(F(")"));
#endif
}
void BLESerial::_received(BLECentral& /*central*/, BLECharacteristic& rxCharacteristic) {
BLESerial::_instance->_received(rxCharacteristic.value(), rxCharacteristic.valueLength());
}

View File

@ -0,0 +1,46 @@
#ifndef _BLE_SERIAL_H_
#define _BLE_SERIAL_H_
#include <Arduino.h>
#include <BLEPeripheral.h>
class BLESerial : public BLEPeripheral, public Stream
{
public:
BLESerial(unsigned char req, unsigned char rdy, unsigned char rst);
void begin(...);
void poll();
void end();
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t byte);
using Print::write;
virtual operator bool();
private:
unsigned long _flushed;
static BLESerial* _instance;
size_t _rxHead;
size_t _rxTail;
size_t _rxCount() const;
uint8_t _rxBuffer[BLE_ATTRIBUTE_MAX_VALUE_LENGTH];
size_t _txCount;
uint8_t _txBuffer[BLE_ATTRIBUTE_MAX_VALUE_LENGTH];
BLEService _uartService = BLEService("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
BLEDescriptor _uartNameDescriptor = BLEDescriptor("2901", "UART");
BLECharacteristic _rxCharacteristic = BLECharacteristic("6E400002-B5A3-F393-E0A9-E50E24DCCA9E", BLEWriteWithoutResponse, BLE_ATTRIBUTE_MAX_VALUE_LENGTH);
BLEDescriptor _rxNameDescriptor = BLEDescriptor("2901", "RX - Receive Data (Write)");
BLECharacteristic _txCharacteristic = BLECharacteristic("6E400003-B5A3-F393-E0A9-E50E24DCCA9E", BLENotify, BLE_ATTRIBUTE_MAX_VALUE_LENGTH);
BLEDescriptor _txNameDescriptor = BLEDescriptor("2901", "TX - Transfer Data (Notify)");
void _received(const uint8_t* data, size_t size);
static void _received(BLECentral& /*central*/, BLECharacteristic& rxCharacteristic);
};
#endif

View File

@ -0,0 +1,192 @@
/****************************************************************************
* This example was developed by the Hackerspace San Salvador to demonstrate
* the simultaneous use of the NeoPixel library and the Bluetooth SoftDevice.
* To compile this example you'll need to add support for the NRF52 based
* following the instructions at:
* https://github.com/sandeepmistry/arduino-nRF5
* Or adding the following URL to the board manager URLs on Arduino preferences:
* https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
* Then you can install the BLEPeripheral library avaiable at:
* https://github.com/sandeepmistry/arduino-BLEPeripheral
* To test it, compile this example and use the UART module from the nRF
* Toolbox App for Android. Edit the interface and send the characters
* 'a' to 'i' to switch the animation.
* There is a delay because this example blocks the thread of execution but
* the change will be shown after the current animation ends. (This might
* take a couple of seconds)
* For more info write us at: info _at- teubi.co
*/
#include <SPI.h>
#include <BLEPeripheral.h>
#include "BLESerial.h"
#include <Adafruit_NeoPixel.h>
#define PIN 15 // Pin where NeoPixels are connected
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(64, PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
// define pins (varies per shield/board)
#define BLE_REQ 10
#define BLE_RDY 2
#define BLE_RST 9
// create ble serial instance, see pinouts above
BLESerial BLESerial(BLE_REQ, BLE_RDY, BLE_RST);
uint8_t current_state = 0;
uint8_t rgb_values[3];
void setup() {
Serial.begin(115200);
Serial.println("Hello World!");
// custom services and characteristics can be added as well
BLESerial.setLocalName("UART_HS");
BLESerial.begin();
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
//pinMode(PIN, OUTPUT);
//digitalWrite(PIN, LOW);
current_state = 'a';
}
void loop() {
while(BLESerial.available()) {
uint8_t character = BLESerial.read();
switch(character) {
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
current_state = character;
break;
};
}
switch(current_state) {
case 'a':
colorWipe(strip.Color(255, 0, 0), 20); // Red
break;
case 'b':
colorWipe(strip.Color( 0, 255, 0), 20); // Green
break;
case 'c':
colorWipe(strip.Color( 0, 0, 255), 20); // Blue
break;
case 'd':
theaterChase(strip.Color(255, 0, 0), 20); // Red
break;
case 'e':
theaterChase(strip.Color( 0, 255, 0), 20); // Green
break;
case 'f':
theaterChase(strip.Color(255, 0, 255), 20); // Cyan
break;
case 'g':
rainbow(10);
break;
case 'h':
theaterChaseRainbow(20);
break;
}
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
for(int a=0; a<10; a++) { // Repeat 10 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
// Hue of first pixel runs 5 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
// means we'll make 5*65536/256 = 1280 passes through this outer loop:
for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the single-argument hue variant. The result
// is passed through strip.gamma32() to provide 'truer' colors
// before assigning to each pixel:
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
int firstPixelHue = 0; // First pixel starts at red (hue 0)
for(int a=0; a<30; a++) { // Repeat 30 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int hue = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}

View File

@ -0,0 +1,133 @@
#include "BLESerial.h"
// #define BLE_SERIAL_DEBUG
BLESerial* BLESerial::_instance = NULL;
BLESerial::BLESerial(unsigned char req, unsigned char rdy, unsigned char rst) :
BLEPeripheral(req, rdy, rst)
{
this->_txCount = 0;
this->_rxHead = this->_rxTail = 0;
this->_flushed = 0;
BLESerial::_instance = this;
addAttribute(this->_uartService);
addAttribute(this->_uartNameDescriptor);
setAdvertisedServiceUuid(this->_uartService.uuid());
addAttribute(this->_rxCharacteristic);
addAttribute(this->_rxNameDescriptor);
this->_rxCharacteristic.setEventHandler(BLEWritten, BLESerial::_received);
addAttribute(this->_txCharacteristic);
addAttribute(this->_txNameDescriptor);
}
void BLESerial::begin(...) {
BLEPeripheral::begin();
#ifdef BLE_SERIAL_DEBUG
Serial.println(F("BLESerial::begin()"));
#endif
}
void BLESerial::poll() {
if (millis() < this->_flushed + 100) {
BLEPeripheral::poll();
} else {
flush();
}
}
void BLESerial::end() {
this->_rxCharacteristic.setEventHandler(BLEWritten, NULL);
this->_rxHead = this->_rxTail = 0;
flush();
BLEPeripheral::disconnect();
}
int BLESerial::available(void) {
BLEPeripheral::poll();
int retval = (this->_rxHead - this->_rxTail + sizeof(this->_rxBuffer)) % sizeof(this->_rxBuffer);
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::available() = "));
Serial.println(retval);
#endif
return retval;
}
int BLESerial::peek(void) {
BLEPeripheral::poll();
if (this->_rxTail == this->_rxHead) return -1;
uint8_t byte = this->_rxBuffer[this->_rxTail];
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::peek() = "));
Serial.print((char) byte);
Serial.print(F(" 0x"));
Serial.println(byte, HEX);
#endif
return byte;
}
int BLESerial::read(void) {
BLEPeripheral::poll();
if (this->_rxTail == this->_rxHead) return -1;
this->_rxTail = (this->_rxTail + 1) % sizeof(this->_rxBuffer);
uint8_t byte = this->_rxBuffer[this->_rxTail];
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::read() = "));
Serial.print((char) byte);
Serial.print(F(" 0x"));
Serial.println(byte, HEX);
#endif
return byte;
}
void BLESerial::flush(void) {
if (this->_txCount == 0) return;
this->_txCharacteristic.setValue(this->_txBuffer, this->_txCount);
this->_flushed = millis();
this->_txCount = 0;
BLEPeripheral::poll();
#ifdef BLE_SERIAL_DEBUG
Serial.println(F("BLESerial::flush()"));
#endif
}
size_t BLESerial::write(uint8_t byte) {
BLEPeripheral::poll();
if (this->_txCharacteristic.subscribed() == false) return 0;
this->_txBuffer[this->_txCount++] = byte;
if (this->_txCount == sizeof(this->_txBuffer)) flush();
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::write("));
Serial.print((char) byte);
Serial.print(F(" 0x"));
Serial.print(byte, HEX);
Serial.println(F(") = 1"));
#endif
return 1;
}
BLESerial::operator bool() {
bool retval = BLEPeripheral::connected();
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::operator bool() = "));
Serial.println(retval);
#endif
return retval;
}
void BLESerial::_received(const uint8_t* data, size_t size) {
for (int i = 0; i < size; i++) {
this->_rxHead = (this->_rxHead + 1) % sizeof(this->_rxBuffer);
this->_rxBuffer[this->_rxHead] = data[i];
}
#ifdef BLE_SERIAL_DEBUG
Serial.print(F("BLESerial::received("));
for (int i = 0; i < size; i++) Serial.print((char) data[i]);
Serial.println(F(")"));
#endif
}
void BLESerial::_received(BLECentral& /*central*/, BLECharacteristic& rxCharacteristic) {
BLESerial::_instance->_received(rxCharacteristic.value(), rxCharacteristic.valueLength());
}

View File

@ -0,0 +1,46 @@
#ifndef _BLE_SERIAL_H_
#define _BLE_SERIAL_H_
#include <Arduino.h>
#include <BLEPeripheral.h>
class BLESerial : public BLEPeripheral, public Stream
{
public:
BLESerial(unsigned char req, unsigned char rdy, unsigned char rst);
void begin(...);
void poll();
void end();
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t byte);
using Print::write;
virtual operator bool();
private:
unsigned long _flushed;
static BLESerial* _instance;
size_t _rxHead;
size_t _rxTail;
size_t _rxCount() const;
uint8_t _rxBuffer[BLE_ATTRIBUTE_MAX_VALUE_LENGTH];
size_t _txCount;
uint8_t _txBuffer[BLE_ATTRIBUTE_MAX_VALUE_LENGTH];
BLEService _uartService = BLEService("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
BLEDescriptor _uartNameDescriptor = BLEDescriptor("2901", "UART");
BLECharacteristic _rxCharacteristic = BLECharacteristic("6E400002-B5A3-F393-E0A9-E50E24DCCA9E", BLEWriteWithoutResponse, BLE_ATTRIBUTE_MAX_VALUE_LENGTH);
BLEDescriptor _rxNameDescriptor = BLEDescriptor("2901", "RX - Receive Data (Write)");
BLECharacteristic _txCharacteristic = BLECharacteristic("6E400003-B5A3-F393-E0A9-E50E24DCCA9E", BLENotify, BLE_ATTRIBUTE_MAX_VALUE_LENGTH);
BLEDescriptor _txNameDescriptor = BLEDescriptor("2901", "TX - Transfer Data (Notify)");
void _received(const uint8_t* data, size_t size);
static void _received(BLECentral& /*central*/, BLECharacteristic& rxCharacteristic);
};
#endif

View File

@ -0,0 +1,198 @@
/****************************************************************************
* This example was developed by the Hackerspace San Salvador to demonstrate
* the simultaneous use of the NeoPixel library and the Bluetooth SoftDevice.
* To compile this example you'll need to add support for the NRF52 based
* following the instructions at:
* https://github.com/sandeepmistry/arduino-nRF5
* Or adding the following URL to the board manager URLs on Arduino preferences:
* https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
* Then you can install the BLEPeripheral library avaiable at:
* https://github.com/sandeepmistry/arduino-BLEPeripheral
* To test it, compile this example and use the UART module from the nRF
* Toolbox App for Android. Edit the interface and send the characters
* 'a' to 'i' to switch the animation.
* There is a no delay because this example does not block the threads execution
* so the change will be shown immediately and will not need to wait for the current
* animation to end.
* For more info write us at: info _at- teubi.co
*/
#include <SPI.h>
#include <BLEPeripheral.h>
#include "BLESerial.h"
#include <Adafruit_NeoPixel.h>
#define PIN 15 // Pin where NeoPixels are connected
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(64, PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
// define pins (varies per shield/board)
#define BLE_REQ 10
#define BLE_RDY 2
#define BLE_RST 9
// create ble serial instance, see pinouts above
BLESerial BLESerial(BLE_REQ, BLE_RDY, BLE_RST);
uint8_t current_state = 0;
uint8_t rgb_values[3];
void setup() {
Serial.begin(115200);
Serial.println("Hello World!");
// custom services and characteristics can be added as well
BLESerial.setLocalName("UART_HS");
BLESerial.begin();
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
//pinMode(PIN, OUTPUT);
//digitalWrite(PIN, LOW);
current_state = 'a';
}
void loop() {
while(BLESerial.available()) {
uint8_t character = BLESerial.read();
switch(character) {
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
current_state = character;
break;
};
}
switch(current_state) {
case 'a':
colorWipe(strip.Color(255, 0, 0), 20); // Red
break;
case 'b':
colorWipe(strip.Color( 0, 255, 0), 20); // Green
break;
case 'c':
colorWipe(strip.Color( 0, 0, 255), 20); // Blue
break;
case 'd':
theaterChase(strip.Color(255, 0, 0), 20); // Red
break;
case 'e':
theaterChase(strip.Color( 0, 255, 0), 20); // Green
break;
case 'f':
theaterChase(strip.Color(255, 0, 255), 20); // Cyan
break;
case 'g':
rainbow(10);
break;
case 'h':
theaterChaseRainbow(20);
break;
}
}
// Some functions of our own for creating animated effects -----------------
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
if(pixelInterval != wait)
pixelInterval = wait; // Update delay time
strip.setPixelColor(pixelCurrent, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
pixelCurrent++; // Advance current pixel
if(pixelCurrent >= pixelNumber) // Loop the pattern from the first LED
pixelCurrent = 0;
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
if(pixelInterval != wait)
pixelInterval = wait; // Update delay time
for(int i = 0; i < pixelNumber; i++) {
strip.setPixelColor(i + pixelQueue, color); // Set pixel's color (in RAM)
}
strip.show(); // Update strip to match
for(int i=0; i < pixelNumber; i+3) {
strip.setPixelColor(i + pixelQueue, strip.Color(0, 0, 0)); // Set pixel's color (in RAM)
}
pixelQueue++; // Advance current pixel
if(pixelQueue >= 3)
pixelQueue = 0; // Loop the pattern from the first LED
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(uint8_t wait) {
if(pixelInterval != wait)
pixelInterval = wait;
for(uint16_t i=0; i < pixelNumber; i++) {
strip.setPixelColor(i, Wheel((i + pixelCycle) & 255)); // Update delay time
}
strip.show(); // Update strip to match
pixelCycle++; // Advance current cycle
if(pixelCycle >= 256)
pixelCycle = 0; // Loop the cycle back to the begining
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
if(pixelInterval != wait)
pixelInterval = wait; // Update delay time
for(int i=0; i < pixelNumber; i+3) {
strip.setPixelColor(i + pixelQueue, Wheel((i + pixelCycle) % 255)); // Update delay time
}
strip.show();
for(int i=0; i < pixelNumber; i+3) {
strip.setPixelColor(i + pixelQueue, strip.Color(0, 0, 0)); // Update delay time
}
pixelQueue++; // Advance current queue
pixelCycle++; // Advance current cycle
if(pixelQueue >= 3)
pixelQueue = 0; // Loop
if(pixelCycle >= 256)
pixelCycle = 0; // Loop
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

View File

@ -0,0 +1,164 @@
// Simple demonstration on using an input device to trigger changes on your
// NeoPixels. Wire a momentary push button to connect from ground to a
// digital IO pin. When the button is pressed it will change to a new pixel
// animation. Initial state has all pixels off -- press the button once to
// start the first animation. As written, the button does not interrupt an
// animation in-progress, it works only when idle.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Digital IO pin connected to the button. This will be driven with a
// pull-up resistor so the switch pulls the pin to ground momentarily.
// On a high -> low transition the button press logic will execute.
#define BUTTON_PIN 2
#define PIXEL_PIN 6 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 16 // Number of NeoPixels
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
boolean oldState = HIGH;
int mode = 0; // Currently-active animation mode, 0-9
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Get current button state.
boolean newState = digitalRead(BUTTON_PIN);
// Check if state changed from high to low (button press).
if((newState == LOW) && (oldState == HIGH)) {
// Short delay to debounce button.
delay(20);
// Check if button is still low after debounce.
newState = digitalRead(BUTTON_PIN);
if(newState == LOW) { // Yes, still low
if(++mode > 8) mode = 0; // Advance to next mode, wrap around after #8
switch(mode) { // Start the new animation...
case 0:
colorWipe(strip.Color( 0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe(strip.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe(strip.Color( 0, 255, 0), 50); // Green
break;
case 3:
colorWipe(strip.Color( 0, 0, 255), 50); // Blue
break;
case 4:
theaterChase(strip.Color(127, 127, 127), 50); // White
break;
case 5:
theaterChase(strip.Color(127, 0, 0), 50); // Red
break;
case 6:
theaterChase(strip.Color( 0, 0, 127), 50); // Blue
break;
case 7:
rainbow(10);
break;
case 8:
theaterChaseRainbow(50);
break;
}
}
}
// Set the last-read button state to the old state.
oldState = newState;
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
for(int a=0; a<10; a++) { // Repeat 10 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
// Hue of first pixel runs 3 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 3*65536. Adding 256 to firstPixelHue each time
// means we'll make 3*65536/256 = 768 passes through this outer loop:
for(long firstPixelHue = 0; firstPixelHue < 3*65536; firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the single-argument hue variant. The result
// is passed through strip.gamma32() to provide 'truer' colors
// before assigning to each pixel:
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
int firstPixelHue = 0; // First pixel starts at red (hue 0)
for(int a=0; a<30; a++) { // Repeat 30 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int hue = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}

View File

@ -0,0 +1,50 @@
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// Released under the GPLv3 license to match the rest of the
// Adafruit NeoPixel library
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 16 // Popular NeoPixel ring size
// When setting up the NeoPixel library, we tell it how many pixels,
// and which pin to use to send signals. Note that for older NeoPixel
// strips you might need to change the third parameter -- see the
// strandtest example for more information on possible values.
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}
void loop() {
pixels.clear(); // Set all pixel colors to 'off'
// The first NeoPixel in a strand is #0, second is 1, all the way up
// to the count of pixels minus one.
for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
// Here we're using a moderately bright green color:
pixels.setPixelColor(i, pixels.Color(0, 150, 0));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL); // Pause before next pass through loop
}
}

View File

@ -0,0 +1,67 @@
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// Released under the GPLv3 license to match the rest of the
// Adafruit NeoPixel library
// This sketch shows use of the "new" operator with Adafruit_NeoPixel.
// It's helpful if you don't know NeoPixel settings at compile time or
// just want to store this settings in EEPROM or a file on an SD card.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
int pin = 6; // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
int numPixels = 16; // Popular NeoPixel ring size
// NeoPixel color format & data rate. See the strandtest example for
// information on possible values.
int pixelFormat = NEO_GRB + NEO_KHZ800;
// Rather than declaring the whole NeoPixel object here, we just create
// a pointer for one, which we'll then allocate later...
Adafruit_NeoPixel *pixels;
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
// Right about here is where we could read 'pin', 'numPixels' and/or
// 'pixelFormat' from EEPROM or a file on SD or whatever. This is a simple
// example and doesn't do that -- those variables are just set to fixed
// values at the top of this code -- but this is where it would happen.
// Then create a new NeoPixel object dynamically with these values:
pixels = new Adafruit_NeoPixel(numPixels, pin, pixelFormat);
// Going forward from here, code works almost identically to any other
// NeoPixel example, but instead of the dot operator on function calls
// (e.g. pixels.begin()), we instead use pointer indirection (->) like so:
pixels->begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
// You'll see more of this in the loop() function below.
}
void loop() {
pixels->clear(); // Set all pixel colors to 'off'
// The first NeoPixel in a strand is #0, second is 1, all the way up
// to the count of pixels minus one.
for(int i=0; i<numPixels; i++) { // For each pixel...
// pixels->Color() takes RGB values, from 0,0,0 up to 255,255,255
// Here we're using a moderately bright green color:
pixels->setPixelColor(i, pixels->Color(0, 150, 0));
pixels->show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL); // Pause before next pass through loop
}
}

View File

@ -0,0 +1,143 @@
// A basic everyday NeoPixel strip test program.
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN 6
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 60
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// setup() function -- runs once at startup --------------------------------
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}
// loop() function -- runs repeatedly as long as board is on ---------------
void loop() {
// Fill along the length of the strip in various colors...
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color( 0, 255, 0), 50); // Green
colorWipe(strip.Color( 0, 0, 255), 50); // Blue
// Do a theater marquee effect in various colors...
theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness
theaterChase(strip.Color(127, 0, 0), 50); // Red, half brightness
theaterChase(strip.Color( 0, 0, 127), 50); // Blue, half brightness
rainbow(10); // Flowing rainbow cycle along the whole strip
theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}
// Some functions of our own for creating animated effects -----------------
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
for(int a=0; a<10; a++) { // Repeat 10 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
// Hue of first pixel runs 5 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
// means we'll make 5*65536/256 = 1280 passes through this loop:
for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
// strip.rainbow() can take a single argument (first pixel hue) or
// optionally a few extras: number of rainbow repetitions (default 1),
// saturation and value (brightness) (both 0-255, similar to the
// ColorHSV() function, default 255), and a true/false flag for whether
// to apply gamma correction to provide 'truer' colors (default true).
strip.rainbow(firstPixelHue);
// Above line is equivalent to:
// strip.rainbow(firstPixelHue, 1, 255, 255, true);
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
int firstPixelHue = 0; // First pixel starts at red (hue 0)
for(int a=0; a<30; a++) { // Repeat 30 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int hue = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}

View File

@ -0,0 +1,200 @@
// A non-blocking everyday NeoPixel strip test program.
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#ifdef ESP32
// Cannot use 6 as output for ESP. Pins 6-11 are connected to SPI flash. Use 16 instead.
#define LED_PIN 16
#else
#define LED_PIN 6
#endif
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 60
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
unsigned long pixelPrevious = 0; // Previous Pixel Millis
unsigned long patternPrevious = 0; // Previous Pattern Millis
int patternCurrent = 0; // Current Pattern Number
int patternInterval = 5000; // Pattern Interval (ms)
bool patternComplete = false;
int pixelInterval = 50; // Pixel Interval (ms)
int pixelQueue = 0; // Pattern Pixel Queue
int pixelCycle = 0; // Pattern Pixel Cycle
uint16_t pixelNumber = LED_COUNT; // Total Number of Pixels
// setup() function -- runs once at startup --------------------------------
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}
// loop() function -- runs repeatedly as long as board is on ---------------
void loop() {
unsigned long currentMillis = millis(); // Update current time
if( patternComplete || (currentMillis - patternPrevious) >= patternInterval) { // Check for expired time
patternComplete = false;
patternPrevious = currentMillis;
patternCurrent++; // Advance to next pattern
if(patternCurrent >= 7)
patternCurrent = 0;
}
if(currentMillis - pixelPrevious >= pixelInterval) { // Check for expired time
pixelPrevious = currentMillis; // Run current frame
switch (patternCurrent) {
case 7:
theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
break;
case 6:
rainbow(10); // Flowing rainbow cycle along the whole strip
break;
case 5:
theaterChase(strip.Color(0, 0, 127), 50); // Blue
break;
case 4:
theaterChase(strip.Color(127, 0, 0), 50); // Red
break;
case 3:
theaterChase(strip.Color(127, 127, 127), 50); // White
break;
case 2:
colorWipe(strip.Color(0, 0, 255), 50); // Blue
break;
case 1:
colorWipe(strip.Color(0, 255, 0), 50); // Green
break;
default:
colorWipe(strip.Color(255, 0, 0), 50); // Red
break;
}
}
}
// Some functions of our own for creating animated effects -----------------
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
static uint16_t current_pixel = 0;
pixelInterval = wait; // Update delay time
strip.setPixelColor(current_pixel++, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
if(current_pixel >= pixelNumber) { // Loop the pattern from the first LED
current_pixel = 0;
patternComplete = true;
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
static uint32_t loop_count = 0;
static uint16_t current_pixel = 0;
pixelInterval = wait; // Update delay time
strip.clear();
for(int c=current_pixel; c < pixelNumber; c += 3) {
strip.setPixelColor(c, color);
}
strip.show();
current_pixel++;
if (current_pixel >= 3) {
current_pixel = 0;
loop_count++;
}
if (loop_count >= 10) {
current_pixel = 0;
loop_count = 0;
patternComplete = true;
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(uint8_t wait) {
if(pixelInterval != wait)
pixelInterval = wait;
for(uint16_t i=0; i < pixelNumber; i++) {
strip.setPixelColor(i, Wheel((i + pixelCycle) & 255)); // Update delay time
}
strip.show(); // Update strip to match
pixelCycle++; // Advance current cycle
if(pixelCycle >= 256)
pixelCycle = 0; // Loop the cycle back to the begining
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
if(pixelInterval != wait)
pixelInterval = wait; // Update delay time
for(int i=0; i < pixelNumber; i+=3) {
strip.setPixelColor(i + pixelQueue, Wheel((i + pixelCycle) % 255)); // Update delay time
}
strip.show();
for(int i=0; i < pixelNumber; i+=3) {
strip.setPixelColor(i + pixelQueue, strip.Color(0, 0, 0)); // Update delay time
}
pixelQueue++; // Advance current queue
pixelCycle++; // Advance current cycle
if(pixelQueue >= 3)
pixelQueue = 0; // Loop
if(pixelCycle >= 256)
pixelCycle = 0; // Loop
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

View File

@ -0,0 +1,134 @@
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 6
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first.
void setup() {
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
strip.begin();
strip.setBrightness(50);
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
// Send a theater pixel chase in...
theaterChase(strip.Color(127, 127, 127), 50); // White
theaterChase(strip.Color(127, 0, 0), 50); // Red
theaterChase(strip.Color(0, 0, 127), 50); // Blue
rainbow(20);
rainbowCycle(20);
theaterChaseRainbow(50);
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

View File

@ -0,0 +1,74 @@
// This is a mash-up of the Due show() code + insights from Michael Miller's
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
#if defined(K210)
#define KENDRYTE_K210 1
#endif
#if defined(KENDRYTE_K210)
#include <Arduino.h>
#include "sysctl.h"
void k210Show(
uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
{
#define CYCLES_800_T0H (sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 2500000) // 0.4us
#define CYCLES_800_T1H (sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 1250000) // 0.8us
#define CYCLES_800 (sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 800000) // 1.25us per bit
#define CYCLES_400_T0H (sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 2000000) // 0.5uS
#define CYCLES_400_T1H (sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 833333) // 1.2us
#define CYCLES_400 (sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / 400000) // 2.5us per bit
uint8_t *p, *end, pix, mask;
uint32_t t, time0, time1, period, c, startTime;
p = pixels;
end = p + numBytes;
pix = *p++;
mask = 0x80;
startTime = 0;
#ifdef NEO_KHZ400
if (is800KHz)
{
#endif
time0 = CYCLES_800_T0H;
time1 = CYCLES_800_T1H;
period = CYCLES_800;
#ifdef NEO_KHZ400
}
else
{ // 400 KHz bitstream
time0 = CYCLES_400_T0H;
time1 = CYCLES_400_T1H;
period = CYCLES_400;
}
#endif
for (t = time0;; t = time0)
{
if (pix & mask)
t = time1; // Bit high duration
while (((c = read_cycle()) - startTime) < period)
; // Wait for bit start
digitalWrite(pin, HIGH);
startTime = c; // Save start time
while (((c = read_cycle()) - startTime) < t)
; // Wait high duration
digitalWrite(pin, LOW);
if (!(mask >>= 1))
{ // Next bit/byte
if (p >= end)
break;
pix = *p++;
mask = 0x80;
}
}
while ((read_cycle() - startTime) < period)
; // Wait for last bit
}
#endif // KENDRYTE_K210

View File

@ -0,0 +1,72 @@
#######################################
# Syntax Coloring Map For Adafruit_NeoPixel
#######################################
# Class
#######################################
Adafruit_NeoPixel KEYWORD1
#######################################
# Methods and Functions
#######################################
begin KEYWORD2
show KEYWORD2
setPin KEYWORD2
setPixelColor KEYWORD2
fill KEYWORD2
setBrightness KEYWORD2
clear KEYWORD2
updateLength KEYWORD2
updateType KEYWORD2
canShow KEYWORD2
getPixels KEYWORD2
getBrightness KEYWORD2
getPin KEYWORD2
numPixels KEYWORD2
getPixelColor KEYWORD2
sine8 KEYWORD2
gamma8 KEYWORD2
Color KEYWORD2
ColorHSV KEYWORD2
gamma32 KEYWORD2
#######################################
# Constants
#######################################
NEO_COLMASK LITERAL1
NEO_SPDMASK LITERAL1
NEO_KHZ800 LITERAL1
NEO_KHZ400 LITERAL1
NEO_RGB LITERAL1
NEO_RBG LITERAL1
NEO_GRB LITERAL1
NEO_GBR LITERAL1
NEO_BRG LITERAL1
NEO_BGR LITERAL1
NEO_WRGB LITERAL1
NEO_WRBG LITERAL1
NEO_WGRB LITERAL1
NEO_WGBR LITERAL1
NEO_WBRG LITERAL1
NEO_WBGR LITERAL1
NEO_RWGB LITERAL1
NEO_RWBG LITERAL1
NEO_RGWB LITERAL1
NEO_RGBW LITERAL1
NEO_RBWG LITERAL1
NEO_RBGW LITERAL1
NEO_GWRB LITERAL1
NEO_GWBR LITERAL1
NEO_GRWB LITERAL1
NEO_GRBW LITERAL1
NEO_GBWR LITERAL1
NEO_GBRW LITERAL1
NEO_BWRG LITERAL1
NEO_BWGR LITERAL1
NEO_BRWG LITERAL1
NEO_BRGW LITERAL1
NEO_BGWR LITERAL1
NEO_BGRW LITERAL1

View File

@ -0,0 +1,10 @@
name=Adafruit NeoPixel
version=1.12.3
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for controlling single-wire-based LED pixels and strip.
paragraph=Arduino library for controlling single-wire-based LED pixels and strip.
category=Display
url=https://github.com/adafruit/Adafruit_NeoPixel
architectures=*
includes=Adafruit_NeoPixel.h

View File

@ -0,0 +1,63 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //
// Unless you know what you are doing...
// Lines 47 and 52 have been edited to set transmit bit count
#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif
// ------ //
// ws2812 //
// ------ //
#define ws2812_wrap_target 0
#define ws2812_wrap 3
#define ws2812_T1 2
#define ws2812_T2 5
#define ws2812_T3 3
static const uint16_t ws2812_program_instructions[] = {
// .wrap_target
0x6221, // 0: out x, 1 side 0 [2]
0x1123, // 1: jmp !x, 3 side 1 [1]
0x1400, // 2: jmp 0 side 1 [4]
0xa442, // 3: nop side 0 [4]
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program ws2812_program = {
.instructions = ws2812_program_instructions,
.length = 4,
.origin = -1,
};
static inline pio_sm_config ws2812_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + ws2812_wrap_target, offset + ws2812_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
#include "hardware/clocks.h"
static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin,
float freq, uint bits) {
pio_gpio_init(pio, pin);
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
pio_sm_config c = ws2812_program_get_default_config(offset);
sm_config_set_sideset_pins(&c, pin);
sm_config_set_out_shift(&c, false, true,
bits); // <----<<< Length changed to "bits"
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
sm_config_set_clkdiv(&c, div);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
#endif

View File

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

View File

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

View File

@ -0,0 +1,32 @@
name: Arduino Library CI
on: [pull_request, push, repository_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py main_platforms
- name: clang
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: doxygen
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit BNO055 Library"
run: bash ci/doxy_gen_and_deploy.sh

View File

@ -0,0 +1,8 @@
# osx
.DS_Store
# doxygen
Doxyfile*
doxygen_sqlite3.db
html
*.tmp

View File

@ -0,0 +1,867 @@
/*!
* @file Adafruit_BNO055.cpp
*
* @mainpage Adafruit BNO055 Orientation Sensor
*
* @section intro_sec Introduction
*
* This is a library for the BNO055 orientation sensor
*
* Designed specifically to work with the Adafruit BNO055 9-DOF Breakout.
*
* Pick one up today in the adafruit shop!
* ------> https://www.adafruit.com/product/2472
*
* These sensors use I2C to communicate, 2 pins are required to interface.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit andopen-source hardware by purchasing products
* from Adafruit!
*
* @section author Author
*
* K.Townsend (Adafruit Industries)
*
* @section license License
*
* MIT license, all text above must be included in any redistribution
*/
#include "Arduino.h"
#include <limits.h>
#include <math.h>
#include "Adafruit_BNO055.h"
/*!
* @brief Instantiates a new Adafruit_BNO055 class
* @param sensorID
* sensor ID
* @param address
* i2c address
* @param theWire
* Wire object
*/
Adafruit_BNO055::Adafruit_BNO055(int32_t sensorID, uint8_t address,
TwoWire *theWire) {
// BNO055 clock stretches for 500us or more!
#ifdef ESP8266
theWire->setClockStretchLimit(1000); // Allow for 1000us of clock stretching
#endif
_sensorID = sensorID;
i2c_dev = new Adafruit_I2CDevice(address, theWire);
}
/*!
* @brief Sets up the HW
* @param mode
* mode values
* [OPERATION_MODE_CONFIG,
* OPERATION_MODE_ACCONLY,
* OPERATION_MODE_MAGONLY,
* OPERATION_MODE_GYRONLY,
* OPERATION_MODE_ACCMAG,
* OPERATION_MODE_ACCGYRO,
* OPERATION_MODE_MAGGYRO,
* OPERATION_MODE_AMG,
* OPERATION_MODE_IMUPLUS,
* OPERATION_MODE_COMPASS,
* OPERATION_MODE_M4G,
* OPERATION_MODE_NDOF_FMC_OFF,
* OPERATION_MODE_NDOF]
* @return true if process is successful
*/
bool Adafruit_BNO055::begin(adafruit_bno055_opmode_t mode) {
// Start without a detection
i2c_dev->begin(false);
#if defined(TARGET_RP2040)
// philhower core seems to work with this speed?
i2c_dev->setSpeed(50000);
#endif
// can take 850 ms to boot!
int timeout = 850; // in ms
while (timeout > 0) {
if (i2c_dev->begin()) {
break;
}
// wasnt detected... we'll retry!
delay(10);
timeout -= 10;
}
if (timeout <= 0)
return false;
/* Make sure we have the right device */
uint8_t id = read8(BNO055_CHIP_ID_ADDR);
if (id != BNO055_ID) {
delay(1000); // hold on for boot
id = read8(BNO055_CHIP_ID_ADDR);
if (id != BNO055_ID) {
return false; // still not? ok bail
}
}
/* Switch to config mode (just in case since this is the default) */
setMode(OPERATION_MODE_CONFIG);
/* Reset */
write8(BNO055_SYS_TRIGGER_ADDR, 0x20);
/* Delay incrased to 30ms due to power issues https://tinyurl.com/y375z699 */
delay(30);
while (read8(BNO055_CHIP_ID_ADDR) != BNO055_ID) {
delay(10);
}
delay(50);
/* Set to normal power mode */
write8(BNO055_PWR_MODE_ADDR, POWER_MODE_NORMAL);
delay(10);
write8(BNO055_PAGE_ID_ADDR, 0);
/* Set the output units */
/*
uint8_t unitsel = (0 << 7) | // Orientation = Android
(0 << 4) | // Temperature = Celsius
(0 << 2) | // Euler = Degrees
(1 << 1) | // Gyro = Rads
(0 << 0); // Accelerometer = m/s^2
write8(BNO055_UNIT_SEL_ADDR, unitsel);
*/
/* Configure axis mapping (see section 3.4) */
/*
write8(BNO055_AXIS_MAP_CONFIG_ADDR, REMAP_CONFIG_P2); // P0-P7, Default is P1
delay(10);
write8(BNO055_AXIS_MAP_SIGN_ADDR, REMAP_SIGN_P2); // P0-P7, Default is P1
delay(10);
*/
write8(BNO055_SYS_TRIGGER_ADDR, 0x0);
delay(10);
/* Set the requested operating mode (see section 3.3) */
setMode(mode);
delay(20);
return true;
}
/*!
* @brief Puts the chip in the specified operating mode
* @param mode
* mode values
* [OPERATION_MODE_CONFIG,
* OPERATION_MODE_ACCONLY,
* OPERATION_MODE_MAGONLY,
* OPERATION_MODE_GYRONLY,
* OPERATION_MODE_ACCMAG,
* OPERATION_MODE_ACCGYRO,
* OPERATION_MODE_MAGGYRO,
* OPERATION_MODE_AMG,
* OPERATION_MODE_IMUPLUS,
* OPERATION_MODE_COMPASS,
* OPERATION_MODE_M4G,
* OPERATION_MODE_NDOF_FMC_OFF,
* OPERATION_MODE_NDOF]
*/
void Adafruit_BNO055::setMode(adafruit_bno055_opmode_t mode) {
_mode = mode;
write8(BNO055_OPR_MODE_ADDR, _mode);
delay(30);
}
/*!
* @brief Gets the current operating mode of the chip
* @return operating_mode in integer which can be mapped in Section 3.3
* for example: a return of 12 (0X0C) => NDOF
*/
adafruit_bno055_opmode_t Adafruit_BNO055::getMode() {
return (adafruit_bno055_opmode_t)read8(BNO055_OPR_MODE_ADDR);
}
/*!
* @brief Changes the chip's axis remap
* @param remapcode
* remap code possible values
* [REMAP_CONFIG_P0
* REMAP_CONFIG_P1 (default)
* REMAP_CONFIG_P2
* REMAP_CONFIG_P3
* REMAP_CONFIG_P4
* REMAP_CONFIG_P5
* REMAP_CONFIG_P6
* REMAP_CONFIG_P7]
*/
void Adafruit_BNO055::setAxisRemap(
adafruit_bno055_axis_remap_config_t remapcode) {
adafruit_bno055_opmode_t modeback = _mode;
setMode(OPERATION_MODE_CONFIG);
delay(25);
write8(BNO055_AXIS_MAP_CONFIG_ADDR, remapcode);
delay(10);
/* Set the requested operating mode (see section 3.3) */
setMode(modeback);
delay(20);
}
/*!
* @brief Changes the chip's axis signs
* @param remapsign
* remap sign possible values
* [REMAP_SIGN_P0
* REMAP_SIGN_P1 (default)
* REMAP_SIGN_P2
* REMAP_SIGN_P3
* REMAP_SIGN_P4
* REMAP_SIGN_P5
* REMAP_SIGN_P6
* REMAP_SIGN_P7]
*/
void Adafruit_BNO055::setAxisSign(adafruit_bno055_axis_remap_sign_t remapsign) {
adafruit_bno055_opmode_t modeback = _mode;
setMode(OPERATION_MODE_CONFIG);
delay(25);
write8(BNO055_AXIS_MAP_SIGN_ADDR, remapsign);
delay(10);
/* Set the requested operating mode (see section 3.3) */
setMode(modeback);
delay(20);
}
/*!
* @brief Use the external 32.768KHz crystal
* @param usextal
* use external crystal boolean
*/
void Adafruit_BNO055::setExtCrystalUse(boolean usextal) {
adafruit_bno055_opmode_t modeback = _mode;
/* Switch to config mode (just in case since this is the default) */
setMode(OPERATION_MODE_CONFIG);
delay(25);
write8(BNO055_PAGE_ID_ADDR, 0);
if (usextal) {
write8(BNO055_SYS_TRIGGER_ADDR, 0x80);
} else {
write8(BNO055_SYS_TRIGGER_ADDR, 0x00);
}
delay(10);
/* Set the requested operating mode (see section 3.3) */
setMode(modeback);
delay(20);
}
/*!
* @brief Gets the latest system status info
* @param system_status
* system status info
* @param self_test_result
* self test result
* @param system_error
* system error info
*/
void Adafruit_BNO055::getSystemStatus(uint8_t *system_status,
uint8_t *self_test_result,
uint8_t *system_error) {
write8(BNO055_PAGE_ID_ADDR, 0);
/* System Status (see section 4.3.58)
0 = Idle
1 = System Error
2 = Initializing Peripherals
3 = System Iniitalization
4 = Executing Self-Test
5 = Sensor fusio algorithm running
6 = System running without fusion algorithms
*/
if (system_status != 0)
*system_status = read8(BNO055_SYS_STAT_ADDR);
/* Self Test Results
1 = test passed, 0 = test failed
Bit 0 = Accelerometer self test
Bit 1 = Magnetometer self test
Bit 2 = Gyroscope self test
Bit 3 = MCU self test
0x0F = all good!
*/
if (self_test_result != 0)
*self_test_result = read8(BNO055_SELFTEST_RESULT_ADDR);
/* System Error (see section 4.3.59)
0 = No error
1 = Peripheral initialization error
2 = System initialization error
3 = Self test result failed
4 = Register map value out of range
5 = Register map address out of range
6 = Register map write error
7 = BNO low power mode not available for selected operat ion mode
8 = Accelerometer power mode not available
9 = Fusion algorithm configuration error
A = Sensor configuration error
*/
if (system_error != 0)
*system_error = read8(BNO055_SYS_ERR_ADDR);
delay(200);
}
/*!
* @brief Gets the chip revision numbers
* @param info
* revision info
*/
void Adafruit_BNO055::getRevInfo(adafruit_bno055_rev_info_t *info) {
uint8_t a, b;
memset(info, 0, sizeof(adafruit_bno055_rev_info_t));
/* Check the accelerometer revision */
info->accel_rev = read8(BNO055_ACCEL_REV_ID_ADDR);
/* Check the magnetometer revision */
info->mag_rev = read8(BNO055_MAG_REV_ID_ADDR);
/* Check the gyroscope revision */
info->gyro_rev = read8(BNO055_GYRO_REV_ID_ADDR);
/* Check the SW revision */
info->bl_rev = read8(BNO055_BL_REV_ID_ADDR);
a = read8(BNO055_SW_REV_ID_LSB_ADDR);
b = read8(BNO055_SW_REV_ID_MSB_ADDR);
info->sw_rev = (((uint16_t)b) << 8) | ((uint16_t)a);
}
/*!
* @brief Gets current calibration state. Each value should be a uint8_t
* pointer and it will be set to 0 if not calibrated and 3 if
* fully calibrated.
* See section 34.3.54
* @param sys
* Current system calibration status, depends on status of all sensors,
* read-only
* @param gyro
* Current calibration status of Gyroscope, read-only
* @param accel
* Current calibration status of Accelerometer, read-only
* @param mag
* Current calibration status of Magnetometer, read-only
*/
void Adafruit_BNO055::getCalibration(uint8_t *sys, uint8_t *gyro,
uint8_t *accel, uint8_t *mag) {
uint8_t calData = read8(BNO055_CALIB_STAT_ADDR);
if (sys != NULL) {
*sys = (calData >> 6) & 0x03;
}
if (gyro != NULL) {
*gyro = (calData >> 4) & 0x03;
}
if (accel != NULL) {
*accel = (calData >> 2) & 0x03;
}
if (mag != NULL) {
*mag = calData & 0x03;
}
}
/*!
* @brief Gets the temperature in degrees celsius
* @return temperature in degrees celsius
*/
int8_t Adafruit_BNO055::getTemp() {
int8_t temp = (int8_t)(read8(BNO055_TEMP_ADDR));
return temp;
}
/*!
* @brief Gets a vector reading from the specified source
* @param vector_type
* possible vector type values
* [VECTOR_ACCELEROMETER
* VECTOR_MAGNETOMETER
* VECTOR_GYROSCOPE
* VECTOR_EULER
* VECTOR_LINEARACCEL
* VECTOR_GRAVITY]
* @return vector from specified source
*/
imu::Vector<3> Adafruit_BNO055::getVector(adafruit_vector_type_t vector_type) {
imu::Vector<3> xyz;
uint8_t buffer[6];
memset(buffer, 0, 6);
int16_t x, y, z;
x = y = z = 0;
/* Read vector data (6 bytes) */
readLen((adafruit_bno055_reg_t)vector_type, buffer, 6);
x = ((int16_t)buffer[0]) | (((int16_t)buffer[1]) << 8);
y = ((int16_t)buffer[2]) | (((int16_t)buffer[3]) << 8);
z = ((int16_t)buffer[4]) | (((int16_t)buffer[5]) << 8);
/*!
* Convert the value to an appropriate range (section 3.6.4)
* and assign the value to the Vector type
*/
switch (vector_type) {
case VECTOR_MAGNETOMETER:
/* 1uT = 16 LSB */
xyz[0] = ((double)x) / 16.0;
xyz[1] = ((double)y) / 16.0;
xyz[2] = ((double)z) / 16.0;
break;
case VECTOR_GYROSCOPE:
/* 1dps = 16 LSB */
xyz[0] = ((double)x) / 16.0;
xyz[1] = ((double)y) / 16.0;
xyz[2] = ((double)z) / 16.0;
break;
case VECTOR_EULER:
/* 1 degree = 16 LSB */
xyz[0] = ((double)x) / 16.0;
xyz[1] = ((double)y) / 16.0;
xyz[2] = ((double)z) / 16.0;
break;
case VECTOR_ACCELEROMETER:
/* 1m/s^2 = 100 LSB */
xyz[0] = ((double)x) / 100.0;
xyz[1] = ((double)y) / 100.0;
xyz[2] = ((double)z) / 100.0;
break;
case VECTOR_LINEARACCEL:
/* 1m/s^2 = 100 LSB */
xyz[0] = ((double)x) / 100.0;
xyz[1] = ((double)y) / 100.0;
xyz[2] = ((double)z) / 100.0;
break;
case VECTOR_GRAVITY:
/* 1m/s^2 = 100 LSB */
xyz[0] = ((double)x) / 100.0;
xyz[1] = ((double)y) / 100.0;
xyz[2] = ((double)z) / 100.0;
break;
}
return xyz;
}
/*!
* @brief Gets a quaternion reading from the specified source
* @return quaternion reading
*/
imu::Quaternion Adafruit_BNO055::getQuat() {
uint8_t buffer[8];
memset(buffer, 0, 8);
int16_t x, y, z, w;
x = y = z = w = 0;
/* Read quat data (8 bytes) */
readLen(BNO055_QUATERNION_DATA_W_LSB_ADDR, buffer, 8);
w = (((uint16_t)buffer[1]) << 8) | ((uint16_t)buffer[0]);
x = (((uint16_t)buffer[3]) << 8) | ((uint16_t)buffer[2]);
y = (((uint16_t)buffer[5]) << 8) | ((uint16_t)buffer[4]);
z = (((uint16_t)buffer[7]) << 8) | ((uint16_t)buffer[6]);
/*!
* Assign to Quaternion
* See
* https://cdn-shop.adafruit.com/datasheets/BST_BNO055_DS000_12.pdf
* 3.6.5.5 Orientation (Quaternion)
*/
const double scale = (1.0 / (1 << 14));
imu::Quaternion quat(scale * w, scale * x, scale * y, scale * z);
return quat;
}
/*!
* @brief Provides the sensor_t data for this sensor
* @param sensor
* Sensor description
*/
void Adafruit_BNO055::getSensor(sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy(sensor->name, "BNO055", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name) - 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_ORIENTATION;
sensor->min_delay = 0;
sensor->max_value = 0.0F;
sensor->min_value = 0.0F;
sensor->resolution = 0.01F;
}
/*!
* @brief Reads the sensor and returns the data as a sensors_event_t
* @param event
* Event description
* @return always returns true
*/
bool Adafruit_BNO055::getEvent(sensors_event_t *event) {
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_ORIENTATION;
event->timestamp = millis();
/* Get a Euler angle sample for orientation */
imu::Vector<3> euler = getVector(Adafruit_BNO055::VECTOR_EULER);
event->orientation.x = euler.x();
event->orientation.y = euler.y();
event->orientation.z = euler.z();
return true;
}
/*!
* @brief Reads the sensor and returns the data as a sensors_event_t
* @param event
* Event description
* @param vec_type
* specify the type of reading
* @return always returns true
*/
bool Adafruit_BNO055::getEvent(sensors_event_t *event,
adafruit_vector_type_t vec_type) {
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->timestamp = millis();
// read the data according to vec_type
imu::Vector<3> vec;
if (vec_type == Adafruit_BNO055::VECTOR_LINEARACCEL) {
event->type = SENSOR_TYPE_LINEAR_ACCELERATION;
vec = getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);
event->acceleration.x = vec.x();
event->acceleration.y = vec.y();
event->acceleration.z = vec.z();
} else if (vec_type == Adafruit_BNO055::VECTOR_ACCELEROMETER) {
event->type = SENSOR_TYPE_ACCELEROMETER;
vec = getVector(Adafruit_BNO055::VECTOR_ACCELEROMETER);
event->acceleration.x = vec.x();
event->acceleration.y = vec.y();
event->acceleration.z = vec.z();
} else if (vec_type == Adafruit_BNO055::VECTOR_GRAVITY) {
event->type = SENSOR_TYPE_GRAVITY;
vec = getVector(Adafruit_BNO055::VECTOR_GRAVITY);
event->acceleration.x = vec.x();
event->acceleration.y = vec.y();
event->acceleration.z = vec.z();
} else if (vec_type == Adafruit_BNO055::VECTOR_EULER) {
event->type = SENSOR_TYPE_ORIENTATION;
vec = getVector(Adafruit_BNO055::VECTOR_EULER);
event->orientation.x = vec.x();
event->orientation.y = vec.y();
event->orientation.z = vec.z();
} else if (vec_type == Adafruit_BNO055::VECTOR_GYROSCOPE) {
event->type = SENSOR_TYPE_GYROSCOPE;
vec = getVector(Adafruit_BNO055::VECTOR_GYROSCOPE);
event->gyro.x = vec.x() * SENSORS_DPS_TO_RADS;
event->gyro.y = vec.y() * SENSORS_DPS_TO_RADS;
event->gyro.z = vec.z() * SENSORS_DPS_TO_RADS;
} else if (vec_type == Adafruit_BNO055::VECTOR_MAGNETOMETER) {
event->type = SENSOR_TYPE_MAGNETIC_FIELD;
vec = getVector(Adafruit_BNO055::VECTOR_MAGNETOMETER);
event->magnetic.x = vec.x();
event->magnetic.y = vec.y();
event->magnetic.z = vec.z();
}
return true;
}
/*!
* @brief Reads the sensor's offset registers into a byte array
* @param calibData
* Calibration offset (buffer size should be 22)
* @return true if read is successful
*/
bool Adafruit_BNO055::getSensorOffsets(uint8_t *calibData) {
if (isFullyCalibrated()) {
adafruit_bno055_opmode_t lastMode = _mode;
setMode(OPERATION_MODE_CONFIG);
readLen(ACCEL_OFFSET_X_LSB_ADDR, calibData, NUM_BNO055_OFFSET_REGISTERS);
setMode(lastMode);
return true;
}
return false;
}
/*!
* @brief Reads the sensor's offset registers into an offset struct
* @param offsets_type
* type of offsets
* @return true if read is successful
*/
bool Adafruit_BNO055::getSensorOffsets(
adafruit_bno055_offsets_t &offsets_type) {
if (isFullyCalibrated()) {
adafruit_bno055_opmode_t lastMode = _mode;
setMode(OPERATION_MODE_CONFIG);
delay(25);
/* Accel offset range depends on the G-range:
+/-2g = +/- 2000 mg
+/-4g = +/- 4000 mg
+/-8g = +/- 8000 mg
+/-1§g = +/- 16000 mg */
offsets_type.accel_offset_x = (read8(ACCEL_OFFSET_X_MSB_ADDR) << 8) |
(read8(ACCEL_OFFSET_X_LSB_ADDR));
offsets_type.accel_offset_y = (read8(ACCEL_OFFSET_Y_MSB_ADDR) << 8) |
(read8(ACCEL_OFFSET_Y_LSB_ADDR));
offsets_type.accel_offset_z = (read8(ACCEL_OFFSET_Z_MSB_ADDR) << 8) |
(read8(ACCEL_OFFSET_Z_LSB_ADDR));
/* Magnetometer offset range = +/- 6400 LSB where 1uT = 16 LSB */
offsets_type.mag_offset_x =
(read8(MAG_OFFSET_X_MSB_ADDR) << 8) | (read8(MAG_OFFSET_X_LSB_ADDR));
offsets_type.mag_offset_y =
(read8(MAG_OFFSET_Y_MSB_ADDR) << 8) | (read8(MAG_OFFSET_Y_LSB_ADDR));
offsets_type.mag_offset_z =
(read8(MAG_OFFSET_Z_MSB_ADDR) << 8) | (read8(MAG_OFFSET_Z_LSB_ADDR));
/* Gyro offset range depends on the DPS range:
2000 dps = +/- 32000 LSB
1000 dps = +/- 16000 LSB
500 dps = +/- 8000 LSB
250 dps = +/- 4000 LSB
125 dps = +/- 2000 LSB
... where 1 DPS = 16 LSB */
offsets_type.gyro_offset_x =
(read8(GYRO_OFFSET_X_MSB_ADDR) << 8) | (read8(GYRO_OFFSET_X_LSB_ADDR));
offsets_type.gyro_offset_y =
(read8(GYRO_OFFSET_Y_MSB_ADDR) << 8) | (read8(GYRO_OFFSET_Y_LSB_ADDR));
offsets_type.gyro_offset_z =
(read8(GYRO_OFFSET_Z_MSB_ADDR) << 8) | (read8(GYRO_OFFSET_Z_LSB_ADDR));
/* Accelerometer radius = +/- 1000 LSB */
offsets_type.accel_radius =
(read8(ACCEL_RADIUS_MSB_ADDR) << 8) | (read8(ACCEL_RADIUS_LSB_ADDR));
/* Magnetometer radius = +/- 960 LSB */
offsets_type.mag_radius =
(read8(MAG_RADIUS_MSB_ADDR) << 8) | (read8(MAG_RADIUS_LSB_ADDR));
setMode(lastMode);
return true;
}
return false;
}
/*!
* @brief Writes an array of calibration values to the sensor's offset
* @param calibData
* calibration data
*/
void Adafruit_BNO055::setSensorOffsets(const uint8_t *calibData) {
adafruit_bno055_opmode_t lastMode = _mode;
setMode(OPERATION_MODE_CONFIG);
delay(25);
/* Note: Configuration will take place only when user writes to the last
byte of each config data pair (ex. ACCEL_OFFSET_Z_MSB_ADDR, etc.).
Therefore the last byte must be written whenever the user wants to
changes the configuration. */
/* A writeLen() would make this much cleaner */
write8(ACCEL_OFFSET_X_LSB_ADDR, calibData[0]);
write8(ACCEL_OFFSET_X_MSB_ADDR, calibData[1]);
write8(ACCEL_OFFSET_Y_LSB_ADDR, calibData[2]);
write8(ACCEL_OFFSET_Y_MSB_ADDR, calibData[3]);
write8(ACCEL_OFFSET_Z_LSB_ADDR, calibData[4]);
write8(ACCEL_OFFSET_Z_MSB_ADDR, calibData[5]);
write8(MAG_OFFSET_X_LSB_ADDR, calibData[6]);
write8(MAG_OFFSET_X_MSB_ADDR, calibData[7]);
write8(MAG_OFFSET_Y_LSB_ADDR, calibData[8]);
write8(MAG_OFFSET_Y_MSB_ADDR, calibData[9]);
write8(MAG_OFFSET_Z_LSB_ADDR, calibData[10]);
write8(MAG_OFFSET_Z_MSB_ADDR, calibData[11]);
write8(GYRO_OFFSET_X_LSB_ADDR, calibData[12]);
write8(GYRO_OFFSET_X_MSB_ADDR, calibData[13]);
write8(GYRO_OFFSET_Y_LSB_ADDR, calibData[14]);
write8(GYRO_OFFSET_Y_MSB_ADDR, calibData[15]);
write8(GYRO_OFFSET_Z_LSB_ADDR, calibData[16]);
write8(GYRO_OFFSET_Z_MSB_ADDR, calibData[17]);
write8(ACCEL_RADIUS_LSB_ADDR, calibData[18]);
write8(ACCEL_RADIUS_MSB_ADDR, calibData[19]);
write8(MAG_RADIUS_LSB_ADDR, calibData[20]);
write8(MAG_RADIUS_MSB_ADDR, calibData[21]);
setMode(lastMode);
}
/*!
* @brief Writes to the sensor's offset registers from an offset struct
* @param offsets_type
* accel_offset_x = acceleration offset x
* accel_offset_y = acceleration offset y
* accel_offset_z = acceleration offset z
*
* mag_offset_x = magnetometer offset x
* mag_offset_y = magnetometer offset y
* mag_offset_z = magnetometer offset z
*
* gyro_offset_x = gyroscrope offset x
* gyro_offset_y = gyroscrope offset y
* gyro_offset_z = gyroscrope offset z
*/
void Adafruit_BNO055::setSensorOffsets(
const adafruit_bno055_offsets_t &offsets_type) {
adafruit_bno055_opmode_t lastMode = _mode;
setMode(OPERATION_MODE_CONFIG);
delay(25);
/* Note: Configuration will take place only when user writes to the last
byte of each config data pair (ex. ACCEL_OFFSET_Z_MSB_ADDR, etc.).
Therefore the last byte must be written whenever the user wants to
changes the configuration. */
write8(ACCEL_OFFSET_X_LSB_ADDR, (offsets_type.accel_offset_x) & 0x0FF);
write8(ACCEL_OFFSET_X_MSB_ADDR, (offsets_type.accel_offset_x >> 8) & 0x0FF);
write8(ACCEL_OFFSET_Y_LSB_ADDR, (offsets_type.accel_offset_y) & 0x0FF);
write8(ACCEL_OFFSET_Y_MSB_ADDR, (offsets_type.accel_offset_y >> 8) & 0x0FF);
write8(ACCEL_OFFSET_Z_LSB_ADDR, (offsets_type.accel_offset_z) & 0x0FF);
write8(ACCEL_OFFSET_Z_MSB_ADDR, (offsets_type.accel_offset_z >> 8) & 0x0FF);
write8(MAG_OFFSET_X_LSB_ADDR, (offsets_type.mag_offset_x) & 0x0FF);
write8(MAG_OFFSET_X_MSB_ADDR, (offsets_type.mag_offset_x >> 8) & 0x0FF);
write8(MAG_OFFSET_Y_LSB_ADDR, (offsets_type.mag_offset_y) & 0x0FF);
write8(MAG_OFFSET_Y_MSB_ADDR, (offsets_type.mag_offset_y >> 8) & 0x0FF);
write8(MAG_OFFSET_Z_LSB_ADDR, (offsets_type.mag_offset_z) & 0x0FF);
write8(MAG_OFFSET_Z_MSB_ADDR, (offsets_type.mag_offset_z >> 8) & 0x0FF);
write8(GYRO_OFFSET_X_LSB_ADDR, (offsets_type.gyro_offset_x) & 0x0FF);
write8(GYRO_OFFSET_X_MSB_ADDR, (offsets_type.gyro_offset_x >> 8) & 0x0FF);
write8(GYRO_OFFSET_Y_LSB_ADDR, (offsets_type.gyro_offset_y) & 0x0FF);
write8(GYRO_OFFSET_Y_MSB_ADDR, (offsets_type.gyro_offset_y >> 8) & 0x0FF);
write8(GYRO_OFFSET_Z_LSB_ADDR, (offsets_type.gyro_offset_z) & 0x0FF);
write8(GYRO_OFFSET_Z_MSB_ADDR, (offsets_type.gyro_offset_z >> 8) & 0x0FF);
write8(ACCEL_RADIUS_LSB_ADDR, (offsets_type.accel_radius) & 0x0FF);
write8(ACCEL_RADIUS_MSB_ADDR, (offsets_type.accel_radius >> 8) & 0x0FF);
write8(MAG_RADIUS_LSB_ADDR, (offsets_type.mag_radius) & 0x0FF);
write8(MAG_RADIUS_MSB_ADDR, (offsets_type.mag_radius >> 8) & 0x0FF);
setMode(lastMode);
}
/*!
* @brief Checks of all cal status values are set to 3 (fully calibrated)
* @return status of calibration
*/
bool Adafruit_BNO055::isFullyCalibrated() {
uint8_t system, gyro, accel, mag;
getCalibration(&system, &gyro, &accel, &mag);
switch (_mode) {
case OPERATION_MODE_ACCONLY:
return (accel == 3);
case OPERATION_MODE_MAGONLY:
return (mag == 3);
case OPERATION_MODE_GYRONLY:
case OPERATION_MODE_M4G: /* No magnetometer calibration required. */
return (gyro == 3);
case OPERATION_MODE_ACCMAG:
case OPERATION_MODE_COMPASS:
return (accel == 3 && mag == 3);
case OPERATION_MODE_ACCGYRO:
case OPERATION_MODE_IMUPLUS:
return (accel == 3 && gyro == 3);
case OPERATION_MODE_MAGGYRO:
return (mag == 3 && gyro == 3);
default:
return (system == 3 && gyro == 3 && accel == 3 && mag == 3);
}
}
/*!
* @brief Enter Suspend mode (i.e., sleep)
*/
void Adafruit_BNO055::enterSuspendMode() {
adafruit_bno055_opmode_t modeback = _mode;
/* Switch to config mode (just in case since this is the default) */
setMode(OPERATION_MODE_CONFIG);
delay(25);
write8(BNO055_PWR_MODE_ADDR, 0x02);
/* Set the requested operating mode (see section 3.3) */
setMode(modeback);
delay(20);
}
/*!
* @brief Enter Normal mode (i.e., wake)
*/
void Adafruit_BNO055::enterNormalMode() {
adafruit_bno055_opmode_t modeback = _mode;
/* Switch to config mode (just in case since this is the default) */
setMode(OPERATION_MODE_CONFIG);
delay(25);
write8(BNO055_PWR_MODE_ADDR, 0x00);
/* Set the requested operating mode (see section 3.3) */
setMode(modeback);
delay(20);
}
/*!
* @brief Writes an 8 bit value over I2C
*/
bool Adafruit_BNO055::write8(adafruit_bno055_reg_t reg, byte value) {
uint8_t buffer[2] = {(uint8_t)reg, (uint8_t)value};
return i2c_dev->write(buffer, 2);
}
/*!
* @brief Reads an 8 bit value over I2C
*/
byte Adafruit_BNO055::read8(adafruit_bno055_reg_t reg) {
uint8_t buffer[1] = {reg};
i2c_dev->write_then_read(buffer, 1, buffer, 1);
return (byte)buffer[0];
}
/*!
* @brief Reads the specified number of bytes over I2C
*/
bool Adafruit_BNO055::readLen(adafruit_bno055_reg_t reg, byte *buffer,
uint8_t len) {
uint8_t reg_buf[1] = {(uint8_t)reg};
return i2c_dev->write_then_read(reg_buf, 1, buffer, len);
}

View File

@ -0,0 +1,328 @@
/*!
* @file Adafruit_BNO055.h
*
* This is a library for the BNO055 orientation sensor
*
* Designed specifically to work with the Adafruit BNO055 Breakout.
*
* Pick one up today in the adafruit shop!
* ------> https://www.adafruit.com/product/2472
*
* These sensors use I2C to communicate, 2 pins are required to interface.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit andopen-source hardware by purchasing products
* from Adafruit!
*
* K.Townsend (Adafruit Industries)
*
* MIT license, all text above must be included in any redistribution
*/
#ifndef __ADAFRUIT_BNO055_H__
#define __ADAFRUIT_BNO055_H__
#include "Arduino.h"
#include "utility/imumaths.h"
#include <Adafruit_I2CDevice.h>
#include <Adafruit_Sensor.h>
/** BNO055 Address A **/
#define BNO055_ADDRESS_A (0x28)
/** BNO055 Address B **/
#define BNO055_ADDRESS_B (0x29)
/** BNO055 ID **/
#define BNO055_ID (0xA0)
/** Offsets registers **/
#define NUM_BNO055_OFFSET_REGISTERS (22)
/** A structure to represent offsets **/
typedef struct {
int16_t accel_offset_x; /**< x acceleration offset */
int16_t accel_offset_y; /**< y acceleration offset */
int16_t accel_offset_z; /**< z acceleration offset */
int16_t mag_offset_x; /**< x magnetometer offset */
int16_t mag_offset_y; /**< y magnetometer offset */
int16_t mag_offset_z; /**< z magnetometer offset */
int16_t gyro_offset_x; /**< x gyroscrope offset */
int16_t gyro_offset_y; /**< y gyroscrope offset */
int16_t gyro_offset_z; /**< z gyroscrope offset */
int16_t accel_radius; /**< acceleration radius */
int16_t mag_radius; /**< magnetometer radius */
} adafruit_bno055_offsets_t;
/** Operation mode settings **/
typedef enum {
OPERATION_MODE_CONFIG = 0X00,
OPERATION_MODE_ACCONLY = 0X01,
OPERATION_MODE_MAGONLY = 0X02,
OPERATION_MODE_GYRONLY = 0X03,
OPERATION_MODE_ACCMAG = 0X04,
OPERATION_MODE_ACCGYRO = 0X05,
OPERATION_MODE_MAGGYRO = 0X06,
OPERATION_MODE_AMG = 0X07,
OPERATION_MODE_IMUPLUS = 0X08,
OPERATION_MODE_COMPASS = 0X09,
OPERATION_MODE_M4G = 0X0A,
OPERATION_MODE_NDOF_FMC_OFF = 0X0B,
OPERATION_MODE_NDOF = 0X0C
} adafruit_bno055_opmode_t;
/*!
* @brief Class that stores state and functions for interacting with
* BNO055 Sensor
*/
class Adafruit_BNO055 : public Adafruit_Sensor {
public:
/** BNO055 Registers **/
typedef enum {
/* Page id register definition */
BNO055_PAGE_ID_ADDR = 0X07,
/* PAGE0 REGISTER DEFINITION START*/
BNO055_CHIP_ID_ADDR = 0x00,
BNO055_ACCEL_REV_ID_ADDR = 0x01,
BNO055_MAG_REV_ID_ADDR = 0x02,
BNO055_GYRO_REV_ID_ADDR = 0x03,
BNO055_SW_REV_ID_LSB_ADDR = 0x04,
BNO055_SW_REV_ID_MSB_ADDR = 0x05,
BNO055_BL_REV_ID_ADDR = 0X06,
/* Accel data register */
BNO055_ACCEL_DATA_X_LSB_ADDR = 0X08,
BNO055_ACCEL_DATA_X_MSB_ADDR = 0X09,
BNO055_ACCEL_DATA_Y_LSB_ADDR = 0X0A,
BNO055_ACCEL_DATA_Y_MSB_ADDR = 0X0B,
BNO055_ACCEL_DATA_Z_LSB_ADDR = 0X0C,
BNO055_ACCEL_DATA_Z_MSB_ADDR = 0X0D,
/* Mag data register */
BNO055_MAG_DATA_X_LSB_ADDR = 0X0E,
BNO055_MAG_DATA_X_MSB_ADDR = 0X0F,
BNO055_MAG_DATA_Y_LSB_ADDR = 0X10,
BNO055_MAG_DATA_Y_MSB_ADDR = 0X11,
BNO055_MAG_DATA_Z_LSB_ADDR = 0X12,
BNO055_MAG_DATA_Z_MSB_ADDR = 0X13,
/* Gyro data registers */
BNO055_GYRO_DATA_X_LSB_ADDR = 0X14,
BNO055_GYRO_DATA_X_MSB_ADDR = 0X15,
BNO055_GYRO_DATA_Y_LSB_ADDR = 0X16,
BNO055_GYRO_DATA_Y_MSB_ADDR = 0X17,
BNO055_GYRO_DATA_Z_LSB_ADDR = 0X18,
BNO055_GYRO_DATA_Z_MSB_ADDR = 0X19,
/* Euler data registers */
BNO055_EULER_H_LSB_ADDR = 0X1A,
BNO055_EULER_H_MSB_ADDR = 0X1B,
BNO055_EULER_R_LSB_ADDR = 0X1C,
BNO055_EULER_R_MSB_ADDR = 0X1D,
BNO055_EULER_P_LSB_ADDR = 0X1E,
BNO055_EULER_P_MSB_ADDR = 0X1F,
/* Quaternion data registers */
BNO055_QUATERNION_DATA_W_LSB_ADDR = 0X20,
BNO055_QUATERNION_DATA_W_MSB_ADDR = 0X21,
BNO055_QUATERNION_DATA_X_LSB_ADDR = 0X22,
BNO055_QUATERNION_DATA_X_MSB_ADDR = 0X23,
BNO055_QUATERNION_DATA_Y_LSB_ADDR = 0X24,
BNO055_QUATERNION_DATA_Y_MSB_ADDR = 0X25,
BNO055_QUATERNION_DATA_Z_LSB_ADDR = 0X26,
BNO055_QUATERNION_DATA_Z_MSB_ADDR = 0X27,
/* Linear acceleration data registers */
BNO055_LINEAR_ACCEL_DATA_X_LSB_ADDR = 0X28,
BNO055_LINEAR_ACCEL_DATA_X_MSB_ADDR = 0X29,
BNO055_LINEAR_ACCEL_DATA_Y_LSB_ADDR = 0X2A,
BNO055_LINEAR_ACCEL_DATA_Y_MSB_ADDR = 0X2B,
BNO055_LINEAR_ACCEL_DATA_Z_LSB_ADDR = 0X2C,
BNO055_LINEAR_ACCEL_DATA_Z_MSB_ADDR = 0X2D,
/* Gravity data registers */
BNO055_GRAVITY_DATA_X_LSB_ADDR = 0X2E,
BNO055_GRAVITY_DATA_X_MSB_ADDR = 0X2F,
BNO055_GRAVITY_DATA_Y_LSB_ADDR = 0X30,
BNO055_GRAVITY_DATA_Y_MSB_ADDR = 0X31,
BNO055_GRAVITY_DATA_Z_LSB_ADDR = 0X32,
BNO055_GRAVITY_DATA_Z_MSB_ADDR = 0X33,
/* Temperature data register */
BNO055_TEMP_ADDR = 0X34,
/* Status registers */
BNO055_CALIB_STAT_ADDR = 0X35,
BNO055_SELFTEST_RESULT_ADDR = 0X36,
BNO055_INTR_STAT_ADDR = 0X37,
BNO055_SYS_CLK_STAT_ADDR = 0X38,
BNO055_SYS_STAT_ADDR = 0X39,
BNO055_SYS_ERR_ADDR = 0X3A,
/* Unit selection register */
BNO055_UNIT_SEL_ADDR = 0X3B,
/* Mode registers */
BNO055_OPR_MODE_ADDR = 0X3D,
BNO055_PWR_MODE_ADDR = 0X3E,
BNO055_SYS_TRIGGER_ADDR = 0X3F,
BNO055_TEMP_SOURCE_ADDR = 0X40,
/* Axis remap registers */
BNO055_AXIS_MAP_CONFIG_ADDR = 0X41,
BNO055_AXIS_MAP_SIGN_ADDR = 0X42,
/* SIC registers */
BNO055_SIC_MATRIX_0_LSB_ADDR = 0X43,
BNO055_SIC_MATRIX_0_MSB_ADDR = 0X44,
BNO055_SIC_MATRIX_1_LSB_ADDR = 0X45,
BNO055_SIC_MATRIX_1_MSB_ADDR = 0X46,
BNO055_SIC_MATRIX_2_LSB_ADDR = 0X47,
BNO055_SIC_MATRIX_2_MSB_ADDR = 0X48,
BNO055_SIC_MATRIX_3_LSB_ADDR = 0X49,
BNO055_SIC_MATRIX_3_MSB_ADDR = 0X4A,
BNO055_SIC_MATRIX_4_LSB_ADDR = 0X4B,
BNO055_SIC_MATRIX_4_MSB_ADDR = 0X4C,
BNO055_SIC_MATRIX_5_LSB_ADDR = 0X4D,
BNO055_SIC_MATRIX_5_MSB_ADDR = 0X4E,
BNO055_SIC_MATRIX_6_LSB_ADDR = 0X4F,
BNO055_SIC_MATRIX_6_MSB_ADDR = 0X50,
BNO055_SIC_MATRIX_7_LSB_ADDR = 0X51,
BNO055_SIC_MATRIX_7_MSB_ADDR = 0X52,
BNO055_SIC_MATRIX_8_LSB_ADDR = 0X53,
BNO055_SIC_MATRIX_8_MSB_ADDR = 0X54,
/* Accelerometer Offset registers */
ACCEL_OFFSET_X_LSB_ADDR = 0X55,
ACCEL_OFFSET_X_MSB_ADDR = 0X56,
ACCEL_OFFSET_Y_LSB_ADDR = 0X57,
ACCEL_OFFSET_Y_MSB_ADDR = 0X58,
ACCEL_OFFSET_Z_LSB_ADDR = 0X59,
ACCEL_OFFSET_Z_MSB_ADDR = 0X5A,
/* Magnetometer Offset registers */
MAG_OFFSET_X_LSB_ADDR = 0X5B,
MAG_OFFSET_X_MSB_ADDR = 0X5C,
MAG_OFFSET_Y_LSB_ADDR = 0X5D,
MAG_OFFSET_Y_MSB_ADDR = 0X5E,
MAG_OFFSET_Z_LSB_ADDR = 0X5F,
MAG_OFFSET_Z_MSB_ADDR = 0X60,
/* Gyroscope Offset register s*/
GYRO_OFFSET_X_LSB_ADDR = 0X61,
GYRO_OFFSET_X_MSB_ADDR = 0X62,
GYRO_OFFSET_Y_LSB_ADDR = 0X63,
GYRO_OFFSET_Y_MSB_ADDR = 0X64,
GYRO_OFFSET_Z_LSB_ADDR = 0X65,
GYRO_OFFSET_Z_MSB_ADDR = 0X66,
/* Radius registers */
ACCEL_RADIUS_LSB_ADDR = 0X67,
ACCEL_RADIUS_MSB_ADDR = 0X68,
MAG_RADIUS_LSB_ADDR = 0X69,
MAG_RADIUS_MSB_ADDR = 0X6A
} adafruit_bno055_reg_t;
/** BNO055 power settings */
typedef enum {
POWER_MODE_NORMAL = 0X00,
POWER_MODE_LOWPOWER = 0X01,
POWER_MODE_SUSPEND = 0X02
} adafruit_bno055_powermode_t;
/** Remap settings **/
typedef enum {
REMAP_CONFIG_P0 = 0x21,
REMAP_CONFIG_P1 = 0x24, // default
REMAP_CONFIG_P2 = 0x24,
REMAP_CONFIG_P3 = 0x21,
REMAP_CONFIG_P4 = 0x24,
REMAP_CONFIG_P5 = 0x21,
REMAP_CONFIG_P6 = 0x21,
REMAP_CONFIG_P7 = 0x24
} adafruit_bno055_axis_remap_config_t;
/** Remap Signs **/
typedef enum {
REMAP_SIGN_P0 = 0x04,
REMAP_SIGN_P1 = 0x00, // default
REMAP_SIGN_P2 = 0x06,
REMAP_SIGN_P3 = 0x02,
REMAP_SIGN_P4 = 0x03,
REMAP_SIGN_P5 = 0x01,
REMAP_SIGN_P6 = 0x07,
REMAP_SIGN_P7 = 0x05
} adafruit_bno055_axis_remap_sign_t;
/** A structure to represent revisions **/
typedef struct {
uint8_t accel_rev; /**< acceleration rev */
uint8_t mag_rev; /**< magnetometer rev */
uint8_t gyro_rev; /**< gyroscrope rev */
uint16_t sw_rev; /**< SW rev */
uint8_t bl_rev; /**< bootloader rev */
} adafruit_bno055_rev_info_t;
/** Vector Mappings **/
typedef enum {
VECTOR_ACCELEROMETER = BNO055_ACCEL_DATA_X_LSB_ADDR,
VECTOR_MAGNETOMETER = BNO055_MAG_DATA_X_LSB_ADDR,
VECTOR_GYROSCOPE = BNO055_GYRO_DATA_X_LSB_ADDR,
VECTOR_EULER = BNO055_EULER_H_LSB_ADDR,
VECTOR_LINEARACCEL = BNO055_LINEAR_ACCEL_DATA_X_LSB_ADDR,
VECTOR_GRAVITY = BNO055_GRAVITY_DATA_X_LSB_ADDR
} adafruit_vector_type_t;
Adafruit_BNO055(int32_t sensorID = -1, uint8_t address = BNO055_ADDRESS_A,
TwoWire *theWire = &Wire);
bool begin(adafruit_bno055_opmode_t mode = OPERATION_MODE_NDOF);
void setMode(adafruit_bno055_opmode_t mode);
adafruit_bno055_opmode_t getMode();
void setAxisRemap(adafruit_bno055_axis_remap_config_t remapcode);
void setAxisSign(adafruit_bno055_axis_remap_sign_t remapsign);
void getRevInfo(adafruit_bno055_rev_info_t *);
void setExtCrystalUse(boolean usextal);
void getSystemStatus(uint8_t *system_status, uint8_t *self_test_result,
uint8_t *system_error);
void getCalibration(uint8_t *system, uint8_t *gyro, uint8_t *accel,
uint8_t *mag);
imu::Vector<3> getVector(adafruit_vector_type_t vector_type);
imu::Quaternion getQuat();
int8_t getTemp();
/* Adafruit_Sensor implementation */
bool getEvent(sensors_event_t *);
bool getEvent(sensors_event_t *, adafruit_vector_type_t);
void getSensor(sensor_t *);
/* Functions to deal with raw calibration data */
bool getSensorOffsets(uint8_t *calibData);
bool getSensorOffsets(adafruit_bno055_offsets_t &offsets_type);
void setSensorOffsets(const uint8_t *calibData);
void setSensorOffsets(const adafruit_bno055_offsets_t &offsets_type);
bool isFullyCalibrated();
/* Power managments functions */
void enterSuspendMode();
void enterNormalMode();
private:
byte read8(adafruit_bno055_reg_t);
bool readLen(adafruit_bno055_reg_t, byte *buffer, uint8_t len);
bool write8(adafruit_bno055_reg_t, byte value);
Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface
int32_t _sensorID;
adafruit_bno055_opmode_t _mode;
};
#endif

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Adafruit Industries
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,47 @@
# UTF-8 supported.
# The name of your library as you want it formatted
name = OBJLoader
# List of authors. Links can be provided using the syntax [author name](url)
authorList = [Tatsuya Saito](http://saito-tatsuya.net/) and [Matt Ditton](http://thequietvoid.com/)
# A web page for your library, NOT a direct link to where to download it
url = http://code.google.com/p/saitoobjloader/
# The category of your library, must be one (or many) of the following:
# "3D" "Animation" "Compilations" "Data"
# "Fabrication" "Geometry" "GUI" "Hardware"
# "I/O" "Language" "Math" "Simulation"
# "Sound" "Utilities" "Typography" "Video & Vision"
#
# If a value other than those listed is used, your library will listed as "Other."
category = 3D
# A short sentence (or fragment) to summarize the library's function. This will be
# shown from inside the PDE when the library is being installed. Avoid repeating
# the name of your library here. Also, avoid saying anything redundant like
# mentioning that its a library. This should start with a capitalized letter, and
# end with a period.
sentence = .OBJ 3D model file loader
# Additional information suitable for the Processing website. The value of
# 'sentence' always will be prepended, so you should start by writing the
# second sentence here. If your library only works on certain operating systems,
# mention it here.
paragraph =
# Links in the 'sentence' and 'paragraph' attributes can be inserted using the
# same syntax as for authors. That is, [here is a link to Processing](http://processing.org/)
# A version number that increments once with each release. This
# is used to compare different versions of the same library, and
# check if an update is available. You should think of it as a
# counter, counting the total number of releases you've had.
version = 23 # This must be parsable as an int
# The version as the user will see it. If blank, the version attribute will be used here
prettyVersion = 0.99 # This is treated as a String

View File

@ -0,0 +1,32 @@
Adafruit Unified BNO055 Driver (AHRS/Orientation) [![Build Status](https://github.com/adafruit/Adafruit_BNO055/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BNO055/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_BNO055/html/index.html)
================
<a href="https://www.adafruit.com/product/2472"><img src="assets/board.jpg?raw=true" width="500px"></a>
This driver is for the Adafruit BNO055 Breakout, and is based on Adafruit's Unified Sensor Library (Adafruit_Sensor).
Tested and works great with the Adafruit Si4713 Breakout Board.
To work with the Arduino Zero, the BNO055's ADR pin must be high.
* http://www.adafruit.com/products/2472
## What is the Adafruit Unified Sensor Library? ##
The Adafruit Unified Sensor Library ([Adafruit_Sensor](https://github.com/adafruit/Adafruit_Sensor)) provides a common interface and data type for any supported sensor. It defines some basic information about the sensor (sensor limits, etc.), and returns standard SI units of a specific type and scale for each supported sensor type.
It provides a simple abstraction layer between your application and the actual sensor HW, allowing you to drop in any comparable sensor with only one or two lines of code to change in your project (essentially the constructor since the functions to read sensor data and get information about the sensor are defined in the base Adafruit_Sensor class).
This is important and useful for two reasons:
1.) You can use the data right away because it's already converted to SI units that you understand and can compare, rather than meaningless values like 0..1023.
2.) Because SI units are standardised in the sensor library, you can also do quick sanity checks when working with new sensors, or drop in any comparable sensor if you need better sensitivity or if a lower cost unit becomes available, etc.
Light sensors will always report units in lux, gyroscopes will always report units in rad/s, etc. ... freeing you up to focus on the data, rather than digging through the datasheet to understand what the sensor's raw numbers really mean.
Adafruit invests time and resources providing this open source code. Please support Adafruit and open-source hardware by purchasing products from Adafruit!
Kevin (KTOWN) Townsend Adafruit Industries.
MIT license, check license.txt for more information
All text above must be included in any redistribution
To install, use the Arduino Library Manager and search for "Adafruit BNO055" and install the library.

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

View File

@ -0,0 +1,127 @@
# Adafruit Community Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and leaders pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level or type of
experience, education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
## Our Standards
We are committed to providing a friendly, safe and welcoming environment for
all.
Examples of behavior that contributes to creating a positive environment
include:
* Be kind and courteous to others
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Collaborating with other community members
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and sexual attention or advances
* The use of inappropriate images, including in a community member's avatar
* The use of inappropriate language, including in a community member's nickname
* Any spamming, flaming, baiting or other attention-stealing behavior
* Excessive or unwelcome helping; answering outside the scope of the question
asked
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate
The goal of the standards and moderation guidelines outlined here is to build
and maintain a respectful community. We ask that you dont just aim to be
"technically unimpeachable", but rather try to be your best self.
We value many things beyond technical expertise, including collaboration and
supporting others within our community. Providing a positive experience for
other community members can have a much more significant impact than simply
providing the correct answer.
## Our Responsibilities
Project leaders are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project leaders have the right and responsibility to remove, edit, or
reject messages, comments, commits, code, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any community member for other behaviors that they deem
inappropriate, threatening, offensive, or harmful.
## Moderation
Instances of behaviors that violate the Adafruit Community Code of Conduct
may be reported by any member of the community. Community members are
encouraged to report these situations, including situations they witness
involving other community members.
You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel
to all Community Helpers by tagging @community helpers. You may also send an
open message from any channel, or a direct message to @kattni#1507,
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
@Andon#8175.
Email and direct message reports will be kept confidential.
In situations on Discord where the issue is particularly egregious, possibly
illegal, requires immediate action, or violates the Discord terms of service,
you should also report the message directly to Discord.
These are the steps for upholding our communitys standards of conduct.
1. Any member of the community may report any situation that violates the
Adafruit Community Code of Conduct. All reports will be reviewed and
investigated.
2. If the behavior is an egregious violation, the community member who
committed the violation may be banned immediately, without warning.
3. Otherwise, moderators will first respond to such behavior with a warning.
4. Moderators follow a soft "three strikes" policy - the community member may
be given another chance, if they are receptive to the warning and change their
behavior.
5. If the community member is unreceptive or unreasonable when warned by a
moderator, or the warning goes unheeded, they may be banned for a first or
second offense. Repeated offenses will result in the community member being
banned.
## Scope
This Code of Conduct and the enforcement policies listed above apply to all
Adafruit Community venues. This includes but is not limited to any community
spaces (both public and private), the entire Adafruit Discord server, and
Adafruit GitHub repositories. Examples of Adafruit Community spaces include
but are not limited to meet-ups, audio chats on the Adafruit Discord, or
interaction at a conference.
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. As a community
member, you are representing our community, and are expected to behave
accordingly.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4, available at
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
For other projects adopting the Adafruit Community Code of
Conduct, please contact the maintainers of those projects for enforcement.
If you wish to use this code of conduct for your own project, consider
explicitly mentioning your moderation policy or making a copy with your
own moderation policy so as to avoid confusion.

View File

@ -0,0 +1,131 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3.3-5V DC
Connect GROUND to common ground
History
=======
2015/MAR/03 - First release (KTOWN)
*/
/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (100)
// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
// id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);
/**************************************************************************/
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
sensor_t sensor;
bno.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" xxx");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" xxx");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" xxx");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(115200);
Serial.println("Orientation Sensor Test"); Serial.println("");
/* Initialise the sensor */
if(!bno.begin())
{
/* There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while(1);
}
delay(1000);
/* Use external crystal for better accuracy */
bno.setExtCrystalUse(true);
/* Display some basic information on this sensor */
displaySensorDetails();
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
bno.getEvent(&event);
/* Board layout:
+----------+
| *| RST PITCH ROLL HEADING
ADR |* *| SCL
INT |* *| SDA ^ /->
PS1 |* *| GND | |
PS0 |* *| 3VO Y Z--> \-X
| *| VIN
+----------+
*/
/* The processing sketch expects data as roll, pitch, heading */
Serial.print(F("Orientation: "));
Serial.print((float)event.orientation.x);
Serial.print(F(" "));
Serial.print((float)event.orientation.y);
Serial.print(F(" "));
Serial.print((float)event.orientation.z);
Serial.println(F(""));
/* Also send calibration data for each sensor. */
uint8_t sys, gyro, accel, mag = 0;
bno.getCalibration(&sys, &gyro, &accel, &mag);
Serial.print(F("Calibration: "));
Serial.print(sys, DEC);
Serial.print(F(" "));
Serial.print(gyro, DEC);
Serial.print(F(" "));
Serial.print(accel, DEC);
Serial.print(F(" "));
Serial.println(mag, DEC);
delay(BNO055_SAMPLERATE_DELAY_MS);
}

View File

@ -0,0 +1,109 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
double xPos = 0, yPos = 0, headingVel = 0;
uint16_t BNO055_SAMPLERATE_DELAY_MS = 10; //how often to read data from the board
uint16_t PRINT_DELAY_MS = 500; // how often to print the data
uint16_t printCount = 0; //counter to avoid printing every 10MS sample
//velocity = accel*dt (dt in seconds)
//position = 0.5*accel*dt^2
double ACCEL_VEL_TRANSITION = (double)(BNO055_SAMPLERATE_DELAY_MS) / 1000.0;
double ACCEL_POS_TRANSITION = 0.5 * ACCEL_VEL_TRANSITION * ACCEL_VEL_TRANSITION;
double DEG_2_RAD = 0.01745329251; //trig functions require radians, BNO055 outputs degrees
// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
// id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);
void setup(void)
{
Serial.begin(115200);
while (!Serial) delay(10); // wait for serial port to open!
if (!bno.begin())
{
Serial.print("No BNO055 detected");
while (1);
}
delay(1000);
}
void loop(void)
{
//
unsigned long tStart = micros();
sensors_event_t orientationData , linearAccelData;
bno.getEvent(&orientationData, Adafruit_BNO055::VECTOR_EULER);
// bno.getEvent(&angVelData, Adafruit_BNO055::VECTOR_GYROSCOPE);
bno.getEvent(&linearAccelData, Adafruit_BNO055::VECTOR_LINEARACCEL);
xPos = xPos + ACCEL_POS_TRANSITION * linearAccelData.acceleration.x;
yPos = yPos + ACCEL_POS_TRANSITION * linearAccelData.acceleration.y;
// velocity of sensor in the direction it's facing
headingVel = ACCEL_VEL_TRANSITION * linearAccelData.acceleration.x / cos(DEG_2_RAD * orientationData.orientation.x);
if (printCount * BNO055_SAMPLERATE_DELAY_MS >= PRINT_DELAY_MS) {
//enough iterations have passed that we can print the latest data
Serial.print("Heading: ");
Serial.println(orientationData.orientation.x);
Serial.print("Position: ");
Serial.print(xPos);
Serial.print(" , ");
Serial.println(yPos);
Serial.print("Speed: ");
Serial.println(headingVel);
Serial.println("-------");
printCount = 0;
}
else {
printCount = printCount + 1;
}
while ((micros() - tStart) < (BNO055_SAMPLERATE_DELAY_MS * 1000))
{
//poll until the next sample is ready
}
}
void printEvent(sensors_event_t* event) {
Serial.println();
Serial.print(event->type);
double x = -1000000, y = -1000000 , z = -1000000; //dumb values, easy to spot problem
if (event->type == SENSOR_TYPE_ACCELEROMETER) {
x = event->acceleration.x;
y = event->acceleration.y;
z = event->acceleration.z;
}
else if (event->type == SENSOR_TYPE_ORIENTATION) {
x = event->orientation.x;
y = event->orientation.y;
z = event->orientation.z;
}
else if (event->type == SENSOR_TYPE_MAGNETIC_FIELD) {
x = event->magnetic.x;
y = event->magnetic.y;
z = event->magnetic.z;
}
else if ((event->type == SENSOR_TYPE_GYROSCOPE) || (event->type == SENSOR_TYPE_ROTATION_VECTOR)) {
x = event->gyro.x;
y = event->gyro.y;
z = event->gyro.z;
}
Serial.print(": x= ");
Serial.print(x);
Serial.print(" | y= ");
Serial.print(y);
Serial.print(" | z= ");
Serial.println(z);
}

View File

@ -0,0 +1,115 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
/* This driver reads raw data from the BNO055
Connections
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3.3V DC
Connect GROUND to common ground
History
=======
2015/MAR/03 - First release (KTOWN)
*/
/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (100)
// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
// id, address
Adafruit_BNO055 bno = Adafruit_BNO055(-1, 0x28, &Wire);
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(115200);
while (!Serial) delay(10); // wait for serial port to open!
Serial.println("Orientation Sensor Raw Data Test"); Serial.println("");
/* Initialise the sensor */
if(!bno.begin())
{
/* There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while(1);
}
delay(1000);
/* Display the current temperature */
int8_t temp = bno.getTemp();
Serial.print("Current Temperature: ");
Serial.print(temp);
Serial.println(" C");
Serial.println("");
bno.setExtCrystalUse(true);
Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
// Possible vector values can be:
// - VECTOR_ACCELEROMETER - m/s^2
// - VECTOR_MAGNETOMETER - uT
// - VECTOR_GYROSCOPE - rad/s
// - VECTOR_EULER - degrees
// - VECTOR_LINEARACCEL - m/s^2
// - VECTOR_GRAVITY - m/s^2
imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);
/* Display the floating point data */
Serial.print("X: ");
Serial.print(euler.x());
Serial.print(" Y: ");
Serial.print(euler.y());
Serial.print(" Z: ");
Serial.print(euler.z());
Serial.print("\t\t");
/*
// Quaternion data
imu::Quaternion quat = bno.getQuat();
Serial.print("qW: ");
Serial.print(quat.w(), 4);
Serial.print(" qX: ");
Serial.print(quat.x(), 4);
Serial.print(" qY: ");
Serial.print(quat.y(), 4);
Serial.print(" qZ: ");
Serial.print(quat.z(), 4);
Serial.print("\t\t");
*/
/* Display calibration status for each sensor. */
uint8_t system, gyro, accel, mag = 0;
bno.getCalibration(&system, &gyro, &accel, &mag);
Serial.print("CALIBRATION: Sys=");
Serial.print(system, DEC);
Serial.print(" Gyro=");
Serial.print(gyro, DEC);
Serial.print(" Accel=");
Serial.print(accel, DEC);
Serial.print(" Mag=");
Serial.println(mag, DEC);
delay(BNO055_SAMPLERATE_DELAY_MS);
}

View File

@ -0,0 +1,151 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3.3-5V DC
Connect GROUND to common ground
History
=======
2015/MAR/03 - First release (KTOWN)
*/
/* Set the delay between fresh samples */
uint16_t BNO055_SAMPLERATE_DELAY_MS = 100;
// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
// id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28, &Wire);
void setup(void)
{
Serial.begin(115200);
while (!Serial) delay(10); // wait for serial port to open!
Serial.println("Orientation Sensor Test"); Serial.println("");
/* Initialise the sensor */
if (!bno.begin())
{
/* There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while (1);
}
delay(1000);
}
void loop(void)
{
//could add VECTOR_ACCELEROMETER, VECTOR_MAGNETOMETER,VECTOR_GRAVITY...
sensors_event_t orientationData , angVelocityData , linearAccelData, magnetometerData, accelerometerData, gravityData;
bno.getEvent(&orientationData, Adafruit_BNO055::VECTOR_EULER);
bno.getEvent(&angVelocityData, Adafruit_BNO055::VECTOR_GYROSCOPE);
bno.getEvent(&linearAccelData, Adafruit_BNO055::VECTOR_LINEARACCEL);
bno.getEvent(&magnetometerData, Adafruit_BNO055::VECTOR_MAGNETOMETER);
bno.getEvent(&accelerometerData, Adafruit_BNO055::VECTOR_ACCELEROMETER);
bno.getEvent(&gravityData, Adafruit_BNO055::VECTOR_GRAVITY);
printEvent(&orientationData);
printEvent(&angVelocityData);
printEvent(&linearAccelData);
printEvent(&magnetometerData);
printEvent(&accelerometerData);
printEvent(&gravityData);
int8_t boardTemp = bno.getTemp();
Serial.println();
Serial.print(F("temperature: "));
Serial.println(boardTemp);
uint8_t system, gyro, accel, mag = 0;
bno.getCalibration(&system, &gyro, &accel, &mag);
Serial.println();
Serial.print("Calibration: Sys=");
Serial.print(system);
Serial.print(" Gyro=");
Serial.print(gyro);
Serial.print(" Accel=");
Serial.print(accel);
Serial.print(" Mag=");
Serial.println(mag);
Serial.println("--");
delay(BNO055_SAMPLERATE_DELAY_MS);
}
void printEvent(sensors_event_t* event) {
double x = -1000000, y = -1000000 , z = -1000000; //dumb values, easy to spot problem
if (event->type == SENSOR_TYPE_ACCELEROMETER) {
Serial.print("Accl:");
x = event->acceleration.x;
y = event->acceleration.y;
z = event->acceleration.z;
}
else if (event->type == SENSOR_TYPE_ORIENTATION) {
Serial.print("Orient:");
x = event->orientation.x;
y = event->orientation.y;
z = event->orientation.z;
}
else if (event->type == SENSOR_TYPE_MAGNETIC_FIELD) {
Serial.print("Mag:");
x = event->magnetic.x;
y = event->magnetic.y;
z = event->magnetic.z;
}
else if (event->type == SENSOR_TYPE_GYROSCOPE) {
Serial.print("Gyro:");
x = event->gyro.x;
y = event->gyro.y;
z = event->gyro.z;
}
else if (event->type == SENSOR_TYPE_ROTATION_VECTOR) {
Serial.print("Rot:");
x = event->gyro.x;
y = event->gyro.y;
z = event->gyro.z;
}
else if (event->type == SENSOR_TYPE_LINEAR_ACCELERATION) {
Serial.print("Linear:");
x = event->acceleration.x;
y = event->acceleration.y;
z = event->acceleration.z;
}
else if (event->type == SENSOR_TYPE_GRAVITY) {
Serial.print("Gravity:");
x = event->acceleration.x;
y = event->acceleration.y;
z = event->acceleration.z;
}
else {
Serial.print("Unk:");
}
Serial.print("\tx= ");
Serial.print(x);
Serial.print(" |\ty= ");
Serial.print(y);
Serial.print(" |\tz= ");
Serial.println(z);
}

View File

@ -0,0 +1,295 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <EEPROM.h>
/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3-5V DC
Connect GROUND to common ground
History
=======
2015/MAR/03 - First release (KTOWN)
2015/AUG/27 - Added calibration and system status helpers
2015/NOV/13 - Added calibration save and restore
*/
/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (100)
// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
// id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);
/**************************************************************************/
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
sensor_t sensor;
bno.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print("Sensor: "); Serial.println(sensor.name);
Serial.print("Driver Ver: "); Serial.println(sensor.version);
Serial.print("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print("Max Value: "); Serial.print(sensor.max_value); Serial.println(" xxx");
Serial.print("Min Value: "); Serial.print(sensor.min_value); Serial.println(" xxx");
Serial.print("Resolution: "); Serial.print(sensor.resolution); Serial.println(" xxx");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Display some basic info about the sensor status
*/
/**************************************************************************/
void displaySensorStatus(void)
{
/* Get the system status values (mostly for debugging purposes) */
uint8_t system_status, self_test_results, system_error;
system_status = self_test_results = system_error = 0;
bno.getSystemStatus(&system_status, &self_test_results, &system_error);
/* Display the results in the Serial Monitor */
Serial.println("");
Serial.print("System Status: 0x");
Serial.println(system_status, HEX);
Serial.print("Self Test: 0x");
Serial.println(self_test_results, HEX);
Serial.print("System Error: 0x");
Serial.println(system_error, HEX);
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Display sensor calibration status
*/
/**************************************************************************/
void displayCalStatus(void)
{
/* Get the four calibration values (0..3) */
/* Any sensor data reporting 0 should be ignored, */
/* 3 means 'fully calibrated" */
uint8_t system, gyro, accel, mag;
system = gyro = accel = mag = 0;
bno.getCalibration(&system, &gyro, &accel, &mag);
/* The data should be ignored until the system calibration is > 0 */
Serial.print("\t");
if (!system)
{
Serial.print("! ");
}
/* Display the individual values */
Serial.print("Sys:");
Serial.print(system, DEC);
Serial.print(" G:");
Serial.print(gyro, DEC);
Serial.print(" A:");
Serial.print(accel, DEC);
Serial.print(" M:");
Serial.print(mag, DEC);
}
/**************************************************************************/
/*
Display the raw calibration offset and radius data
*/
/**************************************************************************/
void displaySensorOffsets(const adafruit_bno055_offsets_t &calibData)
{
Serial.print("Accelerometer: ");
Serial.print(calibData.accel_offset_x); Serial.print(" ");
Serial.print(calibData.accel_offset_y); Serial.print(" ");
Serial.print(calibData.accel_offset_z); Serial.print(" ");
Serial.print("\nGyro: ");
Serial.print(calibData.gyro_offset_x); Serial.print(" ");
Serial.print(calibData.gyro_offset_y); Serial.print(" ");
Serial.print(calibData.gyro_offset_z); Serial.print(" ");
Serial.print("\nMag: ");
Serial.print(calibData.mag_offset_x); Serial.print(" ");
Serial.print(calibData.mag_offset_y); Serial.print(" ");
Serial.print(calibData.mag_offset_z); Serial.print(" ");
Serial.print("\nAccel Radius: ");
Serial.print(calibData.accel_radius);
Serial.print("\nMag Radius: ");
Serial.print(calibData.mag_radius);
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(115200);
delay(1000);
Serial.println("Orientation Sensor Test"); Serial.println("");
/* Initialise the sensor */
if (!bno.begin())
{
/* There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while (1);
}
int eeAddress = 0;
long bnoID;
bool foundCalib = false;
EEPROM.get(eeAddress, bnoID);
adafruit_bno055_offsets_t calibrationData;
sensor_t sensor;
/*
* Look for the sensor's unique ID at the beginning oF EEPROM.
* This isn't foolproof, but it's better than nothing.
*/
bno.getSensor(&sensor);
if (bnoID != sensor.sensor_id)
{
Serial.println("\nNo Calibration Data for this sensor exists in EEPROM");
delay(500);
}
else
{
Serial.println("\nFound Calibration for this sensor in EEPROM.");
eeAddress += sizeof(long);
EEPROM.get(eeAddress, calibrationData);
displaySensorOffsets(calibrationData);
Serial.println("\n\nRestoring Calibration data to the BNO055...");
bno.setSensorOffsets(calibrationData);
Serial.println("\n\nCalibration data loaded into BNO055");
foundCalib = true;
}
delay(1000);
/* Display some basic information on this sensor */
displaySensorDetails();
/* Optional: Display current status */
displaySensorStatus();
/* Crystal must be configured AFTER loading calibration data into BNO055. */
bno.setExtCrystalUse(true);
sensors_event_t event;
bno.getEvent(&event);
/* always recal the mag as It goes out of calibration very often */
if (foundCalib){
Serial.println("Move sensor slightly to calibrate magnetometers");
while (!bno.isFullyCalibrated())
{
bno.getEvent(&event);
delay(BNO055_SAMPLERATE_DELAY_MS);
}
}
else
{
Serial.println("Please Calibrate Sensor: ");
while (!bno.isFullyCalibrated())
{
bno.getEvent(&event);
Serial.print("X: ");
Serial.print(event.orientation.x, 4);
Serial.print("\tY: ");
Serial.print(event.orientation.y, 4);
Serial.print("\tZ: ");
Serial.print(event.orientation.z, 4);
/* Optional: Display calibration status */
displayCalStatus();
/* New line for the next sample */
Serial.println("");
/* Wait the specified delay before requesting new data */
delay(BNO055_SAMPLERATE_DELAY_MS);
}
}
Serial.println("\nFully calibrated!");
Serial.println("--------------------------------");
Serial.println("Calibration Results: ");
adafruit_bno055_offsets_t newCalib;
bno.getSensorOffsets(newCalib);
displaySensorOffsets(newCalib);
Serial.println("\n\nStoring calibration data to EEPROM...");
eeAddress = 0;
bno.getSensor(&sensor);
bnoID = sensor.sensor_id;
EEPROM.put(eeAddress, bnoID);
eeAddress += sizeof(long);
EEPROM.put(eeAddress, newCalib);
Serial.println("Data stored to EEPROM.");
Serial.println("\n--------------------------------\n");
delay(500);
}
void loop() {
/* Get a new sensor event */
sensors_event_t event;
bno.getEvent(&event);
/* Display the floating point data */
Serial.print("X: ");
Serial.print(event.orientation.x, 4);
Serial.print("\tY: ");
Serial.print(event.orientation.y, 4);
Serial.print("\tZ: ");
Serial.print(event.orientation.z, 4);
/* Optional: Display calibration status */
displayCalStatus();
/* Optional: Display sensor status (debug only) */
//displaySensorStatus();
/* New line for the next sample */
Serial.println("");
/* Wait the specified delay before requesting new data */
delay(BNO055_SAMPLERATE_DELAY_MS);
}

View File

@ -0,0 +1,179 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections
===========
Connect SCL to SCL pin (analog 5 on Arduino UNO)
Connect SDA to SDA pin (analog 4 on Arduino UNO)
Connect VDD to 3-5V DC (depending on your board's logic level)
Connect GROUND to common ground
History
=======
2015/MAR/03 - First release (KTOWN)
2015/AUG/27 - Added calibration and system status helpers
*/
/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (100)
// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
// id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28, &Wire);
/**************************************************************************/
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
sensor_t sensor;
bno.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" xxx");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" xxx");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" xxx");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Display some basic info about the sensor status
*/
/**************************************************************************/
void displaySensorStatus(void)
{
/* Get the system status values (mostly for debugging purposes) */
uint8_t system_status, self_test_results, system_error;
system_status = self_test_results = system_error = 0;
bno.getSystemStatus(&system_status, &self_test_results, &system_error);
/* Display the results in the Serial Monitor */
Serial.println("");
Serial.print("System Status: 0x");
Serial.println(system_status, HEX);
Serial.print("Self Test: 0x");
Serial.println(self_test_results, HEX);
Serial.print("System Error: 0x");
Serial.println(system_error, HEX);
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Display sensor calibration status
*/
/**************************************************************************/
void displayCalStatus(void)
{
/* Get the four calibration values (0..3) */
/* Any sensor data reporting 0 should be ignored, */
/* 3 means 'fully calibrated" */
uint8_t system, gyro, accel, mag;
system = gyro = accel = mag = 0;
bno.getCalibration(&system, &gyro, &accel, &mag);
/* The data should be ignored until the system calibration is > 0 */
Serial.print("\t");
if (!system)
{
Serial.print("! ");
}
/* Display the individual values */
Serial.print("Sys:");
Serial.print(system, DEC);
Serial.print(" G:");
Serial.print(gyro, DEC);
Serial.print(" A:");
Serial.print(accel, DEC);
Serial.print(" M:");
Serial.print(mag, DEC);
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(115200);
while (!Serial) delay(10); // wait for serial port to open!
Serial.println("Orientation Sensor Test"); Serial.println("");
/* Initialise the sensor */
if(!bno.begin())
{
/* There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while(1);
}
delay(1000);
/* Display some basic information on this sensor */
displaySensorDetails();
/* Optional: Display current status */
displaySensorStatus();
bno.setExtCrystalUse(true);
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
bno.getEvent(&event);
/* Display the floating point data */
Serial.print("X: ");
Serial.print(event.orientation.x, 4);
Serial.print("\tY: ");
Serial.print(event.orientation.y, 4);
Serial.print("\tZ: ");
Serial.print(event.orientation.z, 4);
/* Optional: Display calibration status */
displayCalStatus();
/* Optional: Display sensor status (debug only) */
//displaySensorStatus();
/* New line for the next sample */
Serial.println("");
/* Wait the specified delay before requesting nex data */
delay(BNO055_SAMPLERATE_DELAY_MS);
}

View File

@ -0,0 +1,148 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
/* Returns the IMU data as both a euler angles and quaternions as the WebSerial
3D Model viewer at https://adafruit-3dmodel-viewer.glitch.me/ expects.
This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3.3-5V DC
Connect GROUND to common ground
History
=======
2020/JUN/01 - First release (Melissa LeBlanc-Williams)
*/
/* Set the delay between fresh samples */
#define BNO055_SAMPLERATE_DELAY_MS (100)
// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
// id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);
/**************************************************************************/
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
sensor_t sensor;
bno.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" xxx");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" xxx");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" xxx");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(9600);
Serial.println("WebSerial 3D Firmware"); Serial.println("");
/* Initialise the sensor */
if(!bno.begin())
{
/* There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while(1);
}
delay(1000);
/* Use external crystal for better accuracy */
bno.setExtCrystalUse(true);
/* Display some basic information on this sensor */
displaySensorDetails();
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
bno.getEvent(&event);
/* Board layout:
+----------+
| *| RST PITCH ROLL HEADING
ADR |* *| SCL
INT |* *| SDA ^ /->
PS1 |* *| GND | |
PS0 |* *| 3VO Y Z--> \-X
| *| VIN
+----------+
*/
/* The WebSerial 3D Model Viewer expects data as heading, pitch, roll */
Serial.print(F("Orientation: "));
Serial.print(360 - (float)event.orientation.x);
Serial.print(F(", "));
Serial.print((float)event.orientation.y);
Serial.print(F(", "));
Serial.print((float)event.orientation.z);
Serial.println(F(""));
/* The WebSerial 3D Model Viewer also expects data as roll, pitch, heading */
imu::Quaternion quat = bno.getQuat();
Serial.print(F("Quaternion: "));
Serial.print((float)quat.w(), 4);
Serial.print(F(", "));
Serial.print((float)quat.x(), 4);
Serial.print(F(", "));
Serial.print((float)quat.y(), 4);
Serial.print(F(", "));
Serial.print((float)quat.z(), 4);
Serial.println(F(""));
/* Also send calibration data for each sensor. */
uint8_t sys, gyro, accel, mag = 0;
bno.getCalibration(&sys, &gyro, &accel, &mag);
Serial.print(F("Calibration: "));
Serial.print(sys, DEC);
Serial.print(F(", "));
Serial.print(gyro, DEC);
Serial.print(F(", "));
Serial.print(accel, DEC);
Serial.print(F(", "));
Serial.print(mag, DEC);
Serial.println(F(""));
delay(BNO055_SAMPLERATE_DELAY_MS);
}

View File

@ -0,0 +1,181 @@
import processing.serial.*;
import java.awt.datatransfer.*;
import java.awt.Toolkit;
import processing.opengl.*;
import saito.objloader.*;
import g4p_controls.*;
float roll = 0.0F;
float pitch = 0.0F;
float yaw = 0.0F;
float temp = 0.0F;
float alt = 0.0F;
OBJModel model;
// Serial port state.
Serial port;
final String serialConfigFile = "serialconfig.txt";
boolean printSerial = false;
// UI controls.
GPanel configPanel;
GDropList serialList;
GLabel serialLabel;
GLabel calLabel;
GCheckbox printSerialCheckbox;
void setup()
{
size(640, 480, OPENGL);
frameRate(30);
model = new OBJModel(this);
model.load("bunny.obj");
model.scale(20);
// Serial port setup.
// Grab list of serial ports and choose one that was persisted earlier or default to the first port.
int selectedPort = 0;
String[] availablePorts = Serial.list();
if (availablePorts == null) {
println("ERROR: No serial ports available!");
exit();
}
String[] serialConfig = loadStrings(serialConfigFile);
if (serialConfig != null && serialConfig.length > 0) {
String savedPort = serialConfig[0];
// Check if saved port is in available ports.
for (int i = 0; i < availablePorts.length; ++i) {
if (availablePorts[i].equals(savedPort)) {
selectedPort = i;
}
}
}
// Build serial config UI.
configPanel = new GPanel(this, 10, 10, width-20, 90, "Configuration (click to hide/show)");
serialLabel = new GLabel(this, 0, 20, 80, 25, "Serial port:");
configPanel.addControl(serialLabel);
serialList = new GDropList(this, 90, 20, 200, 200, 6);
serialList.setItems(availablePorts, selectedPort);
configPanel.addControl(serialList);
calLabel = new GLabel(this, 300, 20, 350, 25, "Calibration: Sys=? Gyro=? Accel=? Mag=?");
configPanel.addControl(calLabel);
printSerialCheckbox = new GCheckbox(this, 5, 50, 200, 20, "Print serial data");
printSerialCheckbox.setSelected(printSerial);
configPanel.addControl(printSerialCheckbox);
// Set serial port.
setSerialPort(serialList.getSelectedText());
}
void draw()
{
background(0,0,0);
// Set a new co-ordinate space
pushMatrix();
// Simple 3 point lighting for dramatic effect.
// Slightly red light in upper right, slightly blue light in upper left, and white light from behind.
pointLight(255, 200, 200, 400, 400, 500);
pointLight(200, 200, 255, -400, 400, 500);
pointLight(255, 255, 255, 0, 0, -500);
// Move bunny from 0,0 in upper left corner to roughly center of screen.
translate(300, 380, 0);
// Rotate shapes around the X/Y/Z axis (values in radians, 0..Pi*2)
//rotateZ(radians(roll));
//rotateX(radians(pitch)); // extrinsic rotation
//rotateY(radians(yaw));
float c1 = cos(radians(roll));
float s1 = sin(radians(roll));
float c2 = cos(radians(pitch)); // intrinsic rotation
float s2 = sin(radians(pitch));
float c3 = cos(radians(yaw));
float s3 = sin(radians(yaw));
applyMatrix( c2*c3, s1*s3+c1*c3*s2, c3*s1*s2-c1*s3, 0,
-s2, c1*c2, c2*s1, 0,
c2*s3, c1*s2*s3-c3*s1, c1*c3+s1*s2*s3, 0,
0, 0, 0, 1);
pushMatrix();
noStroke();
model.draw();
popMatrix();
popMatrix();
//print("draw");
}
void serialEvent(Serial p)
{
String incoming = p.readString();
if (printSerial) {
println(incoming);
}
if ((incoming.length() > 8))
{
String[] list = split(incoming, " ");
if ( (list.length > 0) && (list[0].equals("Orientation:")) )
{
roll = float(list[3]); // Roll = Z
pitch = float(list[2]); // Pitch = Y
yaw = float(list[1]); // Yaw/Heading = X
}
if ( (list.length > 0) && (list[0].equals("Alt:")) )
{
alt = float(list[1]);
}
if ( (list.length > 0) && (list[0].equals("Temp:")) )
{
temp = float(list[1]);
}
if ( (list.length > 0) && (list[0].equals("Calibration:")) )
{
int sysCal = int(list[1]);
int gyroCal = int(list[2]);
int accelCal = int(list[3]);
int magCal = int(trim(list[4]));
calLabel.setText("Calibration: Sys=" + sysCal + " Gyro=" + gyroCal + " Accel=" + accelCal + " Mag=" + magCal);
}
}
}
// Set serial port to desired value.
void setSerialPort(String portName) {
// Close the port if it's currently open.
if (port != null) {
port.stop();
}
try {
// Open port.
port = new Serial(this, portName, 115200);
port.bufferUntil('\n');
// Persist port in configuration.
saveStrings(serialConfigFile, new String[] { portName });
}
catch (RuntimeException ex) {
// Swallow error if port can't be opened, keep port closed.
port = null;
}
}
// UI event handlers
void handlePanelEvents(GPanel panel, GEvent event) {
// Panel events, do nothing.
}
void handleDropListEvents(GDropList list, GEvent event) {
// Drop list events, check if new serial port is selected.
if (list == serialList) {
setSerialPort(serialList.getSelectedText());
}
}
void handleToggleControlEvents(GToggleControl checkbox, GEvent event) {
// Checkbox toggle events, check if print events is toggled.
if (checkbox == printSerialCheckbox) {
printSerial = printSerialCheckbox.isSelected();
}
}

View File

@ -0,0 +1,13 @@
# 3ds Max Wavefront OBJ Exporter v0.94b - (c)2007 guruware
# File Created: 04.07.2010 10:41:39
newmtl Body
Ns 32
d 1
Tr 1
Tf 1 1 1
illum 2
Ka 0.0000 0.0000 0.0000
Kd 0.7412 0.4784 0.4765
Ks 0.3500 0.3500 0.6500

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
/dev/tty.usbmodem141121

View File

@ -0,0 +1,10 @@
name=Adafruit BNO055
version=1.6.3
author=Adafruit <info@adafruit.com>
maintainer=Adafruit <info@adafruit.com>
sentence=Library for the Adafruit BNO055 Absolute Orientation Sensor.
paragraph=Designed specifically to work with the Adafruit BNO055 Breakout, and is based on Adafruit's Unified Sensor Library.
category=Sensors
url=https://github.com/adafruit/Adafruit_BNO055
architectures=*
depends=Adafruit Unified Sensor, Adafruit BusIO

View File

@ -0,0 +1,31 @@
// Inertial Measurement Unit Maths Library
//
// Copyright 2013-2021 Sam Cowen <samuel.cowen@camelsoftware.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef IMUMATH_H
#define IMUMATH_H
#include "matrix.h"
#include "quaternion.h"
#include "vector.h"
#endif

View File

@ -0,0 +1,185 @@
// Inertial Measurement Unit Maths Library
//
// Copyright 2013-2021 Sam Cowen <samuel.cowen@camelsoftware.com>
// Bug fixes and cleanups by Gé Vissers (gvissers@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef IMUMATH_MATRIX_HPP
#define IMUMATH_MATRIX_HPP
#include <stdint.h>
#include <string.h>
#include "vector.h"
namespace imu {
template <uint8_t N> class Matrix {
public:
Matrix() { memset(_cell_data, 0, N * N * sizeof(double)); }
Matrix(const Matrix &m) {
for (int ij = 0; ij < N * N; ++ij) {
_cell_data[ij] = m._cell_data[ij];
}
}
~Matrix() {}
Matrix &operator=(const Matrix &m) {
for (int ij = 0; ij < N * N; ++ij) {
_cell_data[ij] = m._cell_data[ij];
}
return *this;
}
Vector<N> row_to_vector(int i) const {
Vector<N> ret;
for (int j = 0; j < N; j++) {
ret[j] = cell(i, j);
}
return ret;
}
Vector<N> col_to_vector(int j) const {
Vector<N> ret;
for (int i = 0; i < N; i++) {
ret[i] = cell(i, j);
}
return ret;
}
void vector_to_row(const Vector<N> &v, int i) {
for (int j = 0; j < N; j++) {
cell(i, j) = v[j];
}
}
void vector_to_col(const Vector<N> &v, int j) {
for (int i = 0; i < N; i++) {
cell(i, j) = v[i];
}
}
double operator()(int i, int j) const { return cell(i, j); }
double &operator()(int i, int j) { return cell(i, j); }
double cell(int i, int j) const { return _cell_data[i * N + j]; }
double &cell(int i, int j) { return _cell_data[i * N + j]; }
Matrix operator+(const Matrix &m) const {
Matrix ret;
for (int ij = 0; ij < N * N; ++ij) {
ret._cell_data[ij] = _cell_data[ij] + m._cell_data[ij];
}
return ret;
}
Matrix operator-(const Matrix &m) const {
Matrix ret;
for (int ij = 0; ij < N * N; ++ij) {
ret._cell_data[ij] = _cell_data[ij] - m._cell_data[ij];
}
return ret;
}
Matrix operator*(double scalar) const {
Matrix ret;
for (int ij = 0; ij < N * N; ++ij) {
ret._cell_data[ij] = _cell_data[ij] * scalar;
}
return ret;
}
Matrix operator*(const Matrix &m) const {
Matrix ret;
for (int i = 0; i < N; i++) {
Vector<N> row = row_to_vector(i);
for (int j = 0; j < N; j++) {
ret(i, j) = row.dot(m.col_to_vector(j));
}
}
return ret;
}
Matrix transpose() const {
Matrix ret;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
ret(j, i) = cell(i, j);
}
}
return ret;
}
Matrix<N - 1> minor_matrix(int row, int col) const {
Matrix<N - 1> ret;
for (int i = 0, im = 0; i < N; i++) {
if (i == row)
continue;
for (int j = 0, jm = 0; j < N; j++) {
if (j != col) {
ret(im, jm++) = cell(i, j);
}
}
im++;
}
return ret;
}
double determinant() const {
// specialization for N == 1 given below this class
double det = 0.0, sign = 1.0;
for (int i = 0; i < N; ++i, sign = -sign)
det += sign * cell(0, i) * minor_matrix(0, i).determinant();
return det;
}
Matrix invert() const {
Matrix ret;
double det = determinant();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
ret(i, j) = minor_matrix(j, i).determinant() / det;
if ((i + j) % 2 == 1)
ret(i, j) = -ret(i, j);
}
}
return ret;
}
double trace() const {
double tr = 0.0;
for (int i = 0; i < N; ++i)
tr += cell(i, i);
return tr;
}
private:
double _cell_data[N * N];
};
template <> inline double Matrix<1>::determinant() const { return cell(0, 0); }
}; // namespace imu
#endif

View File

@ -0,0 +1,214 @@
// Inertial Measurement Unit Maths Library
//
// Copyright 2013-2021 Sam Cowen <samuel.cowen@camelsoftware.com>
// Bug fixes and cleanups by Gé Vissers (gvissers@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef IMUMATH_QUATERNION_HPP
#define IMUMATH_QUATERNION_HPP
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
namespace imu {
class Quaternion {
public:
Quaternion() : _w(1.0), _x(0.0), _y(0.0), _z(0.0) {}
Quaternion(double w, double x, double y, double z)
: _w(w), _x(x), _y(y), _z(z) {}
Quaternion(double w, Vector<3> vec)
: _w(w), _x(vec.x()), _y(vec.y()), _z(vec.z()) {}
double &w() { return _w; }
double &x() { return _x; }
double &y() { return _y; }
double &z() { return _z; }
double w() const { return _w; }
double x() const { return _x; }
double y() const { return _y; }
double z() const { return _z; }
double magnitude() const {
return sqrt(_w * _w + _x * _x + _y * _y + _z * _z);
}
void normalize() {
double mag = magnitude();
*this = this->scale(1 / mag);
}
Quaternion conjugate() const { return Quaternion(_w, -_x, -_y, -_z); }
void fromAxisAngle(const Vector<3> &axis, double theta) {
_w = cos(theta / 2);
// only need to calculate sine of half theta once
double sht = sin(theta / 2);
_x = axis.x() * sht;
_y = axis.y() * sht;
_z = axis.z() * sht;
}
void fromMatrix(const Matrix<3> &m) {
double tr = m.trace();
double S;
if (tr > 0) {
S = sqrt(tr + 1.0) * 2;
_w = 0.25 * S;
_x = (m(2, 1) - m(1, 2)) / S;
_y = (m(0, 2) - m(2, 0)) / S;
_z = (m(1, 0) - m(0, 1)) / S;
} else if (m(0, 0) > m(1, 1) && m(0, 0) > m(2, 2)) {
S = sqrt(1.0 + m(0, 0) - m(1, 1) - m(2, 2)) * 2;
_w = (m(2, 1) - m(1, 2)) / S;
_x = 0.25 * S;
_y = (m(0, 1) + m(1, 0)) / S;
_z = (m(0, 2) + m(2, 0)) / S;
} else if (m(1, 1) > m(2, 2)) {
S = sqrt(1.0 + m(1, 1) - m(0, 0) - m(2, 2)) * 2;
_w = (m(0, 2) - m(2, 0)) / S;
_x = (m(0, 1) + m(1, 0)) / S;
_y = 0.25 * S;
_z = (m(1, 2) + m(2, 1)) / S;
} else {
S = sqrt(1.0 + m(2, 2) - m(0, 0) - m(1, 1)) * 2;
_w = (m(1, 0) - m(0, 1)) / S;
_x = (m(0, 2) + m(2, 0)) / S;
_y = (m(1, 2) + m(2, 1)) / S;
_z = 0.25 * S;
}
}
void toAxisAngle(Vector<3> &axis, double &angle) const {
double sqw = sqrt(1 - _w * _w);
if (sqw == 0) // it's a singularity and divide by zero, avoid
return;
angle = 2 * acos(_w);
axis.x() = _x / sqw;
axis.y() = _y / sqw;
axis.z() = _z / sqw;
}
Matrix<3> toMatrix() const {
Matrix<3> ret;
ret.cell(0, 0) = 1 - 2 * _y * _y - 2 * _z * _z;
ret.cell(0, 1) = 2 * _x * _y - 2 * _w * _z;
ret.cell(0, 2) = 2 * _x * _z + 2 * _w * _y;
ret.cell(1, 0) = 2 * _x * _y + 2 * _w * _z;
ret.cell(1, 1) = 1 - 2 * _x * _x - 2 * _z * _z;
ret.cell(1, 2) = 2 * _y * _z - 2 * _w * _x;
ret.cell(2, 0) = 2 * _x * _z - 2 * _w * _y;
ret.cell(2, 1) = 2 * _y * _z + 2 * _w * _x;
ret.cell(2, 2) = 1 - 2 * _x * _x - 2 * _y * _y;
return ret;
}
// Returns euler angles that represent the quaternion. Angles are
// returned in rotation order and right-handed about the specified
// axes:
//
// v[0] is applied 1st about z (ie, roll)
// v[1] is applied 2nd about y (ie, pitch)
// v[2] is applied 3rd about x (ie, yaw)
//
// Note that this means result.x() is not a rotation about x;
// similarly for result.z().
//
Vector<3> toEuler() const {
Vector<3> ret;
double sqw = _w * _w;
double sqx = _x * _x;
double sqy = _y * _y;
double sqz = _z * _z;
ret.x() = atan2(2.0 * (_x * _y + _z * _w), (sqx - sqy - sqz + sqw));
ret.y() = asin(-2.0 * (_x * _z - _y * _w) / (sqx + sqy + sqz + sqw));
ret.z() = atan2(2.0 * (_y * _z + _x * _w), (-sqx - sqy + sqz + sqw));
return ret;
}
Vector<3> toAngularVelocity(double dt) const {
Vector<3> ret;
Quaternion one(1.0, 0.0, 0.0, 0.0);
Quaternion delta = one - *this;
Quaternion r = (delta / dt);
r = r * 2;
r = r * one;
ret.x() = r.x();
ret.y() = r.y();
ret.z() = r.z();
return ret;
}
Vector<3> rotateVector(const Vector<2> &v) const {
return rotateVector(Vector<3>(v.x(), v.y()));
}
Vector<3> rotateVector(const Vector<3> &v) const {
Vector<3> qv(_x, _y, _z);
Vector<3> t = qv.cross(v) * 2.0;
return v + t * _w + qv.cross(t);
}
Quaternion operator*(const Quaternion &q) const {
return Quaternion(_w * q._w - _x * q._x - _y * q._y - _z * q._z,
_w * q._x + _x * q._w + _y * q._z - _z * q._y,
_w * q._y - _x * q._z + _y * q._w + _z * q._x,
_w * q._z + _x * q._y - _y * q._x + _z * q._w);
}
Quaternion operator+(const Quaternion &q) const {
return Quaternion(_w + q._w, _x + q._x, _y + q._y, _z + q._z);
}
Quaternion operator-(const Quaternion &q) const {
return Quaternion(_w - q._w, _x - q._x, _y - q._y, _z - q._z);
}
Quaternion operator/(double scalar) const {
return Quaternion(_w / scalar, _x / scalar, _y / scalar, _z / scalar);
}
Quaternion operator*(double scalar) const { return scale(scalar); }
Quaternion scale(double scalar) const {
return Quaternion(_w * scalar, _x * scalar, _y * scalar, _z * scalar);
}
private:
double _w, _x, _y, _z;
};
} // namespace imu
#endif

View File

@ -0,0 +1,184 @@
// Inertial Measurement Unit Maths Library
//
// Copyright 2013-2021 Sam Cowen <samuel.cowen@camelsoftware.com>
// Bug fixes and cleanups by Gé Vissers (gvissers@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef IMUMATH_VECTOR_HPP
#define IMUMATH_VECTOR_HPP
#include <math.h>
#include <stdint.h>
#include <string.h>
namespace imu {
template <uint8_t N> class Vector {
public:
Vector() { memset(p_vec, 0, sizeof(double) * N); }
Vector(double a) {
memset(p_vec, 0, sizeof(double) * N);
p_vec[0] = a;
}
Vector(double a, double b) {
memset(p_vec, 0, sizeof(double) * N);
p_vec[0] = a;
p_vec[1] = b;
}
Vector(double a, double b, double c) {
memset(p_vec, 0, sizeof(double) * N);
p_vec[0] = a;
p_vec[1] = b;
p_vec[2] = c;
}
Vector(double a, double b, double c, double d) {
memset(p_vec, 0, sizeof(double) * N);
p_vec[0] = a;
p_vec[1] = b;
p_vec[2] = c;
p_vec[3] = d;
}
Vector(const Vector<N> &v) {
for (int x = 0; x < N; x++)
p_vec[x] = v.p_vec[x];
}
~Vector() {}
uint8_t n() { return N; }
double magnitude() const {
double res = 0;
for (int i = 0; i < N; i++)
res += p_vec[i] * p_vec[i];
return sqrt(res);
}
void normalize() {
double mag = magnitude();
if (isnan(mag) || mag == 0.0)
return;
for (int i = 0; i < N; i++)
p_vec[i] /= mag;
}
double dot(const Vector &v) const {
double ret = 0;
for (int i = 0; i < N; i++)
ret += p_vec[i] * v.p_vec[i];
return ret;
}
// The cross product is only valid for vectors with 3 dimensions,
// with the exception of higher dimensional stuff that is beyond
// the intended scope of this library.
// Only a definition for N==3 is given below this class, using
// cross() with another value for N will result in a link error.
Vector cross(const Vector &v) const;
Vector scale(double scalar) const {
Vector ret;
for (int i = 0; i < N; i++)
ret.p_vec[i] = p_vec[i] * scalar;
return ret;
}
Vector invert() const {
Vector ret;
for (int i = 0; i < N; i++)
ret.p_vec[i] = -p_vec[i];
return ret;
}
Vector &operator=(const Vector &v) {
for (int x = 0; x < N; x++)
p_vec[x] = v.p_vec[x];
return *this;
}
double &operator[](int n) { return p_vec[n]; }
double operator[](int n) const { return p_vec[n]; }
double &operator()(int n) { return p_vec[n]; }
double operator()(int n) const { return p_vec[n]; }
Vector operator+(const Vector &v) const {
Vector ret;
for (int i = 0; i < N; i++)
ret.p_vec[i] = p_vec[i] + v.p_vec[i];
return ret;
}
Vector operator-(const Vector &v) const {
Vector ret;
for (int i = 0; i < N; i++)
ret.p_vec[i] = p_vec[i] - v.p_vec[i];
return ret;
}
Vector operator*(double scalar) const { return scale(scalar); }
Vector operator/(double scalar) const {
Vector ret;
for (int i = 0; i < N; i++)
ret.p_vec[i] = p_vec[i] / scalar;
return ret;
}
void toDegrees() {
for (int i = 0; i < N; i++)
p_vec[i] *= 57.2957795131; // 180/pi
}
void toRadians() {
for (int i = 0; i < N; i++)
p_vec[i] *= 0.01745329251; // pi/180
}
double &x() { return p_vec[0]; }
double &y() { return p_vec[1]; }
double &z() { return p_vec[2]; }
double x() const { return p_vec[0]; }
double y() const { return p_vec[1]; }
double z() const { return p_vec[2]; }
private:
double p_vec[N];
};
template <> inline Vector<3> Vector<3>::cross(const Vector &v) const {
return Vector(p_vec[1] * v.p_vec[2] - p_vec[2] * v.p_vec[1],
p_vec[2] * v.p_vec[0] - p_vec[0] * v.p_vec[2],
p_vec[0] * v.p_vec[1] - p_vec[1] * v.p_vec[0]);
}
} // namespace imu
#endif

395
lib/OSC/API.md 100644
View File

@ -0,0 +1,395 @@
# OSCMessage
An OSCMessage is an address followed by any number of data. Messages can have mixed data types like an integer followed by a string followed by a float, etc.
## Constructor
OSCMessages can be constructed with or without an address.
### `OSCMessage(const char *)`
Set the address of the message in the constructor
```C++
OSCMessage msg("/address");
```
### `OSCMessage()`
An OSCMessage constructed without an address is not valid until it is given an address.
## Add/Set Data
### `OSCMessage& add(int i)`
Append an integer to the OSCMessage.
```C++
msg.add(1);
```
### `OSCMessage& add(float f)`
Append a float to the OSCMessage.
### `OSCMessage& add(bool b)`
Append a boolean to the OSCMessage.
### `OSCMessage& add(const char * str)`
Append a string to the OSCMessage.
```C++
msg.add("hello");
```
### `OSCMessage& add(uint8_t * blob, int length)`
Append a [blob](https://en.wikipedia.org/wiki/Binary_large_object) to the OSCMessage. Pass in the length of the blob as the second argument.
### `OSCMessage& set(int position, Type data)`
Replace the data at the given position with the data. `Type` can be any of the supported data types.
```C++
//replace the data at the 0th position with a string
msg.set(0, "string");
```
### `OSCMessage& set(int position, uint8_t * data, int length)`
Set the data at the given position to be a blob of the given length.
### `OSCMessage& add(double d)`
Append a double precision floating point value to the OSCMessage. NOTE: double is not supported on most Arduino platforms. It will fall back to float, when double is not supported.
## Get Data
### `int getInt(int position)`
Returns the integer at the given position
```C++
//returns the integer at the third position
msg.getInt(2);
```
### `float getFloat(int position)`
Returns the float at the given position
### `bool getBoolean(int position)`
Returns the boolean at the given position
### `double getDouble(int position)`
Returns the double at the given position. NOTE: double is not supported by most Arduino platforms. This will fail silently if double is not supported.
### `int getString(int position, char * strBuffer)`
Copy the strings characters into the `strBuffer`, without any safety check.
Returns the number of copied characters.
### `int getString(int position, char * strBuffer, int length)`
Copy the strings characters into the `strBuffer`, after checking that this doesnt exceed the buffers `length`.
Returns the number of copied characters. NOTE that if the string length is greater than the available buffer length, then NO characters are copied.
### `int getString(int position, char * strBuffer, int length, int offset, int size)`
Copy `size` number of characters from the given `offset` into the `strBuffer`, after checking that this doesnt exceed the buffers `length`. Returns `size`, even if the number of copied characters is lower.
```C++
char str[8];
//fill str with 8 characters from the 0th datum
msg.getString(0, str, 8, 0, 8);
```
### `int getBlob(int position, uint8_t * blobBuffer)`
Directly copy the blobs bytes into the `blob` buffer (without safety-check).
Returns the number of bytes from the blob.
### `int getBlob(int position, uint8_t * blobBuffer, int length)`
Copy the blob's bytes into the given `blobBuffer`, if the blob's size doesnt exceed the blobBuffer's `length`.
Returns the number of bytes copied from the blob. NOTE that if the blob length is greater than the available buffer length, then NO bytes are copied.
### `int getBlob(int position, uint8_t * blobBuffer, int length, int offset, int size)`
Copy `size` bytes from the blob, starting from `offset`, into the given `blobBuffer`, if the size doesnt exceed the buffers `length` or the blobs data length.
Returns the number of bytes copied from the blob. NOTE that if the requested size is greater than *either* the available buffer length *or* the (partial) blob length, then NO bytes are copied.
### `const uint8_t* getBlob(int position)`
Get a pointer to blob data.
### `int getBlobLength(int position)`
Returns the length of the blob in bytes.
### `char getType(int position)`
Returns the type of the data at the given position.
```C++
OSCMessage msg("/address");
msg.add(1);
msg.getType(0); //-> returns 'i'
```
## Query Data
### `bool isInt(int position)`
Returns `true` when the data at the given position is an integer.
### `bool isFloat(int position)`
Returns `true` when the data at the given position is a float.
### `bool isBoolean(int position)`
Returns `true` when the data at the given position is a boolean.
### `bool isString(int position)`
Returns `true` when the data at the given position is a string.
### `bool isBlob(int position)`
Returns `true` when the data at the given position is a blob.
### `bool isDouble(int position)`
Returns `true` when the data at the given position is a double.
### `int size()`
Returns the number of data the OSCMessage has.
### `int bytes()`
Returns the size of the OSCMessage in bytes (if everything is 32-bit aligned).
## Address
### `OSCMessage& setAddress(const char * address)`
Set the address of the OSCMessage.
### `int getAddress(char * str, int offset=0)`
Copy the address of the OSCMessage into the `str` buffer. Copy after the given address `offset` (defaults to 0). Returns the length of the resulting string. If the offset is past the end of the address an empty string / zero length are returned.
### `int getAddress(char * str, int offset, int len)`
Copy a maximum of len characters of the address of the OSCMessage into the `str` buffer, starting at at the given address `offset`. Returns the length of the resulting string. If the offset is past the end of the address an empty string / zero length are returned.
### `int getAddressLength(int offset=0)`
Returns the length of the OSCMessage's address, starting after the given address `offset` (defaults to 0). If the offset is
greater than the address length then it returns zero.
### `const char* getAddress()`
Get a pointer to the address as a C string.
## Send Receive
### `OSCMessage& send(Print &p)`
Output the message to the given transport layer which extends Arduino's [Print class](http://playground.arduino.cc/Code/Printclass) like the `Serial` out.
```C++
msg.send(SLIPSerial);
```
### `OSCMessage& fill(uint8_t incomingByte)`
Add the incoming byte to the OSCMessage where it will be decoded.
### `OSCMessage& fill(uint8_t * bytes, int length)`
Add and decode the array of `bytes` as an OSCMessage.
## Matching / Routing
### `bool fullMatch( const char * pattern, int offset = 0)`
Returns true if the message's address is a full match to the given `pattern` after the `offset`.
```C++
OSCMessage msg("/a/0");
msg.fullMatch("/0", 2); // ->returns true
```
### `int match( const char * pattern, int offset = 0)`
Returns the number of matched characters of the message's address against the given `pattern` (optionally with an `offset`). Unlike `fullMatch`, `match` allows for partial matches
```C++
OSCMessage msg("/a/0");
msg.match("/a"); // ->returns 2
```
### `bool dispatch(const char * pattern, void (*callback)(OSCMessage &), int offset = 0)`
Invoke the given `callback` if the address is a full match with the `pattern` (after the `offset`). The message is passed into the callback function. Returns true if the pattern was a match and the callback function was invoked.
### `bool route(const char * pattern, void (*callback)(OSCMessage &, int), int offset = 0)`
Invoke the given `callback` if the address if a match with the `pattern` (after the `offset`). The OSCMessage and the address offset is passed into the callback function. Returns true if the pattern was a match and the callback function was invoked.
```C++
//define a callback function for matching messages
void routeCallback(OSCMessage & message, int addressOffset){
//do something with the message...
//with the message below, the addressOffset will equal 2.
}
OSCMessage msg("/a/0");
msg.route("/a", routeCallback);
```
## Address Patterns
OSCMessages can be constructed with patterns and later routed or dispatched against addresses.
```C++
OSCMessage msg("/{a,b}/[0-9]");
msg.route("/a/0", a0_callback); //matches the address
msg.route("/b/2", b2_callback); //matches the address
msg.route("/c/11", c11_callback); //not invoked
```
# OSCBundle
A bundle is a group of OSCMessages with a timetag.
## Constructor
### `OSCBundle()`
Construct an empty OSCBundle.
### `OSCBundle(osctime_t = zerotime)`
Construct the bundle with a timetag. timetag defaults to 0 (immediate).
## Add OSCMessage
### `OSCMessage & add(char * address)`
Create a new message with the given `address` in the bundle. Returns the newly created OSCMessage.
```C++
//create a new OSCMessage and add some data to it
bundle.add("/message").add("data");
```
## Get OSCMessage
### `OSCMessage * getOSCMessage(int position)`
Return the OSCMessage in the bundle at the given `position`.
```C++
OSCBundle bundle
bundle.add("/a");
bundle.add("/b");
bundle.getOSCMessage(0);//returns the OSCMessage with the address "/a".
```
### `OSCMessage * getOSCMessage(char * address)`
Return the OSCMessage in the bundle which matches the given address.
```C++
OSCBundle bundle
bundle.add("/a");
bundle.add("/b");
bundle.getOSCMessage("/b");//returns the second OSCMessage in the bundle
```
## Routing
### `bool dispatch(const char * pattern, void (*callback)(OSCMessage&), int offset = 0)`
Invoke the `callback` function with all messages in the bundle which match the given pattern after the offset.
```C++
bundle.add("/a/0");
bundle.add("/b/0");
bundle.dispatch("/0", dispatchZero, 2);
```
### `bool route(const char * pattern, void (*callback)(OSCMessage &, int), int offset = 0)`
Invoke the `callback` with all the OSCMessages in the bundle which match the given `pattern`. `route` allows for partial matches.
## Send/Receive
### `OSCBundle& send(Print &p)`
Output the bundle to the given transport layer which extends Arduino's [Print class](http://playground.arduino.cc/Code/Printclass) (such as `SLIPSerial` out).
```C++
bundle.send(SLIPSerial);
```
### `OSCBundle& fill(uint8_t incomingByte)`
Add the incoming byte to the OSCBundle where it will be decoded.
### `OSCBundle& fill(uint8_t * bytes, int length)`
Add and decode the array of bytes as an OSCBundle.
# Chaining
Many methods return `this` which enables you to string together multiple commands.
This technique allows multiple lines to be condensed into one:
```C++
bundle.add("/address").add("data").add(0).send(SLIPSerial).empty();
```

View File

@ -0,0 +1,306 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 130.0, 174.0, 983.0, 623.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontface" : 0,
"fontsize" : 12.0,
"id" : "obj-5",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 141.0, 266.0, 150.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-3",
"linecount" : 6,
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 422.5, 125.0, 158.0, 101.0 ],
"text" : "/port : \"usbmodemOSCes41\",\n/rate/output : 0,\n/rate/input : 0,\n/mediansize/received : -1,\n/baud",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-2",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 389.5, -32.5, 170.0, 33.0 ],
"style" : "",
"text" : "Look for your device in the menu list of serial USB"
}
}
, {
"box" : {
"bgmode" : 0,
"border" : 0,
"clickthrough" : 0,
"enablehscroll" : 0,
"enablevscroll" : 0,
"id" : "obj-7",
"lockeddragscroll" : 0,
"maxclass" : "bpatcher",
"name" : "o.io.serial.display.maxpat",
"numinlets" : 1,
"numoutlets" : 1,
"offset" : [ 3.0, 0.0 ],
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 81.5, 29.0, 340.5, 25.0 ],
"viewvisibility" : 1
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-23",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 20.5, 68.0, 80.0, 22.0 ],
"style" : "",
"text" : "o.io.slipserial"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-11",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 471.0, 29.0, 150.0, 54.0 ],
"style" : "",
"text" : "stats on serial OSC communications"
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 12.0,
"id" : "obj-6",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 214.0, 285.0, 150.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 12.0,
"id" : "obj-4",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 23.0, 285.0, 150.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-1",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "", "", "FullPacket" ],
"patching_rect" : [ 23.0, 176.0, 119.0, 22.0 ],
"style" : "",
"text" : "o.route /raw /cooked"
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-4", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-1", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-1", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-1", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-23", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-3", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 91.0, 109.0, 432.0, 109.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-5", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-23", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-7", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 91.0, 95.0, 433.0, 95.0, 433.0, 5.0, 91.0, 5.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-23", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-7", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.slipserial.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "~/Documents/Max/Packages/odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.io.serial.display.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.route.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
, {
"name" : "o.pack.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.validate.mxo",
"type" : "iLaX"
}
, {
"name" : "o.print.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.encode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.decode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
],
"embedsnapshot" : 0
}
}

View File

@ -0,0 +1,974 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 140.0, 78.0, 1266.0, 737.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 14.0,
"default_fontface" : 0,
"default_fontname" : "Andale Mono",
"gridonopen" : 1,
"gridsize" : [ 5.0, 5.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-6",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 725.5, 158.0, 170.0, 33.0 ],
"style" : "",
"text" : "Look for your device in the menu list of serial USB"
}
}
, {
"box" : {
"bgmode" : 0,
"border" : 0,
"clickthrough" : 0,
"enablehscroll" : 0,
"enablevscroll" : 0,
"id" : "obj-9",
"lockeddragscroll" : 0,
"maxclass" : "bpatcher",
"name" : "o.io.serial.display.maxpat",
"numinlets" : 1,
"numoutlets" : 1,
"offset" : [ 3.0, 0.0 ],
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 338.5, 162.0, 340.5, 25.0 ],
"viewvisibility" : 1
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 14.0,
"id" : "obj-8",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 240.5, 252.0, 150.0, 36.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 14.0,
"id" : "obj-5",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 491.0, 252.0, 150.0, 36.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-7",
"maxclass" : "o.message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 521.0, 81.0, 150.0, 20.0 ],
"text" : "/analog/{2,3}/u",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-1",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 524.5, 16.0, 222.0, 38.0 ],
"style" : "",
"text" : "read analog pins 2 and 3 with pullup turned on"
}
}
, {
"box" : {
"id" : "obj-78",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 504.5, 15.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-79",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 504.5, 46.0, 86.0, 24.0 ],
"style" : "",
"text" : "qmetro 20"
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-55",
"maxclass" : "o.message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 266.0, 81.0, 150.0, 20.0 ],
"text" : "/analog/[0-3]/u",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-28",
"maxclass" : "o.message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 19.0, 81.0, 150.0, 20.0 ],
"text" : "/analog/*",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"id" : "obj-56",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 174.0, 455.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-64",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 172.0, 350.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[37]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[25]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-13",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 3.0, 493.0, 145.0, 22.0 ],
"style" : "",
"text" : "analog readings"
}
}
, {
"box" : {
"id" : "obj-110",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 135.0, 454.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-109",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 102.0, 454.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-108",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 69.0, 454.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-107",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 36.0, 454.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-105",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 135.0, 350.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[19]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[4]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-104",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 102.0, 350.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[20]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[3]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-103",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 69.0, 350.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[21]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[2]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-102",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 36.0, 350.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[22]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[1]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-101",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 3.0, 350.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[23]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a"
}
}
, {
"box" : {
"id" : "obj-84",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 3.0, 454.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-81",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 7,
"outlettype" : [ "", "", "", "", "", "", "FullPacket" ],
"patching_rect" : [ 8.0, 310.0, 221.0, 24.0 ],
"style" : "",
"text" : "o.route /0 /1 /2 /3 /4 /5"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-45",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "FullPacket" ],
"patching_rect" : [ 3.0, 252.0, 137.0, 24.0 ],
"style" : "",
"text" : "o.route /analog"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-15",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 269.5, 17.0, 187.0, 38.0 ],
"style" : "",
"text" : "read analog pins 0-3 with pullup turned on"
}
}
, {
"box" : {
"id" : "obj-18",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 249.5, 17.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-22",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 249.5, 47.0, 86.0, 24.0 ],
"style" : "",
"text" : "qmetro 20"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-46",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 32.5, 18.0, 187.0, 22.0 ],
"style" : "",
"text" : "read all analog pins"
}
}
, {
"box" : {
"id" : "obj-60",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 12.5, 18.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-61",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 12.5, 47.0, 95.0, 24.0 ],
"style" : "",
"text" : "qmetro 100"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-4",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 702.5, 243.0, 150.0, 54.0 ],
"style" : "",
"text" : "stats on serial OSC communications"
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-26",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 220.5, 201.0, 137.0, 24.0 ],
"style" : "",
"text" : "o.io.slipserial"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-91",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 0,
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 34.0, 78.0, 738.0, 421.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 14.0,
"default_fontface" : 0,
"default_fontname" : "Andale Mono",
"gridonopen" : 1,
"gridsize" : [ 5.0, 5.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-2",
"linecount" : 25,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 15.0, 20.0, 768.0, 400.0 ],
"style" : "",
"text" : "/*\n Written by Yotam Mann and Adrian freed,\n The Center for New Music and Audio Technologies,\n University of California, Berkeley. Copyright (c) 2012, The Regents of\n the University of California (Regents).\n \n Permission to use, copy, modify, distribute, and distribute modified versions\n of this software and its documentation without fee and without a signed\n licensing agreement, is hereby granted, provided that the above copyright\n notice, this paragraph and the following two paragraphs appear in all copies,\n modifications, and distributions.\n \n IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,\n SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING\n OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS\n BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n \n REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED\n HEREUNDER IS PROVIDED \"AS IS\". REGENTS HAS NO OBLIGATION TO PROVIDE\n MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\n \n For bug reports and feature requests please email me at yotam@cnmat.berkeley.edu\n */"
}
}
],
"lines" : [ ]
}
,
"patching_rect" : [ 8.0, 570.0, 111.0, 24.0 ],
"saved_object_attributes" : {
"description" : "",
"digest" : "",
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"globalpatchername" : "",
"style" : "",
"tags" : ""
}
,
"style" : "",
"text" : "p disclaimer"
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-84", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-101", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-107", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-102", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-108", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-103", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-109", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-104", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-110", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-105", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-22", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-18", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-55", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-22", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-45", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-5", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-8", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-9", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 348.0, 229.0, 717.0, 229.0, 717.0, 131.0, 348.0, 131.0 ],
"source" : [ "obj-26", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-28", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-81", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-45", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-55", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-61", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-60", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-28", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-61", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-56", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-64", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-7", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-79", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-78", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-7", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-79", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-101", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-102", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-103", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 2 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-104", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 3 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-105", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 4 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-64", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 5 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-26", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-9", 0 ]
}
}
],
"parameters" : {
"obj-105" : [ "a[19]", "a", 0 ],
"obj-104" : [ "a[20]", "a", 0 ],
"obj-103" : [ "a[21]", "a", 0 ],
"obj-64" : [ "a[37]", "a", 0 ],
"obj-102" : [ "a[22]", "a", 0 ],
"obj-101" : [ "a[23]", "a", 0 ]
}
,
"dependency_cache" : [ {
"name" : "o.io.slipserial.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "~/Documents/Max/Packages/odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.io.serial.display.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.pack.mxo",
"type" : "iLaX"
}
, {
"name" : "o.route.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.validate.mxo",
"type" : "iLaX"
}
, {
"name" : "o.print.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.encode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.decode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.message.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
],
"embedsnapshot" : 0
}
}

View File

@ -0,0 +1,304 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 6,
"minor" : 1,
"revision" : 6,
"architecture" : "x86"
}
,
"rect" : [ 608.0, 81.0, 1202.0, 749.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 14.0,
"default_fontface" : 0,
"default_fontname" : "Andale Mono",
"gridonopen" : 0,
"gridsize" : [ 5.0, 5.0 ],
"gridsnaponopen" : 0,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"boxes" : [ {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-1",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 218.0, 295.0, 95.0, 22.0 ],
"text" : "o.downcast"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-18",
"linecount" : 10,
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 28.5, 425.0, 267.0, 155.0 ],
"text" : "/ping : 100,\n/thing : [2., 3.04, 1242., 23., \"thing\"],\n/stuff : [1, 2, 3, 4, 5],\n/fsakjfskfsdkasfk : [234, 242, 234, 234, 4],\n/decision : 1,\n/notdecision : 0,\n/micros : 616229100,\n/sequencenumber : 20557,\n/digital/5 : false,\n/lsb : false",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-3",
"linecount" : 5,
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 404.5, 425.0, 158.0, 88.0 ],
"text" : "/port : \"usbmodem12341\",\n/rate/output : 32,\n/rate/input : 39,\n/mediansize/received : -1,\n/baud",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"frgb" : 0.0,
"id" : "obj-19",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 424.5, 269.5, 170.0, 33.0 ],
"text" : "Look for your device in the menu list of serial USB"
}
}
, {
"box" : {
"id" : "obj-20",
"maxclass" : "bpatcher",
"name" : "o.io.serial.display.maxpat",
"numinlets" : 1,
"numoutlets" : 1,
"offset" : [ 3.0, 0.0 ],
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 404.5, 340.0, 164.0, 24.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-23",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 343.5, 379.0, 80.0, 20.0 ],
"text" : "o.io.slipserial"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-2",
"linecount" : 6,
"maxclass" : "o.compose",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 45.0, 90.166656, 964.0, 105.0 ],
"text" : "/ping : 100,\n/thing : [2., 3.04, 1242., 23., \"thing\"],\n/stuff : [1, 2, 3, 4, 5],\n/fsakjfskfsdkasfk : [234, 242, 234, 234, 4],\n/decision : true,\n/notdecision : false",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"frgb" : 0.0,
"id" : "obj-4",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 595.0, 415.0, 150.0, 54.0 ],
"text" : "stats on serial OSC communications"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-61",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 45.0, 38.166656, 162.0, 22.0 ],
"text" : "metro 22 @active 1"
}
}
],
"lines" : [ {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-23", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-1", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-1", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-2", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-23", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-20", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-18", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-23", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-20", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 414.0, 406.0, 583.0, 406.0, 583.0, 316.0, 414.0, 316.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-3", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 414.0, 420.0, 414.0, 420.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-2", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-61", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.slipserial.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/CNMAT-MMJSS/patchers/esplora",
"patcherrelativepath" : "../../../../../Documents/Max/Packages/CNMAT-MMJSS/patchers/esplora",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/CNMAT-odot/patchers/ordering",
"patcherrelativepath" : "../../../../../Documents/Max/Packages/CNMAT-odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.io.serial.display.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/CNMAT-MMJSS/patchers/esplora",
"patcherrelativepath" : "../../../../../Documents/Max/Packages/CNMAT-MMJSS/patchers/esplora",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.compose.mxo",
"type" : "iLaX"
}
, {
"name" : "o.pack.mxo",
"type" : "iLaX"
}
, {
"name" : "o.route.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.validate.mxo",
"type" : "iLaX"
}
, {
"name" : "o.print.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.encode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.decode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
, {
"name" : "o.downcast.mxo",
"type" : "iLaX"
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,428 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 378.0, 174.0, 792.0, 490.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-5",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 68.0, 374.0, 267.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-12",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 164.0, 202.0, 69.0, 22.0 ],
"style" : "",
"text" : "o.pack /led"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-1",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 164.0, 244.0, 95.0, 24.0 ],
"style" : "",
"text" : "o.downcast"
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-18",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 164.0, 314.0, 92.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-3",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 350.5, 374.0, 158.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-2",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 370.5, 218.5, 170.0, 33.0 ],
"style" : "",
"text" : "Look for your device in the menu list of serial USB"
}
}
, {
"box" : {
"bgmode" : 0,
"border" : 0,
"clickthrough" : 0,
"enablehscroll" : 0,
"enablevscroll" : 0,
"id" : "obj-4",
"lockeddragscroll" : 0,
"maxclass" : "bpatcher",
"name" : "o.io.serial.display.maxpat",
"numinlets" : 1,
"numoutlets" : 1,
"offset" : [ 3.0, 0.0 ],
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 350.5, 289.0, 340.5, 25.0 ],
"viewvisibility" : 1
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-23",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 289.5, 328.0, 80.0, 22.0 ],
"style" : "",
"text" : "o.io.slipserial"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-11",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 541.0, 364.0, 150.0, 54.0 ],
"style" : "",
"text" : "stats on serial OSC communications"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-19",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 43.5, 42.0, 156.0, 33.0 ],
"style" : "",
"text" : "PWM control of brightness of LED"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-15",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 114.0, 151.0, 32.5, 22.0 ],
"style" : "",
"text" : "on"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-13",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 56.0, 151.0, 32.5, 22.0 ],
"style" : "",
"text" : "off"
}
}
, {
"box" : {
"contdata" : 1,
"id" : "obj-9",
"maxclass" : "multislider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 220.5, 31.0, 20.0, 140.0 ],
"setminmax" : [ 0.0, 1.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-8",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 164.0, 151.0, 20.0, 20.0 ],
"style" : ""
}
}
],
"lines" : [ {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-18", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-1", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-23", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-1", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-1", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-12", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-12", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-13", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-12", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-15", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-3", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 360.0, 369.0, 360.0, 369.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-4", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 360.0, 355.0, 702.0, 355.0, 702.0, 265.0, 360.0, 265.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-5", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-23", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-23", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-4", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-12", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-8", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-12", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-9", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.slipserial.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "~/Documents/Max/Packages/odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.io.serial.display.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.pack.mxo",
"type" : "iLaX"
}
, {
"name" : "o.route.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.validate.mxo",
"type" : "iLaX"
}
, {
"name" : "o.print.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.encode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.decode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
, {
"name" : "o.downcast.mxo",
"type" : "iLaX"
}
],
"embedsnapshot" : 0
}
}

View File

@ -0,0 +1,297 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 125.0, 78.0, 1072.0, 480.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-12",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 27.5, 386.0, 158.0, 34.0 ],
"presentation_rect" : [ 534.5, 418.0, 0.0, 0.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"id" : "obj-6",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 137.5, 194.0, 82.0, 22.0 ],
"style" : "",
"text" : "o.pack /servo"
}
}
, {
"box" : {
"contdata" : 1,
"id" : "obj-11",
"maxclass" : "multislider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 139.0, 27.0, 20.0, 140.0 ],
"setminmax" : [ 0.0, 180.0 ],
"settype" : 0,
"style" : ""
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-3",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 198.5, 386.0, 158.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-1",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 218.5, 230.5, 170.0, 33.0 ],
"style" : "",
"text" : "Look for your device in the menu list of serial USB"
}
}
, {
"box" : {
"bgmode" : 0,
"border" : 0,
"clickthrough" : 0,
"enablehscroll" : 0,
"enablevscroll" : 0,
"id" : "obj-20",
"lockeddragscroll" : 0,
"maxclass" : "bpatcher",
"name" : "o.io.serial.display.maxpat",
"numinlets" : 1,
"numoutlets" : 1,
"offset" : [ 3.0, 0.0 ],
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 198.5, 301.0, 164.0, 24.0 ],
"viewvisibility" : 1
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-23",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 137.5, 337.0, 80.0, 22.0 ],
"style" : "",
"text" : "o.io.slipserial"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-5",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 389.0, 376.0, 150.0, 54.0 ],
"style" : "",
"text" : "stats on serial OSC communications"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-19",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 335.0, 151.0, 156.0, 20.0 ],
"style" : "",
"text" : "Servo control (from 0-180)"
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-11", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-23", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-20", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-12", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-23", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-20", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 208.0, 367.0, 377.0, 367.0, 377.0, 277.0, 208.0, 277.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-3", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 208.0, 381.0, 208.0, 381.0 ],
"source" : [ "obj-23", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-23", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-6", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.slipserial.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "~/Documents/Max/Packages/odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.io.serial.display.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.pack.mxo",
"type" : "iLaX"
}
, {
"name" : "o.route.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.validate.mxo",
"type" : "iLaX"
}
, {
"name" : "o.print.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.encode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.decode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
],
"embedsnapshot" : 0
}
}

View File

@ -0,0 +1,227 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 6,
"minor" : 1,
"revision" : 9,
"architecture" : "x86"
}
,
"rect" : [ 196.0, 152.0, 1072.0, 480.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 0,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 0,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"boxes" : [ {
"box" : {
"fontsize" : 12.0,
"id" : "obj-8",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 572.0, 228.0, 207.0, 34.0 ],
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontsize" : 12.0,
"id" : "obj-6",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 95.0, 228.0, 394.0, 34.0 ],
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontsize" : 12.0,
"id" : "obj-9",
"maxclass" : "o.expr.codebox",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 95.0, 172.0, 251.0, 37.0 ],
"text" : " /bundle/time = gettimetag()",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"id" : "obj-7",
"maxclass" : "bpatcher",
"name" : "o.io.serial.display.maxpat",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 271.0, 58.0, 331.0, 28.0 ]
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"frgb" : 0.0,
"id" : "obj-4",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 592.0, 119.0, 150.0, 54.0 ],
"text" : "stats on serial OSC communications"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-26",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 95.0, 119.0, 195.0, 22.0 ],
"text" : "o.io.slipserial f 9600"
}
}
],
"lines" : [ {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-7", 0 ],
"disabled" : 0,
"hidden" : 0,
"midpoints" : [ 280.5, 141.0, 300.0, 141.0, 300.0, 96.0, 258.0, 96.0, 258.0, 54.0, 280.5, 54.0 ],
"source" : [ "obj-26", 1 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-8", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 1 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-9", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-26", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-7", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-9", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.slipserial.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"patcherrelativepath" : "../../../../../../Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/CNMAT-odot/patchers/ordering",
"patcherrelativepath" : "../../../../../../Documents/Max/Packages/CNMAT-odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.io.serial.display.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/o.io/experimental/Protocols/serial",
"patcherrelativepath" : "../../../../../../Documents/Max/Packages/o.io/experimental/Protocols/serial",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.pack.mxo",
"type" : "iLaX"
}
, {
"name" : "o.route.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.validate.mxo",
"type" : "iLaX"
}
, {
"name" : "o.print.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.encode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.slip.decode.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.expr.codebox.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
]
}
}

View File

@ -0,0 +1,947 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 140.0, 78.0, 982.0, 632.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 14.0,
"default_fontface" : 0,
"default_fontname" : "Andale Mono",
"gridonopen" : 1,
"gridsize" : [ 5.0, 5.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-10",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 246.5, 265.0, 128.0, 24.0 ],
"style" : "",
"text" : "o.betweentimes"
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 14.0,
"id" : "obj-9",
"maxclass" : "o.compose",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 699.5, 158.0, 157.0, 26.0 ],
"saved_bundle_data" : [ 35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 47, 97, 110, 97, 108, 111, 103, 47, 123, 50, 44, 51, 125, 47, 117, 0, 44, 0, 0, 0 ],
"saved_bundle_length" : 40,
"text" : "/analog/{2,3}/u",
"textcolor" : [ 0.188, 0.188, 0.188, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 14.0,
"id" : "obj-8",
"maxclass" : "o.compose",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 448.5, 159.0, 150.0, 26.0 ],
"saved_bundle_data" : [ 35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 47, 97, 110, 97, 108, 111, 103, 47, 91, 48, 45, 51, 93, 47, 117, 0, 44, 0, 0, 0 ],
"saved_bundle_length" : 40,
"text" : "/analog/[0-3]/u",
"textcolor" : [ 0.188, 0.188, 0.188, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 14.0,
"id" : "obj-6",
"maxclass" : "o.compose",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 246.5, 159.0, 150.0, 26.0 ],
"saved_bundle_data" : [ 35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 47, 97, 110, 97, 108, 111, 103, 47, 42, 0, 0, 0, 44, 0, 0, 0 ],
"saved_bundle_length" : 36,
"text" : "/analog/*",
"textcolor" : [ 0.188, 0.188, 0.188, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 14.0,
"id" : "obj-4",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 246.5, 308.0, 265.0, 36.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-3",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 246.5, 55.0, 95.0, 24.0 ],
"style" : "",
"text" : "loadmess 1"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-1",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 726.5, 77.0, 222.0, 38.0 ],
"style" : "",
"text" : "read analog pins 2 and 3 with pullup turned on"
}
}
, {
"box" : {
"id" : "obj-78",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 699.5, 95.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-79",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 699.5, 126.0, 86.0, 24.0 ],
"style" : "",
"text" : "qmetro 20"
}
}
, {
"box" : {
"id" : "obj-56",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 179.333328, 500.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-64",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 179.333328, 396.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[37]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[25]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-13",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 11.0, 542.0, 137.0, 22.0 ],
"style" : "",
"text" : "analog readings"
}
}
, {
"box" : {
"id" : "obj-110",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 145.666672, 500.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-109",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 112.0, 500.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-108",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 78.333336, 500.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-107",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 44.666668, 500.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-105",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 145.666672, 396.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[19]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[4]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-104",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 112.0, 396.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[20]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[3]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-103",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 78.333336, 396.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[21]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[2]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-102",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 44.666668, 396.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[22]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a[1]"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"id" : "obj-101",
"maxclass" : "live.slider",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "float" ],
"parameter_enable" : 1,
"patching_rect" : [ 11.0, 396.0, 34.0, 95.0 ],
"saved_attribute_attributes" : {
"valueof" : {
"parameter_longname" : "a[23]",
"parameter_shortname" : "a",
"parameter_type" : 0,
"parameter_mmax" : 1023.0,
"parameter_unitstyle" : 0
}
}
,
"varname" : "a"
}
}
, {
"box" : {
"id" : "obj-84",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 11.0, 500.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-81",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 7,
"outlettype" : [ "", "", "", "", "", "", "FullPacket" ],
"patching_rect" : [ 11.0, 323.0, 221.0, 24.0 ],
"style" : "",
"text" : "o.route /0 /1 /2 /3 /4 /5"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-45",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "FullPacket" ],
"patching_rect" : [ 11.0, 265.0, 137.0, 24.0 ],
"style" : "",
"text" : "o.route /analog"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-15",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 475.5, 86.0, 187.0, 38.0 ],
"style" : "",
"text" : "read analog pins 0-3 with pullup turned on"
}
}
, {
"box" : {
"id" : "obj-18",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 448.5, 95.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-22",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 448.5, 125.0, 86.0, 24.0 ],
"style" : "",
"text" : "qmetro 20"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-46",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 261.5, 95.0, 187.0, 22.0 ],
"style" : "",
"text" : "read all analog pins"
}
}
, {
"box" : {
"id" : "obj-60",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 246.5, 95.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-61",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 246.5, 124.0, 95.0, 24.0 ],
"style" : "",
"text" : "qmetro 100"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-26",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 246.5, 214.0, 288.0, 24.0 ],
"style" : "",
"text" : "o.io.udp 128.32.122.252 8888 9999"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-91",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 0,
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 34.0, 78.0, 738.0, 421.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 14.0,
"default_fontface" : 0,
"default_fontname" : "Andale Mono",
"gridonopen" : 1,
"gridsize" : [ 5.0, 5.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-2",
"linecount" : 25,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 15.0, 20.0, 768.0, 400.0 ],
"style" : "",
"text" : "/*\n Written by Yotam Mann and Adrian Freed,\n The Center for New Music and Audio Technologies,\n University of California, Berkeley. Copyright (c) 2012, The Regents of\n the University of California (Regents).\n \n Permission to use, copy, modify, distribute, and distribute modified versions\n of this software and its documentation without fee and without a signed\n licensing agreement, is hereby granted, provided that the above copyright\n notice, this paragraph and the following two paragraphs appear in all copies,\n modifications, and distributions.\n \n IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,\n SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING\n OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS\n BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n \n REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED\n HEREUNDER IS PROVIDED \"AS IS\". REGENTS HAS NO OBLIGATION TO PROVIDE\n MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\n \n For bug reports and feature requests please email me at yotam@cnmat.berkeley.edu\n */"
}
}
],
"lines" : [ ]
}
,
"patching_rect" : [ 666.5, 494.0, 111.0, 24.0 ],
"saved_object_attributes" : {
"description" : "",
"digest" : "",
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"globalpatchername" : "",
"style" : "",
"tags" : ""
}
,
"style" : "",
"text" : "p disclaimer"
}
}
],
"lines" : [ {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-4", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-10", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-84", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-101", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-107", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-102", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-108", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-103", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-109", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-104", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-110", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-105", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-22", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-18", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-8", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-22", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-10", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-45", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-60", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-3", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-81", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-45", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-6", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-61", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-60", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-61", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-56", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-64", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-79", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-78", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-9", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-79", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-8", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-101", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-102", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-103", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 2 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-104", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 3 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-105", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 4 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-64", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-81", 5 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-9", 0 ]
}
}
],
"parameters" : {
"obj-105" : [ "a[19]", "a", 0 ],
"obj-104" : [ "a[20]", "a", 0 ],
"obj-103" : [ "a[21]", "a", 0 ],
"obj-64" : [ "a[37]", "a", 0 ],
"obj-102" : [ "a[22]", "a", 0 ],
"obj-101" : [ "a[23]", "a", 0 ]
}
,
"dependency_cache" : [ {
"name" : "o.io.udp.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/udp",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.betweentimes.maxpat",
"bootpath" : "~/Documents/Max/Packages/odot/patchers/time",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.was.maxpat",
"bootpath" : "~/Documents/Max/Packages/odot/dev",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "~/Documents/Max/Packages/odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.route.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
, {
"name" : "o.compose.mxo",
"type" : "iLaX"
}
, {
"name" : "o.timetag.mxo",
"type" : "iLaX"
}
, {
"name" : "o.prepend.mxo",
"type" : "iLaX"
}
, {
"name" : "o.intersection.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.var.mxo",
"type" : "iLaX"
}
, {
"name" : "o.collect.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.expr.codebox.mxo",
"type" : "iLaX"
}
],
"embedsnapshot" : 0
}
}

View File

@ -0,0 +1,215 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 6,
"minor" : 1,
"revision" : 9,
"architecture" : "x86"
}
,
"rect" : [ 153.0, 100.0, 758.0, 531.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 14.0,
"default_fontface" : 0,
"default_fontname" : "Andale Mono",
"gridonopen" : 0,
"gridsize" : [ 5.0, 5.0 ],
"gridsnaponopen" : 0,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"boxes" : [ {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-8",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "FullPacket" ],
"patching_rect" : [ 20.5, 240.0, 128.0, 22.0 ],
"text" : "o.betweentimes"
}
}
, {
"box" : {
"fontsize" : 14.0,
"id" : "obj-7",
"linecount" : 2,
"maxclass" : "o.compose",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 20.5, 112.0, 510.0, 42.0 ],
"saved_bundle_data" : [ 35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 47, 112, 105, 110, 103, 0, 0, 0, 44, 105, 0, 0, 0, 0, 0, 100, 0, 0, 0, 76, 47, 116, 104, 105, 110, 103, 0, 0, 44, 100, 105, 105, 105, 105, 105, 105, 105, 105, 115, 0, 64, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 98, 105, 103, 103, 101, 114, 32, 112, 97, 99, 107, 101, 116, 0, 0, 0 ],
"saved_bundle_length" : 116,
"text" : "/ping : 100,\n/thing : [100., 100, 1, 2, 3, 4, 4, 4, 4, \"bigger packet\"]",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontsize" : 14.0,
"id" : "obj-5",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 20.5, 296.0, 517.0, 36.0 ],
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-61",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 20.5, 22.0, 153.0, 22.0 ],
"text" : "metro 2 @active 1"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-26",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 20.5, 191.0, 288.0, 22.0 ],
"text" : "o.io.udp 128.32.122.252 8888 9999"
}
}
],
"lines" : [ {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-8", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-7", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-61", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-7", 0 ]
}
}
, {
"patchline" : {
"color" : [ 1.0, 0.8, 0.4, 1.0 ],
"destination" : [ "obj-5", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-8", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.udp.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/o.io/experimental/Protocols/udp",
"patcherrelativepath" : "../../../../../../Documents/Max/Packages/o.io/experimental/Protocols/udp",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.betweentimes.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/CNMAT-odot/patchers/time",
"patcherrelativepath" : "../../../../../../Documents/Max/Packages/CNMAT-odot/patchers/time",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.was.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/CNMAT-odot/dev",
"patcherrelativepath" : "../../../../../../Documents/Max/Packages/CNMAT-odot/dev",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.righttoleft.maxpat",
"bootpath" : "/Users/adrian2013/Documents/Max/Packages/CNMAT-odot/patchers/ordering",
"patcherrelativepath" : "../../../../../../Documents/Max/Packages/CNMAT-odot/patchers/ordering",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
, {
"name" : "o.compose.mxo",
"type" : "iLaX"
}
, {
"name" : "o.timetag.mxo",
"type" : "iLaX"
}
, {
"name" : "o.prepend.mxo",
"type" : "iLaX"
}
, {
"name" : "o.intersection.mxo",
"type" : "iLaX"
}
, {
"name" : "o.union.mxo",
"type" : "iLaX"
}
, {
"name" : "o.var.mxo",
"type" : "iLaX"
}
, {
"name" : "o.collect.mxo",
"type" : "iLaX"
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.expr.codebox.mxo",
"type" : "iLaX"
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,319 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 334.0, 78.0, 1072.0, 480.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontface" : 0,
"fontsize" : 12.0,
"id" : "obj-5",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 183.5, 341.0, 150.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-18",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 498.0, 91.0, 150.0, 33.0 ],
"style" : "",
"text" : "control Arduino square wave tone on pin 3"
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-15",
"maxclass" : "o.message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 406.0, 168.0, 150.0, 22.0 ],
"text" : "/tone/3",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-12",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 134.0, 127.0, 34.0, 22.0 ],
"style" : "",
"text" : "mtof"
}
}
, {
"box" : {
"id" : "obj-11",
"maxclass" : "kslider",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "int", "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 132.0, 65.0, 336.0, 53.0 ],
"presentation_rect" : [ 0.0, 0.0, 336.0, 53.0 ],
"style" : "",
"varname" : "kslider"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-9",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 242.0, 140.0, 32.5, 22.0 ],
"style" : "",
"text" : "220"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-8",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 184.0, 137.0, 34.0, 22.0 ],
"style" : "",
"text" : "440."
}
}
, {
"box" : {
"id" : "obj-4",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 402.0, 137.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-3",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 489.0, 279.0, 154.0, 47.0 ],
"style" : "",
"text" : "8888 is the port sent to on the Arduino node 128.32.122.252"
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-20",
"maxclass" : "o.message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 235.0, 234.0, 150.0, 22.0 ],
"text" : "/tone/3 130.813 \n",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-6",
"maxclass" : "o.message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 185.0, 191.0, 150.0, 22.0 ],
"text" : "/tone/3 \"$1\" ",
"textcolor" : [ 0.0, 0.0, 0.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-26",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 183.5, 290.0, 288.0, 24.0 ],
"style" : "",
"text" : "o.io.udp 128.32.122.252 8888 9999"
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-12", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-11", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-12", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-15", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-5", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-15", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-4", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-20", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-6", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-26", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-6", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-8", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-9", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.udp.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/udp",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.message.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
],
"embedsnapshot" : 0
}
}

View File

@ -0,0 +1,159 @@
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 0,
"revision" : 4,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 443.0, 218.0, 1072.0, 480.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontface" : 0,
"fontsize" : 12.0,
"id" : "obj-8",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 277.0, 243.0, 150.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 0,
"fontsize" : 12.0,
"id" : "obj-6",
"maxclass" : "o.display",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 91.0, 243.0, 150.0, 34.0 ],
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-2",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "FullPacket", "FullPacket" ],
"patching_rect" : [ 91.0, 149.0, 97.0, 22.0 ],
"style" : "",
"text" : "o.if exists(/units)"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-4",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 95.0, 62.0, 150.0, 33.0 ],
"style" : "",
"text" : "Set udp port, send and receive port respectively"
}
}
, {
"box" : {
"fontname" : "Andale Mono",
"fontsize" : 14.0,
"id" : "obj-26",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 91.0, 107.0, 288.0, 24.0 ],
"style" : "",
"text" : "o.io.udp 128.32.122.26 8888 9999"
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-2", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-8", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-2", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-2", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-26", 0 ]
}
}
],
"dependency_cache" : [ {
"name" : "o.io.udp.maxpat",
"bootpath" : "~/Documents/Max/Packages/o.io/experimental/Protocols/udp",
"type" : "JSON",
"implicit" : 1
}
, {
"name" : "o.if.mxo",
"type" : "iLaX"
}
, {
"name" : "o.display.mxo",
"type" : "iLaX"
}
],
"embedsnapshot" : 0
}
}

Some files were not shown because too many files have changed in this diff Show More