1/350 USS Enterprise Model

Prototype Arduino Control Board

YouTube Preview Image

I forgot to mention in the video a big thank you to Bernie over at ModelSlouch! He was a BIG help in terms of getting the code I was writing shored up and everything working correctly on my breadboard. I’m still very much a novice when it comes to electrical engineering and the Arduino coding language, so it can’t be said enough how much of a help he was. Thanks Bernie!

To check out the code for your own project, take a look below. Or you can just go ahead and download the .pde file here: Enterprise Control Program (1451)

Enterprise Control Program

/*
***********************************************************
Enterprise Lighting Effects
Created by Bernie Pottrell 2011
Modified by Doug Hogan 2011
***********************************************************
Photon Torpedo and Main Deflector Dish Control Program

This code fades up the red side of a dual LED and flashes the white side of the LED to simulate
a photon torpedo launch when the Torpedo Launch switch is pressed.
Next press of the switch changes the launcher side and repeats the code for the other side LED.

This code also fades the colour of an RGB LED between copper and cyan when the Warp button is pressed.
Next press of the switch reverses the colour change.

The Torpedo Circuit:
Red/white common anode LEDs with left red cathode attached to PWM pin 5, right red cathode
attached to PWM pin 6 and left white cathode attached to digital pin 4, right white cathode
attached to digital pin 7.  Anode attached to +5 V.

The Deflector Circuit:
RGB common anode LED with red cathode attached to PWM pin 9, green cathode attached to
PWM pin 10 and blue cathode attached to PWM pin 11.  Anode attached to +5 V.

Running and Anti-collision Light Circuit:
Just need to add blinking light patterns that don’t require a delay function!

*/

// Initial Declarations of Pins and Variables (Torpedo Control Program):
int TorpedoSwitchPin = 2;                         // Torpedo switch is connected to pin 2
int LeftTorpedoWhiteLEDpin = 7;                     // Left white led attached to digital pin 7
int LeftTorpedoRedLEDpin = 6;                       // Left red led attached to pwm pin 6
int RightTorpedoRedLEDpin = 5;                      // Right red led attached to pwm pin 5
int RightTorpedoWhiteLEDpin = 4;                    // Right white led attached to digital pin 4
int TorpedoVal;                                     // Variable for reading the torpedo switch pin status
int TorpedoVal2;                                    // Variable for reading the torpedo delayed/debounced status
int TorpedoButtonState;                             // Variable to hold the torpedo button state
int FireMode = 0;                                   // Variable to hold fire decision
int LRchoice = 0;                                   // Variable to hold next Left/Right cycle

// Initial Declarations of Pins and Variables (Deflector Dish Control Program / Impulse Engines):
int WswitchPin = 3;                              // Warp switch is connected to pwm pin 3
int RGBled[] = {9,0,11};                         // RGB pins.  9 = redPin, 10 = greenPin, 11 = bluePin
int IMPengines[] = {10,10,10};                                    // Impulse Engines connected to pin 10
int Wval;                                        // Variable for reading the warp switch pin status
int Wval2;                                       // Variable for reading the warp delayed/debounced status
int WbuttonState;                                // Variable to hold the warp button state
int WMode = 0;                                   // Variable to hold warp decision
int WIchoice = 0;                                   // Variable to hold next Warp selection

// Deflector Dish Colour Modes
const byte CYAN[] = {100,100,255};                   // Cyan colour definition for Warp Mode
const byte BLACK[] = {0,0,0};                     // Black colour definition
const byte WHITE[] = {255,255,255};
const byte COPPER[] = {255,255,0};                // Copper colour definition for Impulse Mode
const byte RED[] = {255,255,255};                     // Red colour definition for Impulse ENGINES

int ledState = LOW;             // ledState used to set the LED
int ledState2 = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated
long previousMillis2 = 0;        // will store last time LED was updated
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1700;           // interval at which to blink (milliseconds)
long interval1 = 300;           // interval at which to blink (milliseconds)

