Skip to content

Commit

Permalink
Merge pull request #69 from blair-robot-project/merge_multi_module
Browse files Browse the repository at this point in the history
Merge multi module
rytse authored Jun 1, 2017
2 parents 6f8136f + 170d649 commit c0a0008
Showing 360 changed files with 11,981 additions and 10,647 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -13,11 +13,17 @@ gradle-app.setting
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties

# IntelliJ files
.idea/
*.idea
gen/
classes/
out/
build
*build
*.iml
*.ipr
*.iws

# GradleRIO files
robot2017.iml
@@ -31,3 +37,6 @@ robot2017.iws
#Other
.metadata/
.DS_Store

#Copied log files
logs/
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -8,4 +8,4 @@ script:
notifications:
email:
on_success: never
on_failure: always # default: always
on_failure: always # default: always
29 changes: 29 additions & 0 deletions Arduino/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app
86 changes: 86 additions & 0 deletions Arduino/AnalogInOutSerial/AnalogInOutSerial.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#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(150, 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./*
/* Analog input, analog output, serial output
Reads an analog input pin, maps the result to a range from 0 to 255
and uses the result to set the pulsewidth modulation (PWM) of an output pin.
Also prints the results to the serial monitor.
The circuit:
* potentiometer connected to analog pin 0.
Center pin of the potentiometer goes to the analog pin.
side pins of the potentiometer go to +5V and ground
* LED connected from digital pin 9 to ground
created 29 Dec. 2008
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/

// These constants won't change. They're used to give names
// to the pins used:
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)

void setup() {
// initialize serial communications at 9600 bps:
strip.begin();
Serial.begin(9600);
}

void loop() {
// read the analog in value:
sensorValue = analogRead(analogInPin);
// map it to the range of the analog out:
outputValue = map(sensorValue, 0, 1023, 0, 255);
// change the analog out value:
analogWrite(analogOutPin, outputValue);

// print the results to the serial monitor:
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);

// wait 2 milliseconds before the next loop
// for the analog-to-digital converter to settle
// after the last reading:
uint16_t i;
setRed(10, outputValue);
strip.show();
delay(2);
}

void setRed(uint16_t wait, uint8_t color) {
uint16_t i;
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, 0, color, color/2);
}

delay(wait);
}
172 changes: 172 additions & 0 deletions Arduino/AutoTeleop/AutoTeleop.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#include <Wire.h>
#include <Adafruit_NeoPixel.h>

#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, PIN, NEO_GRB + NEO_KHZ800);

String state;

uint32_t red = strip.Color(60,0,0);
uint32_t green = strip.Color(0,100,15);
uint32_t oyellow = strip.Color(140,40,0);
uint32_t blue = strip.Color(0,0,100);
uint32_t orange = strip.Color(140,10,0);
uint32_t yellow = strip.Color(90,20,0);
uint32_t purple = strip.Color(55,0,75);
uint32_t pink = strip.Color(80,0,65);
uint32_t lgreen = strip.Color(10,80,10);
uint32_t lblue = strip.Color(15,35,135);
uint32_t cyan = strip.Color(0,80,60);
uint32_t white = strip.Color(40,40,40);

const int rgbChangeSpeed = 18;

//highest value a color would reach.
const int colorMax = 108;
int rred = colorMax;
int rgreen = 0;
int rblue = 0;

//information about the white pixel bit that flows around
int currentPos = 0;
const int whiteLength = 7;
const int whiteSpeed = 2;

int tempIndex;

//last position position that the white pixel bit was at.
int lastPos = strip.numPixels();
//previous color that gets overwritten by the white pixel bit.
uint32_t lastColor;

uint32_t ra1 = purple;
uint32_t ra2 = pink;
uint32_t ba1 = lgreen;
uint32_t ba2 = cyan;
uint32_t rt1 = red;
uint32_t rt2 = orange;
uint32_t bt1 = blue;
uint32_t bt2 = purple;

int loopCounter;
boolean rippleInvert = false;
int ripplePos = 0;

void setup() {
// put your setup code here, to run once:
Wire.begin(4);
Serial.begin(9600);
Wire.onReceive(receiveEventWire);
strip.begin();
strip.show();
state = "init";
}

void loop() {
if (loopCounter % 2 == 0) {
ripplePos++;
loopCounter = 1;
} else {
loopCounter++;
}

if (ripplePos > strip.numPixels() / 2) {
ripplePos = ripplePos % (strip.numPixels()/2);
rippleInvert = !rippleInvert;
}

if (state.equals("init")) {
//if you've completed a cycle (ie current position is now 0, last position is 150)
if (currentPos < lastPos || currentPos > 149) {
//store lastColor, then find your next incremented color
lastColor = strip.Color(rred,rgreen,rblue);
nextRGB();
}
lastPos = currentPos;
tempIndex = currentPos;
//sets the little white pixel bit to white.
while (tempIndex != (currentPos + whiteLength) % 150) {
strip.setPixelColor(tempIndex,100,100,100);
tempIndex = (tempIndex + 1) % 150;
}
//if you're behind the white thing, get set to the new color
for (int i = 0; i < currentPos; i++) {
strip.setPixelColor(i,rred,rgreen,rblue);
}
//if you're beyond the white thing, get set to the old color.
for (int i = currentPos + whiteLength + 1; i < 150; i++) {
strip.setPixelColor(i,lastColor);
}
//update strip, move white pixel bit forward by speed defined above
strip.show();
currentPos += whiteSpeed;
currentPos %= 150;
delay(17);
} else if (state.equals("red_auto")) {
for (int i = 0; i < strip.numPixels(); i++) {
setColor(i, ra1, ra2);
}
} else if (state.equals("blue_auto")) {
for (int i = 0; i < strip.numPixels(); i++) {
setColor(i, ba1, ba2);
}
} else if (state.equals("red_teleop")) {
for (int i = 0; i < strip.numPixels(); i++) {
setColor(i, rt1, rt2);
}
} else if (state.equals("blue_teleop")) {
for (int i = 0; i < strip.numPixels(); i++) {
setColor(i, bt1, bt2);
}
}
strip.show();
delay(1);
}

void receiveEventWire(int numBytes) {
//Serial.println("just entered event");
String temp = "";
while(Wire.available() > 0){
char n = (char) Wire.read();
temp+=n;
}

state = temp;
}

void setColor(int i, uint32_t c1, uint32_t c2) {
if (!rippleInvert) {
if (i < strip.numPixels()/2 - ripplePos || i > strip.numPixels()/2+ripplePos) {
strip.setPixelColor(i,c2);
} else if (i == strip.numPixels()/2 - ripplePos || i == strip.numPixels()/2+ripplePos){
strip.setPixelColor(i,90,90,90);
} else {
strip.setPixelColor(i,c1);
}
} else {
if (i < strip.numPixels()/2 - ripplePos || i > strip.numPixels()/2+ripplePos) {
strip.setPixelColor(i,c1);
} else if (i == strip.numPixels()/2 - ripplePos || i == strip.numPixels()/2+ripplePos) {
strip.setPixelColor(i,90,90,90);
}
else {
strip.setPixelColor(i,c2);
}
}
}

void nextRGB() {
if (rred == colorMax && rgreen < colorMax && rblue == 0) {
rgreen += rgbChangeSpeed;
} else if (rgreen == colorMax && rred > 0 && rblue == 0) {
rred -= rgbChangeSpeed * 1.5;
} else if (rgreen == colorMax && rblue < colorMax && rred == 0) {
rblue += rgbChangeSpeed;
} else if (rblue == colorMax && rgreen > 0 && rred == 0) {
rgreen -= rgbChangeSpeed;
} else if (rblue == colorMax && rred < colorMax && rgreen == 0) {
rred += rgbChangeSpeed;
} else if (rred == colorMax && rblue > 0 && rgreen == 0) {
rblue -= rgbChangeSpeed * .5;
}
}
674 changes: 674 additions & 0 deletions Arduino/LICENSE

Large diffs are not rendered by default.

219 changes: 219 additions & 0 deletions Arduino/Lights_Final/Lights_Final.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/* Team 449 2017 LED Strip Code
* Written by Rafi Pedersen
*
* Operates under a 4-State premise:
* State 1: Neither gear nor peg
* State 2: Gear only
* State 3: Peg Only (pretty much useless)
* State 4: Peg and Gear
*
* Each state has two colors, which alternately expand from
* the middle of the strip.
*
* Detects the peg using six analog IR sensors
* Detects the gear using two digital IR sensors, one for gear
* in and one for gear out.
*
* Uses a 150 pixel Adafruit Neopixel strip.
*/

#include <Wire.h>
#include <Adafruit_NeoPixel.h>

#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(150, PIN, NEO_GRB + NEO_KHZ800);

//define a bunch of colors
uint32_t red = strip.Color(60,0,0);
uint32_t green = strip.Color(0,100,15);
uint32_t oyellow = strip.Color(140,40,0);
uint32_t blue = strip.Color(0,0,100);
uint32_t orange = strip.Color(140,10,0);
uint32_t yellow = strip.Color(90,20,0);
uint32_t purple = strip.Color(55,0,75);
uint32_t pink = strip.Color(80,0,65);
uint32_t lgreen = strip.Color(10,80,10);
uint32_t lblue = strip.Color(15,35,135);
uint32_t cyan = strip.Color(0,80,60);
uint32_t white = strip.Color(40,40,40);

//define 2 colors for each of the four states.
uint32_t neutral1 = red;
uint32_t neutral2 = orange;
uint32_t gear1 = yellow;
uint32_t gear2 = oyellow;
uint32_t peg1 = purple;
uint32_t peg2 = pink;
uint32_t gearPeg1 = blue;
uint32_t gearPeg2 = lblue;


int threshold = 320; //threshold for the analog peg-detecting sensors
int gearSensorBuffer = 15; //buffer for the gear sensors
//higher values make less flicker, more delay
int gearBufferState1 = 0; //initialize both sensors' buffers
int gearBufferState2 = 0;
//buffers for the gear sensors add or subtract based on their reading
//then state is determined by positive/negative of buffers

//used to make transition animation between two colors
int barrier = 0;
int ripplePos = 0;
boolean rippleInvert = false;

//set up analog sensors
const int sensorCount = 6; //number of sensors
const int analogInPins[] = {A0, A1, A2, A3, A4, A5};
uint32_t sensorSums[sensorCount];

const int sensorReadingCount = 20;
uint32_t pegSensorReadings[sensorCount][sensorReadingCount];
int sensorIndex = 0;

