Welcome, %1$s. Please login or register. - Did you miss your activation email?

Login with username, password and session length
 

Author Topic: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution  (Read 1014 times)

Offline RossW

  • Captain
  • ****
  • Posts: 277
Together with my warp engine light solution, here is my main board which controls the speed and direction of the motors and also includes the blinking running lights (saucer) and strobes (secondary hull). The board includes connectors to provide the +5V/GND power for the nacelle boards I previously posted, so all of this together will let you do the electronics for the 1/350 TOS E PL kit (except for the windows).

The video explains all the features:

  • Motor speed (onboard trim pot or external)
  • Motor direction
  • Motor Voltage Select
  • Running lights (saucer)
  • Strobes (secondary hull)
  • Power for nacelle boards (blinking warp engine lights)

YouTube Video
https://youtu.be/us76p66Hac0

Arduino Code
Code: [Select]
/*

Copyright (c) 2017 Ross A. Waddell. Sketch is for personal use only.


Before uploading, change:

  Board -> Ardunio Pro or Pro Mini
  Processor -> ATmega328 (5V, 16Mhz)
  Port -> (whichever one has "usb" in it; board needs to be connected first)
  Programmer -> AVRISP mkII
*/


// Comment out the line below for production
// (serial monitoring affects timings)
//#define DEVMODE 1


/* 
    TODO:
    ----

    1. Add motor spin up (first time through loop only)             -> DONE
    2. When changing motor direction, spin down then spin up
    3. Add running/strobe lights code                               -> DONE
    4. Add exponential weighting smoothing of trim pot value        -> DONE
    5. Add conditional compile to output to serial monitor          -> DONE
    6. Add fade up/down for LEDs                                    -> DONE
    7. Adjust on/off timings to account for fades                   -> DONE

*/

/*

    - 10k trim pot controls motor speed (both).
    - Mini SPDT switches control each motors direction


HOW TO TWEAK THE MOTOR CONTROL SKETCH
-------------------------------------
You may find that there is a minimum speed after which the motor will just hum. It does so because it does not have enough power to spin.
By monitoring the values sent to the motor using the MotorControl sketch, you can find the motors minimum value to turn, and optimize the
motorValue to turn the motor within its true range.

To find the range of motorValue, follow these steps:

1) With the MotorControl sketch uploaded, click the serial monitor button at the top right of your Arduino window.
The serial monitor window will show you the potentiometer value followed by the output value that is being sent to the motor, in this fashion:
potentiometer = 1023 motor = 255
These values are displayed in a long list and update as you turn the potentiometer. If you do not see the list scrolling down, make sure that the
Autoscroll option is selected.

2) Starting with your potentiometer reading a value of 0, turn your potentiometer very slowly until the humming stops and the motor starts spinning.

   set "minRPM" variable to 0 first

3) Make a note of the value displayed at this point.

4) Use an if statement to tell the motor to change speed only if the value is greater than the minimum speed needed to spin the motor, as follows:
  (a). Find the part of your code that writes the motorValue to the motor:
analogWrite(motorPin, motorValue);
  (b). Replace it with the following piece of code:
if(motorValue > yourValue) {
 analogWrite(motorPin, motorValue);
} else {
 digitalWrite(motorPin, LOW);
}

5) Now replace yourValue with the number that you made a note of.
If the value motorValue is greater than that, the motor speeds up. If it is lower than that, the pin is written LOW so that it is fully off.
You could also type analogWrite(motorPin, 0) to accomplish the same thing. Tiny optimizations like this can help your project function smoothly,
with no wasted movement or values.
 
*/

// Motor setup
// *****************************************************************************

#define enablePin1 3              // Same RPM for both motors, but use separate outputs in case
                                  // need to adjust PWM value for different motor pairs
#define switchPin1 2              // connected to switch to control motor 1 spin direction
#define motor1Pin2 4              // pins which control motor 1 spin direction
#define motor1Pin1 5