// Set Up
void setup() {

//Torpedo Setup (INPUT OUTPUT)
pinMode(TorpedoSwitchPin, INPUT);                   // Set the torpedo switch pin as input
pinMode(LeftTorpedoRedLEDpin, OUTPUT);              // Set the left red led pin as output
pinMode(LeftTorpedoWhiteLEDpin, OUTPUT);            // Set the left white led pin as output
pinMode(RightTorpedoRedLEDpin, OUTPUT);             // Set the right red led pin as output
pinMode(RightTorpedoWhiteLEDpin, OUTPUT);           // Set the right white led pin as output
digitalWrite(LeftTorpedoWhiteLEDpin, HIGH);         // Ensure the left white led is OFF
analogWrite(LeftTorpedoRedLEDpin, 255);             // Ensure the left red led is OFF
digitalWrite(RightTorpedoWhiteLEDpin, HIGH);        // Ensure the right white led is OFF
analogWrite(RightTorpedoRedLEDpin, 255);            // Ensure the right red led is OFF

//Deflector Dish Setup (INPUT OUTPUT)
pinMode(WswitchPin, INPUT);                      // Set the warp switch pin as input

for(int i = 0; i < 3; i++){
pinMode(RGBled[i], OUTPUT);                       //Set the three RGBLed pins as outputs
pinMode(IMPengines[i], OUTPUT);                   //Set the Impulse Engine LEDs as outputs
}

setColour(RGBled, COPPER);                          //Set initial colour of deflector dish to copper
setColour (IMPengines, BLACK);                       // Turn Impulse Engines ON

//Switch Debugs
Serial.begin(9600);                                 // Set up serial communication at 9600bps (if reqd for debugging)
TorpedoButtonState = digitalRead(TorpedoSwitchPin); // Read the initial state of the torpedo switch
WbuttonState = digitalRead(WswitchPin);       // Read the initial state of the warp switch

/*
*  Ship Status Reports (just for fun)
*/
Serial.println(“USS Enterprise 1701A: Status Report -“);
Serial.println(” “);
Serial.println(“Command: Computer main frame ONLINE”);
Serial.println(“Enginneering: Anti-matter Warp core ONLINE. Impulse Engines at 1/4 speed.”);
Serial.println(“Tactical: Photon Torpedos, ARMED. Phaser banks fully CHARGED.”);
Serial.println(” “);
Serial.println(“Greetings Captain. Awaiting your orders…”);
Serial.println(” “);
}

// Main Loop
void loop()
{

/*
*  Torpedo launch, single pushbutton, debounced
*/
{
photonTorpedos();
}

/*
*  Deflector Dish Colour, single pushbutton, debounced
*/
{
deflectorDish();
}

}

//ENTERPRISE MODULAR CONTROL FUCTIONS.

/*
*  Deflector Dish Colour, single pushbutton, debounced
*/
void deflectorDish() {

WMode = 0;                                     // Set Warp mode to OFF
Wval = digitalRead(WswitchPin);                // Read warp switch input value and store it in Wval
delay(10);                                     // 10 milliseconds is a good amount of time to wait
Wval2 = digitalRead(WswitchPin);               // Read the input again to check for bounces
if (Wval == Wval2) {                           // 2 consistant readings?
if (Wval != WbuttonState) {                  // The button state has changed
if (Wval == LOW) {                         // Check if the button is pressed
if (WMode == 0) {                        // Is the warp decision OFF?
WMode = 1;                             // Then turn warp decision on!
}
}
WbuttonState = Wval;                       // Save the new state in status variable
}
if (WMode == 1) {                          // Decision made to change warp status?
if (WIchoice == 0) {                     // If its Go To Warp……

Serial.println(“Warp Engines…ENGAGED!”);
// Fade deflector from copper to cyan
fadeToColour(RGBled, COPPER, CYAN, 10); //fadeToColour takes 4 parameters
fadeToColour(IMPengines, BLACK, RED, 10); //fadeToColour takes 4 parameters
//RGBled – an array with 3 values defining the red, green and blue pins of the LED
//COPPER – This is the start colour
//CYAN – This is the end colour
//10 – the delay (in milliseconds between updates) (determines the fade speed)
delay (15);                                     // Wait 15 milliseconds
WIchoice = 1;                             // Set deflector dish cycle to Warp Mode…
}

else    {           // or go to impulse

Serial.println(“Warp Engines disengaged. Impulse Engines online. Standing by for your orders, Captain…”);
// Fade deflector from cyan to copper
fadeToColour(RGBled, CYAN, COPPER, 10); //Fades from Cyan to Copper
fadeToColour(IMPengines, RED, BLACK, 10); //fadeToColour takes 4 parameters
delay (15);                                     // Wait 15 milliseconds
WIchoice = 0;                            // Set deflector dish cycle to Standby Impulse Mode…
}
}
}
}