boolean pegIn = false;
boolean gearIn = false;

int loopCounter = 0;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
strip.begin();
strip.show();
}

void loop() {
// put your main code here, to run repeatedly:
readSensors();

if (loopCounter % 2 == 0) {
ripplePos++;
loopCounter = 1;
} else {
loopCounter++;
}

if (ripplePos > strip.numPixels() / 2) {
ripplePos = ripplePos % (strip.numPixels()/2);
rippleInvert = !rippleInvert;
}

if (gearIn) {
if (pegIn) {
for (int i = 0; i <= strip.numPixels()/2; i++) {
setColor(strip.numPixels()/2+i, gearPeg1, gearPeg2);
setColor(strip.numPixels()/2 - i, gearPeg1, gearPeg2);
}
} else {
for (int i = 0; i <= strip.numPixels()/2; i++) {
setColor(strip.numPixels()/2+i, gear1, gear2);
setColor(strip.numPixels()/2 - i, gear1, gear2);
}
}
} else if (pegIn) {
for (int i = 0; i <= strip.numPixels()/2; i++) {
setColor(strip.numPixels()/2+i, peg1, peg2);
setColor(strip.numPixels()/2 - i, peg1, peg2);
}
} else {
for (int i = 0; i <= strip.numPixels()/2; i++) {
setColor(strip.numPixels()/2+i, neutral1, neutral2);
setColor(strip.numPixels()/2-i, neutral1, neutral2);
}
}
strip.show();
delay(1);
}

void setColor(int i, uint32_t c1, uint32_t c2) {
if (!rippleInvert) {
if (i < strip.numPixels()/2 - ripplePos || i > strip.numPixels()/2+ripplePos) {
strip.setPixelColor(i,c2);
} else if (i == strip.numPixels()/2 - ripplePos || i == strip.numPixels()/2+ripplePos){
strip.setPixelColor(i,90,90,90);
} else {
strip.setPixelColor(i,c1);
}
} else {
if (i < strip.numPixels()/2 - ripplePos || i > strip.numPixels()/2+ripplePos) {
strip.setPixelColor(i,c1);
} else if (i == strip.numPixels()/2 - ripplePos || i == strip.numPixels()/2+ripplePos) {
strip.setPixelColor(i,90,90,90);
}
else {
strip.setPixelColor(i,c2);
}
}
}

void readSensors() {
if (digitalRead(2) == 0) {
if (gearBufferState1 < gearSensorBuffer) {
gearBufferState1++;
}
} else {
if (gearBufferState1 > gearSensorBuffer * -1) {
gearBufferState1--;
}
}
if (digitalRead(3) == 0) {
if (gearBufferState2 < gearSensorBuffer) {
gearBufferState2++;
}
} else {
if (gearBufferState2 > gearSensorBuffer * -1) {
gearBufferState2--;
}
}
if (gearBufferState2 >= 0) {
gearIn = true;
} else if (gearBufferState1 < 0 && gearBufferState2 < 0) {
gearIn = false;
}

for (int i = 0; i < sensorCount; i++) {
pegSensorReadings[i][sensorIndex] = analogRead(analogInPins[i]);
//Serial.print(pegSensorReadings[i][sensorIndex]); Serial.print('\t');
sensorSums[i] = findAverage(pegSensorReadings[i]);
}
sensorIndex++;
if (sensorIndex == sensorReadingCount) {
sensorIndex = 0;
}
//sensorSums[1] *= 2.5;
for (int i = 0; i < sensorCount; i++) {
Serial.print(sensorSums[i]); Serial.print('\t');
}
Serial.println();
if (maxValue(sensorSums, sensorCount) > threshold) {
/*if(redColor < 100){
redColor+=15;
}
if (blueColor > 0) {
blueColor -= 15;
}*/
pegIn = true;
} else {
pegIn = false;
}
}

uint32_t maxValue( uint32_t myArray[], int size) {
int i; uint32_t maxValue;
maxValue=myArray[0];

//find the largest no
for (i=0;i < size; i++) {
if (myArray[i]>maxValue)
maxValue=myArray[i];
}
return maxValue;
}

uint32_t findAverage(uint32_t input[]) {
uint32_t sum = 0;
for (int i = 0; i < sensorReadingCount; i++) {
sum += input[i];
}
return (sum / sensorReadingCount);
}
76 changes: 76 additions & 0 deletions Arduino/WhiteLoopRainbow/WhiteLoopRainbow.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(150, PIN, NEO_GRB + NEO_KHZ800);

//Amount of change for each of the colors at each step
const int rgbChangeSpeed = 5;

//highest value a color would reach.
const int colorMax = 100;
int red = colorMax;
int green = 0;
int blue = 0;

//information about the white pixel bit that flows around
int currentPos = 0;
const int whiteLength = 3;
const int whiteSpeed = 1;

int tempIndex;

//last position position that the white pixel bit was at.
int lastPos = 150;
//previous color that gets overwritten by the white pixel bit.
uint32_t lastColor;

void setup() {
// put your setup code here, to run once:
strip.begin();
strip.show();
}

void loop() {
//if you've completed a cycle (ie current position is now 0, last position is 150)
if (currentPos < lastPos) {
//store lastColor, then find your next incremented color
lastColor = strip.Color(red,green,blue);
nextRGB();
}
lastPos = currentPos;
tempIndex = currentPos;
//sets the little white pixel bit to white.
while (tempIndex != (currentPos + whiteLength) % 150) {
strip.setPixelColor(tempIndex,100,100,100);
tempIndex = (tempIndex + 1) % 150;
}
//if you're behind the white thing, get set to the new color
for (int i = 0; i < currentPos; i++) {
strip.setPixelColor(i,red,green,blue);
}
//if you're beyond the white thing, get set to the old color.
for (int i = currentPos + whiteLength + 1; i < 150; i++) {
strip.setPixelColor(i,lastColor);
}
//update strip, move white pixel bit forward by speed defined above
strip.show();
currentPos += whiteSpeed;
delay(10);
}

//generates the next color based on the graph: https://academe.co.uk/wp-content/uploads/2012/04/451px-HSV-RGB-comparison.svg_.png
void nextRGB() {
if (red == colorMax && green < colorMax && blue == 0) {
green += rgbChangeSpeed;
} else if (green == colorMax && red > 0 && blue == 0) {
red -= rgbChangeSpeed;
} else if (green == colorMax && blue < colorMax && red == 0) {
blue += rgbChangeSpeed;
} else if (blue == colorMax && green > 0 && red == 0) {
green -= rgbChangeSpeed;
} else if (blue == colorMax && red < colorMax && green == 0) {
red += rgbChangeSpeed;
} else if (red == colorMax && blue > 0 && green == 0) {
blue -= rgbChangeSpeed;
}
}

76 changes: 76 additions & 0 deletions Arduino/WhiteRainbow/WhiteRainbow.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(150, PIN, NEO_GRB + NEO_KHZ800);

//Amount of change for each of the colors at each step
const int rgbChangeSpeed = 18;

//highest value a color would reach.
const int colorMax = 108;
int red = colorMax;
int green = 0;
int blue = 0;

//information about the white pixel bit that flows around
int currentPos = 0;
const int whiteLength = 7;
const int whiteSpeed = 2;

int tempIndex;

//last position position that the white pixel bit was at.
int lastPos = 150;
//previous color that gets overwritten by the white pixel bit.
uint32_t lastColor;

void setup() {
// put your setup code here, to run once:
strip.begin();
strip.show();
}

void loop() {
//if you've completed a cycle (ie current position is now 0, last position is 150)
if (currentPos < lastPos || currentPos > 149) {
//store lastColor, then find your next incremented color
lastColor = strip.Color(red,green,blue);
nextRGB();
}
lastPos = currentPos;
tempIndex = currentPos;
//sets the little white pixel bit to white.
while (tempIndex != (currentPos + whiteLength) % 150) {
strip.setPixelColor(tempIndex,100,100,100);
tempIndex = (tempIndex + 1) % 150;
}
//if you're behind the white thing, get set to the new color
for (int i = 0; i < currentPos; i++) {
strip.setPixelColor(i,red,green,blue);
}
//if you're beyond the white thing, get set to the old color.
for (int i = currentPos + whiteLength + 1; i < 150; i++) {
strip.setPixelColor(i,lastColor);
}
//update strip, move white pixel bit forward by speed defined above
strip.show();
currentPos += whiteSpeed;
currentPos %= 150;
delay(18);
}

//generates the next color based on the graph: https://academe.co.uk/wp-content/uploads/2012/04/451px-HSV-RGB-comparison.svg_.png
void nextRGB() {
if (red == colorMax && green < colorMax && blue == 0) {
green += rgbChangeSpeed;
} else if (green == colorMax && red > 0 && blue == 0) {
red -= rgbChangeSpeed * 1.5;
} else if (green == colorMax && blue < colorMax && red == 0) {
blue += rgbChangeSpeed;
} else if (blue == colorMax && green > 0 && red == 0) {
green -= rgbChangeSpeed;
} else if (blue == colorMax && red < colorMax && green == 0) {
red += rgbChangeSpeed;
} else if (red == colorMax && blue > 0 && green == 0) {
blue -= rgbChangeSpeed * .5;
}
}
1,730 changes: 1,730 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp

Large diffs are not rendered by default.

181 changes: 181 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*--------------------------------------------------------------------
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 ADAFRUIT_NEOPIXEL_H
#define ADAFRUIT_NEOPIXEL_H

#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#include <pins_arduino.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
// 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.

// 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))
#define NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1))
#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2))
#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1))
#define NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0))
#define NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0))

// RGBW NeoPixel permutations; all 4 offsets are distinct
// Offset: W R G B
#define NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
#define NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
#define NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))

#define NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
#define NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
#define NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
#define NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))

#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
#define NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
#define NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
#define NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))

#define NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
#define NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
#define NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))

// 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 datastream
#ifndef __AVR_ATtiny85__
#define NEO_KHZ400 0x0100 // 400 KHz datastream
#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;
#else
typedef uint8_t neoPixelType;
#endif