#define enablePin2 9              // Same RPM for both motors, but use separate outputs in case
                                  // need to adjust PWM value for different motor pairs
#define switchPin2 7              // connected to switch to control motor 2 spin direction
#define motor2Pin2 8              // pins which control motor 2 spin direction
#define motor2Pin1 12

int motorPins[6] = {              // array to hold pins associated with each motor; used in CheckMotorDirSwitch()
  switchPin1,                     // function to check if motor direction switch value has changed.
  motor1Pin2,
  motor1Pin1,
  switchPin2,
  motor2Pin2,
  motor2Pin1
};

#define potPin 0                  // Trim pot middle wiper arm connected to A0

const int startRPM = 10;          // Starting speed when spinning up motors
boolean spinUpMtrs = true;        // Boolean variable to tell main loop() to spin up motors on startup
const int motorDelay = 50;        // Delay in microseconds for spinning up motors
unsigned long msLstMtrUpd;        // Variable to hold time motor speed was incremented
const int minRPM = 20;            // The min mapped value depends on your motor and the voltage applied; you want
                                  // this to be the slowest observed speed (no stall) for your selected motor


int RPM = 0;                      // Variable to hold current motor speed setting
int tempRPM = startRPM;           // Temp variable to hold current motor speed while spinning up on startup

int setRPM(int readPotValue = 0); // Set up function for optional parameter

// Even though you are using 2 identical motors (presumably), it is possible that they will not spin at the same speed
// although we are passing in the same PWM/relative voltage to both motors. To allow for some degree of customization,
// the two parameters below can be used to alter the PWM/relative voltage to one or both motors to try and balance
// them out. Chances are you will not need to touch these, but they are here if you do.

// You can set these to +ve or -ve values, but they should be in the range of -10 to +10 at most. Note that you are
// still limited to PWM values of 0-255. However, there is the stall PWM value for a motor to consider where the relative
// voltage is too low for it to spin; the setRPM() function limits that to the minRPM but you could go below that
// depending on the set value below and a too-large -ve adjustment.

int motor1PWMAdj = 0;
int motor2PWMAdj = 0;

// *****************************************************************************


// Running lights and Strobe lights LED setup
// *****************************************************************************
#include <Curve.h>                    // Part of library below; helps make fade in/out more smooth
#include <LEDFader.h>                 // Library used to fade running lights LEDs without using delay()

#define FADE_TIME_RUN_LTS 125
LEDFader ledRunLts;

#define LED_RUN_LTS_PIN 10
const int LED_RUN_LTS_ON_DUR = (1500 - FADE_TIME_RUN_LTS*2);  // Time on in milliseconds
                                                              // This takes into account the fade in/down time
const int LED_RUN_LTS_OFF_DUR = 500;  // Time off in milliseconds
boolean ledRunLtsState = HIGH;

#define LED_STB_LTS_PIN 11
const int LED_STB_LTS_ON_DUR = 20;    // Time on in milliseconds
const int LED_STB_LTS_OFF_DUR = 500;  // Time off in milliseconds
boolean ledStbLtsState = LOW;

// *****************************************************************************

#if defined(DEVMODE)
int j=0;                              // Counter iterations through loop(); for debugging purposes only
#endif


void setup() 
{
#if defined(DEVMODE)
  Serial.begin(9600);
  Serial.println("-----------");
  Serial.println("DEVMODE ON");
  Serial.println("-----------");
#endif

  ledRunLts = LEDFader(LED_RUN_LTS_PIN);
  ledRunLts.set_curve(&Curve::exponential);
  ledRunLts.fade(255,FADE_TIME_RUN_LTS);

  pinMode(LED_STB_LTS_PIN, OUTPUT);

  pinMode(enablePin1, OUTPUT);
  pinMode(switchPin1, INPUT_PULLUP);
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);

  pinMode(enablePin2, OUTPUT);
  pinMode(switchPin2, INPUT_PULLUP);
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);

  // Initial trim pot readings
  analogRead(potPin);                         // Discard first reading
  RPM = setRPM(1);                            // Call function to set motor RPM (first time)

  CheckMotorDirSwitch(0);                     // Call function to set motor 1 direction based on initial switch position
  CheckMotorDirSwitch(1);                     // Call function to set motor 2 direction based on initial switch position

}

