Go Down

Topic: Newbie needs assistance (Read 51734 times) previous topic - next topic


In the hope it won't cause more confusion, here's a simple fading sketch I wrote sometime ago that I forgot about...

The main point about this program is the separation between the fading algorithm (which just makes an integer run back and forth between two values) and the output function (which does something with the fading value).

The LCD code can be safely commented out or deleted.

Code: [Select]

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);    // nuelectronics lcd-shield v1.1

int numCols = 16;
int numRows = 2;

const int PWM_pin  = 3;    // change this if the led is not on pin 3
const unsigned long Fade_delayMs = 500;    // change to something like 50ms for a smooth fading
const int Fade_start  =   0;    // This can be 0 .. 254
const int Fade_end    = 255;    // this can be PWMstart+1..255

int Fade_step = 1;    // this can be increased for more coarse fading
int Fade_value;
int Fade_direction = +1;

unsigned long Fade_prevMillis;

/* to be used with the real circuit */
void pwmOut(int value) {
    analogWrite(PWM_pin, value);

/* to run a simulation */
void lcdOut(int value) {
    lcd.print(value, DEC);

void Fade_outFunc(int value) {
    // run one or both output functions...

void setup() {
    lcd.begin(numCols, numRows);

    Fade_value = Fade_start;

void loop() {
    unsigned long currentMillis = millis();

    if(currentMillis - Fade_prevMillis > Fade_delayMs) {
        Fade_prevMillis = currentMillis;

        Fade_value += Fade_direction * Fade_step;
        if (Fade_value >= Fade_end) {
            Fade_value = Fade_end;
            Fade_direction = -Fade_direction;
        else if (Fade_value <= Fade_start) {
            Fade_value = Fade_start;
            Fade_direction = -Fade_direction;



I found the forum topic where I first published the previous code.

This particular message


shows how to use the "class version" of the code.


i still have to change the delay()

You don't.

delay() is not your enemy. It is simply a tool in your toolbox for you to use. What you can do with it is entirely up to you.

I talked about this away back. One way to "unblock" long delays is to chop it down into multiple pieces.

Here is an example:

Code: [Select]

#define DLY_MIN  10  //minimum delay, in ms
void delay2(signed long dly, void (* dly2_handler)(void)){
  while (dly>=DLY_MIN) {
    dly -= DLY_MIN; //update dly
    dly2_handler(); //run my handler
  delay(dly); //delay the reminders

//fade led1
void fadeled1(void) {
  static unsigned char dc=0; //duty cycle
  static unsigned char cycle_count=0; //cycle count
  cycle_count+=1; //increment cycle count
  if (cycle_count==3) {
    cycle_count-=3; //update cycle count
    analogWrite(LED1, dc); //vary dc

void loop(void) {
  digitalWrite(LED0, !digitalRead(LED0)); //flip led0
  delay2(1000, fadeled1);  //every 1 second, while fading led1

delay2() is a form of delay, except that it chops down a long delay into small chunks (defined by DLY_MIN) and in between those chunks, it executes dly_handler(), a routine you specify. In this case, we are going to execute fadeled1(), which changes the duty cycle on led1 once every 3 times fadeled1() is called.

So LED0 is blinking every 1 second, yet LED1 is fading. You can obviously insert your own handlers for different and more complex tasks.

The bad thing about the hardware / avr is that it is single thread so it cannot truly multitask. The good thing is that it is so fast that it can handle multiple tasks in serial and gives the appearance of multitasking.

The above example shows how that can be done, as pretty much everything in life.

BTW, you can actually modify delay2() so that it looks identical to the stock delay() (taking 1 parameter, yet executing a user-specified handler).


dhenry, the OP has barely grasped blink without delay; don't you think function pointers and triadic operators are going to be a tad mind-boggling?
Some people are like Slinkies.

Not really good for anything, but they bring a smile to your face when pushed down the stairs.


Dec 27, 2012, 05:14 pm Last Edit: Dec 27, 2012, 05:37 pm by secretreeve Reason: 1
not really well rested. tenants above us was banging and crashing around all night so a little slow today. but managable. :)

groove thats not really helping. and if anything it makes more sense than blink without delay.

the problem i have with millis is i dont know its full capabilities or now to use them yet.

henry, i have changed the delay code to 6 line of delay(10), and set the State in the chaser sequence values to true,

This resolved the problem shown in both videos of the delay causing problems. However, I'm going to look at using your idea instead of the 6 lines of delay.

I have also had to rethink the pin outputs.

Originally i was going to use RGB leds in the impulse engine, nacells and deflector dish. But when i was reading around and cleaning up the pin assignments i realised i would have to use shiftregisters or something due to the lack of pins. and this would make my head spin off.

So instead i am going to use 2 leds. It also makes more sense because the fading leds are like this:

impulse engine = red and orange
deflector dish = blue and orange
nacelles = blue and violet.

Now you can buy violet leds and as each thing only fades between 2 colours it just made sense. The down side to this is, I will have to tie in the cabin lights (primary and secondary) and the flood lights into some kind of 555 based timer circuit to have them come on at specific times and being triggered from 1 pin. This isnt a problem as these come on in the first sequence and just stay on until shut down.

The other down side is im loosing the torpedo fade and RCS fade. but i dont think the studio model has those changing brightness between modes anyway so its a little more accurate.

The new pin assignments are:

Code: [Select]
cabins, 1    //this is the primary, secondary and floodlights
shuttlebaydoors, 7   //about the only thing that HASNT changed
shuttlebay, 8

impulsered, 3
impulseorange, 5

nacellsviolet, 6
nacellesblue, 9

deflectororange, 10
deflectorblue, 11

navigation, 12
strobes, 13

The final change was the shuttlebay room lights and the shuttlebay landing strips will also be on their own hardware based controller but triggered by a signal from pin 8.

Here is my code with those changes in effect, Its still fairly messy but a little bit cleaner.

Code: [Select]
void setup(){
void loop(){

long sequenceDelay = 1000;
boolean Primarystate = false;
boolean Secondarystate = false;
boolean Shuttlebaystate = false;
boolean Floodlightstate = false;
long waitUntilShuttlebay = sequenceDelay*2;
long waitUntilFloodlight = sequenceDelay*3;
long waitUntillPrimary = 0;
long waitUntillSecondary = sequenceDelay;
//definitions for fade
 int impulsered = 3;
 int impulseblue = 5;
 int nacellsviolet = 6;
 int nacellsblue = 9;
 int deflectororange = 10;
 int deflectorblue = 11;
 int brightness = 100;
 int fadeAmount = 5;
//definitions for blink and strobe
 const byte strobe =  13;
 const byte navigation = 12;
 byte strobeState = LOW;
 byte navigationState = LOW;
 unsigned long previousMillis_1 = 0;
 unsigned long previousMillis_2 = 0;
 unsigned long nextInterval_1;
 unsigned long nextInterval_2;

void setupChaser() {
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(4, OUTPUT);
void loopChaser() {
  digitalWrite(1, Primarystate);
  digitalWrite(2, Secondarystate);
  digitalWrite(4, Shuttlebaystate);
  digitalWrite(8, Floodlightstate);
  if (millis() >= waitUntillPrimary) {
     Primarystate = true;
  if (millis() >= waitUntillSecondary) {
     Secondarystate = true;
  if (millis() >= waitUntilShuttlebay) {
     Shuttlebaystate = true;
  if (millis() >= waitUntilFloodlight) {
     Floodlightstate = true;
void setupFade()  {
 pinMode(impulsered, OUTPUT);
 pinMode(impulseblue, OUTPUT);
 pinMode(deflectororange, OUTPUT);
 pinMode(deflectorblue, OUTPUT);
 pinMode(nacellsviolet, OUTPUT);
 pinMode(nacellsblue, OUTPUT);
void loopFade()  {
 analogWrite(impulsered, brightness);    
 brightness = brightness + fadeAmount;
 if (brightness == 0 || brightness == 255) {
   fadeAmount = -fadeAmount ;
   analogWrite(impulseblue, brightness);
brightness = brightness + fadeAmount;
 if (brightness == 0 || brightness == 255){
   fadeAmount = -fadeAmount ;
   analogWrite(nacellsviolet, brightness);
brightness = brightness + fadeAmount;
 if (brightness == 0 || brightness == 255){
   fadeAmount = -fadeAmount ;
   analogWrite(nacellsblue, brightness);
brightness = brightness + fadeAmount;
 if (brightness == 0 || brightness == 255){
   fadeAmount = -fadeAmount ;
 analogWrite(deflectororange, brightness);
brightness = brightness + fadeAmount;
 if (brightness == 0 || brightness == 255){
   fadeAmount = -fadeAmount ;
 analogWrite(deflectorblue, brightness);
brightness = brightness + fadeAmount;
 if (brightness == 0 || brightness == 255){
   fadeAmount = -fadeAmount ;
void setupBlink()
 pinMode(strobe, OUTPUT);  
 nextInterval_1 = 2000;  
 pinMode(navigation, OUTPUT);
 nextInterval_2 = 2000;
 }  // end of setup
void loopBlink()  {
 unsigned long currentMillis_1 = millis();
 if (currentMillis_1 - previousMillis_1 > nextInterval_1)
   previousMillis_1 = currentMillis_1;  
   if (strobeState == LOW)
     strobeState = HIGH;
     nextInterval_1 = 100;
     strobeState = LOW;
     nextInterval_1 = 8000;
   digitalWrite(strobe, strobeState);
   }  // end if time up
 unsigned long currentMillis_2 = millis();
 if (currentMillis_2 - previousMillis_2 > nextInterval_2)
   previousMillis_2 = currentMillis_2;  
   if (navigationState == LOW)
     navigationState = HIGH;
     nextInterval_2 = 100;
     navigationState = LOW;
     nextInterval_2 = 2000;
   digitalWrite(navigation, navigationState);

Of course, I'm very interested in nicks code that he posted. Although its very far beyond me until I can play with it and see how to do things with it.

so theres that, and i will also be trying to change the 6 lines of delay to henry's delay idea.

To be perfectly honest, the pin changes should have been made from the very beginning and should NOT have been screwing around with code until i had those settings locked in and finalised. So im sorry about that. I know now, and it wont happen again in the future.

I also spent an hour last night cleaning up my breadboard and getting the leds on it in the right colors and groupings.

I'll post a new video later with the sequence working correctly.

OH!!!! can anyone tell me the load resistance, controller voltage and max current per pin please? I will need to know this for the hardware side of things.



voila. Obviously, the led at the very bottom in the middle doesn't activate because thats the "visual representation" for the shuttlebay doors which i have not started the code for yet due to it being a servo control.


Code: [Select]

That's no different than "delay(60);"

The purpose to bring a large delay() into smaller chunks is so that in between those chunks, you can do something else - aka unblocking a delay().

On the bright side, you have something working.

the pin changes should have been made from the very beginning

It depends on how you code. I typically code to a logic pin and once the code is taking up shape, I start to firm up the pin assignment. The benefit of that approach is that it enhances its portability: if you were to change the pin assignment, you just need to change the defines and recompile.


Well I do feel bad because people are trying their best to help and i keep changing the pin assignments. Its not the most helpful of things in the world!

I'm going to look into changing those delay lines to what you posted, or a variation of it.


Dec 27, 2012, 08:25 pm Last Edit: Dec 27, 2012, 08:34 pm by secretreeve Reason: 1
Nick =

Here is the code you posted with the pin changes in effect.

Code: [Select]
// The Enterprise
// Author: Nick Gammon
// Date:   27 December 2012

#include <LedFader.h>
#include <LedFlasher.h>

// pin assignments
const byte StrobesPin = 13;
const byte NavigationPin = 12;
const byte DeflectorbluePin = 11;   // PWM
const byte DeflectororangePin = 10;    // PWM
const byte NacellsbluePin = 9;      // PWM
const byte ShuttlebayPin = 8;
const byte DoorsPin = 7;
const byte NacellsvioletPin = 6;   // PWM
const byte ImpulseorangePin = 5;  // PWM
const byte TorpedoPin = 4;
const byte ImpulseredPin = 3;   // PWM
const byte RCSPin = 2;
const byte CabinPin = 1;

// Faders

//                                  pin           min   max   millis  on?    stop?
LedFader impulseredFader      (ImpulseredPin,      0,   40,  3000,   false,  true);
LedFader impulseorangeFader   (ImpulseorangePin,   0,   40,  3000,   false,  true);
LedFader deflectororangeFader (DeflectororangePin, 0,   40,  3000,   false,  true);
LedFader deflectorblueFader   (DeflectorbluePin,   0,   40,  3000,   false,  true);
LedFader nacellsvioletFader   (NacellsvioletPin,   0,   40,  3000,   false,  true);
LedFader nacellsblueFader     (NacellsbluePin,     0,   40,  3000,   false,  true);

// Flashers

//                        pin          off-time  on-time       on?
LedFlasher strobes    (StrobesPin,        8000,      100,     false);
LedFlasher navigation (NavigationPin,     2000,      500,     false);

// states for the state machine
typedef enum
 // more states here
 } states;

// state machine variables
states state = initialState;
unsigned long lastStateChange = 0;
unsigned long timeInThisState = 1000;

void setup ()
 pinMode (CabinPin, OUTPUT);
 pinMode (RCSPin, OUTPUT);
 pinMode (ShuttlebayPin, OUTPUT);
 pinMode (NavigationPin, OUTPUT);
 pinMode (StrobesPin, OUTPUT);
 pinMode (TorpedoPin, OUTPUT);
 pinMode (NavigationPin, OUTPUT);

 // set up faders, flashers  
 impulseredFader.begin ();
 impulseredFader.begin ();
 deflectororangeFader.begin ();
 deflectorblueFader.begin ();
 nacellsvioletFader.begin ();
 nacellsblueFader.begin ();
 strobes.begin ();
 navigation.begin ();
 }  // end of setup

void doStateChange ()
 lastStateChange = millis ();    // when we last changed states
 timeInThisState = 1000;         // default one second between states

 switch (state)
   case initialState:
        state = wantCabin;
   case wantCabin:
        digitalWrite (CabinPin, HIGH);
        state = wantRCS;
   case wantRCS:
        digitalWrite (RCSPin, HIGH);
        state = wantDeflectororange;
   case wantDeflectororange:
        deflectororangeFader.on ();
        state = wantDeflectorblue;
   case wantDeflectorblue:
        state = wantNacellsviolet;
   case wantNacellsviolet:
        state = wantNacellsblue;
   case wantNacellsblue:
        state = wantImpulseorange;
   case wantImpulseorange:
        state = wantImpulsered;
   case wantImpulsered:
        impulseredFader.on ();
        state = wantShuttleBay;
   case wantShuttleBay:
        digitalWrite (ShuttlebayPin, HIGH);
        state = wantStrobes;
       case wantStrobes:
        state = wantNavigation;
   case wantNavigation:
        state = wantTorpedo;
   case wantTorpedo:
        digitalWrite (TorpedoPin, HIGH);

        timeInThisState = 5000;         // no rush

        // what next?
  }  // end of switch on state
 }  // end of doStateChange

void loop ()
  if (millis () - lastStateChange >= timeInThisState)
    doStateChange ();

  // update faders, flashers
  impulseorangeFader.update ();
  impulseredFader.update ();
  deflectororangeFader.update ();
  deflectorblueFader.update ();
  nacellsvioletFader.update ();
  nacellsblueFader.update ();
  navigation.update ();
  strobes.update ();

 // other stuff here like testing switches
 }  // end of loop

Honestly, i've uploaded it to the arduino and I'm almost in love with the visual appearence of the sequence. I guess it helps i can picture the led pin names floating above them. But its AWESOME! I have no idea how it works due to most of it being in the library you made. but i understand WHY it works. Which it guess is important part. because if you dont know why, then its a full stop. at least im understand the commands going through the code to make it work.

Now, I need to figure out how to control the fades, because obviously, at the moment, they all fade on, but only one of the "pairs" (deflectororange, deflector blue, would be a "pair") is meant to be on at any singular time. then later on they're told to cross fade or just fade on then the other one fades on. i dont know yet, depends on whats easiest.

BTW i know i just need to remove specific sections, like take out the case for deflectorblue if deflector orange is only supposed to be on at that time. its more the cross fading and down fading in quite keen to experiment with.

Also, i assume once i know how to control everything, i can "duplicate" that, change the setup and loop names add "setup () { setup1 setup 2}" and same for loop (not quite right i know) and use the same code essentialy for next sequence?




Also, i assume once i know how to control everything, i can "duplicate" that, change the setup and loop names add "setup () { setup1 setup 2}" and same for loop (not quite right i know) and use the same code essentialy for next sequence?

Not really. Just add more states to the state machine. Think of a state as a point in time, a line in your list you published about 10 pages back of what turns on when.

At a particular state transition you:

  • Turn on stuff

  • Turn off other stuff

You can always switch states (jump) by doing something like:

Code: [Select]

state = wantImpulsered;

However if you jump around like that you may need to make the state you choose turn things off which might be on.

Think of a state engine as a recipe in a cooking book. It might read:

  • Put roast on, wait 10 minutes.

  • Put potatoes on, wait 5 minutes.

  • Set table.

  • Put carrots on, wait 3 minutes.

  • Make gravy.

  • Take roast out to rest.

You glance at the clock (ie. you read millis) and see if it is time for the next state. Nothing complicated about it. If you want to make another roast tomorrow you go back to the first state. In between states (while stuff is cooking) you can do other things like watch the TV.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


My only concern with that is the impulse mode and warp mode have to cycle through each other in repetition until the shutdown sequence is triggers with a push button.

so its the impulse and warp loop that will give me trouble.

However, I will add in the other stages just to see how things run their course.

thank you again! Nick, i've given you credit for the code on my youtube page, im sorry its not much but i do think its important to give you credit for it!


The states can go backwards you know. So after state 50 the "next" state can be 10. So that way it loops. Just make sure that state 10 turns off anything that might be left over after state 50.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


Dec 28, 2012, 12:19 am Last Edit: Dec 28, 2012, 12:42 am by secretreeve Reason: 1
Um, not sure I follow entirely.

The only other thing is I'm getting errors because of duplicate uses. Is there an easy way around that without having lists of defines and so on longer than the operating code?


guessing not then?

Nick what did you mean about the state 50 and so on?

Go Up