class Adafruit_NeoPixel {

public:

// Constructor: number of LEDs, pin number, LED type
Adafruit_NeoPixel(uint16_t n, uint8_t p=6, neoPixelType t=NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel(void);
~Adafruit_NeoPixel();

void
begin(void),
show(void),
setPin(uint8_t p),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w),
setPixelColor(uint16_t n, uint32_t c),
setBrightness(uint8_t),
clear(),
updateLength(uint16_t n),
updateType(neoPixelType t);
uint8_t
*getPixels(void) const,
getBrightness(void) const;
int8_t
getPin(void) { return pin; };
uint16_t
numPixels(void) const;
static uint32_t
Color(uint8_t r, uint8_t g, uint8_t b),
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
uint32_t
getPixelColor(uint16_t n) const;
inline bool
canShow(void) { return (micros() - endTime) >= 50L; }

private:

boolean
#ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled...
is800KHz, // ...true if 800 KHz pixels
#endif
begun; // true if begin() previously called
uint16_t
numLEDs, // Number of RGB LEDs in strip
numBytes; // Size of 'pixels' buffer below (3 or 4 bytes/pixel)
int8_t
pin; // Output pin number (-1 if not yet set)
uint8_t
brightness,
*pixels, // Holds LED color values (3 or 4 bytes each)
rOffset, // Index of red byte within each 3- or 4-byte pixel
gOffset, // Index of green byte
bOffset, // Index of blue byte
wOffset; // Index of white byte (same as 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

};

#endif // ADAFRUIT_NEOPIXEL_H
165 changes: 165 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/COPYING
Original file line number Diff line number Diff line change
@@ -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.
11 changes: 11 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Adafruit NeoPixel Library [![Build Status](https://travis-ci.org/adafruit/Adafruit_NeoPixel.svg?branch=master)](https://travis-ci.org/adafruit/Adafruit_NeoPixel)

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.

[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
67 changes: 67 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/esp8266.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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.

#ifdef ESP8266

#include <Arduino.h>
#include <eagle_soc.h>

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;
}

void ICACHE_RAM_ATTR espShow(
uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {

#define CYCLES_800_T0H (F_CPU / 2500000) // 0.4us
#define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us
#define CYCLES_800 (F_CPU / 800000) // 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, pinMask;

pinMask = _BV(pin);
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
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
startTime = c; // Save start time
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
if(!(mask >>= 1)) { // Next bit/byte
if(p >= end) break;
pix = *p++;
mask = 0x80;
}
}
while((_getCycleCount() - startTime) < period); // Wait for last bit
}

#endif // ESP8266
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#define PIN 6

#define NUM_LEDS 60

#define BRIGHTNESS 50

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);

int gamma[] = {
0, 0, 0, 0, 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, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 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, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };


void setup() {
Serial.begin(115200);
// 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.setBrightness(BRIGHTNESS);
strip.begin();
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

whiteOverRainbow(20,75,5);

pulseWhite(5);

// fullWhite();
// delay(2000);

rainbowFade2White(3,3,1);


}

// 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 pulseWhite(uint8_t wait) {
for(int j = 0; j < 256 ; j++){
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
}
delay(wait);
strip.show();
}

for(int j = 255; j >= 0 ; j--){
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
}
delay(wait);
strip.show();
}
}


void rainbowFade2White(uint8_t wait, int rainbowLoops, int whiteLoops) {
float fadeMax = 100.0;
int fadeVal = 0;
uint32_t wheelVal;
int redVal, greenVal, blueVal;

for(int k = 0 ; k < rainbowLoops ; k ++){

for(int j=0; j<256; j++) { // 5 cycles of all colors on wheel

for(int i=0; i< strip.numPixels(); i++) {

wheelVal = Wheel(((i * 256 / strip.numPixels()) + j) & 255);

redVal = red(wheelVal) * float(fadeVal/fadeMax);
greenVal = green(wheelVal) * float(fadeVal/fadeMax);
blueVal = blue(wheelVal) * float(fadeVal/fadeMax);

strip.setPixelColor( i, strip.Color( redVal, greenVal, blueVal ) );

}

//First loop, fade in!
if(k == 0 && fadeVal < fadeMax-1) {
fadeVal++;
}

//Last loop, fade out!
else if(k == rainbowLoops - 1 && j > 255 - fadeMax ){
fadeVal--;
}

strip.show();
delay(wait);
}

}



delay(500);


for(int k = 0 ; k < whiteLoops ; k ++){

for(int j = 0; j < 256 ; j++){

for(uint16_t i=0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
}
strip.show();
}

delay(2000);
for(int j = 255; j >= 0 ; j--){

for(uint16_t i=0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
}
strip.show();
}
}

delay(500);


}

void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength ) {

if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;

int head = whiteLength - 1;
int tail = 0;

int loops = 3;
int loopNum = 0;

static unsigned long lastTime = 0;


while(true){
for(int j=0; j<256; j++) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
if((i >= tail && i <= head) || (tail > head && i >= tail) || (tail > head && i <= head) ){
strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
}
else{
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}

}

if(millis() - lastTime > whiteSpeed) {
head++;
tail++;
if(head == strip.numPixels()){
loopNum++;
}
lastTime = millis();
}

if(loopNum == loops) return;

head%=strip.numPixels();
tail%=strip.numPixels();
strip.show();
delay(wait);
}
}

}
void fullWhite() {

for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
}
strip.show();
}


// 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);
}
}

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);
}
}

// 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,0);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3,0);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0,0);
}

uint8_t red(uint32_t c) {
return (c >> 8);
}
uint8_t green(uint32_t c) {
return (c >> 16);
}
uint8_t blue(uint32_t c) {
return (c);
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// This is a demonstration on how to use an input device to trigger changes on your neo pixels.
// You should wire a momentary push button to connect from ground to a digital IO pin. When you
// press the button it will change to a new pixel animation. Note that you need to press the
// button once to start the first animation!

#include <Adafruit_NeoPixel.h>

#define BUTTON_PIN 2 // Digital IO pin connected to the button. This will be
// driven with a pull-up resistor so the switch should
// pull the pin to ground momentarily. On a high -> low
// transition the button press logic will execute.

#define PIXEL_PIN 6 // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 16

// Parameter 1 = number of pixels in strip, neopixel stick has 8
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_RGB Pixels are wired for RGB bitstream
// NEO_GRB Pixels are wired for GRB bitstream, correct for neopixel stick
// NEO_KHZ400 400 KHz bitstream (e.g. FLORA pixels)
// NEO_KHZ800 800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

bool oldState = HIGH;
int showType = 0;

void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}

void loop() {
// Get current button state.
bool 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) {
showType++;
if (showType > 9)
showType=0;
startShow(showType);
}
}

// Set the last button state to the old state.
oldState = newState;
}

void startShow(int i) {
switch(i){
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(20);
break;
case 8: rainbowCycle(20);
break;
case 9: theaterChaseRainbow(50);
break;
}
}

// 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 (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();

delay(wait);

for (int 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 (int 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 (int 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);
}
47 changes: 47 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/examples/simple/simple.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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>
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN 6

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 16

// When we setup 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 = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second

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

pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {

// For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.

for(int i=0;i<NUMPIXELS;i++){

// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.

pixels.show(); // This sends the updated pixel color to the hardware.

delay(delayval); // Delay for a period of time (in milliseconds).

}
}
134 changes: 134 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/examples/strandtest/strandtest.ino
Original file line number Diff line number Diff line change
@@ -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.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);
}
29 changes: 29 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#######################################
# Syntax Coloring Map For Adafruit_NeoPixel
#######################################
# Class
#######################################

Adafruit_NeoPixel KEYWORD1

#######################################
# Methods and Functions
#######################################

setPixelColor KEYWORD2
setPin KEYWORD2
setBrightness KEYWORD2
numPixels KEYWORD2
getPixelColor KEYWORD2
Color KEYWORD2

#######################################
# Constants
#######################################

NEO_GRB LITERAL1
NEO_COLMASK LITERAL1
NEO_KHZ800 LITERAL1
NEO_SPDMASK LITERAL1
NEO_RGB LITERAL1
NEO_KHZ400 LITERAL1
9 changes: 9 additions & 0 deletions Arduino/libraries/Adafruit_NeoPixel/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=Adafruit NeoPixel
version=1.0.6
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=*
1 change: 1 addition & 0 deletions Arduino/libraries/readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries
12 changes: 12 additions & 0 deletions Pathgen/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
plugins {
id 'java'
id 'application'
id "eclipse"
id "idea"
}

mainClassName = 'org.usfirst.frc.team449.pathgen.Pathgen'

dependencies {
compile fileTree(dir: "lib", include: "*.jar")
}
Binary file added Pathgen/lib/Pathfinder-Java.jar
Binary file not shown.
146 changes: 146 additions & 0 deletions Pathgen/src/main/R/drawMP.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
plotProfile <- function(profileName, inverted = FALSE, wheelbaseDiameter, centerToFront, centerToBack, centerToSide, startY = 0, startPos = c(-1,-1,-1,-1,-1), usePosition = TRUE){
left <- read.csv(paste("../../../../calciferLeft",profileName,"Profile.csv",sep=""), header=FALSE)
right <- read.csv(paste("../../../../calciferRight",profileName,"Profile.csv",sep=""), header=FALSE)
startingCenter <- c(startY, centerToBack)
left$V1[1] <- 0
left$V2[1] <- 0
left$V3[1] <- left$V3[2]
right$V1[1] <- 0
right$V2[1] <- 0
right$V3[1] <- right$V3[2]
#Position,Velocity,Delta t, Elapsed time
left$V4 <- (0:(length(left$V1)-1))*left$V3[1]
right$V4 <- (0:(length(right$V1)-1))*right$V3[1]
#Time, Left X, Left Y, Right X, Right Y
out <- array(dim=c(length(left$V1),5))
if(identical(startPos, c(-1,-1,-1,-1,-1))){
out[1,]<-c(0, startingCenter[2], (startingCenter[1]+wheelbaseDiameter/2.), startingCenter[2], (startingCenter[1]-wheelbaseDiameter/2.))
} else {
out[1,]<-startPos
}

for(i in 2:length(left$V4)){
theta <- angleBetween(leftX = out[i-1,2], leftY = out[i-1,3], rightX = out[i-1,4], rightY = out[i-1,5])

out[i,1] <- out[i-1,1]+left$V3[i]

if (usePosition){
deltaLeft <- left$V1[i] - left$V1[i-1]
deltaRight <- right$V1[i] - right$V1[i-1]
} else {
deltaLeft <- left$V2[i]*left$V3[i]
deltaRight <- right$V2[i]*left$V3[i]
}

if (inverted){
deltaLeft <- -deltaLeft
deltaRight <- -deltaRight
}

perpendicular <- theta - pi/2

if(inverted){
out[i, 2] <- out[i-1,2]+deltaRight*round(cos(perpendicular), digits = 3)
out[i, 3] <- out[i-1,3]+deltaRight*round(sin(perpendicular), digits = 3)
out[i, 4] <- out[i-1,4]+deltaLeft*round(cos(perpendicular), digits = 3)
out[i, 5] <- out[i-1,5]+deltaLeft*round(sin(perpendicular), digits = 3)
} else {
out[i, 2] <- out[i-1,2]+deltaLeft*round(cos(perpendicular), digits = 3)
out[i, 3] <- out[i-1,3]+deltaLeft*round(sin(perpendicular), digits = 3)
out[i, 4] <- out[i-1,4]+deltaRight*round(cos(perpendicular), digits = 3)
out[i, 5] <- out[i-1,5]+deltaRight*round(sin(perpendicular), digits = 3)
}
}
return(out)
}