/*
*  Torpedo launch, single pushbutton, debounced
*/
void photonTorpedos() {
FireMode = 0;                                     // Set Torpedo fire decision to OFF
digitalWrite (LeftTorpedoWhiteLEDpin, LOW);       // First turn off white LED
digitalWrite (LeftTorpedoRedLEDpin, LOW);         // First turn off white LED
digitalWrite (RightTorpedoWhiteLEDpin, LOW);       // First turn off white LED
digitalWrite (RightTorpedoRedLEDpin, LOW);         // First turn off white LED
TorpedoVal = digitalRead(TorpedoSwitchPin);       // Read left switch input value and store it in val
delay(10);                                        // 10 milliseconds is a good amount of time to wait
TorpedoVal2 = digitalRead(TorpedoSwitchPin);      // Read the input again to check for bounces
if (TorpedoVal == TorpedoVal2) {                  // 2 consistant readings?
if (TorpedoVal != TorpedoButtonState) {         // The button state has changed
if (TorpedoVal == LOW) {                      // Check if the button is pressed
if (FireMode == 0) {                        // Is the fire decision OFF?
FireMode = 1;                             // Then turn fire decision on!
}
}
TorpedoButtonState = TorpedoVal;              // Save the new state in status variable
}
if (FireMode == 1) {                            // Decision made to fire?
if (LRchoice == 0) {                          // If its Left……

// Fire LEFT Torpedo
//fade in from min to max in increments of 1:

Serial.println(“Firing Left Photon Torpedo…”);

//fade out from min to max in increments of 2:
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue +=2) {
analogWrite (LeftTorpedoRedLEDpin, fadeValue);  // Fade down red LED
delay (15);                                     // Wait 15 milliseconds to see the fade down effect
LRchoice = 1;                                   // Set cycle to RIGHT
}
delay (1150);                                // Hold red led at full brightness for 1150 milliseconds

//fire off 75 millisecond burst from white LED
Serial.println(“Photon Torpedo Away!”);
digitalWrite (LeftTorpedoWhiteLEDpin, LOW);       // First turn on white LED
delay (1);                                       // Hold for 1 millisecond
digitalWrite (LeftTorpedoWhiteLEDpin, HIGH);      // Then turn off white LED

for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
// sets the value (range from 255 to 100 in steps of -5:
analogWrite (LeftTorpedoRedLEDpin, fadeValue);
delay (2);                               // Wait 1 millisecond to see the fade up effect
}

}

else {                                              // If not left, then must be right…

// Fire RIGHT Torpedo
//fade in from min to max in increments of 1:

Serial.println(“Firing Right Photon Torpedo…”);

//fade out from min to max in increments of 2:
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue +=2) {
analogWrite (RightTorpedoRedLEDpin, fadeValue);  // Fade down red LED
delay (15);                                     // Wait 15 milliseconds to see the fade down effect
LRchoice = 1;                                   // Set cycle to RIGHT
}
delay (1150);                                // Hold red led at full brightness for 1150 milliseconds

//fire off 75 millisecond burst from white LED
Serial.println(“Photon Torpedo Away!”);
digitalWrite (RightTorpedoWhiteLEDpin, LOW);       // First turn on white LED
delay (1);                                       // Hold for 1 millisecond
digitalWrite (RightTorpedoWhiteLEDpin, HIGH);      // Then turn off white LED

for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
// sets the value (range from 255 to 100 in steps of -5:
analogWrite (RightTorpedoRedLEDpin, fadeValue);
delay (2);                               // Wait 1 millisecond to see the fade up effect
LRchoice = 0;                                   // Set cycle back to LEFT
}
}
}
}
}

//MATHEMATICAL FUNCTIONS FOR DEFLECTOR DISH CONTROL (DO NOT MODIFY):

/* Sets the colour of the LED to any RGB Value
led – (int array of three values defining the LEDs pins (led[0] = redPin, led[1] = greenPin, led[2] = bluePin))
colour – (byte array of three values defing an RGB colour to display (colour[0] = new Red value, colour[1] = new Green value, colour[2] = new Red value
*/
void setColour(int* led, byte* colour){
for(int i = 0; i < 3; i++){                     //iterate through each of the three pins (red green blue)
analogWrite(led[i], 255 – colour[i]);  //set the analog output value of each pin to the input value (ie led[0] (red pin) to 255- colour[0] (red input colour)
//we use 255 – the value because our RGB LED is common anode, this means a colour is full on when we output analogWrite(pin, 0)
//and off when we output analogWrite(pin, 255).
}
}

