- August 22nd, 2017, 9:33 am#4897282
Oh oh! And if you get a chance, I would be ever so honored if you would show me the wiring you have from your nano to your sound board and to your audio amplifier!
// for the sound board
#include <SoftwareSerial.h>
#include "Adafruit_Soundboard.h"
#include <Wire.h> // Include the I2C library (required)
#include <SparkFunSX1509.h> // Include SX1509 library
#include <Adafruit_NeoPixel.h>
// for led triggers
#define HIGH 0x1
#define LOW 0x0
// neopixel pins
#define NEO_NOSE 9 // for nose of wand
Adafruit_NeoPixel noseJewel = Adafruit_NeoPixel(7, NEO_NOSE, NEO_GRB + NEO_KHZ800);
#define NEO_POWER 10 // for cyclotron and powercell
Adafruit_NeoPixel powerStick = Adafruit_NeoPixel(16, NEO_POWER, NEO_GRB + NEO_KHZ800);
bool powerBooted = false; // has the pack booted up
// soundboard
#define SFX_RST 2
#define SFX_RX 3
#define SFX_TX 4
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
Adafruit_Soundboard sfx = Adafruit_Soundboard( & ss, NULL, SFX_RST);
const int ACT = 13;
// inputs
const int THEME_SWITCH = 5;
const int STARTUP_SWITCH = 6;
const int SAFETY_SWITCH = 7;
const int FIRE_BUTTON = 8;
// switch states
bool theme = false;
bool startup = false;
bool safety = false;
bool fire = false;
bool warning = false;
// audio track locations on soundboard
const int startupTrack = 0;
const int blastTrack = 1;
const int endTrack = 2;
const int idleTrack = 3;
const int shutdownTrack = 4;
const int clickTrack = 5;
const int warnTrack = 6;
const int texTrack = 7;
const int choreTrack = 8;
const int toolsTrack = 9;
const int themeTrack = 10;
// dialog trigger times/states
unsigned long startDialogMillis;
const int numDialog = 3;
int currentDialog = 1;
const int dialogWaitTime = 5000;
const int warnWaitTime = 10000;
// SX1509 I2C address (set by ADDR1 and ADDR0 (00 by default):
const byte SX1509_ADDRESS = 0x3E; // SX1509 I2C address
SX1509 io; // Create an SX1509 object to be used throughout
int seq_1_current = 0; // current led in sequence 1
const int num_led = 15; // total number of leds in bar graph
// SX1509 pin definitions:
const byte SX1509_BAR_01 = 0;
const byte SX1509_BAR_02 = 1;
const byte SX1509_BAR_03 = 2;
const byte SX1509_BAR_04 = 3;
const byte SX1509_BAR_05 = 4;
const byte SX1509_BAR_06 = 5;
const byte SX1509_BAR_07 = 6;
const byte SX1509_BAR_08 = 7;
const byte SX1509_BAR_09 = 8;
const byte SX1509_BAR_10 = 9;
const byte SX1509_BAR_11 = 10;
const byte SX1509_BAR_12 = 11;
const byte SX1509_BAR_13 = 12;
const byte SX1509_BAR_14 = 13;
const byte SX1509_BAR_15 = 14;
void setup() {
// softwareserial at 9600 baud
ss.begin(9600);
// see if we have the soundboard
// if not we gotta flash lights or something
if (!sfx.reset()) {
while (1);
}
// set pin modes for the board
pinMode(ACT, INPUT);
// Call io.begin(<address>) to initialize the SX1509. If it
// successfully communicates, it'll return 1.
if (!io.begin(SX1509_ADDRESS)){
while (1) ; // If we fail to communicate, loop forever for now but lets warn the user somehow
}
// configure nose jewel
noseJewel.begin();
noseJewel.show(); // Initialize all pixels to 'off'
// configure powercell/cyclotron
powerStick.begin();
powerStick.setBrightness(10);
powerStick.show(); // Initialize all pixels to 'off'
// handle the switches
pinMode(THEME_SWITCH, INPUT);
digitalWrite(THEME_SWITCH, HIGH);
pinMode(STARTUP_SWITCH, INPUT);
digitalWrite(STARTUP_SWITCH, HIGH);
pinMode(SAFETY_SWITCH, INPUT);
digitalWrite(SAFETY_SWITCH, HIGH);
pinMode(FIRE_BUTTON, INPUT);
digitalWrite(FIRE_BUTTON, HIGH);
// configuration for the bargraph
io.pinMode(SX1509_BAR_01, OUTPUT);
io.pinMode(SX1509_BAR_02, OUTPUT);
io.pinMode(SX1509_BAR_03, OUTPUT);
io.pinMode(SX1509_BAR_04, OUTPUT);
io.pinMode(SX1509_BAR_05, OUTPUT);
io.pinMode(SX1509_BAR_06, OUTPUT);
io.pinMode(SX1509_BAR_07, OUTPUT);
io.pinMode(SX1509_BAR_08, OUTPUT);
io.pinMode(SX1509_BAR_09, OUTPUT);
io.pinMode(SX1509_BAR_10, OUTPUT);
io.pinMode(SX1509_BAR_11, OUTPUT);
io.pinMode(SX1509_BAR_12, OUTPUT);
io.pinMode(SX1509_BAR_13, OUTPUT);
io.pinMode(SX1509_BAR_14, OUTPUT);
io.pinMode(SX1509_BAR_15, OUTPUT);
shutdown_leds();
}
bool isFiring = false;
void playTrack(int num) {
// stop track if one is going
int playing = digitalRead(ACT);
if (playing == 0) {
sfx.stop();
}
// now go play
if (sfx.playTrack(num)) {
sfx.unpause();
}
}
void stopTrack() {
sfx.stop();
}
void resetSoundboard() {
sfx.reset();
}
int pwr_interval = 60; // interval at which to cycle lights for the powercell. We update this in the loop so must be declared here
void loop() {
int currentMillis = millis();
int theme_switch = digitalRead(THEME_SWITCH);
int playing = digitalRead(ACT);
if (theme_switch == 1) {
if (theme == false) {
playTrack(themeTrack); // send message to other board to play track
theme = true;
}
} else {
theme = false;
}
int startup_switch = digitalRead(STARTUP_SWITCH);
int safety_switch = digitalRead(SAFETY_SWITCH);
int fire_button = digitalRead(FIRE_BUTTON);
if (startup_switch == 1) {
if (playing == 1) {
playTrack(idleTrack); // send message to other board to play track
}
if( powerBooted == true ){
powerSequenceOne(currentMillis, pwr_interval);
}else{
powerSequenceBoot(currentMillis);
}
if (startup == false) {
startup = true;
playTrack(startupTrack); // send message to other board to play track
if (safety_switch == 1 && safety == false) {
safety = true;
}
}
if( safety_switch == 1 && fire_button == 0){
if( isFiring == false ){
shutdown_leds();
isFiring = true;
}
barGraphSequenceTwo(currentMillis);
}else{
if( isFiring == true ){
shutdown_leds();
isFiring = false;
}
barGraphSequenceOne(currentMillis);
}
// fire loop
if (startup == true && safety_switch == 1) {
if (safety == false) {
safety = true;
playTrack(clickTrack); // send message to other board to play track
}
if (fire_button == 0) {
fireStrobe();
if (fire == false) {
fire = true;
startDialogMillis = millis();
playTrack(blastTrack); // send message to other board to play track
} else {
if (playing == 1) {
playTrack(blastTrack); // send message to other board to play track
}
long diff = millis() - startDialogMillis;
if( diff > warnWaitTime){
pwr_interval = 20;
}else if( diff > dialogWaitTime){
pwr_interval = 40;
}
}
} else {
if (fire == true) {
clearFireStrobe();
pwr_interval = 60;
fire = false;
// see if we've been firing long enough to get the dialog
long diff = millis() - startDialogMillis;
if( diff > warnWaitTime){
playTrack(warnTrack); // send message to other board to play track
clearPowerStrip();
}else if( diff > dialogWaitTime){
switch(currentDialog){
case(1):
playTrack(choreTrack); // send message to other board to play track
break;
case(2):
playTrack(toolsTrack); // send message to other board to play track
break;
case(3):
playTrack(texTrack); // send message to other board to play track
break;
}
if( currentDialog >= numDialog ){
currentDialog = 1;
}else{
currentDialog++;
}
}else{
playTrack(endTrack); // send message to other board to play track
}
}
}
} else {
if (safety == true) {
safety = false;
playTrack(clickTrack); // send message to other board to play track
}
}
} else {
clearPowerStrip();
shutdown_leds();
if (startup == true) {
startup = false;
safety = false;
fire = false;
playTrack(shutdownTrack); // send message to other board to play track
}
}
delay(1);
}
/*************** Powercell Animations *********************/
unsigned long prevPwrBootMillis = 0;
const long pwr_boot_interval = 300; // interval at which to cycle lights (milliseconds).
unsigned long prevPwrMillis = 0;
int powerSeqTotal = 16; // total number of led's for power
int powerBootSeqNum = 16;
int powerSeqNum = 0;
void clearPowerStrip(){
powerBooted = false;
for( int i=0; i< powerSeqTotal; i++) {
powerStick.setPixelColor(i, 0);
}
powerStick.show();
powerSeqNum = 0;
powerBootSeqNum = 16;
}
void powerSequenceBoot(int currentMillis){
// normal sync animation on the bar graph
if (currentMillis - prevPwrBootMillis > pwr_boot_interval) {
// save the last time you blinked the LED
prevPwrBootMillis = currentMillis;
for( int i = powerSeqTotal; i > 0; i--) {
if( i <= powerBootSeqNum ){
powerStick.setPixelColor(i, powerStick.Color(0,0,150));
}else{
powerStick.setPixelColor(i, 0);
}
}
powerStick.show();
if( powerBootSeqNum > 0){
powerBootSeqNum--;
}else{
powerBooted = true;
powerBootSeqNum = 16;
}
}
}
void powerSequenceOne(int currentMillis, int anispeed){
powerBootSeqNum = 16;
// normal sync animation on the bar graph
if (currentMillis - prevPwrMillis > anispeed) {
// save the last time you blinked the LED
prevPwrMillis = currentMillis;
for( int i=0; i< powerSeqTotal; i++) {
if( i <= powerSeqNum ){
powerStick.setPixelColor(i, powerStick.Color(0,0,150));
}else{
powerStick.setPixelColor(i, 0);
}
}
powerStick.show();
if( powerSeqNum < powerSeqTotal){
powerSeqNum++;
}else{
powerSeqNum = 0;
}
}
}
/*************** Firing Animations *********************/
unsigned long prevFireMillis = 0;
const long fire_interval = 2; // interval at which to cycle lights (milliseconds).
int fireSeqNum = 0;
int fireSeqTotal = 3;
void clearFireStrobe(){
for( int i=0; i< 7; i++) {
noseJewel.setPixelColor(i, 0);
}
noseJewel.show();
fireSeqNum = 0;
}
void fireStrobe(){
switch( fireSeqNum ){
case 0:
noseJewel.setPixelColor(0, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(1, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(2, 0);
noseJewel.setPixelColor(3, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(4, 0);
noseJewel.setPixelColor(5, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(6, 0);
break;
case 1:
noseJewel.setPixelColor(0, noseJewel.Color(0,0,255));
noseJewel.setPixelColor(1, noseJewel.Color(255,0,0));
noseJewel.setPixelColor(2, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(3, noseJewel.Color(255,0,0));
noseJewel.setPixelColor(4, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(5, noseJewel.Color(255,0,0));
noseJewel.setPixelColor(6, noseJewel.Color(255,255,255));
break;
case 2:
noseJewel.setPixelColor(0, noseJewel.Color(255,0,0));
noseJewel.setPixelColor(1, 0);
noseJewel.setPixelColor(2, noseJewel.Color(0,0,255));
noseJewel.setPixelColor(3, 0);
noseJewel.setPixelColor(4, noseJewel.Color(0,0,255));
noseJewel.setPixelColor(5, 0);
noseJewel.setPixelColor(6, noseJewel.Color(0,0,255));
break;
case 3:
noseJewel.setPixelColor(0, noseJewel.Color(0,0,255));
noseJewel.setPixelColor(1, noseJewel.Color(255,0,0));
noseJewel.setPixelColor(2, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(3, noseJewel.Color(255,0,0));
noseJewel.setPixelColor(4, noseJewel.Color(255,255,255));
noseJewel.setPixelColor(5, noseJewel.Color(255,0,0));
noseJewel.setPixelColor(6, noseJewel.Color(255,255,255));
break;
}
noseJewel.show();
fireSeqNum++;
if( fireSeqNum > fireSeqTotal ){
fireSeqNum = 0;
}
}
/*************** Bar Graph Animations *********************/
unsigned long prevBarMillis_on = 0; // bargraph on tracker
const long pwrcl_interval = 60; // interval at which to cycle lights (milliseconds).
bool reverseSequenceOne = false;
void barGraphSequenceOne(int currentMillis){
// normal sync animation on the bar graph
if (currentMillis - prevBarMillis_on > pwrcl_interval) {
// save the last time you blinked the LED
prevBarMillis_on = currentMillis;
if( reverseSequenceOne == false ){
switch_graph_led(seq_1_current, HIGH);
seq_1_current++;
if( seq_1_current > num_led ) {
reverseSequenceOne = true;
}
}else{
switch_graph_led(seq_1_current, LOW);
seq_1_current--;
if( seq_1_current < 0 ) {
reverseSequenceOne = false;
}
}
}
}
unsigned long prevBarMillis_fire = 0; // bargraph firing tracker
const long firing_interval = 40; // interval at which to cycle firing lights (milliseconds).
int fireSequenceNum = 1;
void barGraphSequenceTwo(int currentMillis){
// normal sync animation on the bar graph
if (currentMillis - prevBarMillis_fire > firing_interval) {
// save the last time you blinked the LED
prevBarMillis_fire = currentMillis;
switch (fireSequenceNum) {
case 1:
switch_graph_led(2, LOW);
switch_graph_led(14, LOW);
switch_graph_led(1, HIGH);
switch_graph_led(15, HIGH);
fireSequenceNum++;
break;
case 2:
switch_graph_led(1, LOW);
switch_graph_led(15, LOW);
switch_graph_led(2, HIGH);
switch_graph_led(14, HIGH);
fireSequenceNum++;
break;
case 3:
switch_graph_led(2, LOW);
switch_graph_led(14, LOW);
switch_graph_led(3, HIGH);
switch_graph_led(13, HIGH);
fireSequenceNum++;
break;
case 4:
switch_graph_led(3, LOW);
switch_graph_led(13, LOW);
switch_graph_led(4, HIGH);
switch_graph_led(12, HIGH);
fireSequenceNum++;
break;
case 5:
switch_graph_led(4, LOW);
switch_graph_led(12, LOW);
switch_graph_led(5, HIGH);
switch_graph_led(11, HIGH);
fireSequenceNum++;
break;
case 6:
switch_graph_led(5, LOW);
switch_graph_led(11, LOW);
switch_graph_led(6, HIGH);
switch_graph_led(10, HIGH);
fireSequenceNum++;
break;
case 7:
switch_graph_led(6, LOW);
switch_graph_led(10, LOW);
switch_graph_led(7, HIGH);
switch_graph_led(9, HIGH);
fireSequenceNum++;
break;
case 8:
switch_graph_led(7, LOW);
switch_graph_led(9, LOW);
switch_graph_led(6, HIGH);
switch_graph_led(10, HIGH);
fireSequenceNum++;
break;
case 9:
switch_graph_led(6, LOW);
switch_graph_led(10, LOW);
switch_graph_led(5, HIGH);
switch_graph_led(11, HIGH);
fireSequenceNum++;
break;
case 10:
switch_graph_led(5, LOW);
switch_graph_led(11, LOW);
switch_graph_led(4, HIGH);
switch_graph_led(12, HIGH);
fireSequenceNum++;
break;
case 11:
switch_graph_led(4, LOW);
switch_graph_led(12, LOW);
switch_graph_led(3, HIGH);
switch_graph_led(13, HIGH);
fireSequenceNum++;
break;
case 12:
switch_graph_led(3, LOW);
switch_graph_led(13, LOW);
switch_graph_led(2, HIGH);
switch_graph_led(14, HIGH);
fireSequenceNum = 1;
break;
}
}
}
/************************* Shutdown and helper functions ****************************/
void shutdown_leds(){
// reset the sequence
seq_1_current = 1;
fireSequenceNum = 1;
// shut all led's off
// shut all led's off
for(int i=1;i<=15;i++){
switch_graph_led(i, LOW);
}
}
void switch_graph_led(int num, int state){
switch (num) {
case 1:
io.digitalWrite(SX1509_BAR_01, state);
break;
case 2:
io.digitalWrite(SX1509_BAR_02, state);
break;
case 3:
io.digitalWrite(SX1509_BAR_03, state);
break;
case 4:
io.digitalWrite(SX1509_BAR_04, state);
break;
case 5:
io.digitalWrite(SX1509_BAR_05, state);
break;
case 6:
io.digitalWrite(SX1509_BAR_06, state);
break;
case 7:
io.digitalWrite(SX1509_BAR_07, state);
break;
case 8:
io.digitalWrite(SX1509_BAR_08, state);
break;
case 9:
io.digitalWrite(SX1509_BAR_09, state);
break;
case 10:
io.digitalWrite(SX1509_BAR_10, state);
break;
case 11:
io.digitalWrite(SX1509_BAR_11, state);
break;
case 12:
io.digitalWrite(SX1509_BAR_12, state);
break;
case 13:
io.digitalWrite(SX1509_BAR_13, state);
break;
case 14:
io.digitalWrite(SX1509_BAR_14, state);
break;
case 15:
io.digitalWrite(SX1509_BAR_15, state);
break;
}
}
CountDeMonet wrote:The brightness is pure preference. I want them lit but not blindingly bright so I used 330. 220 is a little brighter but the current draw goes up quite a bit. The more current you draw the less time your battery works. You also have to watch the current draw on the SX1509. There are 2 modes. Sourcing current and Sinking current and they are wired differently. Sourcing currently only supports 8ma per pin and I've clocked my setup at 4ma with the 330 ohm resistor network so I'm safe. If you go smaller on the resistor network you may need to change how you wire it. I think the 220 was closer to 8ma current if I remember correctly which is pretty close to the limit.Yeah, I'm doing sinking, and that requires individual resistors. In fact, I ended up making a custom PCB for it because it was so complex. I'll have the boards in my hands this weekend and will post about them!
xoff00 has experience wiring the sx1509 so you get more current per pin. I've not done that. You might be safe without a resistor because the sx1509 is limiting to 8ma current. Search for Source vs. Sink on this page for more info
I would suggest getting a resistor kit and testing various resistors to see the brightness you like. Then when you find it purchase the resistor network for that value. My guess is you'll like something closer to 100 ohm
CountDeMonet wrote:Yeah, taking a good look at the models I think if I bring the powercell up and have it touch the ion arm holder I could create a mount near the same height as the gun mount on the other side. Basically it would look something like this where the gun mount would be off the side of the powercell. To me it looks off balance visually with the gun on the left and not the right. What do you all think?Personally, I like just moving the gun to the other side.
talem84 wrote:Would anyone be able to give me a parts list ?We're not really at that stage, Talem84, but assuming you're fairly Arduino savvy the key part that I found and CountDeMonet ran with is a good I2C I/O Expander called the SX1509, which has a great breakout board made by Sparkfun: https://www.sparkfun.com/products/13601
My Little Pony/Ghostbusters crossover done by my d[…]
Great work identifying the RS Temperature Control […]
I read Back in Town #1. Spoilers : Hate to b[…]
I'd really like to see the new t-shirt unlocks tra[…]