drawProfile <- function (coords, centerToFront, centerToBack, wheelbaseDiameter, clear=TRUE, linePlot = TRUE){

if (clear){
if (linePlot){
plot(coords[,2],coords[,3], type="l", col="Green", ylim=c(-16, 16),xlim = c(0,54), asp=1)
} else {
plot(coords[,2],coords[,3], col="Green", ylim=c(-16, 16), xlim = c(0,54), asp=1)
}
field <- read.csv("field.csv")
#Strings are read as factors by default, so we need to do this to make it read them as strings
field$col <- as.character(field$col)
for (i in 1:length(field$x1)){
lines(c(field$x1[i], field$x2[i]), c(field$y1[i], field$y2[i]), col=field$col[i])
}
} else {
if (linePlot){
lines(coords[,2],coords[,3],col="Green")
} else {
points(coords[,2],coords[,3],col="Green")
}
}
if (linePlot){
lines(coords[,4],coords[,5],col="Red")
} else {
points(coords[,4],coords[,5],col="Red")
}
}

angleBetween <- function(leftX, leftY, rightX, rightY){
deltaX <- leftX-rightX
deltaY <- leftY-rightY
if (identical(deltaX, 0)){
ans <- pi/2
} else {
#Pretend it's first quadrant because we manually determine quadrants
ans <- atan(abs(deltaY/deltaX))
}
if (deltaY > 0){
if (deltaX > 0){
#If it's actually quadrant 1
return(ans)
}else {
#quadrant 2
return(pi - ans)
}
return(ans)
} else {
if (deltaX > 0){
#quadrant 4
return(-ans)
}else {
#quadrant 3
return(-(pi - ans))
}
}
}

drawRobot <- function(robotFile, robotPos){
theta <- angleBetween(leftX = robotPos[2], leftY = robotPos[3], rightX = robotPos[4], rightY = robotPos[5])
perp <- theta - pi/2
robotCenter <- c((robotPos[2]+robotPos[4])/2.,(robotPos[3]+robotPos[5])/2.)
robot <- read.csv(robotFile)
rotMatrix <- matrix(c(cos(perp), -sin(perp), sin(perp), cos(perp)), nrow=2, ncol=2, byrow=TRUE)

point1s <- rotMatrix %*% matrix(c(robot$x1, robot$y1), nrow = 2, ncol = length(robot$x1), byrow = TRUE)
point1s <- point1s + c(robotCenter[1], robotCenter[2])

point2s <- rotMatrix %*% matrix(c(robot$x2, robot$y2), nrow = 2, ncol = length(robot$x1), byrow = TRUE)
point2s <- point2s + c(robotCenter[1], robotCenter[2])

#Interleave the point1s and point2s so lines() draws them correctly.
xs <- c(rbind(point1s[1,], point2s[1,]))
ys <- c(rbind(point1s[2,], point2s[2,]))

lines(x=xs, y=ys, col="Blue")
}

wheelbaseDiameter <- 26./12.
centerToFront <- (27./2.)/12.
centerToBack <- (27./2.+3.25)/12.
centerToSide <- (29./2.+3.25)/12.
#out <- plotProfile(profileName = "Left", inverted = FALSE, wheelbaseDiameter = wheelbaseDiameter, centerToFront = centerToFront,centerToBack = centerToBack,centerToSide = centerToSide, startPos = c(0, 54-centerToBack, -(10.3449-centerToSide)-wheelbaseDiameter/2., 54-centerToBack, -(10.3449-centerToSide)+wheelbaseDiameter/2.))
out <- plotProfile(profileName = "Right", inverted = FALSE, wheelbaseDiameter = wheelbaseDiameter, centerToFront = centerToFront,centerToBack = centerToBack,centerToSide = centerToSide, startY= -10.3449+centerToSide, usePosition = TRUE)
#out <- plotProfile(profileName = "Mid", inverted = FALSE, wheelbaseDiameter = wheelbaseDiameter, centerToFront = centerToFront,centerToBack = centerToBack,centerToSide = centerToSide, startPos = c(0, 54-centerToBack, -wheelbaseDiameter/2., 54-centerToBack, wheelbaseDiameter/2.))
drawProfile(coords=out, centerToFront=centerToFront, centerToBack=centerToBack, wheelbaseDiameter = wheelbaseDiameter, clear = TRUE, linePlot = TRUE)
tmp <- out[length(out[,1]),]
drawRobot("robot.csv", tmp)
out2 <- plotProfile(profileName = "RedBackup",inverted = TRUE,wheelbaseDiameter = wheelbaseDiameter,centerToFront = centerToFront,centerToBack = centerToBack,centerToSide = centerToSide,startPos = tmp)
drawProfile(coords = out2, centerToFront = centerToFront, centerToBack = centerToBack, wheelbaseDiameter = wheelbaseDiameter, clear = FALSE)
drawRobot("robot.csv", out2[length(out2[,1]),])
84 changes: 84 additions & 0 deletions Pathgen/src/main/R/field.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
x1,y1,x2,y2,col
5.4648,-13.5,48.5352,-13.5,"Black"
48.5352,-13.5,54,-10.3449,"Black"
54,-10.3449,54,10.3449,"Black"
54,10.3449,50.8449,13.5,"Black"
50.8449,13.5,3.1551,13.5,"Black"
3.1551,13.5,0,10.3449,"Black"
0,10.3449,0,-10.3449,"Black"
0,-10.3449,5.4648,-13.5,"Black"

9.525,1.6667,9.525,-1.6667,"Blue"
9.2225,0.16667,9.525,0.16667,"Black"
9.2225,-0.16667,9.525,-0.16667,"Black"
9.2225,0.16667,9.2225,-0.16667,"Black"
9.2225,0,8.3475,0,"Purple"

9.525,1.6667,12.411,3.333,"Blue"
11.1123,2.5833,10.9611,2.8453,"Black"
10.823,2.4167,10.67175,2.6786,"Black"
10.67175,2.6786,10.9611,2.8453,"Black"
10.81675,2.7620,10.37925,3.5198,"Purple"

9.525,-1.6667,12.411,-3.333,"Blue"
11.1123,-2.5833,10.9611,-2.8453,"Black"
10.823,-2.4167,10.67175,-2.6786,"Black"
10.67175,-2.6786,10.9611,-2.8453,"Black"
10.81675,-2.7620,10.37925,-3.5198,"Purple"

12.411,3.333,15.298,1.6667,"Blue"
12.411,-3.333,15.298,-1.6667,"Blue"
15.298,1.6667,15.298,-1.6667,"Blue"

44.475,1.6667,44.475,-1.6667,"Red"
44.7775,0.16667,44.475,0.16667,"Black"
44.7775,-0.16667,44.475,-0.16667,"Black"
44.7775,0.16667,44.7775,-0.16667,"Black"
44.7775,0,45.6525,0,"Purple"

44.475,1.6667,41.589,3.333,"Red"
42.8877,2.5833,43.0389,2.8453,"Black"
43.177,2.4167,43.32825,2.6786,"Black"
43.32825,2.6786,43.0389,2.8453,"Black"
43.18325,2.7620,43.62075,3.5198,"Purple"

44.475,-1.6667,41.589,-3.333,"Red"
42.8877,-2.5833,43.0389,-2.8453,"Black"
43.177,-2.4167,43.32825,-2.6786,"Black"
43.32825,-2.6786,43.0389,-2.8453,"Black"
43.18325,-2.7620,43.62075,-3.5198,"Purple"

41.589,3.333,38.702,1.6667,"Red"
41.589,-3.333,38.702,-1.6667,"Red"
38.702,1.6667,38.702,-1.6667,"Red"

54,4.15,44.65,13.5,"Red"
54,-6.303448,41.5352,-13.5,"Blue"

0,4.15,9.35,13.5,"Blue"
0,-6.303448,12.4648,-13.5,"Red"

6.5417,13.5,13.9417,13.5,"Gray"
6.5417,15.9667,13.9417,15.9667,"Gray"
13.9417,13.5,13.9417,15.9667,"Gray"
6.5417,13.5,6.5417,15.9667,"Gray"

23.7333,13.5,31.1333,13.5,"Gray"
23.7333,15.9667,31.1333,15.9667,"Gray"
31.1333,13.5,31.1333,15.9667,"Gray"
23.7333,13.5,23.7333,15.9667,"Gray"

40.0583,13.5,47.4583,13.5,"Gray"
40.0583,15.9667,47.4583,15.9667,"Gray"
47.4583,13.5,47.4583,15.9667,"Gray"
40.0583,13.5,40.0583,15.9667,"Gray"

13.7917,-13.5,21.1917,-13.5,"Gray"
13.7917,-15.9667,21.1917,-15.9667,"Gray"
21.1917,-13.5,21.1917,-15.9667,"Gray"
13.7917,-13.5,13.7917,-15.9667,"Gray"

32.8083,-13.5,40.2083,-13.5,"Gray"
32.8083,-15.9667,40.2083,-15.9667,"Gray"
40.2083,-13.5,40.2083,-15.9667,"Gray"
32.8083,-13.5,32.8083,-15.9667,"Gray"
9 changes: 9 additions & 0 deletions Pathgen/src/main/R/robot.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
x1, y1, x2, y2
-1.395833, -1.479167, -1.395833, 1.479167
-1.395833, 1.479167, 1.395833, 1.479167
1.395833, 1.479167, 1.395833, 0.541667
1.395833, 0.541667, 1.125, 0.541667
1.125, 0.541667, 1.125, -0.541667
1.125, -0.541667, 1.395833, -0.541667
1.395833, -0.541667, 1.395833, -1.479167
1.395833, -1.479167, -1.395833, -1.479167
168 changes: 168 additions & 0 deletions Pathgen/src/main/java/org/usfirst/frc/team449/pathgen/Pathgen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package org.usfirst.frc.team449.pathgen;

