Arduino R3
IDE 2.2.1
Developing on Ubuntu Linux
I've been doing this about two weeks, I'm sure it's very primitive. The task: visualize three mock "cannons" (or go to the TL;DR below to see them.) The goal is to execute three random signals, one each to lights, sound stored on an ISD chip (or 3) and one to relays to signal three fog machines for a short burst. This will likely be a long thread as I develop, make mistakes, and blow stuff up.
I have the first of the three parts, the lights, complete and working, as below. The LED's are only red, green, and yellow for development, I will probably use 2 reds, 1 yellow in each cannon. I am employing the LD74HC595 shift register to send the signals, as you can see I still have pins open for the other two parts of the project. My questions: does this circuit adequately isolate power demands from the Arduino? I will need to add ISD's for the sounds as suggested here and relays to control the fog machine switches, will I potentially blow up the chip or the Arduino? Am I doing this all wrong and do you have suggestions for a better way?
The schematic (I absolutely LOVE KiCad!) Sorry for the misalignment on the pins, I had to mod the 595 chip to match mine and had the grids messed up.
The Fritzing:
The code is not really relevant at this point, it works, but for reference, well commented as to what it's doing (and not, yet.)
/*
* Cannons project 11/23
*
* Goal is to fire off three sets of synchronized signals to mock cannons: LED lights, sound boom, fog burst.
* See cannons.kicad_pro and cannons-project-1.fzz (fritzing)
*
* Pins for 74Hc595 SPC Shift Register
*
* 1 = LED set 2 (3 green) register 6
* 2 = LED set 3 (3 yellow) register 5
* 8 = ground, 3-7 empty
* 9 = empty
* 10 = +5v PS
* 11 = Arduino 9 clock
* 12 = Arduino 11 latch
* 13 GND
* 14 = Arduino 12 data
* 15 = LED set 1 (3 red) register 7
* 16 = +5v
*
* LED's - + to PS, 220 ohm resistor, common pinned as above (red -> 15, green -> 1, yellow -> 2)
*
* @TODO: Only lights implemented 11/23. We'll require two other sets of registers to fire at the same time:
* 1) 3 DSI chips to hold "boom" sounds (or will one do?) Amplifier will not be needed, connects to
* external speaker jack with its own power.
* 2) 3 relays to control fog machine trigger switched for momentary "puff"
*
*/
// Set to false to remove iteration stop and serial output
bool debug = true;
// 12 ST_CP [RCK] on 74HC595
int latchPin = 11;
// 11 SH_CP [SCK] on 74HC595
int clockPin = 9;
// 14 DS [S1] on 74HC595
int dataPin = 12;
// Only using 3 registers on the 595: 7 is pin 15, 6 is pin 1, 5 is pin 2
// @TODO pick randomly, currently cycles through 0, 1, 2
int ledRegisters[] = { 7, 6, 5 };
// @TODO sound - need chip first to configure, dummy pin for testing to LED.
int soundPins[] = {5, 6, 7};
// @TODO fog relays - also dummies at this point.
int fogPins[] = {8, 10, 13};
// Fire the sequence, restart after (ms). @TODO control by potentiometer.
int fireDelay = 3000;
// holds max time between firing the 3 events, stored boomDelay. @TODO: Another potentiometer
// Should probably make sure this does not exceed fireDelay
int maxRandom = 400;
// How long to leave pin on HIGH. May need to address the three individually.
int fireLength = 100;
// For the shiftOut
byte leds = 0;
// Delay to the next "boom"
int boomDelay;
// Just for testing - if exceeds numIterations return from loop
int numIterations = 5;
int numRun = 0;
/*
* Print Serial messages. Only runs if debug == true
* Must have a code error somewhere, won't run if this is below
* @return bool
*/
bool debugPrint(int eventNum = 0, int boomDelay = 0)
{
if (! debug) {
return false;
}
Serial.println( "Current event " + String(eventNum) + " Current LED " + ledRegisters[eventNum] +
" boom delay " + String(boomDelay) + " current sound " + String(soundPins[eventNum]) +
" current fog relay " + String(fogPins[eventNum]));
return true;
}
/*
* - Set random seed from analog 0
* - setup pins
* - setup variables
* @return void
*/
void setup()
{
if (debug) { Serial.begin(9600);}
// Guess we should be sure not to use analog 0
randomSeed(analogRead(0));
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}
/*
* Loop through the process.
* @return void
*/
void loop()
{
if (isMaxIterations()) { return; }
for (int currentEvent = 0; currentEvent < 3; currentEvent++) {
// Only need this in a variable for debugPrint, otherwise could be in the last delay
boomDelay = (int)random(100,maxRandom);
debugPrint(currentEvent, boomDelay);
bitSet(leds, ledRegisters[currentEvent]);
updateShiftRegister();
delay(fireLength);
bitClear(leds, ledRegisters[currentEvent]);
updateShiftRegister();
delay(boomDelay);
}
// delay the next firing by fireDelay
delay(fireDelay);
}
/*
* Write the data to the register
* @return void
*/
void updateShiftRegister()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, leds);
digitalWrite(latchPin, HIGH);
}
/*
* only used if debug == true; exit execution in loop()
* Puts Arduino in infinate loop that does nothing.
* @return void
*/
bool isMaxIterations()
{
numRun++;
if (numRun > numIterations) {
Serial.println("Exiting after " + String(numRun) + "iterations");
return true;
}
return false;
}
The TL;DR
Why am I doing this? Halloween is my wife's favorite holiday, Christmas, blah, New Years, we're in bed by 10. This year she said we were doing pirates and wanted a pirate ship. Hoo boy. So I built one, all out of scrap materials that would be thrown away. The relevance: you can see the cannons here and they're doing stock long bursts, totally un-cannon like, no booms, I just can't let it happen next year.
You can see the cannons, but you'll also see something else at 1:30, which is another Arduino project. There are two skeletons in a sword fight - static. That doesn't fly with me either, nope, uh uh, those characters gotta move. I already have a ton of servos, both micro and high torque, on the table for that one. But that's another day.