void loop() 
{   
#if defined(DEVMODE)
  Serial.print("j = ");
  Serial.println(j);
  Serial.print("Run lts state = ");
  Serial.println(ledRunLtsState);
  j++;
#endif
 
  unsigned long ms = millis();                // Get current time in milliseconds (for LEDs)

  ledRunLts.update();
#if defined(DEVMODE)
  Serial.print("ledRunLts.isFading() = ");
  Serial.println(ledRunLts.is_fading());
  Serial.print("at time = ");
  Serial.println(ms);
#endif

  blinkLED_Run_Lts(ms);                       // Call function to blink running lights
  blinkLED_Stb_Lts(ms);                       // Call function to blink strobe lights

  if(spinUpMtrs)
  {
    if(ms - msLstMtrUpd > motorDelay)
    {
#if defined(DEVMODE)
      Serial.print("tempRPM = ");
      Serial.println(tempRPM);
#endif

      SetMotorSpeed(tempRPM);                 // Call function to set motor speed

      tempRPM++;                              // increment tempRPM by 1     
      msLstMtrUpd = ms;                       // set time counter
    }

    if(tempRPM >= RPM)
    {
      spinUpMtrs = false;                     // Fully spun up, so set variable to false
    }
  }
  else
  {
    // Motors fully spun up now, so just react to changes in motor direction switch
    // and trim pot setting
    RPM = setRPM();                           // Call function to read pot to set RPM
    SetMotorSpeed(RPM);                       // Call function to set motor speed

    CheckMotorDirSwitch(0);                   // Call function to set motor 1 direction
    CheckMotorDirSwitch(1);                   // Call function to set motor 2 direction
  }

}

// FUNCTIONS
// ---------

int setRPM(int readPotValue)
{
/*

  Function has optional parameter (int readPotValue) to set static variable first time through; each subsequent call
  excludes this parameter.

  Reads trim pot setting to determine PWM (motor speed). The exponential weighting smoothing attempts to reduce
  trim pot noise, or errant readings when it has not been touched.

  Returns: mappedVal (PWM) to calling function which can then set speed with analogWrite()

*/

  static int ewsPotVal;                             // Static variable; will retain value from previous function call but
                                                    // can only be modified by this function
#if defined(DEVMODE)
  Serial.print("optional readPotValue = " );     
  Serial.println(readPotValue);
#endif

  int newPotValue=analogRead(potPin);               // Read voltage across trim pot; this gets converted to a digital
                                                    // value between 0-1023

  if(readPotValue = 1){
    ewsPotVal = newPotValue;                        // Set ewsPotVal for first time thru function call from Setup()
  }
 
/*
  https://electronics.stackexchange.com/questions/64677/how-to-smooth-potentiometer-values

  A very simple software technique to smooth values is exponentially-weighted smoothing.
  This is a beautiful trick which allows the smoothed value to depend on all prior values,
  without retaining a history of prior samples.
*/
  ewsPotVal += (newPotValue - ewsPotVal)/4;             // optimizes to s += (sample - s) >> 2;
  int mappedVal = map(ewsPotVal, 0, 1023, minRPM, 255); // 8-bit PWM values are limited to 0-255; use map function to set RPM

#if defined(DEVMODE)
  Serial.print("ews trim pot value = " );     
  Serial.print(ewsPotVal);
  Serial.print(", motor RPM = ");
  Serial.println(mappedVal);
#endif

  return mappedVal;
}