import jaci.pathfinder.Pathfinder;
import jaci.pathfinder.Trajectory;
import jaci.pathfinder.Waypoint;
import jaci.pathfinder.modifiers.TankModifier;

import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
* Generates a motion profile that hits any number of waypoints.
*/
public class Pathgen {
public static void main(String[] args) throws IOException {

final double CENTER_TO_FRONT = 27./2.;
final double CENTER_TO_BACK = 27./2. + 3.25;
final double CENTER_TO_SIDE = 29./2. + 3.25;
final double BACK_FROM_PEG = 0;
//DO NOT TOUCH THE ONES BELOW
final double CARRIAGE_LEN = 3.63;
final double BLUE_WALL_TO_CENTER_PEG = 114.;
final double BLUE_WALL_TO_SIDE_PEG = 131.;
final double BLUE_BACK_CORNER_TO_SIDE_PEG = 94.139;
final double BLUE_HALF_KEY_LENGTH = 155./2.;
final double BLUE_KEY_CORNER_TO_SIDE_PEG = 23.;
final double RED_WALL_TO_CENTER_PEG = 114.5;
final double RED_WALL_TO_SIDE_PEG = 131.;
final double RED_BACK_CORNER_TO_SIDE_PEG = 95.;
final double RED_HALF_KEY_LENGTH = 154.5/2.;
final double RED_KEY_CORNER_TO_SIDE_PEG = 23.;
//final double AIRSHIP_PARALLEL_OFFSET = 6.-2.5;
final double AIRSHIP_PARALLEL_OFFSET = 6.;

final double PEG_BASE_TO_CENTER = CENTER_TO_FRONT + CARRIAGE_LEN + BACK_FROM_PEG;

Waypoint[] points = new Waypoint[]{ //Units are feet and radians.
new Waypoint(0, 0, 0),
new Waypoint(100. / 12., 0, 0)
};

Waypoint[] blueLeft = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((BLUE_WALL_TO_SIDE_PEG-CENTER_TO_BACK - 0.5*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.cos(5.*Math.PI/6.))/12.
,-(BLUE_BACK_CORNER_TO_SIDE_PEG - CENTER_TO_SIDE - (Math.sqrt(3.)/2.)*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.sin(5.*Math.PI/6.))/12.,-Math.PI/3.)
};

Waypoint[] blueRight = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((BLUE_WALL_TO_SIDE_PEG-CENTER_TO_BACK - 0.5*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.cos(5.*Math.PI/6.))/12.
,(BLUE_BACK_CORNER_TO_SIDE_PEG - CENTER_TO_SIDE - (Math.sqrt(3.)/2.)*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.sin(5.*Math.PI/6.))/12.,Math.PI/3.)
};

Waypoint[] blueCenter = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((BLUE_WALL_TO_CENTER_PEG - CENTER_TO_BACK - PEG_BASE_TO_CENTER)/12., 0, 0)
};

Waypoint[] redLeft = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((RED_WALL_TO_SIDE_PEG-CENTER_TO_BACK - 0.5*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.cos(5.*Math.PI/6.))/12.
,-(RED_BACK_CORNER_TO_SIDE_PEG - CENTER_TO_SIDE - (Math.sqrt(3.)/2.)*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.sin(5.*Math.PI/6.))/12.,-Math.PI/3.)
};

Waypoint[] redRight = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((RED_WALL_TO_SIDE_PEG-CENTER_TO_BACK - 0.5*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.cos(5.*Math.PI/6.))/12.
,(RED_BACK_CORNER_TO_SIDE_PEG - CENTER_TO_SIDE - (Math.sqrt(3.)/2.)*PEG_BASE_TO_CENTER + AIRSHIP_PARALLEL_OFFSET*Math.sin(5.*Math.PI/6.))/12.,Math.PI/3.)
};

Waypoint[] redCenter = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((RED_WALL_TO_CENTER_PEG - CENTER_TO_BACK - PEG_BASE_TO_CENTER)/12., 0, 0)
};

Waypoint[] redPegToKey = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((PEG_BASE_TO_CENTER*Math.cos(Math.toRadians(180)) + RED_WALL_TO_SIDE_PEG*Math.cos(Math.toRadians(-60)) + RED_KEY_CORNER_TO_SIDE_PEG*Math.cos(Math.toRadians(30))
+ RED_HALF_KEY_LENGTH*Math.cos(Math.toRadians(75)) + CENTER_TO_BACK*Math.cos(Math.toRadians(165)))/12.,
(RED_WALL_TO_SIDE_PEG*Math.sin(Math.toRadians(-60)) + RED_KEY_CORNER_TO_SIDE_PEG*Math.sin(Math.toRadians(30))
+ RED_HALF_KEY_LENGTH*Math.sin(Math.toRadians(75)) + CENTER_TO_BACK*Math.sin(Math.toRadians(165)))/12.,
-Math.toRadians(16))
};

Waypoint[] bluePegToKey = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint((PEG_BASE_TO_CENTER*Math.cos(Math.toRadians(180)) + BLUE_WALL_TO_SIDE_PEG*Math.cos(Math.toRadians(60)) + BLUE_KEY_CORNER_TO_SIDE_PEG*Math.cos(Math.toRadians(-30))
+ BLUE_HALF_KEY_LENGTH*Math.cos(Math.toRadians(-75)) + CENTER_TO_BACK*Math.cos(Math.toRadians(-165)))/12.,
(BLUE_WALL_TO_SIDE_PEG*Math.sin(Math.toRadians(60)) + BLUE_KEY_CORNER_TO_SIDE_PEG*Math.sin(Math.toRadians(-30))
+ BLUE_HALF_KEY_LENGTH*Math.sin(Math.toRadians(-75)) + CENTER_TO_BACK*Math.sin(Math.toRadians(-165)))/12.,
Math.toRadians(16))
};

Waypoint[] backupRed = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint(3, 1, Math.PI/3)
};

Waypoint[] backupBlue = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint(3, -1, -Math.PI/3)
};

Waypoint[] forward = new Waypoint[]{
new Waypoint(0, 0, 0),
new Waypoint(15, 0, 0)
};

Map<String, Waypoint[]> profiles = new HashMap<>();
profiles.put("RedLeft", redLeft);
profiles.put("RedRight", redRight);
profiles.put("RedMid", redCenter);
profiles.put("BlueLeft", blueLeft);
profiles.put("BlueRight", blueRight);
profiles.put("BlueMid", blueCenter);
profiles.put("RedShoot", redPegToKey);
profiles.put("BlueShoot", bluePegToKey);
profiles.put("RedBackup", backupRed);
profiles.put("BlueBackup", backupBlue);

final String ROBOT_NAME = "calcifer";

//Calculated by driving each wheel n inches in opposite directions, then taking the angle moved, θ, and finding
// the circumference of a circle moved by the robot via C = 360 * n / θ
//You then find the diameter via C / π.
double balbasaurWheelbase = 33.3 / 12.;
//200 in: 29.96
//50 in: 34.2

//433.415
double calciferWheelbase = 26./12.;

Trajectory.Config config = new Trajectory.Config(Trajectory.FitMethod.HERMITE_CUBIC, Trajectory.Config.SAMPLES_HIGH,
0.05, 5., 3, 6); //Units are seconds, feet/second, feet/(second^2), and feet/(second^3)

for (String profile : profiles.keySet()) {
Trajectory trajectory = Pathfinder.generate(profiles.get(profile), config);

TankModifier tm = new TankModifier(trajectory).modify(calciferWheelbase); //Units are feet

FileWriter lfw = new FileWriter(ROBOT_NAME + "Left" + profile + "Profile.csv", false);
FileWriter rfw = new FileWriter(ROBOT_NAME + "Right" + profile + "Profile.csv", false);


lfw.write(tm.getLeftTrajectory().length() + "\n");
for (int i = 0; i < tm.getLeftTrajectory().length(); i++) {
lfw.write(tm.getLeftTrajectory().get(i).position + ",\t" + tm.getLeftTrajectory().get(i).velocity + ",\t"
+ tm.getLeftTrajectory().get(i).dt + ",");
lfw.write("\n");
}

rfw.write(tm.getRightTrajectory().length() + "\n");
for (int i = 0; i < tm.getRightTrajectory().length(); i++) {
rfw.write(tm.getRightTrajectory().get(i).position + ",\t" + tm.getRightTrajectory().get(i).velocity + "," +
"\t" + tm.getRightTrajectory().get(i).dt + ",");
rfw.write("\n");
}

lfw.flush();
lfw.close();
rfw.flush();
rfw.close();
}
}
}
139 changes: 139 additions & 0 deletions RoboRIO/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
plugins {
id 'org.hidetake.ssh' version "2.9.0"
id "java"
id "eclipse"
id "idea"
id "jaci.openrio.gradle.GradleRIO" version "2017.1.5"
id "com.google.protobuf" version "0.8.1"
}

group 'org.usfirst.frc.team449.robot2017'
version '1.0'

repositories {
mavenCentral()
maven {
name = "GradleRio"
url = "http://dev.imjac.in/maven"
}

maven { url "https://plugins.gradle.org/m2/" }
}

dependencies {
compile 'com.google.protobuf:protobuf-java:3.0.0'
compile 'io.grpc:grpc-stub:1.0.0-pre2'
compile 'io.grpc:grpc-protobuf:1.0.0-pre2'
compile 'com.github.blair-robot-project:449-central-repo:v4.0.0-WPILib2017'
compile wpilib()
compile talonSrx()
compile fileTree(dir: "lib", include: "*.jar")
}



/* Protobuf stuff */

protobuf {
generatedFilesBaseDir = "$projectDir/gen"
protoc {
// The artifact spec for the Protobuf Compiler
artifact = 'com.google.protobuf:protoc:3.0.0'
}
plugins {
// Optional: an artifact spec for a protoc plugin, with "grpc" as
// the identifier, which can be referred to in the "plugins"
// container of the "generateProtoTasks" closure.
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2'
}
}
generateProtoTasks {
ofSourceSet('main')*.plugins {
// Apply the "grpc" plugin whose spec is defined above, without
// options. Note the braces cannot be omitted, otherwise the
// plugin will not be added. This is because of the implicit way
// NamedDomainObjectContainer binds the methods.
grpc {}
}
}
}

