Hey Everyone,
I apologize in advance if I'm unable to format my code correctly in this post. It's my first in this forum.
I've avoided asking questions because I'm trying to learn all this myself but I've reached a point where I am at a loss.
Project Overview
I'm building a 350 Scale Enterprise Refit from the original series Star Trek movies. I will incorporate 6 buttons, corresponding to each of the 6 movies. Each button activates a 'scene' from one of the movies. A selection of audio from the movie will play (using SD card reader & external amp) combined with a timed LED sequence matching what's happening in the scene.
In this particular instance, I am working on the scene from ST:II, a battle between the Enterprise and Khan.
Scene Reference: Reliant's Prefix Code (1-6-3-0-9) - YouTube
The audio sequence begins at 8:04 and runs to 9:28 in the above Youtube Clip.
The Problem
What I am trying to achieve is lighting a sequence of LEDs in time with the Prefix input (8:21 in the above clip) using a shift register. This has been successful. The LEDs light in sequence with Spock's button pushes. They remain on until the first phaser is fired (8:42) and then shut off.
What I would like next to happen is to blink an LED rapidly (on/off cycle 25/25ms) while the phasers are active, then shut off. At the second phase blast, the same happens again.
I have been able to make the light turn ON steadily, but not turn OFF. And I have been able to get the light to turn ON in time with the phaser blast.
I have tried using the basic blink without delay sketch, which works when it's outside the button press if statement. But when it is placed within that statement, it turns on and does not blink.
I have also tried using the LedFlasher library, which does the same. Works fine outside the code range for the effect, but only turns on and does not blink while inside it.
I have also tried variations of both using the setup array, a new array, and various wild guesses.
I am not expecting anyone to write the code for me. I need to understand how this works so I can replicate and modify as needed for other functions. I am hoping someone can atleast tell me why the BWD sketch doesnt work in this instance, or what I might consider trying, or need to consider, or need to look at to get it to work.
The code is based on Ostrich Longneck's Arduino For Starships Series. It took me a long time and a lot of reading and trial and error with the code to figure out how the array works with the shift register.
Here is the full code:
#include <pcmRF.h>
#include <pcmConfig.h>
#include <TMRpcm.h>
// Audio TMRpcm Library by Various Contributors
#include <TMRpcm.h>
#include <SPI.h>
#include <SD.h>
#include <LedFlasher.h>
const int TwokButton = 18; // TWOK Effect
int TwokButtonState = 0; // flag to check if button has been pressed
// Set up Arrays & Variables used for the Prefix Effect
const int PreFix [5] = {1000, 1980, 2860, 3400, 19692}; // Timeline in milliseconds between floodlights
int PreFixStart = 18500; // Start-up delay
int PreFixStack = 1; // Variable used to calculate value to be written to 74HC595 Shift Register
int PreFixTimer = 0; //Light Number variable
long PreFixSeq = 0; //
long PreFixSeqStart = 0; // Time since sequence was started
// Set up Arrays & Variables used for the Phaser Effect
const int Phaser [2] = {19692, 22000}; // Phaser timing array
long PhaserStart = 0; // The time at which the phaser effect should start
long PhaserEnd = 0; // The time at which the phaser effect should end
int PhaserTimer = 0;
int PhaserState = LOW; // Intitial phaser state when attemping to use Blink w/o delay
const int PhaserLed = 6; // Phaser LED Pin
unsigned long PhaserPulse = 25; // Used in Blink without delay sketch
unsigned long previousMillis = 0; // Used in Blink without delay sketch
// Set up variables for 74HC595 Shift Register
int latchPin = 4; // Pin connected to ST_CP of 74HC595
int clockPin = 2; // Pin connected to SH_CP of 74HC595
int dataPin = 3; // Pin connected to DS of 74HC595
int firstSound = 1; // flag to finish playing intro before other sound effects start
char mychar;
const int CS_PIN = 10;
TMRpcm audio;
int acc = 0 ; // integration state
int acc2 = 0 ;
void noise_shape (int sample) // here sample is signed 16 bit value
{
acc += sample ; // two integral stages
acc2 += acc ;
int top_part = acc2 & 0xFF00 ; // get 8 bits to be output
acc -= top_part ; // feedback negatively to both integral stages
acc2 -= top_part ;
analogWrite (9, 0xFF & (top_part >> 8)) ;
}
void setup()
{
// Setup for TWOK Phaser
pinMode (Phaser, OUTPUT);
// Set up pins used by shift register;
pinMode (latchPin, OUTPUT);
pinMode (clockPin, OUTPUT);
pinMode (dataPin, OUTPUT);
// Clear shift register
digitalWrite (latchPin, LOW);
shiftOut (dataPin, clockPin, MSBFIRST, 0);
digitalWrite (latchPin, HIGH);
// Set up pins for audio effects
audio.speakerPin = 9; // Speaker pin on output pin 9
//Serial.begin(9600);
//Serial.println("Initializing Card");
pinMode(CS_PIN, OUTPUT);
if(!SD.begin(CS_PIN)) {
//Serial.println("Card Failure");
return;
}
//Serial.println("Card Ready");
audio.setVolume(5);
audio.quality(1);
pinMode (TwokButton, INPUT); //Twok Effect on 18
} // end of setup
void loop() // The main program
{
TwokButtonState = digitalRead (TwokButton);
if (TwokButtonState == HIGH){
audio.play("TWOK.wav");
PreFixSeq = millis() + PreFixStart;
while (millis() < PreFixSeq){} //Do Nothing Until Correct Audio Time has Elapsed
PreFixSeqStart = millis(); // Marks time when first leds turns on
for(PreFixTimer; PreFixTimer < 5; PreFixTimer += 1){
digitalWrite (latchPin, LOW);
shiftOut (dataPin, clockPin, MSBFIRST, PreFixStack);
digitalWrite (latchPin, HIGH);
PreFixStack = PreFixStack * 2 + 1;
PreFixSeq = PreFixSeqStart + PreFix [PreFixTimer];
while (millis() < PreFixSeq) { } // Pauses between Prefix Lightup sequence
digitalWrite (latchPin, LOW); // Clear the Shift register at the first phaser fire
shiftOut (dataPin, clockPin, MSBFIRST, 0);
digitalWrite (latchPin, HIGH);
}
PhaserStart = PreFixSeqStart + Phaser [0]; // An attempt to define the time at which Phaser LED should turn on
PhaserEnd = PreFixSeqStart + Phaser [1]; // An attempt to define the time at which the Phaser LED should turn off
if(PhaserStart == millis()){
// digitalWrite(PhaserLed, HIGH); // If I remove BWD code, this works to turn it on at the correct time but doesnt blink.
// Below is the Blink without delay code.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= PhaserPulse) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (PhaserState == LOW) {
PhaserState = HIGH;
} else {
PhaserState = LOW;
}
// set the LED with the PhaserState of the variable:
digitalWrite(PhaserLed, PhaserState);
}
}
}
} // end of loop
Below are the snippets of code I am specifically working with starting with the setup functions:
const int TwokButton = 18; // TWOK Effect
int TwokButtonState = 0; // flag to check if button has been pressed
// Set up Arrays & Variables used for the Prefix Effect
const int PreFix [5] = {1000, 1980, 2860, 3400, 19692}; // Timeline in milliseconds between floodlights
int PreFixStart = 18500; // Start-up delay
int PreFixStack = 1; // Variable used to calculate value to be written to 74HC595 Shift Register
int PreFixTimer = 0; //Light Number variable
long PreFixSeq = 0; //
long PreFixSeqStart = 0; // Time since sequence was started
// Set up Arrays & Variables used for the Phaser Effect
const int Phaser [2] = {19692, 22000}; // Phaser timing array
long PhaserStart = 0; // The time at which the phaser effect should start
long PhaserEnd = 0; // The time at which the phaser effect should end
int PhaserTimer = 0;
int PhaserState = LOW; // Intitial phaser state when attemping to use Blink w/o delay
const int PhaserLed = 6; // Phaser LED Pin
unsigned long PhaserPulse = 25; // Used in Blink without delay sketch
unsigned long previousMillis = 0; // Used in Blink without delay sketch
// Set up variables for 74HC595 Shift Register
int latchPin = 4; // Pin connected to ST_CP of 74HC595
int clockPin = 2; // Pin connected to SH_CP of 74HC595
int dataPin = 3; // Pin connected to DS of 74HC595
The Loop Code
void loop() // The main program
{
TwokButtonState = digitalRead (TwokButton);
if (TwokButtonState == HIGH){
audio.play("TWOK.wav");
PreFixSeq = millis() + PreFixStart;
while (millis() < PreFixSeq){} //Do Nothing Until Correct Audio Time has Elapsed
PreFixSeqStart = millis(); // Marks time when first leds turns on
for(PreFixTimer; PreFixTimer < 5; PreFixTimer += 1){
digitalWrite (latchPin, LOW);
shiftOut (dataPin, clockPin, MSBFIRST, PreFixStack);
digitalWrite (latchPin, HIGH);
PreFixStack = PreFixStack * 2 + 1;
PreFixSeq = PreFixSeqStart + PreFix [PreFixTimer];
while (millis() < PreFixSeq) { } // Pauses between Prefix Lightup sequence
digitalWrite (latchPin, LOW); // Clear the Shift register at the first phaser fire
shiftOut (dataPin, clockPin, MSBFIRST, 0);
digitalWrite (latchPin, HIGH);
}
PhaserStart = PreFixSeqStart + Phaser [0]; // An attempt to define the time at which Phaser LED should turn on
PhaserEnd = PreFixSeqStart + Phaser [1]; // An attempt to define the time at which the Phaser LED should turn off
if(PhaserStart == millis()){
// digitalWrite(PhaserLed, HIGH); // If I remove BWD code, this works to turn it on at the correct time but doesnt blink. You can see what happens when this code is executed in Video 01.
// Below is the Blink without delay code. You can see what this code does in Video 02
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= PhaserPulse) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (PhaserState == LOW) {
PhaserState = HIGH;
} else {
PhaserState = LOW;
}
// set the LED with the PhaserState of the variable:
digitalWrite(PhaserLed, PhaserState);
}
}
}
Thanks for reading!