Last time I gave a talk about the Internet of Things I wished I had a device to demonstrate to the audience what I was talking about.
I took a Particle Internet Button, which consists a ring of color LEDs, 4 buttons, an accelerometer and a buzzer, added a cellular Particle Electron and hooked it up to Twilio so you could text the name of a Crayola color name to see the ring change colors.
Hardware SurgeryThe first challenge was that the Internet Button is designed for the Particle Photon which is shorter than the Electron. I had to modify both the Electron and the Internet Button to put them together.
I desoldered the 12 back pins on the Electron (B0 to B5, C0 to C5). I also had to move the Internet Button LED 6 to position 12 to make room for the SIM card holder on the Electron.
At this point the Electron fit, but the LED didn't light up because they had no power. I had to put a diode in between the lithium battery pin on the Electron and the LED power trace (VIN). The diode is there to prevent short circuiting the USB power to the lithium battery if both are plugged at the same time.
The information flows like this:
SMS -> Twilio -> Webhook running on hook.io -> Particle Electron
The Webhook is a Javascript program that converts the Crayola color names likes Razzle Dazzle Rose and Atomic Tangerine to red, green, blue and publishes a light_demo/color
event to the Particle cloud.
The Electron subscribes to the light_demo/color
event and animates the ring of LEDs.
Start by creating an account at hook.io to be able to quickly write Javascript code that will run when a URL is accessed. My hook.io username is monkbroc and I created the webhook light_demo so my webhook URL is https://hook.io/monkbroc/light_demo
The Javascript code that will receive the SMS from Twilio, translate the color and publish the event to the Particle cloud is attached at the end.
Next create a free account at Twilio and add a phone number with SMS capabilities. Tell Twilio to forward incoming SMS to the webhook above (https://hook.io/monkbroc/light_demo).
Finally, program the Electron with the Internet Button library and the code to subscribe to the color change event. The code for the Electron is attached at the end.
The firmware waits for an event, then turns off the LEDs one by one, then turns them back on with the new color.
The Internet Button a great device to get your creativity going when you're in WiFi range and now with an Electron I can take it anywhere!
Incoming SMS webhook
JavaScriptYou'll connect the URL of this webhook to Twilio
module['exports'] = function (hook) {
// Access the Particle API to publish color change event
var Particle = require('particle-api-js');
// Make easy HTTP requests in Node.js
var request = require('request');
// Check that the SMS came from my Twilio account
function authenticMessage(params) {
return params.AccountSid === hook.env.TWILIO_ACCOUNTID;
}
var twilioResponse = '<?xml version="1.0" encoding="UTF-8"?><Response></Response>';
var particle = new Particle();
var params = hook.params;
console.log("Got request");
// Is the message from Twilio?
if(authenticMessage(params)) {
hook.res.setHeader('Content-Type', 'application/xml');
// The text of the SMS is params.Body
var color = params.Body;
console.log("Authentic message. Color " + color);
// Ask another webhook to translate the name to the rgb color
request("https://hook.io/monkbroc/crayola/"+color, function(error, status, colorCode) {
console.log("Got color code " + colorCode);
// Publish an event to the Particle cloud with the rgb color
particle.publishEvent({ name: "light_demo/color", data: colorCode.trim(), auth: hook.env.PARTICLE_API_TOKEN })
.then(function () {
console.log("Sent " + colorCode);
// Tell Twilio everything was OK
hook.res.end(twilioResponse);
}).catch(function (err) {
console.error("Error " + JSON.stringify(err));
hook.res.end(twilioResponse);
});
});
} else {
hook.res.end("Nothing to do");
}
};
#include "InternetButton.h"
#include "math.h"
//----------------- Button ----------------//
uint8_t pin = 3;
uint8_t b1 = 4;
uint8_t b2 = 5;
uint8_t b3 = 6;
uint8_t b4 = 7;
Adafruit_NeoPixel ring = Adafruit_NeoPixel(PIXEL_COUNT, pin, PIXEL_TYPE);
ADXL362 accelerometer;
InternetButton::InternetButton(){
}
void InternetButton::begin(){
ring.begin();
ring.show();
accelerometer.begin(); // Setup SPI protocol, issue device soft reset
accelerometer.beginMeasure(); // Switch ADXL362 to measure mode
accelerometer.checkAllControlRegs(); // Burst Read all Control Registers, to check for proper setup
pinMode(b1, INPUT_PULLUP);
pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP);
pinMode(b4, INPUT_PULLUP);
}
void InternetButton::begin(int i){
if(i == 1 || i == 0){
pin = 17;
b1 = 1;
b2 = 2;
b3 = 3;
b4 = 4;
}
ring.begin();
ring.setPin(pin);
ring.show();
accelerometer.begin(); // Setup SPI protocol, issue device soft reset
accelerometer.beginMeasure(); // Switch ADXL362 to measure mode
accelerometer.checkAllControlRegs(); // Burst Read all Control Registers, to check for proper setup
pinMode(b1, INPUT_PULLUP);
pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP);
pinMode(b4, INPUT_PULLUP);
}
void InternetButton::ledOn(uint8_t i, uint8_t r, uint8_t g, uint8_t b){
//i-1 shifts the location from human readable to the right index for the LEDs
if(i == 12){
ring.setPixelColor(0, ring.Color(r,g,b));
ring.setPixelColor(10, ring.Color(r,g,b));
}
else{
ring.setPixelColor(i-1, ring.Color(r,g,b));
}
ring.show();
}
void InternetButton::smoothLedOn(float i, uint8_t r, uint8_t g, uint8_t b){
//uint8_t intI = lrintf(i);
//Serial.print("intI: ");
//Serial.println(intI);
//float differ = i-(float)intI + 0.5;
//Serial.print("differ: ");
//Serial.println(differ);
float tempI;
float differ = modff(i, &tempI);
uint8_t intI = (uint8_t)tempI;
// checks to see if it's reeeeally close to being an integer
//if(abs(differ) < 0.01){
// intI-1 shifts the location from human readable to the right index for the LEDs
// ring.setPixelColor(intI-1, ring.Color(r,g,b));
// Serial.println("tripped int check");
//}
//else {
// diff > 0 means that it's closer to the lower one
float differ1 = 1.0-differ;
//differ1 = logf(differ1);
//differ = logf(differ);
if(differ > 0.5){
differ1 /= 2;
//ring.setPixelColor(intI-2, ring.Color((int)(differ1*r),(int)(differ1*g),(int)(differ1*b)));
ring.setPixelColor(intI-1, ring.Color((int)(differ1*r),(int)(differ1*g),(int)(differ1*b)));
ring.setPixelColor(intI, ring.Color((int)(differ*r),(int)(differ*g),(int)(differ*b)));
}
else {
differ /= 2;
//ring.setPixelColor(intI-2, ring.Color((int)(differ*r),(int)(differ*g),(int)(differ*b)));
ring.setPixelColor(intI-1, ring.Color((int)(differ1*r),(int)(differ1*g),(int)(differ1*b)));
ring.setPixelColor(intI, ring.Color((int)(differ*r),(int)(differ*g),(int)(differ*b)));
}
//}
ring.show();
}
void InternetButton::ledOff(uint8_t i){
ledOn(i,0,0,0);
}
void InternetButton::allLedsOff(){
for(int i = 0; i<PIXEL_COUNT; i++){
ring.setPixelColor(i, ring.Color(0, 0, 0));
}
ring.show();
}
void InternetButton::allLedsOn(uint8_t r, uint8_t g, uint8_t b){
for(int i = 0; i<PIXEL_COUNT; i++){
ring.setPixelColor(i, ring.Color(r, g, b));
}
ring.show();
}
uint8_t InternetButton::buttonOn(uint8_t i){
if(b1 == 4){
return !digitalRead(i+3);
}
else {
return !digitalRead(i);
}
}
uint8_t InternetButton::allButtonsOn(){
if(!digitalRead(b1) && !digitalRead(b2) && !digitalRead(b3) && !digitalRead(b4)) {
return 1;
}
else {
return 0;
}
}
uint8_t InternetButton::allButtonsOff(){
if(digitalRead(b1) && digitalRead(b2) && digitalRead(b3) && digitalRead(b4)) {
return 1;
}
else {
return 0;
}
}
void InternetButton::rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) { // 1 cycle of all colors on wheel
for(i=0; i< 12; i++) {
uint8_t WheelPos = ((i * 256 / ring.numPixels()) + j) & 255;
if(WheelPos < 85) {
ring.setPixelColor(i,ring.Color(WheelPos * 3, 255 - WheelPos * 3, 0));
} else if(WheelPos < 170) {
WheelPos -= 85;
ring.setPixelColor(i,ring.Color(255 - WheelPos * 3, 0, WheelPos * 3));
} else {
WheelPos -= 170;
ring.setPixelColor(i,ring.Color(0, WheelPos * 3, 255 - WheelPos * 3));
}
}
ring.show();
delay(wait);
}
}
int InternetButton::readX(){
return accelerometer.readX();
}
int InternetButton::readY(){
return accelerometer.readY();
}
int InternetButton::readZ(){
return accelerometer.readZ();
}
int InternetButton::readX16(){
return accelerometer.readX16();
}
int InternetButton::readY16(){
return accelerometer.readY16();
}
int InternetButton::readZ16(){
return accelerometer.readZ16();
}
//Thanks christophevg!
uint8_t InternetButton::lowestLed(){
float rads = atan2(accelerometer.readY16(),accelerometer.readX16());
uint8_t ledPos = (uint8_t)(12 - (rads/(M_PI/6) - 3)) % 12;
return ledPos;
}
void InternetButton::playSong(String song){
char inputStr[200];
song.toCharArray(inputStr,200);
Serial.println(inputStr);
char *note = strtok(inputStr,",");
char *duration = strtok(NULL,",");
playNote(note,atoi(duration));
while(duration != NULL){
note = strtok(NULL,",");
Serial.println(note);
duration = strtok(NULL,", \n");
Serial.println(duration);
//if(atoi(duration) <= 0){
// break;
//}
playNote(note,atoi(duration));
}
}
void InternetButton::playNote(String note, int duration){
int noteNum = 0;
int octave = 5;
int freq = 256;
//if(9 - int(command.charAt(1)) != null){
char octavo[5];
String tempString = note.substring(1,2);
tempString.toCharArray(octavo,5);
octave = atoi(octavo);
//}
if(duration != 0){
duration = 1000/duration;
}
switch(note.charAt(0)){
case 'C':
noteNum = 0;
break;
case 'D':
noteNum = 2;
break;
case 'E':
noteNum = 4;
break;
case 'F':
noteNum = 5;
break;
case 'G':
noteNum = 7;
break;
case 'A':
noteNum = 9;
break;
case 'B':
noteNum = 11;
break;
case 'R': // Rest note
octave = -1;
break;
default:
break;
//return -1;
}
// based on equation at http://www.phy.mtu.edu/~suits/NoteFreqCalcs.html and the Verdi tuning
// fn = f0*(2^1/12)^n where n = number of half-steps from the reference frequency f0
freq = float(256*pow(1.05946,( 12.0*(octave-4) +noteNum)));
// C4^ (2^1/12)^ 12 half-steps in an octave ^how many extra half-steps within that octave, 0 for a C
tone(D0,int(freq),duration);
delay(duration);
noTone(D0);
//return freq;
}
/*
Arduino Library for Analog Devices ADXL362 - Micropower 3-axis accelerometer
go to http://www.analog.com/ADXL362 for datasheet
License: CC BY-SA 3.0: Creative Commons Share-alike 3.0. Feel free
to use and abuse this code however you'd like. If you find it useful
please attribute, and SHARE-ALIKE!
Created June 2012
by Anne Mahaffey - hosted on http://annem.github.com/ADXL362
Modified Mars 2014
by pixelk
Modified for Spark Core/Button October 2014
by jenesaisdiq
*/
const int slaveSelectPin = A2;
ADXL362::ADXL362() {}
//
// begin()
// Initial SPI setup, soft reset of device
//
void ADXL362::begin() {
pinMode(slaveSelectPin, OUTPUT);
SPI.begin();
SPI.setDataMode(SPI_MODE0); //CPHA = CPOL = 0 MODE = 0
delay(500);
// soft reset
mgperLSB = 1;
SPIwriteOneRegister(XL362_SOFT_RESET, 0x52); // Write to SOFT RESET, "R"
delay(10);
#ifdef ADXL362_DEBUG
Serial.println("Soft Reset\n");
#endif
}
//
// beginMeasure()
// turn on Measurement mode - required after reset
//
void ADXL362::beginMeasure() {
uint8_t temp = SPIreadOneRegister(XL362_POWER_CTL); // read Reg 2D before modifying for measure mode
#ifdef ADXL362_DEBUG
Serial.print( "Setting Measeurement Mode - Reg XL362_POWER_CTL before = ");
Serial.print(temp);
#endif
// turn on measurement mode
temp = (temp & 0b11111100) | XL362_POWER_FLAG_MEASURE_RUNING; // turn on measurement bit in Reg XL362_POWER_CTL
SPIwriteOneRegister(XL362_POWER_CTL, temp); // Write to XL362_POWER_CTL, Measurement Mode
delay(10);
#ifdef ADXL362_DEBUG
temp = SPIreadOneRegister(XL362_POWER_CTL);
Serial.print( ", Reg XL362_POWER_CTL after = ");
Serial.println(temp);
#endif
}
//reading off the 8-bit register as documented in the ADXL362 spec
//IMPORTANT to make it a signed 8-bit int so that the data is interpreted correctly
int ADXL362::readX(){
int8_t XDATA = SPIreadOneRegister(0x08);
//#ifdef ADXL362_DEBUG
// Serial.print( "XDATA = ");
// Serial.println(XDATA);
//#endif
return (int)XDATA;
}
int ADXL362::readY(){
int8_t YDATA = SPIreadOneRegister(0x09);
//#ifdef ADXL362_DEBUG
// Serial.print( "\tYDATA = ");
// Serial.println(YDATA);
//#endif
return (int)YDATA;
}
int ADXL362::readZ(){
int8_t ZDATA = SPIreadOneRegister(0x0A);
//#ifdef ADXL362_DEBUG
// Serial.print( "\tZDATA = ");
// Serial.println(ZDATA);
//#endif
return (int)ZDATA;
}
//
// readXData(), readYData(), readZData(), readTemp()
// Read X, Y, Z, and Temp registers
//
int ADXL362::readX16(){
int16_t XDATA = SPIreadTwoRegisters(XL362_XDATA_L);
#ifdef ADXL362_DEBUG
Serial.print( "XDATA = ");
Serial.println(XDATA);
#endif
return XDATA;
}
int ADXL362::readY16(){
int16_t YDATA = SPIreadTwoRegisters(XL362_YDATA_L);
#ifdef ADXL362_DEBUG
Serial.print( "\tYDATA = ");
Serial.println(YDATA);
#endif
return YDATA;
}
int ADXL362::readZ16(){
int16_t ZDATA = SPIreadTwoRegisters(XL362_ZDATA_L);
#ifdef ADXL362_DEBUG
Serial.print( "\tZDATA = ");
Serial.println(ZDATA);
#endif
return ZDATA;
}
//Temperature only has a 16-bit version, so read two 8-bit regs
//worth knowing that this is an INTERNAL temperature measurement, so doesn't reflect the environment accurately
int16_t ADXL362::readTemp(){
int16_t TEMP = SPIreadTwoRegisters(XL362_TEMP_L);
//#ifdef ADXL362_DEBUG
// Serial.print("\tTEMP = ");
// Serial.println(TEMP);
//#endif
return TEMP;
}
void ADXL362::readXYZTData(short &XData, short &YData, short &ZData, float &Temperature){
// burst SPI read
// A burst read of all three axis is required to guarantee all measurements correspond to same sample time
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x0B); // read instruction
SPI.transfer(XL362_XDATA_L); // Start at XData Reg
XData = SPI.transfer(0x00);
XData = XData + ((short)SPI.transfer(0x00) << 8);
YData = SPI.transfer(0x00);
YData = YData + ((short)SPI.transfer(0x00) << 8);
ZData = SPI.transfer(0x00);
ZData = ZData + ((short)SPI.transfer(0x00) << 8);
short RawTemperature = SPI.transfer(0x00);
RawTemperature = RawTemperature + ((short)SPI.transfer(0x00) << 8);
Temperature = (float)RawTemperature * 0.065;
digitalWrite(slaveSelectPin, HIGH);
#ifdef ADXL362_DEBUG
Serial.print( "XDATA = "); Serial.print(XData);
Serial.print( "\tYDATA = "); Serial.print(YData);
Serial.print( "\tZDATA = "); Serial.print(ZData);
Serial.println( "\tTemperature = "); Serial.println(Temperature);
#endif
}
void ADXL362::readXYZmg(int &X, int &Y, int &Z){
// burst SPI read
// A burst read of all three axis is required to guarantee all measurements correspond to same sample time
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x0B); // read instruction
SPI.transfer(XL362_XDATA_L); // Start at XData Reg
short XData = SPI.transfer(0x00);
XData = XData + ((short)SPI.transfer(0x00) << 8);
short YData = SPI.transfer(0x00);
YData = YData + ((short)SPI.transfer(0x00) << 8);
short ZData = SPI.transfer(0x00);
ZData = ZData + ((short)SPI.transfer(0x00) << 8);
digitalWrite(slaveSelectPin, HIGH);
X = (int)XData * mgperLSB;
Y = (int)YData * mgperLSB;
Z = (int)ZData * mgperLSB;
#ifdef ADXL362_DEBUG
Serial.print( "x = "); Serial.print(X);
Serial.print( "\ty = "); Serial.print(Y);
Serial.println( "\tz = "); Serial.print(Z);
#endif
}
void ADXL362::XYZmgtoRPT(int X, int Y, int Z, float &Rho, float &Phi, float &Theta){
Rho = atan2(float(X), sqrt(pow(float(Y),2)+pow(float(Z),2)));
Rho *= 180/M_PI;
Phi = atan2(float(Y), sqrt(pow(float(X),2)+pow(float(Z),2)));
Phi *= 180/M_PI;
Theta = atan2(sqrt(pow(float(X),2)+pow(float(Y),2)),float(Z));
Theta *= 180/M_PI;
}
void ADXL362::checkAllControlRegs(){
//uint8_t filterCntlReg = SPIreadOneRegister(0x2C);
//uint8_t ODR = filterCntlReg & 0x07; Serial.print("ODR = "); Serial.println(ODR, HEX);
//uint8_t ACT_INACT_CTL_Reg = SPIreadOneRegister(0x27); Serial.print("ACT_INACT_CTL_Reg = "); Serial.println(ACT_INACT_CTL_Reg, HEX);
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x0B); // read instruction
SPI.transfer(0x20); // Start burst read at Reg 20
Serial.println("Start Burst Read of all Control Regs - Library version 6-24-2012:");
Serial.print("Reg XL362_THRESH_ACT_L = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_THRESH_ACT_H = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_TIME_ACT = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_THRESH_INACT_L = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_THRESH_INACT_H = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_TIME_INACT_L = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_TIME_INACT_H = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_ACT_INACT_CTL = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_FIFO_CONTROL = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_FIFO_SAMPLES = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_INTMAP1 = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_INTMAP2 = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_FILTER_CTL = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_POWER_CTL = B"); Serial.println(SPI.transfer(0x00), BIN);
Serial.print("Reg XL362_SELF_TEST = B"); Serial.println(SPI.transfer(0x00), BIN);
digitalWrite(slaveSelectPin, HIGH);
}
void ADXL362::setRange(uint8_t Range){
// Modify range (+-2g +-4g +-8g - ADXL362 Datasheep Page 33
// Choose RangeFlag between XL362_FILTER_FLAG_2G (default), XL362_FILTER_FLAG_4G, XL362_FILTER_FLAG_8G
uint8_t temp = SPIreadOneRegister(XL362_FILTER_CTL); // read Reg XL362_FILTER_CTL before modifying
#ifdef ADXL362_DEBUG
Serial.print( "Setting Measurement Range - Reg XL362_FILTER_CTL before = ");
Serial.print(temp);
#endif
switch ( Range ) { // Range affects converting LSB to mg
case XL362_FILTER_FLAG_2G:
mgperLSB = 1;
break;
case XL362_FILTER_FLAG_4G:
mgperLSB = 2;
break;
case XL362_FILTER_FLAG_8G:
mgperLSB = 4;
break;
default:
// YOU SHOULDN'T BE HERE !
mgperLSB = 1;
break;
}
temp = temp & 0b00111111 | Range;
SPIwriteOneRegister(XL362_FILTER_CTL, temp); // Write to XL362_FILTER_CTL
delay(10);
#ifdef ADXL362_DEBUG
temp = SPIreadOneRegister(XL362_FILTER_CTL);
Serial.print( ", Reg after = ");
Serial.println(temp);
#endif
}
void ADXL362::setBandwidth(uint8_t BandWidth){
// modify Bandwidth - ADXL362 Datasheep Page 33
// Choose Bandwidth between XL362_FILTER_FLAG_HBW (default), XL362_FILTER_FLAG_FBW
uint8_t temp = SPIreadOneRegister(XL362_FILTER_CTL); // read Reg XL362_FILTER_CTL before modifying
#ifdef ADXL362_DEBUG
Serial.print( "Setting BandWidth - Reg XL362_FILTER_CTL before = ");
Serial.print(temp);
#endif
temp = temp & 0b11101111 | BandWidth;
SPIwriteOneRegister(XL362_FILTER_CTL, temp); // Write to XL362_FILTER_CTL
delay(10);
#ifdef ADXL362_DEBUG
temp = SPIreadOneRegister(XL362_FILTER_CTL);
Serial.print( ", Reg after = ");
Serial.println(temp);
#endif
}
void ADXL362::setOutputDatarate(uint8_t ODR){
// modify Output Data Rate - ADXL362 Datasheep Page 33
// Choose ODR between XL362_FILTER_FLAG_ODR12, XL362_FILTER_FLAG_ODR25, XL362_FILTER_FLAG_ODR50, XL362_FILTER_FLAG_ODR100 (default), XL362_FILTER_FLAG_ODR200 , XL362_FILTER_FLAG_ODR400
uint8_t temp = SPIreadOneRegister(XL362_FILTER_CTL); // read Reg XL362_FILTER_CTL before modifying
#ifdef ADXL362_DEBUG
Serial.print( "Setting Output Data Rate - Reg XL362_FILTER_CTL before = ");
Serial.print(temp);
#endif
temp = temp & 0b11111000 | ODR;
SPIwriteOneRegister(XL362_FILTER_CTL, temp); // Write to XL362_FILTER_CTL
delay(10);
#ifdef ADXL362_DEBUG
temp = SPIreadOneRegister(XL362_FILTER_CTL);
Serial.print( ", Reg after = ");
Serial.println(temp);
#endif
}
void ADXL362::setNoiseLevel(uint8_t NoiseLevel){
// modify Noise Level - ADXL362 Datasheep Page 34
// Choose NoiseLevel between XL362_POWER_FLAG_NOISE_NORMAL (default), XL362_POWER_FLAG_NOISE_LOW, XL362_POWER_FLAG_NOISE_ULTRALOW
uint8_t temp = SPIreadOneRegister(XL362_POWER_CTL); // read Reg XL362_FILTER_CTL before modifying
#ifdef ADXL362_DEBUG
Serial.print( "Setting Output Data Rate - Reg XL362_POWER_CTL before = ");
Serial.print(temp);
#endif
temp = temp & 0b11001111 | NoiseLevel;
SPIwriteOneRegister(XL362_POWER_CTL, temp); // Write to XL362_FILTER_CTL
delay(10);
#ifdef ADXL362_DEBUG
temp = SPIreadOneRegister(XL362_POWER_CTL);
Serial.print( ", Reg after = ");
Serial.println(temp);
#endif
}
// Basic SPI routines to simplify code
// read and write one register
uint8_t ADXL362::SPIreadOneRegister(uint8_t regAddress){
uint8_t regValue = 0;
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x0B); // read instruction
SPI.transfer(regAddress);
regValue = SPI.transfer(0x00);
digitalWrite(slaveSelectPin, HIGH);
return regValue;
}
void ADXL362::SPIwriteOneRegister(uint8_t regAddress, uint8_t regValue){
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x0A); // write instruction
SPI.transfer(regAddress);
SPI.transfer(regValue);
digitalWrite(slaveSelectPin, HIGH);
}
int ADXL362::SPIreadTwoRegisters(uint8_t regAddress){
int twoRegValue = 0;
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x0B); // read instruction
SPI.transfer(regAddress);
twoRegValue = SPI.transfer(0x00);
twoRegValue = twoRegValue + (SPI.transfer(0x00) << 8);
digitalWrite(slaveSelectPin, HIGH);
return twoRegValue;
}
void ADXL362::SPIwriteTwoRegisters(uint8_t regAddress, int twoRegValue){
uint8_t twoRegValueH = twoRegValue >> 8;
uint8_t twoRegValueL = twoRegValue;
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x0A); // write instruction
SPI.transfer(regAddress);
SPI.transfer(twoRegValueL);
SPI.transfer(twoRegValueH);
digitalWrite(slaveSelectPin, HIGH);
}
//----------------- LED Handling ------------------------//
/*-------------------------------------------------------------------------
Spark Core library to control WS2811/WS2812 based RGB
LED devices such as Adafruit NeoPixel strips.
Currently handles 800 KHz and 400kHz bitstream on Spark Core,
WS2812, WS2812B and WS2811.
Also supports Radio Shack Tri-Color Strip with TM1803 controller
400kHz bitstream.
Written by Phil Burgess / Paint Your Dragon for Adafruit Industries.
Modified to work with Spark Core by Technobly.
Modified to work with Spark Button by jenesaisdiq.
Contributions by PJRC and other members of the open source community.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing products
from Adafruit!
--------------------------------------------------------------------*/
/* ======================= Adafruit_NeoPixel.cpp ======================= */
/*-------------------------------------------------------------------------
This file is part of the Adafruit NeoPixel library.
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.
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/>.
-------------------------------------------------------------------------*/
#if PLATFORM_ID == 0 // Core
#define pinLO(_pin) (PIN_MAP[_pin].gpio_peripheral->BRR = PIN_MAP[_pin].gpio_pin)
#define pinHI(_pin) (PIN_MAP[_pin].gpio_peripheral->BSRR = PIN_MAP[_pin].gpio_pin)
#else
//#include "pinmap_impl.h"
STM32_Pin_Info* PIN_MAP2 = HAL_Pin_Map(); // Pointer required for highest access speed
#define pinLO(_pin) (PIN_MAP2[_pin].gpio_peripheral->BSRRH = PIN_MAP2[_pin].gpio_pin)
#define pinHI(_pin) (PIN_MAP2[_pin].gpio_peripheral->BSRRL = PIN_MAP2[_pin].gpio_pin)
#endif
// fast pin access
#define pinSet(_pin, _hilo) (_hilo ? pinHI(_pin) : pinLO(_pin))
Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, uint8_t p, uint8_t t) :
numLEDs(n), numBytes(n*3), brightness(0), pixels(NULL), type(t), endTime(0)
{
if((pixels = (uint8_t *)malloc(numBytes))) {
memset(pixels, 0, numBytes);
}
}
Adafruit_NeoPixel::~Adafruit_NeoPixel() {
if(pixels) free(pixels);
pinMode(pin, INPUT);
}
void Adafruit_NeoPixel::begin(void) {
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
void Adafruit_NeoPixel::show(void) {
if(!pixels) return;
// Data latch = 24 or 50 microsecond pause in the output stream. Rather than
// put a delay at the end of the function, the ending time is noted and
// the function will simply hold off (if needed) on issuing the
// subsequent round of data until the latch time has elapsed. This
// allows the mainline code to start generating the next frame of data
// rather than stalling for the latch.
uint32_t wait_time; // wait time in microseconds.
switch(type) {
case TM1803: // TM1803 = 24us reset pulse
wait_time = 24L;
break;
case TM1829: // TM1829 = 500us reset pulse
wait_time = 500L;
break;
case WS2812B: // WS2812 & WS2812B = 50us reset pulse
case WS2812B2:
case WS2811: // WS2811 = 50us reset pulse
default: // default = 50us reset pulse
wait_time = 50L;
break;
}
while((micros() - endTime) < wait_time);
// endTime is a private member (rather than global var) so that multiple
// instances on different pins can be quickly issued in succession (each
// instance doesn't delay the next).
__disable_irq(); // Need 100% focus on instruction timing
volatile uint32_t
c, // 24-bit pixel color
mask; // 8-bit mask
volatile uint16_t i = numBytes; // Output loop counter
volatile uint8_t
j, // 8-bit inner loop counter
*ptr = pixels, // Pointer to next byte
g, // Current green byte value
r, // Current red byte value
b; // Current blue byte value
if(type == WS2812B) { // same as WS2812, 800 KHz bitstream
while(i) { // While bytes left... (3 bytes = 1 pixel)
mask = 0x800000; // reset the mask
i = i-3; // decrement bytes remaining
g = *ptr++; // Next green byte value
r = *ptr++; // Next red byte value
b = *ptr++; // Next blue byte value
c = ((uint32_t)g << 16) | ((uint32_t)r << 8) | b; // Pack the next 3 bytes to keep timing tight
j = 0; // reset the 24-bit counter
do {
pinSet(pin, HIGH); // HIGH
if (c & mask) { // if masked bit is high
// WS2812 spec 700ns HIGH
// Adafruit on Arduino (meas. 812ns)
// This lib on Spark Core (meas. 790ns)
// This lib on Photon (meas. 792ns)
asm volatile(
"mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t"
#if PLATFORM_ID != 0
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
#endif
::: "r0", "cc", "memory");
// WS2812 spec 600ns LOW
// Adafruit on Arduino (meas. 436ns)
// This lib on Spark Core (meas. 445ns)
// This lib on Photon (meas. 434ns)
pinSet(pin, LOW); // LOW
asm volatile(
"mov r0, r0" "\n\t"
#if PLATFORM_ID != 0
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t"
#endif
::: "r0", "cc", "memory");
}
else { // else masked bit is low
// WS2812 spec 350ns HIGH
// Adafruit on Arduino (meas. 312ns)
// This lib on Spark Core (meas. 318ns)
// This lib on Photon (meas. 308ns)
asm volatile(
"mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
#if PLATFORM_ID != 0
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
#endif
::: "r0", "cc", "memory");
// WS2812 spec 800ns LOW
// Adafruit on Arduino (meas. 938ns)
// This lib on Spark Core (meas. 946ns)
// This lib on Photon (meas. 934ns)
pinSet(pin, LOW); // LOW
asm volatile(
"mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
#if PLATFORM_ID != 0
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t"
#endif
::: "r0", "cc", "memory");
}
mask >>= 1;
} while ( ++j < 24 ); // ... pixel done
} // end while(i) ... no more pixels
}
else if(type == WS2812B2) { // WS2812B with DWT timer
#if PLATFORM_ID == 6 // Photon
#define CYCLES_800_T0H 25 // 312ns (meas. 300ns)
#define CYCLES_800_T0L 70 // 938ns (meas. 940ns)
#define CYCLES_800_T1H 80 // 812ns (meas. 792ns)
#define CYCLES_800_T1L 8 // 436ns (meas. 425ns)
volatile uint32_t cyc;
while(i) { // While bytes left... (3 bytes = 1 pixel)
mask = 0x800000; // reset the mask
i = i-3; // decrement bytes remaining
g = *ptr++; // Next green byte value
r = *ptr++; // Next red byte value
b = *ptr++; // Next blue byte value
c = ((uint32_t)g << 16) | ((uint32_t)r << 8) | b; // Pack the next 3 bytes to keep timing tight
j = 0; // reset the 24-bit counter
do {
cyc = DWT->CYCCNT;
pinSet(pin, HIGH); // HIGH
if (c & mask) { // if masked bit is high
while(DWT->CYCCNT - cyc < CYCLES_800_T1H);
pinSet(pin, LOW);
cyc = DWT->CYCCNT;
while(DWT->CYCCNT - cyc < CYCLES_800_T1L);
}
else { // else masked bit is low
while(DWT->CYCCNT - cyc < CYCLES_800_T0H);
pinSet(pin, LOW);
cyc = DWT->CYCCNT;
while(DWT->CYCCNT - cyc < CYCLES_800_T0L);
}
mask >>= 1;
} while ( ++j < 24 ); // ... pixel done
} // end while(i) ... no more pixels
#endif
}
else if(type == WS2811) { // WS2811, 400 KHz bitstream
while(i) { // While bytes left... (3 bytes = 1 pixel)
mask = 0x800000; // reset the mask
i = i-3; // decrement bytes remaining
r = *ptr++; // Next red byte value
g = *ptr++; // Next green byte value
b = *ptr++; // Next blue byte value
c = ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; // Pack the next 3 bytes to keep timing tight
j = 0; // reset the 24-bit counter
do {
pinSet(pin, HIGH); // HIGH
if (c & mask) { // if masked bit is high
// WS2811 spec 1.20us HIGH
// Adafruit on Arduino (meas. 1.25us)
// This lib on Spark Core (meas. 1.25us)
asm volatile(
"mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
::: "r0", "cc", "memory");
// WS2811 spec 1.30us LOW
// Adafruit on Arduino (meas. 1.25us)
// This lib on Spark Core (meas. 1.24us)
pinSet(pin, LOW); // LOW
asm volatile(
"mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t"
::: "r0", "cc", "memory");
}
else { // else masked bit is low
// WS2811 spec 500ns HIGH
// Adafruit on Arduino (meas. 500ns)
// This lib on Spark Core (meas. 500ns)
asm volatile(
"mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t"
::: "r0", "cc", "memory");
// WS2811 spec 2.000us LOW
// Adafruit on Arduino (meas. 2.000us)
// This lib on Spark Core (meas. 2.000us)
pinSet(pin, LOW); // LOW
asm volatile(
"mov r0, r0" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
"nop" "\n\t" "nop" "\n\t" "nop" "\n\t"
::: "r0", "cc", "memory");
}
mask >>= 1;
} while ( ++j < 24 ); // ... pixel done
} // end while(i) ... no more pixels
}
...
This file has been truncated, please download it to see its full contents.
Crayola color conversion
JavaScriptYou'll be able to call it as https://hook.io/monkbroc/crayola/emerald where emerald is any color below
module['exports'] = function (hook) {
var c;
var name = (hook.params.name || '').toLowerCase();
// exact match
for(c in colors) {
if(c.toLowerCase() === name) {
hook.res.end(colors[c]);
return;
}
}
// contains name
for(c in colors) {
if(c.toLowerCase().indexOf(name) != -1) {
hook.res.end(colors[c]);
return;
}
}
// default value
hook.res.end("#ffffff");
};
var colors = {
"white": "#ffffff",
"Red": "#ED0A3F",
"Maroon": "#C32148",
"Scarlet": "#FD0E35",
"Brick Red": "#C62D42",
"English Vermilion": "#CC474B",
"Madder Lake": "#CC3336",
"Permanent Geranium Lake": "#E12C2C",
"Maximum Red": "#D92121",
"Indian Red": "#B94E48",
"Orange-Red": "#FF5349",
"Sunset Orange": "#FE4C40",
"Bittersweet": "#FE6F5E",
"Dark Venetian Red": "#B33B24",
"Venetian Red": "#CC553D",
"Light Venetian Red": "#E6735C",
"Vivid Tangerine": "#FF9980",
"Middle Red": "#E58E73",
"Burnt Orange": "#FF7F49",
"Red-Orange": "#FF681F",
"Orange": "#FF8833",
"Macaroni and Cheese": "#FFB97B",
"Middle Yellow Red": "#ECAC76",
"Mango Tango": "#E77200",
"Yellow-Orange": "#FFAE42",
"Maximum Yellow Red": "#F2BA49",
"Banana Mania": "#FBE7B2",
"Maize": "#F2C649",
"Orange-Yellow": "#F8D568",
"Goldenrod": "#FCD667",
"Dandelion": "#FED85D",
"Yellow": "#FBE870",
"Green-Yellow": "#F1E788",
"Middle Yellow": "#FFEB00",
"Olive Green": "#B5B35C",
"Spring Green": "#ECEBBD",
"Maximum Yellow": "#FAFA37",
"Canary": "#FFFF99",
"Lemon Yellow": "#FFFF9F",
"Maximum Green Yellow": "#D9E650",
"Middle Green Yellow": "#ACBF60",
"Inchworm": "#AFE313",
"Light Chrome Green": "#BEE64B",
"Yellow-Green": "#C5E17A",
"Maximum Green": "#5E8C31",
"Asparagus": "#7BA05B",
"Granny Smith Apple": "#9DE093",
"Fern": "#63B76C",
"Middle Green": "#4D8C57",
"Green": "#3AA655",
"Medium Chrome Green": "#6CA67C",
"Forest Green": "#5FA777",
"Sea Green": "#93DFB8",
"Shamrock": "#33CC99",
"Mountain Meadow": "#1AB385",
"Jungle Green": "#29AB87",
"Caribbean Green": "#00CC99",
"Tropical Rain Forest": "#00755E",
"Middle Blue Green": "#8DD9CC",
"Pine Green": "#01786F",
"Maximum Blue Green": "#30BFBF",
"Robin's Egg Blue": "#00CCCC",
"Teal Blue": "#008080",
"Light Blue": "#8FD8D8",
"Aquamarine": "#95E0E8",
"Turquoise Blue": "#6CDAE7",
"Outer Space": "#2D383A",
"Sky Blue": "#76D7EA",
"Middle Blue": "#7ED4E6",
"Blue-Green": "#0095B7",
"Pacific Blue": "#009DC4",
"Cerulean": "#02A4D3",
"Maximum Blue": "#47ABCC",
"Blue (I)": "#2EB4E6",
"Cerulean Blue": "#339ACC",
"Cornflower": "#93CCEA",
"Green-Blue": "#2887C8",
"Midnight Blue": "#00468C",
"Navy Blue": "#0066CC",
"Denim": "#1560BD",
"Blue (III)": "#0066FF",
"Cadet Blue": "#A9B2C3",
"Periwinkle": "#C3CDE6",
"Blue (II)": "#4570E6",
"Wild Blue Yonder": "#7A89B8",
"Indigo": "#4F69C6",
"Manatee": "#8D90A1",
"Cobalt Blue": "#8C90C8",
"Celestial Blue": "#7070CC",
"Blue Bell": "#9999CC",
"Maximum Blue Purple": "#ACACE6",
"Violet-Blue": "#766EC8",
"Blue-Violet": "#6456B7",
"Ultramarine Blue": "#3F26BF",
"Middle Blue Purple": "#8B72BE",
"Purple Heart": "#652DC1",
"Royal Purple": "#6B3FA0",
"Violet (II)": "#8359A3",
"Medium Violet": "#8F47B3",
"Wisteria": "#C9A0DC",
"Lavender (I)": "#BF8FCC",
"Vivid Violet": "#803790",
"Maximum Purple": "#733380",
"Purple Mountains' Majesty": "#D6AEDD",
"Fuchsia": "#C154C1",
"Pink Flamingo": "#FC74FD",
"Violet (I)": "#732E6C",
"Brilliant Rose": "#E667CE",
"Orchid": "#E29CD2",
"Plum": "#8E3179",
"Medium Rose": "#D96CBE",
"Thistle": "#EBB0D7",
"Mulberry": "#C8509B",
"Red-Violet": "#BB3385",
"Middle Purple": "#D982B5",
"Maximum Red Purple": "#A63A79",
"Jazzberry Jam": "#A50B5E",
"Eggplant": "#614051",
"Magenta": "#F653A6",
"Cerise": "#DA3287",
"Wild Strawberry": "#FF3399",
"Lavender (II)": "#FBAED2",
"Cotton Candy": "#FFB7D5",
"Carnation Pink": "#FFA6C9",
"Violet-Red": "#F7468A",
"Razzmatazz": "#E30B5C",
"Pig Pink": "#FDD7E4",
"Carmine": "#E62E6B",
"Blush": "#DB5079",
"Tickle Me Pink": "#FC80A5",
"Mauvelous": "#F091A9",
"Salmon": "#FF91A4",
"Middle Red Purple": "#A55353",
"Mahogany": "#CA3435",
"Melon": "#FEBAAD",
"Pink Sherbert": "#F7A38E",
"Burnt Sienna": "#E97451",
"Brown": "#AF593E",
"Sepia": "#9E5B40",
"Fuzzy Wuzzy": "#87421F",
"Beaver": "#926F5B",
"Tumbleweed": "#DEA681",
"Raw Sienna": "#D27D46",
"Van Dyke Brown": "#664228",
"Tan": "#D99A6C",
"Desert Sand": "#EDC9AF",
"Peach": "#FFCBA4",
"Burnt Umber": "#805533",
"Apricot": "#FDD5B1",
"Almond": "#EED9C4",
"Raw Umber": "#665233",
"Shadow": "#837050",
"Raw Sienna (I)": "#E6BC5C",
"Timberwolf": "#D9D6CF",
"Gold (I)": "#92926E",
"Gold (II)": "#E6BE8A",
"Silver": "#C9C0BB",
"Copper": "#DA8A67",
"Antique Brass": "#C88A65",
"Black": "#000000",
"Charcoal Gray": "#736A62",
"Gray": "#8B8680",
"Blue-Gray": "#C8C8CD",
"Radical Red": "#FF355E",
"Wild Watermelon": "#FD5B78",
"Outrageous Orange": "#FF6037",
"Atomic Tangerine": "#FF9966",
"Neon Carrot": "#FF9933",
"Sunglow": "#FFCC33",
"Laser Lemon": "#FFFF66",
"Unmellow Yellow": "#FFFF66",
"Electric Lime": "#CCFF00",
"Screamin' Green": "#66FF66",
"Magic Mint": "#AAF0D1",
"Blizzard Blue": "#50BFE6",
"Shocking Pink": "#FF6EFF",
"Razzle Dazzle Rose": "#EE34D2",
"Hot Magenta": "#FF00CC",
"Purple Pizzazz": "#FF00CC",
"Sizzling Red": "#FF3855",
"Red Salsa": "#FD3A4A",
"Tart Orange": "#FB4D46",
"Orange Soda": "#FA5B3D",
"Bright Yellow": "#FFAA1D",
"Yellow Sunshine": "#FFF700",
"Slimy Green": "#299617",
"Green Lizard": "#A7F432",
"Denim Blue": "#2243B6",
"Blue Jeans": "#5DADEC",
"Plump Purple": "#5946B2",
"Purple Plum": "#9C51B6",
"Sweet Brown": "#A83731",
"Brown Sugar": "#AF6E4D",
"Eerie Black": "#1B1B1B",
"Black Shadows": "#BFAFB2",
"Fiery Rose": "#FF5470",
"Sizzling Sunrise": "#FFDB00",
"Heat Wave": "#FF7A00",
"Lemon Glacier": "#FDFF00",
"Spring Frost": "#87FF2A",
"Absolute Zero": "#0048BA",
"Winter Sky": "#FF007C",
"Frostbite": "#E936A7",
"Alloy Orange": "#c46210",
"B'dazzled Blue": "#2e5894",
"Big Dip O' Ruby": "#9c2542",
"Bittersweet Shimmer": "#bf4f51",
"Blast Off Bronze": "#a57164",
"Cyber Grape": "#58427c",
"Deep Space Sparkle": "#4a646c",
"Gold Fusion": "#85754e",
"Illuminating Emerald": "#319177",
"Metallic Seaweed": "#0a7e8c",
"Metallic Sunburst": "#9c7c38",
"Razzmic Berry": "#8d4e85",
"Sheen Green": "#8fd400",
"Shimmering Blush": "#d98695",
"Sonic Silver": "#757575",
"Steel Blue": "#0081ab",
"Aztec Gold": "#C39953",
"Burnished Brown": "#A17A74",
"Cerulean Frost": "#6D9BC3",
"Cinnamon Satin": "#CD607E",
"Copper Penny": "#AD6F69",
"Cosmic Cobalt": "#2E2D88",
"Glossy Grape": "#AB92B3",
"Granite Gray": "#676767",
"Green Sheen": "#6EAEA1",
"Lilac Luster": "#AE98AA",
"Misty Moss": "#BBB477",
"Mystic Maroon": "#AD4379",
"Pearly Purple": "#B768A2",
"Pewter Blue": "#8BA8B7",
"Polished Pine": "#5DA493",
"Quick Silver": "#A6A6A6",
"Rose Dust": "#9E5E6F",
"Rusty Red": "#DA2C43",
"Shadow Blue": "#778BA5",
"Shiny Shamrock": "#5FA778",
"Steel Teal": "#5F8A8B",
"Sugar Plum": "#914E75",
"Twilight Lavender": "#8A496B",
"Wintergreen Dream": "#56887D",
"Baby Powder": "#FEFEFA",
"Banana": "#FFD12A",
"Blueberry": "#4F86F7",
"Bubble Gum": "#FFD3F8",
"Cedar Chest": "#C95A49",
"Cherry": "#DA2647",
"Chocolate": "#BD8260",
"Coconut": "#FEFEFE",
"Daffodil": "#FFFF31",
"Dirt": "#9B7653",
"Eucalyptus": "#44D7A8",
"Fresh Air": "#A6E7FF",
"Grape": "#6F2DA8",
"Jelly Bean": "#DA614E",
"Leather Jacket": "#253529",
"Lemon": "#FFFF38",
"Licorice": "#1A1110",
"Lilac": "#DB91EF",
"Lime": "#B2F302",
"Lumber": "#FFE4CD",
"New Car": "#214FC6",
"Pine": "#45A27D",
"Rose": "#FF5050",
"Shampoo": "#FFCFF1",
"Smoke": "#738276",
"Soap": "#CEC8EF",
"Strawberry": "#FC5A8D",
"Tulip": "#FF878D",
"Amethyst": "#64609A",
"Citrine": "#933709",
"Emerald": "#14A989",
"Jade": "#469A84",
"Jasper": "#D05340",
"Lapis Lazuli": "#436CB9",
"Malachite": "#469496",
"Moonstone": "#3AA8C1",
"Onyx": "#353839",
"Peridot": "#ABAD48",
"Pink Pearl": "#B07080",
"Rose Quartz": "#BD559C",
"Ruby": "#AA4069",
"Sapphire": "#2D5DA1",
"Smokey Topaz": "#832A0D",
"Tiger's Eye": "#B56917",
"Alien Armpit": "#84DE02",
"Big Foot Feet": "#E88E5A",
"Booger Buster": "#DDE26A",
"Dingy Dungeon": "#C53151",
"Gargoyle Gas": "#FFDF46",
"Giant's Club": "#B05C52",
"Magic Potion": "#FF4466",
"Mummy's Tomb": "#828E84",
"Ogre Odor": "#FD5240",
"Pixie Powder": "#391285",
"Princess Perfume": "#FF85CF",
"Sasquatch Socks": "#FF4681",
"Sea Serpent": "#4BC7CF",
"Smashed Pumpkin": "#FF6D3A",
"Sunburnt Cyclops": "#FF404C",
"Winter Wizard": "#A0E6FF",
};
Main firmware file
C/C++Add the InternetButton files too, compile and flash to your Electron.
#include "InternetButton.h"
#include "math.h"
/* Let me show you how easy it is to put the Button on the Internet.
Useful info, like how to access the data from your browser, can be
found here: http://docs.particle.io/photon/firmware/#particle-function
The code to control the number of illuminated LEDs is here:
https://github.com/spark/InternetButton/blob/master/controlKnob.html
Try naming one of your devices "InternetButton" and running controlKnob in your browser or on your phone!
Note that the Core or Photon *must* be named "InternetButton" because the javascript looks for it.
*/
struct rgbColor {
unsigned char red;
unsigned char green;
unsigned char blue;
};
InternetButton b = InternetButton();
float brightness = 0.1;
struct rgbColor currentColor{ 128, 0, 255 };
int howMany = 11;
bool changed = true;
bool unwind = true;
void setup() {
// Use b.begin(1); if you have the original SparkButton, which does not have a buzzer or a plastic enclosure
// to use, just add a '1' between the parentheses in the code below.
b.begin();
Particle.subscribe("light_demo/color", lightColorSubscription);
Particle.function("color", changeLightColor);
System.on(reset_pending, beforePowerDown);
System.disableReset();
}
void loop(){
//Clicking "up" makes the LEDs brighter
if(b.buttonOn(1)){
if(brightness < 1){
brightness += 0.005;
changed = true;
}
}
//Clicking "down" makes the LEDs dimmer
else if (b.buttonOn(3)){
if(brightness > 0){
brightness -= 0.005;
if(brightness < 0){
brightness = 0;
}
changed = true;
}
}
//If anything's been altered by clicking or the Particle.function, update the LEDs
if(changed){
delay(10);
makeColors();
changed = false;
unwind = false;
}
}
void beforePowerDown(system_event_t event, uint32_t param, void *reserved) {
b.allLedsOff();
System.enableReset();
}
int changeLightColor(String colorStr) {
struct rgbColor color;
if(parseColor(colorStr, color)) {
currentColor = color;
unwind = true;
changed = true;
return 0;
}
return 1;
}
void lightColorSubscription(const char* event, const char* colorStr) {
changeLightColor(colorStr);
}
bool parseColor(const char *colorStr, struct rgbColor &color) {
if(colorStr[0] == '#' && strlen(colorStr) == 7) {
long colorCode = strtol(&colorStr[1], NULL, 16);
color.red = (colorCode >> 16) & 0xFF;
color.green = (colorCode >> 8) & 0xFF;
color.blue = colorCode & 0xFF;
return true;
}
return false;
}
//Uses the brightness and the color values to compute what to show
void makeColors() {
uint8_t red = currentColor.red * brightness;
uint8_t green = currentColor.green * brightness;
uint8_t blue = currentColor.blue * brightness;
if(unwind) {
const int pace = 50;
for(int i = howMany; i > 1; i--) {
b.ledOff(i);
delay(pace);
}
delay(pace);
for(int i = 1; i <= howMany; i++){
b.ledOn(i, red, green, blue);
delay(pace);
}
} else {
b.allLedsOff();
for(int i = 1; i <= howMany; i++){
b.ledOn(i, red, green, blue);
}
}
}
/*
Arduino Library for Analog Devices ADXL362 - Micropower 3-axis accelerometer
go to http://www.analog.com/ADXL362 for datasheet
License: CC BY-SA 3.0: Creative Commons Share-alike 3.0. Feel free
to use and abuse this code however you'd like. If you find it useful
please attribute, and SHARE-ALIKE!
Created June 2012
by Anne Mahaffey - hosted on http://annem.github.com/ADXL362
Modified Mars 2014
by pixelk
Modified for Spark Core/Button October 2014
Updated for Particle Photon July 2015
by jenesaisdiq
*/
#include "application.h"
#ifndef InternetButton_h
#define InternetButton_h
class InternetButton {
public:
InternetButton();
void
begin(void),
begin(int i),
allLedsOff(void),
allLedsOn(uint8_t r, uint8_t g, uint8_t b),
ledOn(uint8_t i, uint8_t r, uint8_t g, uint8_t b),
ledOff(uint8_t i),
rainbow(uint8_t wait),
playNote(String note, int duration),
playSong(String song),
smoothLedOn(float i, uint8_t r, uint8_t g, uint8_t b);
uint8_t
buttonOn(uint8_t i),
allButtonsOn(void),
allButtonsOff(void),
lowestLed(void);
int
readX(void),
readY(void),
readZ(void),
readX16(void),
readY16(void),
readZ16(void);
private:
};
//------------- Accelerometer --------------
/**
* Turn debugging on or off
*/
#define ADXL362_DEBUG 0
/* ADXL Registers */
#define XL362_DEVID_AD 0x00
#define XL362_DEVID_MST 0x01
#define XL362_PARTID 0x02
#define XL362_REVID 0x03
#define XL362_XDATA 0x08
#define XL362_YDATA 0x09
#define XL362_ZDATA 0x0A
#define XL362_STATUS 0x0B
#define XL362_FIFO_ENTRIES_L 0x0C
#define XL362_FIFO_ENTRIES_H 0x0D
#define XL362_XDATA_L 0x0E
#define XL362_XDATA_H 0x0F
#define XL362_YDATA_L 0x10
#define XL362_YDATA_H 0x11
#define XL362_ZDATA_L 0x12
#define XL362_ZDATA_H 0x13
#define XL362_TEMP_L 0x14
#define XL362_TEMP_H 0x15
#define XL362_SOFT_RESET 0x1F
#define XL362_THRESH_ACT_L 0x20
#define XL362_THRESH_ACT_H 0x21
#define XL362_TIME_ACT 0x22
#define XL362_THRESH_INACT_L 0x23
#define XL362_THRESH_INACT_H 0x24
#define XL362_TIME_INACT_L 0x25
#define XL362_TIME_INACT_H 0x26
#define XL362_ACT_INACT_CTL 0x27
#define XL362_FIFO_CONTROL 0x28
#define XL362_FIFO_SAMPLES 0x29
#define XL362_INTMAP1 0x2A
#define XL362_INTMAP2 0x2B
#define XL362_FILTER_CTL 0x2C
#define XL362_POWER_CTL 0x2D
#define XL362_SELF_TEST 0x2E
/* Configuration values */
#define XL362_FILTER_FLAG_2G 0b00000000
#define XL362_FILTER_FLAG_4G 0b01000000
#define XL362_FILTER_FLAG_8G 0b10000000
#define XL362_FILTER_FLAG_HBW 0b10000
#define XL362_FILTER_FLAG_FBW 0b00000
#define XL362_FILTER_FLAG_ODR12 0b000
#define XL362_FILTER_FLAG_ODR25 0b001
#define XL362_FILTER_FLAG_ODR50 0b010
#define XL362_FILTER_FLAG_ODR100 0b011
#define XL362_FILTER_FLAG_ODR200 0b100
#define XL362_FILTER_FLAG_ODR400 0b111
#define XL362_POWER_FLAG_NOISE_NORMAL 0b000000
#define XL362_POWER_FLAG_NOISE_LOW 0b010000
#define XL362_POWER_FLAG_NOISE_ULTRALOW 0b100000
#define XL362_POWER_FLAG_MEASURE_STANDBY 0b00
#define XL362_POWER_FLAG_MEASURE_RUNING 0b10
class ADXL362
{
public:
ADXL362();
//
// Basic Device control and readback functions
//
void begin();
void beginMeasure();
int readX16();
int readY16();
int readZ16();
int readX();
int readY();
int readZ();
void readXYZTData(short &XData, short &YData, short &ZData, float &Temperature);
void readXYZmg(int &X, int &Y, int &Z);
void XYZmgtoRPT(int X, int Y, int Z, float &Rho, float &Phi, float &Theta);
int16_t readTemp();
// need to add the following functions
// void mapINT1(
// void mapINT2
// void autoSleep
// void activityInterruptControl
// -Activity, Inactivity, Both
// - Referenced, Absolute
// - Free Fall, Linked Mode, Loop Mode
void checkAllControlRegs();
void setRange(uint8_t Range);
void setBandwidth(uint8_t BandWidth);
void setOutputDatarate(uint8_t ODR);
void setNoiseLevel(uint8_t NoiseLevel);
// Low-level SPI control, to simplify overall coding
uint8_t SPIreadOneRegister(uint8_t regAddress);
void SPIwriteOneRegister(uint8_t regAddress, uint8_t regValue);
int SPIreadTwoRegisters(uint8_t regAddress);
void SPIwriteTwoRegisters(uint8_t regAddress, int twoRegValue);
private:
uint8_t mgperLSB; // default +-2g XL362_FILTER_FLAG_2G -> 1mg/LSB (ADXL362 Datasheet page 4)
};
//----------------- LED Handling ------------------------
#define PIXEL_COUNT 11
//#define PIXEL_PIN D3
#define PIXEL_TYPE WS2812B
/*-------------------------------------------------------------------------
Spark Core library to control WS2811/WS2812 based RGB
LED devices such as Adafruit NeoPixel strips.
Currently handles 800 KHz and 400kHz bitstream on Spark Core,
WS2812, WS2812B and WS2811.
Also supports Radio Shack Tri-Color Strip with TM1803 controller
400kHz bitstream.
Written by Phil Burgess / Paint Your Dragon for Adafruit Industries.
Modified to work with Spark Core by Technobly.
Modified to work with Spark Button by jenesaisdiq.
Contributions by PJRC and other members of the open source community.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing products
from Adafruit!
--------------------------------------------------------------------*/
/* ======================= Adafruit_NeoPixel.h ======================= */
/*--------------------------------------------------------------------
This file is part of the Adafruit NeoPixel library.
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.
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 SPARK_NEOPIXEL_H
#define SPARK_NEOPIXEL_H
#include "application.h"
// 'type' flags for LED pixels (third parameter to constructor):
#define WS2812 0x02 // 800 KHz datastream (NeoPixel)
#define WS2812B 0x02 // 800 KHz datastream (NeoPixel)
#define WS2811 0x00 // 400 KHz datastream (NeoPixel)
#define TM1803 0x03 // 400 KHz datastream (Radio Shack Tri-Color Strip)
#define TM1829 0x04 // 800 KHz datastream ()
#define WS2812B2 0x05 // 800 KHz datastream (NeoPixel)
class Adafruit_NeoPixel {
public:
// Constructor: number of LEDs, pin number, LED type
Adafruit_NeoPixel(uint16_t n, uint8_t p=2, uint8_t t=WS2812B);
~Adafruit_NeoPixel();
void
begin(void),
show(void) __attribute__((optimize("Ofast"))),
setPin(uint8_t p),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
setPixelColor(uint16_t n, uint32_t c),
setBrightness(uint8_t),
clear(void);
uint8_t
*getPixels() const,
getBrightness(void) const;
uint16_t
numPixels(void) const;
static uint32_t
Color(uint8_t r, uint8_t g, uint8_t b);
uint32_t
getPixelColor(uint16_t n) const;
private:
const uint16_t
numLEDs, // Number of RGB LEDs in strip
numBytes; // Size of 'pixels' buffer below
const uint8_t
type; // Pixel type flag (400 vs 800 KHz)
uint8_t
//pin, // Output pin number
brightness,
*pixels; // Holds LED color values (3 bytes each)
uint32_t
endTime; // Latch timing reference
};
#endif // ADAFRUIT_NEOPIXEL_H
#endif // InternetButton_h
Comments
Please log in or sign up to comment.