/* Utils */
clean {
delete protobuf.generatedFilesBaseDir
}

idea {
module {
sourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java")
}
}


task convertFiles {
doLast {
fileTree("src/main/resources").matching { include "*.txt" }.each { aFile ->
exec {
commandLine 'dos2unix'
args aFile.absolutePath
}
}
}
}

/* GradleRIO stuff */
remotes {
rio {
host = 'roboRIO-449-frc.local'
user = 'lvuser'
knownHosts = allowAnyHosts
}
}

frc {
team = '449'
robotClass = "org.usfirst.frc.team449.robot.Robot"
}

wpi {
wpilibVersion = "+"
// The WPILib version to use. For this version of GradleRIO, must be a 2017 version
ntcoreVersion = "+" // The NetworkTables Core version to use.
opencvVersion = "+" // The OpenCV version to use
cscoreVersion = "+" // The CSCore version to use

talonSrxVersion = "+" // The CTRE Toolsuite (Talon SRX) version to use.
}

def robotManifest = {
attributes 'Main-Class': 'edu.wpi.first.wpilibj.RobotBase'
attributes 'Robot-Class': frc.robotClass
}

task('copyResources', dependsOn: convertFiles) {
doLast {
ssh.run {
session(remotes.rio) {
execute 'mkdir ~/449_resources', ignoreError: true
execute 'mkdir ~/logs', ignoreError: true
put from: fileTree('src/main/resources'), into: './449_resources/'
}
}
}
}

/* Generic artifact gen stuff */
jar {
from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
manifest robotManifest
}

task genJavadoc(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}