void SetMotorSpeed(int motorSpeed)
{
/*

  Function has parameter (int motorSpeed) which is the PWM to send to both enable pins.

  Sets motor speed via 8-bit PWM signal.

  Returns: nothing

*/

  analogWrite(enablePin1, motorSpeed + motor1PWMAdj); // (allows for adjusting value depending on motor pairs)
  analogWrite(enablePin2, motorSpeed + motor2PWMAdj); // (allows for adjusting value depending on motor pairs)
}

void CheckMotorDirSwitch(int i)
{
/*

  Function has parameter (int i) which is used to determine which switch was changed.

  If the switch has changed, the motor spin direction is flipped by changing the two pins HIGH/LOW state.

  Returns: nothing

*/
  // switchPin i SPDT switch determines motor i direction
  if (digitalRead(motorPins[i*3]) == HIGH)
  {
    // TODO: if switch value has changed, spin down motor then up
    digitalWrite(motorPins[i*3 + 2], HIGH);
    digitalWrite(motorPins[i*3 + 1], LOW);
  }
  else
  {
    // TODO: if switch value has changed, spin down motor then up
    digitalWrite(motorPins[i*3 + 1], HIGH);
    digitalWrite(motorPins[i*3 + 2], LOW);
  }
}

void blinkLED_Run_Lts(unsigned long currentTime)
{
/*

  Function has parameter (unsigned long currentTime) to determine if it is now time to blink on or off the LED.

  In this case, rather than simply turn on or off the LED a fade is initiated using LEDFader. But, LED will not
  turn off or on again until the specified time has elapsed.

  Returns: nothing

*/

  static unsigned long msLast1;

  if (currentTime - msLast1 >= (ledRunLtsState ? LED_RUN_LTS_ON_DUR : LED_RUN_LTS_OFF_DUR)) {
      ledRunLtsState = !ledRunLtsState;
     
      if(ledRunLtsState == HIGH)
      {
        // Fade up
#if defined(DEVMODE)
        Serial.print("Running lights were OFF for = " );     
        Serial.println((currentTime - msLast1));
        Serial.println("Starting fade UP");
#endif

        ledRunLts.fade(255, FADE_TIME_RUN_LTS);
      }
      else
      {
        // Fade down
#if defined(DEVMODE)
        Serial.print("Running lights were ON for = " );     
        Serial.println((currentTime - msLast1));
        Serial.println("Starting fade DOWN");
#endif

        ledRunLts.fade(0, FADE_TIME_RUN_LTS);
      }
     
      msLast1 = currentTime;
  }
}

void blinkLED_Stb_Lts(unsigned long currentTime)
{
/*

  Function has parameter (unsigned long currentTime) to determine if it is now time to blink on or off the LED.

  Returns: nothing

*/
  static unsigned long msLast2;

  if (currentTime - msLast2 > (ledStbLtsState ? LED_STB_LTS_ON_DUR : LED_STB_LTS_OFF_DUR)) {
      digitalWrite(LED_STB_LTS_PIN, ledStbLtsState = !ledStbLtsState);
      msLast2 = currentTime;
  }
}

My Google drive has all the files, including the Autodesk Eagle .brd file or Gerber zip (depending on what your PCB board house requires):
https://drive.google.com/open?id=1-ePCMR8r8VtMOzJ8iLoWiqSpJdx-mtZL

https://drive.google.com/open?id=1CdCmlb8YskorC3dtHZSRbDU832buvUfF

https://drive.google.com/open?id=1lwl_mNsbvIdkf95_hbBVMyFxgqIVq7E8
« Last Edit: November 26, 2017, 07:31:05 pm by RossW »