// A version of setColour that takes a predefined colour (necessary to allow const int pre-defined colours
void setColour(int* led, const byte* colour){
byte tempByte[] = { colour[0], colour[1], colour[2] };
setColour(led, tempByte);
}

/* Fades the LED from a start colour to an end colour at fadeSpeed
led – (int array of three values defining the LEDs pins (led[0] = redPin, led[1] = greenPin, led[2] = bluePin))
startColour – (byte array of three values defing the start RGB colour (startColour[0] = start Red value, startColour[1] = start Green value, startColour[2] = start Red value
endColour – (byte array of three values defing the finished RGB colour (endColour[0] = end Red value, endColour[1] = end Green value, endColour[2] = end Red value
fadeSpeed – this is the delay in milliseconds between steps, defines the speed of the fade
*/
void fadeToColour(int* led, byte* startColour, byte* endColour, int fadeSpeed){
int changeRed = endColour[0] – startColour[0];                            //the difference in the two colours for the red channel
int changeGreen = endColour[1] – startColour[1];                          //the difference in the two colours for the green channel
int changeBlue = endColour[2] – startColour[2];                           //the difference in the two colours for the blue channel
int steps = max(abs(changeRed),max(abs(changeGreen), abs(changeBlue)));   //make the number of change steps the maximum channel change

for(int i = 0 ; i < steps; i++){                                        //iterate for the channel with the maximum change
byte newRed = startColour[0] + (i * changeRed / steps);                 //the newRed intensity dependant on the start intensity and the change determined above
byte newGreen = startColour[1] + (i * changeGreen / steps);             //the newGreen intensity
byte newBlue = startColour[2] + (i * changeBlue / steps);               //the newBlue intensity
byte newColour[] = { newRed, newGreen, newBlue };                       //Define an RGB colour array for the new colour
setColour(led, newColour);                                              //Set the LED to the calculated value
delay(fadeSpeed);                                                       //Delay fadeSpeed milliseconds before going on to the next colour
}
setColour(led, endColour);                                                //The LED should be at the endColour but set to endColour to avoid rounding errors
}
// A version of fadeToColour that takes predefined colours (necessary to allow const int pre-defined colours
void fadeToColour(int* led, const byte* startColour, const byte* endColour, int fadeSpeed){
byte tempByte1[] = {
startColour[0], startColour[1], startColour[2] };
byte tempByte2[] = {
endColour[0], endColour[1], endColour[2] };
fadeToColour(led, tempByte1, tempByte2, fadeSpeed);
}

Now that everything is pretty solid prototype wise, the next step is going to be getting the Arduino breakout board all soldered up. I’ve already burned the Enterprise lighting program to a new ATMEGA328 chip and triple tested everything. So now it’s all about keeping all the wires and pins labeled correctly, and relatively rats nest free, so that it’s pretty idiot proof when the time comes to actually installing all the LEDs inside the Enterprise. Which will hopefully be soon!

Because once that is done we can get onto the fun stuff. Painting, sanding, gluing, and decalling!

Speaking of, lets talk about what we have been able to put together while all this electrical stuff has been getting sorted out.

Next stop…the Saucer Section and a lighting update!

Pages: 1 2 3 4 5 6 7 8 9

2 Comments

  1. Glad to see you finally plucked up the courage to get started on this beast Doug!
    I too was a bit concerned about the aluminum tape shorting things out (well, I will be when I evenually get round to tackling my big E), and have been experimenting with a second layer of tape (insulating this time) on top of the aluminum tape in the areas at risk – might be worth a try?

    Going to be building the new PL TOS Enterprise? : )

    Nice work so far btw.

    Bernie

    • Doug (Author)

      Hey Bernie! Thanks for the comment!

      Ya the foil tape is pretty tricky. It reflects light amazingly and insulates your wires really well but if things get packed tightly, you’ll definitely start see some shorts like I was finding in my saucer. A trick I used was just using the wax paper from the backside of foil tape to kind of “sandwich” the problem areas. It’s a pretty simple trick but it took quite a few times tearing off the misbehaving foil tape to figure that one out, haha.

      And ya I can’t wait for the 1/350 TOS Enterprise to get out into the wild. Did you sign up for the 1701 club too? It really looks amazing, especially because of the included lights and motors. No more headaches from Arduino coding! haha. Thanks again for all your help on that too btw!

Comments are now closed for this article.