artifacts {
archives genJavadoc
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
449 changes: 449 additions & 0 deletions RoboRIO/src/main/java/org/usfirst/frc/team449/robot/Robot.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.usfirst.frc.team449.robot.autonomous;

import edu.wpi.first.wpilibj.command.CommandGroup;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.TwoSideMPSubsystem.TwoSideMPSubsystem;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.TwoSideMPSubsystem.commands.RunProfileTwoSides;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.commands.RunLoadedProfile;
import org.usfirst.frc.team449.robot.interfaces.subsystem.Shooter.ShooterSubsystem;
import org.usfirst.frc.team449.robot.interfaces.subsystem.Shooter.commands.SpinUpShooter;
import org.usfirst.frc.team449.robot.interfaces.subsystem.Shooter.commands.TurnAllOn;
import org.usfirst.frc.team449.robot.interfaces.subsystem.solenoid.commands.SolenoidReverse;
import org.usfirst.frc.team449.robot.mechanism.activegear.ActiveGearSubsystem;
import org.usfirst.frc.team449.robot.util.MotionProfileData;

/**
* The autonomous routine to deliver a gear to the center gear.
*/
public class BoilerAuto2017 extends CommandGroup {

/**
* Default constructor.
*
* @param drive The drive subsystem to execute this command on. Must also be a {@link
* UnidirectionalDrive}, and
* needs to have the profile to drive up to the peg already loaded into it.
* @param gearHandler The gear handler to execute this command on.
* @param dropGear Whether or not to drop the gear.
* @param leftPegToKeyProfile The motion profile for the left side of the drive to execute to get from the peg to
* the key.
* @param rightPegToKeyProfile The motion profile for the right side of the drive to execute to get from the peg to
* the key.
* @param shooter The shooter subsystem to execute this command on.
*/
public BoilerAuto2017(TwoSideMPSubsystem drive, ActiveGearSubsystem gearHandler, boolean dropGear,
MotionProfileData leftPegToKeyProfile, MotionProfileData rightPegToKeyProfile,
ShooterSubsystem shooter) {
addParallel(new SpinUpShooter(shooter));
addSequential(new RunLoadedProfile(drive, 15, true));
if (dropGear) {
addSequential(new SolenoidReverse(gearHandler));
}
addSequential(new RunProfileTwoSides(drive, leftPegToKeyProfile, rightPegToKeyProfile, 10));
addSequential(new TurnAllOn(shooter));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.usfirst.frc.team449.robot.autonomous;

import edu.wpi.first.wpilibj.command.CommandGroup;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.commands.DriveAtSpeed;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.TwoSideMPSubsystem.TwoSideMPSubsystem;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.commands.RunLoadedProfile;
import org.usfirst.frc.team449.robot.interfaces.subsystem.solenoid.commands.SolenoidReverse;
import org.usfirst.frc.team449.robot.mechanism.activegear.ActiveGearSubsystem;

/**
* The autonomous routine to deliver a gear to the center gear.
*/
public class CenterAuto2017 extends CommandGroup {

/**
* Default constructor.
*
* @param drive The drive subsystem to execute this command on. Must also be a {@link UnidirectionalDrive},
* and
* needs to have the profile to drive up to the peg already loaded into it.
* @param gearHandler The gear handler to execute this command on.
* @param dropGear Whether or not to drop the gear.
* @param driveBackTime How long, in seconds, to drive back from the peg for.
*/
public CenterAuto2017(TwoSideMPSubsystem drive, ActiveGearSubsystem gearHandler, boolean dropGear, double driveBackTime) {
addSequential(new RunLoadedProfile(drive, 15, true));
if (dropGear) {
addSequential(new SolenoidReverse(gearHandler));
}
addSequential(new DriveAtSpeed((UnidirectionalDrive) drive, -0.3, driveBackTime));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.usfirst.frc.team449.robot.autonomous;

import edu.wpi.first.wpilibj.command.CommandGroup;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.TwoSideMPSubsystem.TwoSideMPSubsystem;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.TwoSideMPSubsystem.commands.RunProfileTwoSides;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.commands.RunLoadedProfile;
import org.usfirst.frc.team449.robot.interfaces.subsystem.MotionProfile.commands.RunProfile;
import org.usfirst.frc.team449.robot.interfaces.subsystem.solenoid.commands.SolenoidReverse;
import org.usfirst.frc.team449.robot.mechanism.activegear.ActiveGearSubsystem;
import org.usfirst.frc.team449.robot.util.MotionProfileData;

/**
* The autonomous routine to deliver a gear to the center gear.
*/
public class FeederAuto2017 extends CommandGroup {

/**
* Default constructor.
*
* @param drive The drive subsystem to execute this command on. Must also be a {@link
* UnidirectionalDrive}, and
* needs to have the profile to drive up to the peg already loaded into it.
* @param gearHandler The gear handler to execute this command on.
* @param dropGear Whether or not to drop the gear.
* @param leftBackupProfile The motion profile for the left side of the drive to execute to back up from the peg.
* @param rightBackupProfile The motion profile for the right side of the drive to execute to back up from the peg.
* @param forwardsProfile The motion profile for both sides to drive forwards after backing up from the peg.
*/
public FeederAuto2017(TwoSideMPSubsystem drive, ActiveGearSubsystem gearHandler, boolean dropGear,
MotionProfileData leftBackupProfile, MotionProfileData rightBackupProfile,
MotionProfileData forwardsProfile) {
addSequential(new RunLoadedProfile(drive, 15, true));
if (dropGear) {
addSequential(new SolenoidReverse(gearHandler));
}
addSequential(new RunProfileTwoSides(drive, leftBackupProfile, rightBackupProfile, 10));
addSequential(new RunProfile(drive, forwardsProfile, 5));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.usfirst.frc.team449.robot.components;

import edu.wpi.first.wpilibj.DigitalInput;
import maps.org.usfirst.frc.team449.robot.components.DigitalInputMap;

import java.util.ArrayList;
import java.util.List;

/**
* A series of roboRIO digital input pins.
*/
public class MappedDigitalInput {

/**
* The digitalInputs this class represents
*/
private List<DigitalInput> digitalInputs;

/**
* Construct a MappedDigitalInput.
*
* @param map the map to construct this from.
*/
public MappedDigitalInput(DigitalInputMap.DigitalInput map) {
digitalInputs = new ArrayList<>();
for (int portNum : map.getPortList()) {
DigitalInput tmp = new DigitalInput(portNum);
digitalInputs.add(tmp);
}
}

/**
* Get the status of each pin specified in the map, in the order they were specified.
*
* @return A list of booleans where 1 represents the input receiving a signal and 0 represents no signal.
*/
public List<Boolean> getStatus() {
List<Boolean> digitalValues = new ArrayList<>();
for (DigitalInput digitalInput : digitalInputs) {
digitalValues.add(!digitalInput.get());
}
return digitalValues;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.usfirst.frc.team449.robot.components;

import edu.wpi.first.wpilibj.DoubleSolenoid;
import maps.org.usfirst.frc.team449.robot.components.ModuleDoubleSolenoidMap;

/**
* A wrapper on the {@link DoubleSolenoid} that can be constructed from a map object.
*/
public class MappedDoubleSolenoid extends DoubleSolenoid {

/**
* Default constructor.
*
* @param map A map containing module number, forward port, and reverse port.
*/
public MappedDoubleSolenoid(ModuleDoubleSolenoidMap.ModuleDoubleSolenoid map) {
super(map.getModule(), map.getForward(), map.getReverse());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.usfirst.frc.team449.robot.components;

import edu.wpi.first.wpilibj.VictorSP;
import maps.org.usfirst.frc.team449.robot.components.MotorMap;

/**
* A wrapper for a VictorSP allowing it to be easily constructed from a map object.
*/
public class MappedVictor extends VictorSP {

/**
* Construct a {@link VictorSP} from a {@link MotorMap.Motor}.
*
* @param map a motor map specifying port and inversion.
*/
public MappedVictor(MotorMap.Motor map) {
super(map.getPort());
this.setInverted(map.getInverted());
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
package org.usfirst.frc.team449.robot.components;

import edu.wpi.first.wpilibj.AnalogInput;
import maps.org.usfirst.frc.team449.robot.components.AnalogPressureSensorMap;

/**
* Wrapper for an analog pressure sensor that returns a voltage linearly proportional to pressure.
* Wrapper for an {@link AnalogInput} pressure sensor that returns a voltage linearly proportional to pressure.
*/
public class PressureSensor extends Component {
public AnalogInput sensor;
/**
* The AnalogInput this is a wrapper on.
*/
private AnalogInput sensor;

public PressureSensor(maps.org.usfirst.frc.team449.robot.components.AnalogPressureSensorMap.AnalogPressureSensor
map) {
/**
* Default constructor
*
* @param map map of this object.
*/
public PressureSensor(AnalogPressureSensorMap.AnalogPressureSensor map) {
sensor = new AnalogInput(map.getPort());
sensor.setOversampleBits(map.getOversampleBits());
sensor.setAverageBits(map.getAverageBits());

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.usfirst.frc.team449.robot.drive.talonCluster.commands;

import edu.wpi.first.wpilibj.command.CommandGroup;
import maps.org.usfirst.frc.team449.robot.util.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;

/**
* Rotates the robot back and forth in order to dislodge any stuck balls.
*/
public class JiggleRobot extends CommandGroup {
/**
* Instantiate the CommandGroup
*
* @param subsystem The unidirectionalDrive to execute this command on.
*/
public JiggleRobot(UnidirectionalDrive subsystem, ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID turnPID) {
addSequential(new NavXRelativeTTA(turnPID, 10, subsystem, 3));
addSequential(new NavXRelativeTTA(turnPID, -10, subsystem, 3));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package org.usfirst.frc.team449.robot.drive.talonCluster.commands;

import edu.wpi.first.wpilibj.command.Subsystem;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import maps.org.usfirst.frc.team449.robot.util.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.oi.TankOI;
import org.usfirst.frc.team449.robot.interfaces.subsystem.NavX.NavxSubsystem;
import org.usfirst.frc.team449.robot.interfaces.subsystem.NavX.commands.PIDAngleCommand;
import org.usfirst.frc.team449.robot.util.Logger;

/**
* Drives straight using the NavX gyro to keep a constant alignment.
*/
public class NavXDriveStraight extends PIDAngleCommand {

/**
* The tank OI to get input from.
*/
private TankOI oi;

/**
* The drive subsystem to give output to.
*/
private UnidirectionalDrive drive;

/**
* Whether to use the left joystick to drive straight.
*/
private boolean useLeft;

/**
* Default constructor.
*
* @param map A map with the PID constants for controlling the angular PID loop.
* @param drive The unidirectional drive to execute this command on.
* @param oi The tank OI to take input from.
* @param useLeft Which joystick to use to get the forward component to drive straight. True for left, false for
* right.
*/
public NavXDriveStraight(ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map, UnidirectionalDrive drive,
TankOI oi, boolean useLeft) {
super(map, (NavxSubsystem) drive);
this.oi = oi;
this.drive = drive;
this.useLeft = useLeft;
//This is likely to need to interrupt the DefaultCommand and therefore should require its subsystem.
requires((Subsystem) drive);
}

/**
* Give output to the drive based on the out of the PID loop.
*
* @param output the value the PID loop calculated
*/
@Override
protected void usePIDOutput(double output) {
//Process the PID output with deadband, minimum output, etc.
output = processPIDOutput(output);

//Log processed output.
SmartDashboard.putNumber("NavXDriveStraight PID output", output);

//Set throttle to the specified stick.
double throttle;
if (useLeft) {
throttle = oi.getLeftThrottle();
} else {
throttle = oi.getRightThrottle();
}

//Set the output to the throttle velocity adjusted by the PID output.
drive.setOutput(throttle - output, throttle + output);
}

/**
* Set the setpoint of the angle PID.
*/
@Override
protected void initialize() {
this.getPIDController().setSetpoint(this.returnPIDInput());
this.getPIDController().enable();
}

/**
* Does nothing, the actual work is done in usePIDOutput.
*/
@Override
protected void execute() {
//nada.
}

/**
* Finishes instantaneously.
*
* @return true
*/
@Override
protected boolean isFinished() {
return false;
}

/**
* Log when this command ends
*/
@Override
protected void end() {
Logger.addEvent("NavXDriveStraight end", this.getClass());
this.getPIDController().disable();
}

/**
* Log when this command is interrupted.
*/
@Override
protected void interrupted() {
Logger.addEvent("NavXDriveStraight interrupted!", this.getClass());
this.getPIDController().disable();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.usfirst.frc.team449.robot.drive.talonCluster.commands;

import maps.org.usfirst.frc.team449.robot.util.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.Robot;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.subsystem.NavX.NavxSubsystem;
import org.usfirst.frc.team449.robot.util.Logger;

/**
* Turn a certain number of degrees from the current heading.
*/
public class NavXRelativeTTA extends NavXTurnToAngle {

/**
* Default constructor.
*
* @param map An turnPID map with PID values, an absolute tolerance, and minimum output.
* @param setpoint The setpoint, in degrees from 180 to -180.
* @param drive The drive subsystem to execute this command on.
* @param timeout How long this command is allowed to run for, in seconds. Needed because sometimes floating-point
* errors prevent termination.
*/
public NavXRelativeTTA(ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map, double setpoint, UnidirectionalDrive drive,
double timeout) {
super(map, setpoint, drive, timeout);
}

/**
* Set up the start time and setpoint.
*/
@Override
protected void initialize() {
//Setup start time
this.startTime = Robot.currentTimeMillis();
Logger.addEvent("NavXRelativeTurnToAngle init.", this.getClass());
//Do math to setup the setpoint.
this.setSetpoint(clipTo180(((NavxSubsystem) drive).getGyroOutput() + setpoint));
//Make sure to enable the controller!
this.getPIDController().enable();
}

/**
* Log when the command ends.
*/
@Override
protected void end() {
Logger.addEvent("NavXRelativeTurnToAngle end.", this.getClass());
//Stop the controller
this.getPIDController().disable();
}

/**
* Log when the command is interrupted.
*/
@Override
protected void interrupted() {
Logger.addEvent("NavXRelativeTurnToAngle interrupted!", this.getClass());
//Stop the controller
this.getPIDController().disable();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package org.usfirst.frc.team449.robot.drive.talonCluster.commands;

import edu.wpi.first.wpilibj.command.Subsystem;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import maps.org.usfirst.frc.team449.robot.components.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.components.PIDAngleCommand;
import org.usfirst.frc.team449.robot.drive.talonCluster.TalonClusterDrive;
import maps.org.usfirst.frc.team449.robot.util.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.Robot;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.subsystem.NavX.NavxSubsystem;
import org.usfirst.frc.team449.robot.interfaces.subsystem.NavX.commands.PIDAngleCommand;
import org.usfirst.frc.team449.robot.util.Logger;

/**
* Turns to a specified angle, relative to the angle the NavX was at when the robot was turned on.
@@ -13,75 +17,70 @@ public class NavXTurnToAngle extends PIDAngleCommand {
/**
* The drive subsystem to execute this command on and to get the gyro reading from.
*/
protected TalonClusterDrive drive;
protected UnidirectionalDrive drive;

/**
* The angle to turn to.
*/
protected double setpoint;

/**
* How long this command is allowed to run for (in milliseconds)
* The time this command was initiated
*/
protected long timeout;
protected long startTime;

/**
* The time this command was initiated
* How long this command is allowed to run for (in milliseconds)
*/
protected long startTime;
private long timeout;

/**
* Default constructor.
*
* @param map An turnPID map with PID values, an absolute tolerance, and minimum output.
* @param setpoint The setpoint, in degrees from 180 to -180.
* @param drive The drive subsystem to execute this command on.
* @param timeout How long this command is allowed to run for, in seconds. Needed because sometimes floating-point errors prevent termination.
* @param map A map with PID values, an absolute tolerance, and minimum output.
* @param setpoint The setpoint, in degrees from 180 to -180.
* @param drive The drive subsystem to execute this command on. Must also be a NavX subsystem.
* @param timeout How long this command is allowed to run for, in seconds. Needed because sometimes floating-point
* errors prevent termination.
*/
public NavXTurnToAngle(ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map, double setpoint, TalonClusterDrive drive,
public NavXTurnToAngle(ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map, double setpoint, UnidirectionalDrive drive,
double timeout) {
super(map, drive);
super(map, (NavxSubsystem) drive);
this.drive = drive;
this.setpoint = setpoint;
//Convert from seconds to milliseconds
this.timeout = (long) (timeout * 1000);
requires(drive);
requires((Subsystem) drive);
}

/**
* Clip a degree number to the NavX's -180 to 180 system.
*
* @param theta The angle to clip, in degrees.
* @return The equivalent of that number, clipped to be between -180 and 180.
*/
public static double clipTo180(double theta) {
protected static double clipTo180(double theta) {
return (theta + 180) % 360 - 180;
}

/**
* Give output to the motors based on the output of the PID loop
*
* @param output The output of the angle PID loop
*/
@Override
protected void usePIDOutput(double output) {
//Logging
SmartDashboard.putNumber("Preprocessed output", output);
SmartDashboard.putNumber("NavX Turn To Angle Setpoint", this.getSetpoint());
if (minimumOutputEnabled) {
//Set the output to the minimum if it's too small.
if (output > 0 && output < minimumOutput)
output = minimumOutput;
else if (output < 0 && output > -minimumOutput)
output = -minimumOutput;
}
//If we're within deadband degrees of the setpoint, we stop moving to avoid "dancing" around the setpoint.
if (Math.abs(this.getPIDController().getError()) < deadband) {
output = 0;
}
SmartDashboard.putNumber("NavX Turn To Angle Setpoint", getSetpoint());

//Process the output with deadband, minimum output, etc.
output = processPIDOutput(output);

//More logging
SmartDashboard.putNumber("Processed output", output);
SmartDashboard.putNumber("NavXTurnToAngle PID loop output", output);

//Which one of these is negative may be different from robot to robot, we don't know.
drive.setDefaultThrottle(output, -output); //spin to the right angle
drive.setOutput(-output, output); //spin to the right angle
}

/**
@@ -90,38 +89,38 @@ else if (output < 0 && output > -minimumOutput)
@Override
protected void initialize() {
//Set up start time
this.startTime = System.currentTimeMillis();
this.startTime = Robot.currentTimeMillis();
this.setSetpoint(setpoint);
//Make sure to enable the controller!
this.getPIDController().enable();
}

/**
* Log data to a file and SmartDashboard.
* Log data to SmartDashboard.
*/
@Override
protected void execute() {
drive.logData();
SmartDashboard.putBoolean("onTarget", this.getPIDController().onTarget());
SmartDashboard.putNumber("Avg Navx Error", this.getPIDController().getAvgError());
}

/**
* Exit when the robot reaches the setpoint or enough time has passed.
*
* @return True if timeout seconds have passed or the robot is on target, false otherwise.
*/
@Override
protected boolean isFinished() {
//The NavX onTarget() is crap and sometimes never terminates because of floating point errors, so we have a timeout
return this.getPIDController().onTarget() || System.currentTimeMillis() - startTime > timeout;
//The PIDController onTarget() is crap and sometimes never terminates because of floating point errors, so we need a timeout
return this.getPIDController().onTarget() || Robot.currentTimeMillis() - startTime > timeout;
}

/**
* Log when the command ends.
*/
@Override
protected void end() {
System.out.println("NavXTurnToAngle end.");
Logger.addEvent("NavXTurnToAngle end.", this.getClass());
this.getPIDController().disable();
}

@@ -130,7 +129,7 @@ protected void end() {
*/
@Override
protected void interrupted() {
System.out.println("NavXTurnToAngle interrupted!");
Logger.addEvent("NavXTurnToAngle interrupted!", this.getClass());
this.getPIDController().disable();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.usfirst.frc.team449.robot.drive.talonCluster.commands;

import maps.org.usfirst.frc.team449.robot.util.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.interfaces.drive.shifting.ShiftingDrive;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.oi.ArcadeOI;

/**
* Drive with arcade drive setup, autoshift, and when the driver isn't turning, use a NavX to stabilize the robot's
* alignment.
*/
public class ShiftingUnidirectionalNavXArcadeDrive extends UnidirectionalNavXArcadeDrive {
/**
* Default constructor
*
* @param map The angle PID map containing PID and other tuning constants.
* @param drive The drive to execute this command on. Must also be a NavXSubsystem and a ShiftingDrive.
* @param oi The OI controlling the robot.
*/
public ShiftingUnidirectionalNavXArcadeDrive(ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map, UnidirectionalDrive drive, ArcadeOI oi) {
super(map, drive, oi);
}

/**
* Autoshift, decide whether or not we should be in free drive or straight drive, and log data.
*/
@Override
public void execute() {
//Auto-shifting
((ShiftingDrive) driveSubsystem).autoshift();
super.execute();
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package org.usfirst.frc.team449.robot.drive.talonCluster.commands;

import edu.wpi.first.wpilibj.command.Subsystem;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import maps.org.usfirst.frc.team449.robot.components.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.components.PIDAngleCommand;
import org.usfirst.frc.team449.robot.drive.talonCluster.TalonClusterDrive;
import org.usfirst.frc.team449.robot.drive.talonCluster.commands.ois.ArcadeOI;
import maps.org.usfirst.frc.team449.robot.util.ToleranceBufferAnglePIDMap;
import org.usfirst.frc.team449.robot.interfaces.drive.unidirectional.UnidirectionalDrive;
import org.usfirst.frc.team449.robot.interfaces.oi.ArcadeOI;
import org.usfirst.frc.team449.robot.interfaces.subsystem.NavX.NavxSubsystem;
import org.usfirst.frc.team449.robot.interfaces.subsystem.NavX.commands.PIDAngleCommand;
import org.usfirst.frc.team449.robot.util.BufferTimer;
import org.usfirst.frc.team449.robot.util.Logger;

/**
* Drive with arcade drive setup, and when the driver isn't turning, use a NavX to stabilize the robot's alignment.
*/
public class DefaultArcadeDrive extends PIDAngleCommand {
public class UnidirectionalNavXArcadeDrive extends PIDAngleCommand {
/**
* The UnidirectionalDrive this command is controlling.
*/
protected UnidirectionalDrive driveSubsystem;

/**
* The OI giving the vel and turn stick values.
*/
public ArcadeOI oi;
private ArcadeOI oi;

/**
* Whether or not we should be using the NavX to drive straight stably.
@@ -30,51 +39,38 @@ public class DefaultArcadeDrive extends PIDAngleCommand {
*/
private double rot;

/**
* The talonClusterDrive this command is controlling.
*/
private TalonClusterDrive driveSubsystem;

/**
* The maximum velocity for the robot to be at in order to switch to driveStraight, in degrees/sec
*/
private double maxAngularVel;

private long driveStraightDelay;

private long timeAbleToDriveStraight;

private boolean delayedDriveStraight;

/**
* The map of values
* A bufferTimer so we only switch to driving straight when the conditions are met for a certain period of time.
*/
ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map;
private BufferTimer driveStraightTimer;

/**
* Default constructor
* @param map The angle PID map containing PID and other tuning constants.
* @param drive The drive to execute this command on.
* @param oi The OI controlling the robot.
*
* @param map The angle PID map containing PID and other tuning constants.
* @param drive The drive to execute this command on. Must also be a NavXSubsystem.
* @param oi The OI controlling the robot.
*/
public DefaultArcadeDrive(ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map, TalonClusterDrive drive,
ArcadeOI oi) {
public UnidirectionalNavXArcadeDrive(ToleranceBufferAnglePIDMap.ToleranceBufferAnglePID map, UnidirectionalDrive drive,
ArcadeOI oi) {
//Assign stuff
super(map, drive);
super(map, (NavxSubsystem) drive);
maxAngularVel = map.getMaxAngularVel();
this.oi = oi;
this.map = map;
driveSubsystem = drive;

timeAbleToDriveStraight = 0;
driveStraightDelay = (long) (map.getDriveStraightDelay() * 1000);
delayedDriveStraight = false;
driveStraightTimer = new BufferTimer(map.getDriveStraightDelay());

//Needs a requires because it's a default command.
requires(drive);
requires((Subsystem) drive);

//Logging, but in Spanish.
System.out.println("Drive Robot bueno");
Logger.addEvent("Drive Robot bueno", this.getClass());
}

/**
@@ -85,63 +81,50 @@ protected void initialize() {
//Reset all values of the PIDController and enable it.
this.getPIDController().reset();
this.getPIDController().enable();
System.out.println("DefaultArcadeDrive init.");
Logger.addEvent("UnidirectionalNavXArcadeDrive init.", this.getClass());

//Initial assignment
drivingStraight = false;
vel = oi.getFwd();
rot = oi.getRot();

//starting from rest, we want to be in low gear so we can accelerate
driveSubsystem.setLowGear(true);
}

/**
* Decide whether or not we should be in free drive or straight drive, and log data.
*/
@Override
protected void execute() {
//Auto-shifting
driveSubsystem.autoShift();

//Set vel and rot to what they should be.
vel = oi.getFwd();
rot = oi.getRot();

//If we're driving straight but the driver tries to turn or overrides the NavX:
if (drivingStraight && (rot != 0 || driveSubsystem.overrideNavX)) {
if (drivingStraight && (rot != 0 || ((NavxSubsystem) driveSubsystem).getOverrideNavX())) {
//Switch to free drive
drivingStraight = false;
delayedDriveStraight = false;
//System.out.println("Switching to free drive.");
Logger.addEvent("Switching to free drive.", this.getClass());
}
//If we're free driving and the driver lets go of the turn stick:
else if (!(driveSubsystem.overrideNavX) && !(delayedDriveStraight) && !(drivingStraight) && rot == 0 && Math.abs(driveSubsystem.navx.getRate()) <= maxAngularVel) {
delayedDriveStraight = true;
timeAbleToDriveStraight = System.currentTimeMillis();
}

if(delayedDriveStraight && System.currentTimeMillis() - timeAbleToDriveStraight >= driveStraightDelay){
else if (driveStraightTimer.get(!(((NavxSubsystem) driveSubsystem).getOverrideNavX()) && !(drivingStraight) && rot == 0 && Math.abs(((NavxSubsystem) driveSubsystem).getNavX().getRate()) <= maxAngularVel)) {
//Switch to driving straight
drivingStraight = true;
delayedDriveStraight = false;
//Set the setpoint to the current heading and reset the NavX
this.getPIDController().reset();
this.getPIDController().setSetpoint(subsystem.getGyroOutput());
this.getPIDController().enable();
//System.out.println("Switching to DriveStraight.");
Logger.addEvent("Switching to DriveStraight.", this.getClass());
}

//Log data and stuff
driveSubsystem.logData();
SmartDashboard.putBoolean("driving straight?", drivingStraight);
SmartDashboard.putBoolean("Override Navx", driveSubsystem.overrideNavX);
SmartDashboard.putBoolean("Override Navx", ((NavxSubsystem) driveSubsystem).getOverrideNavX());
SmartDashboard.putNumber("Vel Axis", vel);
SmartDashboard.putNumber("Rot axis", rot);
}

/**
* Run constantly because this is a defaultDrive
*
* @return false
*/
@Override
@@ -154,54 +137,40 @@ protected boolean isFinished() {
*/
@Override
protected void end() {
System.out.println("DefaultArcadeDrive End.");
Logger.addEvent("UnidirectionalNavXArcadeDrive End.", this.getClass());
}

/**
* Stop the motors and log when this command is interrupted.
*/
@Override
protected void interrupted() {
System.out.println("DefaultArcadeDrive Interrupted! Stopping the robot.");
driveSubsystem.setDefaultThrottle(0.0, 0.0);
Logger.addEvent("UnidirectionalNavXArcadeDrive Interrupted! Stopping the robot.", this.getClass());
driveSubsystem.setOutput(0.0, 0.0);
}

/**
* Give the correct output to the motors based on whether we're in free drive or drive straight.
*
* @param output The output of the angular PID loop.
*/
@Override
protected void usePIDOutput(double output) {
//If we're driving straight..
if (drivingStraight) {
//If we're using minimumOutput..
if (minimumOutputEnabled) {
//Set the output to the minimum if it's too small.
if (output > 0 && output < minimumOutput) {
output = minimumOutput;
} else if (output < 0 && output > -minimumOutput) {
output = -minimumOutput;
}
}
//Set the output to 0 if we're within the deadband. Whether or not the deadband is enabled is dealt with
// in PIDAngleCommand.
if (Math.abs(this.getPIDController().getError()) < deadband) {
output = 0;
}
//Process the output (minimumOutput, deadband, etc.)
output = processPIDOutput(output);

//Log stuff
SmartDashboard.putNumber("PID output", output);

//Adjust the heading according to the PID output, it'll be positive if we want to go right.
if (!map.getInverted()) {
driveSubsystem.setDefaultThrottle(vel - output, vel + output);
} else {
driveSubsystem.setDefaultThrottle(vel + output, vel - output);
}
driveSubsystem.setOutput(vel - output, vel + output);
}
//If we're free driving...
else {
//Set the throttle to normal arcade throttle.
driveSubsystem.setDefaultThrottle(vel - rot, vel + rot);
driveSubsystem.setOutput(oi.getLeftOutput(), oi.getRightOutput());
}
}
}
Loading

0 comments on commit c0a0008

Please sign in to comment.