Offline greg

  • Commander
  • ***
  • Posts: 232
  • aka SteveTheFish, TurkeyVolumeGuessingMan
    • Greg's Neat-o Homepage
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #1 on: November 27, 2017, 01:41:04 am »
Aren't those strobes and nav lights flashing a bit faster than they ought to? I don't own the TOS on DVD or anything to check, but if memory serves me, they shouldn't be at that frequency.

Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #2 on: November 27, 2017, 08:40:34 am »
Aren't those strobes and nav lights flashing a bit faster than they ought to? I don't own the TOS on DVD or anything to check, but if memory serves me, they shouldn't be at that frequency.

I spent a lot of time going over clips from the show (the original, not remastered) and after eliminating any shots where the editor had sped up or slowed down the shot I found that these timings were the most common:

  • Running (saucer) lights: 1.5 sec on, 0.5 sec off
  • Strobes (aft secondary hull): flash twice per second, on for around 0.2 sec

There were other timings for the running lights I noted during my investigation:

  • 1/2 sec (12 frames) on, 1-1/2 sec (36 frames) off (Master Replica model)
  • 3/4 sec (18 frames) on, 5/6 sec (20 frames) off ("The Corbomite Maneuver")
  • 1 sec (24 frames) on, 2/3 sec (16 frames) off (2nd pilot, Trek Ace, HobbyTalk)

The beauty of me giving everyone the code is that you can change it as you like.

Quote
const int LED_RUN_LTS_ON_DUR = (1500 - FADE_TIME_RUN_LTS*2);  // Time on in milliseconds
const int LED_RUN_LTS_OFF_DUR = 500;  // Time off in milliseconds

const int LED_STB_LTS_ON_DUR = 20;    // Time on in milliseconds
const int LED_STB_LTS_OFF_DUR = 500;  // Time off in milliseconds
« Last Edit: November 27, 2017, 08:53:22 am by RossW »

Offline Tshark

  • Ensign
  • *
  • Posts: 7
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #3 on: November 27, 2017, 11:29:53 am »
Thank you for sharing all your hard work!  I plan on adapting this to the 1/650 TOS Enterprise.  Any words of wisdom?

Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #4 on: November 27, 2017, 12:17:36 pm »
Thank you for sharing all your hard work!  I plan on adapting this to the 1/650 TOS Enterprise.  Any words of wisdom?

The main board here for controlling motor speed & direction (plus the blinking running/strobe lights) will work just fine with any scale, but my nacelle boards for the warp engine lights are sized for the 1/350 TOS E Polar Lights kit and can't be shrunk for a smaller scale. Did you perhaps mean "1/350"?

Offline Tshark

  • Ensign
  • *
  • Posts: 7
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #5 on: November 27, 2017, 12:57:50 pm »
The main board here for controlling motor speed & direction (plus the blinking running/strobe lights) will work just fine with any scale, but my nacelle boards for the warp engine lights are sized for the 1/350 TOS E Polar Lights kit and can't be shrunk for a smaller scale. Did you perhaps mean "1/350"?

This will be for the AMT 1/650 Enterprise kit.  I have looked at many bussard solutions for this kit, but yours is the most authentic.  Yes, I figured the nacelle boards would need the most modification.  I might have to change the nacelle boards to a different shape (even splitting them in half) then use it in a light box with fiber optics to the bussards.  That is just one idea.  Should be fun to figure out.

Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #6 on: November 27, 2017, 01:08:38 pm »
The main board here for controlling motor speed & direction (plus the blinking running/strobe lights) will work just fine with any scale, but my nacelle boards for the warp engine lights are sized for the 1/350 TOS E Polar Lights kit and can't be shrunk for a smaller scale. Did you perhaps mean "1/350"?

This will be for the AMT 1/650 Enterprise kit.  I have looked at many bussard solutions for this kit, but yours is the most authentic.  Yes, I figured the nacelle boards would need the most modification.  I might have to change the nacelle boards to a different shape (even splitting them in half) then use it in a light box with fiber optics to the bussards.  That is just one idea.  Should be fun to figure out.

Would love to see updates on this project - sounds intriguing!

Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #7 on: November 27, 2017, 03:26:47 pm »
Doug Drexler posted a compilation of original Enterprise effects shots a few years ago to aid the Smithsonian restoration of the 11' miniature:

https://vimeo.com/153272017

At about the 4:40 mark you can see the strobes and running lights pretty clearly, although I do think this specific shot is **slightly** speeded up. This is from the 3rd season, where I feel we got better shots of the production version of the ship as opposed to stock shots of the pilot version.


Offline rmpitzer

  • Lieutenant
  • **
  • Posts: 37
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #8 on: November 29, 2017, 01:01:55 pm »
Awesome, Ross!  I've ordered the parts to build this.  I found the motors here and ordered a pair....
http://www.circuitdiy.com/product/faulhaber-1524e006s123-6v-brushless-dc-micromotors

Do you use the gearbox on your Faulhaber 1524E006S123 motors?

Thanks for all your hard work on this, and your willingness to share the info, it's GREATLY appreciated!

-Rich

Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #9 on: November 29, 2017, 01:39:49 pm »
Awesome, Ross!  I've ordered the parts to build this.  I found the motors here and ordered a pair....
http://www.circuitdiy.com/product/faulhaber-1524e006s123-6v-brushless-dc-micromotors

Do you use the gearbox on your Faulhaber 1524E006S123 motors?

Thanks for all your hard work on this, and your willingness to share the info, it's GREATLY appreciated!

-Rich

Thanks Rich!

I removed the gears, which ain t easy. I did a Google search and found this http://www.robotshop.com/letsmakerobots/faulhaber-1524e006s123-motor-with-155s1411k832-gearhead-and-hes164a-encoder website which described how to remove the gear head. The Allen key did not work for me, so I had to drill out the screws very carefully so as not to put any pressure on the motor shaft.

I checked out your link and it would seem the motor is not exactly as pictured, as it mentions a gear head but just shows one long motor shaft. Show us a photo when you get them.

I got these bearings from Electronic Goldmine: G16273B (Pkg 4) 0.43L x 0.41 Diameter Precision Roller Bearings, but I would also recommend getting some old IBM IDE drives and taking them apart to get the platter bearing - they're very smooth but the screw thread is NOT 4/40.
« Last Edit: November 29, 2017, 02:53:49 pm by RossW »

Offline rmpitzer

  • Lieutenant
  • **
  • Posts: 37
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #10 on: November 29, 2017, 02:33:30 pm »
I removed the gears, which ain

Any tips for separating the motor from the gearbox?


Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #11 on: November 29, 2017, 02:54:24 pm »
I removed the gears, which ain

Any tips for separating the motor from the gearbox?

(Somebody has GOT to fix the problem with using single quotes)

Rich - I just updated my earlier post.

Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #12 on: November 29, 2017, 02:55:55 pm »
Oh, and the power connection to the motor is the outer two wires - the other ones are for the encoder, which you don't need.

Offline rmpitzer

  • Lieutenant
  • **
  • Posts: 37
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #13 on: November 29, 2017, 03:21:56 pm »
Ah, ok, I was thinking the bronze colored part of the motor was a gear housing, and you removed that.  Looks like you kept that in place, and removed the 90 degree gear drive in the document you linked?


Offline RossW

  • Captain
  • ****
  • Posts: 277
Re: TOS E Warp Engine Motor and Running/Strobe Lights - Custom Solution
« Reply #14 on: November 29, 2017, 05:06:43 pm »
Ah, ok, I was thinking the bronze colored part of the motor was a gear housing, and you removed that.  Looks like you kept that in place, and removed the 90 degree gear drive in the document you linked?

Correct. If yours is anything like mine, the rear part of the motor is the encoder (which you do not need but do not try to remove it - I tried it and ruined one) and the gear housing attached to the motor shaft made it 90 degrees.

 




Enterprise © Bloc