Arduino and Trinket Pro 5V

All,

I am considering including this sketch to flash 3 LEDs in a random pattern.

Would someone please paste this sketch into the completed fade up/dn sketch above. It will be helpful to me to see how it's possible to include 2 or more sketches into one.

int red = 2;
int intervalRed = 1000; //how long to delay in millis
unsigned long previousRed = 0;
int redState = LOW;

int blue = 3;
int intervalBlue = 2500; //how long to delay in millis
unsigned long previousBlue = 0;
int blueState = LOW;

int green = 4;
int intervalGreen = 5000; //how long to delay in millis
unsigned long previousGreen = 0;
int greenState = LOW;

void setup() {
  Serial.begin(9600);
  pinMode(red, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(green, OUTPUT);
}

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

  if (currentMillis - previousRed >= intervalRed) {
    //save this reading!
    previousRed = currentMillis;

    //figure out if you should turn the LED on or off
    if (redState == LOW) {
      redState = HIGH;
    } else {
      redState = LOW;
    }
    digitalWrite(red, redState);
  }
}

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

  if (currentMillis - previousGreen >= intervalGreen) {
    //save this reading!
    previousGreen = currentMillis;

    //figure out if you should turn the LED on or off
    if (greenState == LOW) {
      greenState = HIGH;
    } else {
      greenState = LOW;
    }
    digitalWrite(green, greenState);
  }
}

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

  if (currentMillis - previousBlue >= intervalBlue) {
    //save this reading!
    previousBlue = currentMillis;

    //figure out if you should turn the LED on or off
    if (blueState == LOW) {
      blueState = HIGH;
    } else {
      blueState = LOW;
    }
    digitalWrite(blue, blueState);
  }
}


void loop() {
  checkRed();
  checkGreen();
  checkBlue();
}

All,

I am struggling with how to merge random 3 Led flashing sketch with Sterretje's fade sketch.

Any assistance is appreciate

That should be a matter of below and call checkBlue() from loop().

/*
  blink the blue led
*/
void checkBlue()()
{
  // the current state
  static int blueState = LOW;
  // time when an update of the blue led is required
  static uint32_t nextTime;
  // the current time
  uint32_t currentTime = millis();

  // if it's time to update the blue
  if (currentTime >= nextTime)
  {
    // set the next time
    nextTime += blueInterval;

    if (blueState == LOW)
    {
      blueState = HIGH;
    }
    else
    {
      blueState = LOW;
    }
    digitalWrite(blue, blueState);
  }
}

Note that I'm quite fond of static variables. It prevents that you accidentally modify it in e.g. checkGreen due to a copy and paste mistake.

I don't see your random requirement in here :wink:

I was a little fast with the last post keeping it in line with my previous code.

Actually I should have asked the question what happens when you put e.g. your checkBlue() in my program and call it from my loop()?

Hi,

Will not be able to run your sketch to checkblue until Sunday evening.

For my two separate random flash sketches, I would like a variable to set how long each LED is on and off. Another variable to set the flashing rate for each random sketch.

Thanks for all your help.

Sterretje,

Having difficulty running your BlueLed flash code. Keep getting the following message.

exit status 1
'CommLed1interval' was not declared in this scope

Would you please correct my mistake.


/*
  blink CommLed1
*/

int CommLed1 = 5;
//int intervalCommLed1 = 1000;
//int CommLed1=LOW;

void setup()
{
  pinMode(CommLed1, OUTPUT);
}

void checkCommLed1() {

  // the current state
  static int CommLed1State = LOW;
  // time when an update of CommLed1 is required
  static uint32_t nextTime;
  // the current time
  uint32_t currentTime = millis();

  // if it's time to update the blue
  if (currentTime >= nextTime)
  {
    // set the next time
    nextTime += CommLed1interval;

    if (CommLed1State == LOW)
    {
      CommLed1State = HIGH;
    }
    else
    {
      CommLed1State = LOW;
    }
    digitalWrite(CommLed1, CommLed1State);
  }
}


void loop() {
  // put your main code here, to run repeatedly:
  checkCommLed1();


}

In your earlier code, you had e.g. the above; you will have to declare the variable CommLedInterval in the same way.
Note that variables related to millis() timing should be unsigned variables. So

uint16_t CommLedInteval = 1000;

Sterretje,

Finally got your code to work. Seems to do the job.
Here is the working code, is this what you were expecting me to do?

/*
blink CommLed1
*/

int CommLed1 = 5;
uint16_t CommLed1Interval = 1500;
//int intervalCommLed1 = 1000;
//int CommLed1=LOW;

void setup()
{
pinMode(CommLed1, OUTPUT);
}

void checkCommLed1() {

// the current state
static int CommLed1State = LOW;
// time when an update of CommLed1 is required
static uint32_t nextTime;
// the current time
uint32_t currentTime = millis();

// if it's time to update the blue
if (currentTime >= nextTime)
{
// set the next time
nextTime += CommLed1Interval;

if (CommLed1State == LOW)
{
  CommLed1State = HIGH;
}
else
{
  CommLed1State = LOW;
}
digitalWrite(CommLed1, CommLed1State);

}
}

void loop() {
// put your main code here, to run repeatedly:
checkCommLed1();

}```

That looks good.

Some comments:

  1. The pin for the led will never change; you can make that a constant as I did in post #17
const int CommLed1 = 5;
  1. If you run low on dynamic memory, you can change the int to a byte in above.
  2. The static variable CommLed1State does not have to be be the full name; the variable is only known inside the function so you can have multiple functions with the same variable (e.g. ledState).

Regarding your random; do you want a random interval for each led or do you want a random LED out of e.g. the 3.

I'm thinking random interval would be best.

Believe I'm actually learning something.

Thanks for all your support and suggestions.

Left the pin for the led the same name. This way I know which led is assigned to it's output.
I did rename all the static variables are you suggested, code still works.

My 3 random (or not so random) blink pattern, sometimes all 3 outputs are on. Is there a way to improve the pattern so all 3 outputs don't turn on at a regular interval?

Yes. Currently the interval is fixed and on-time equals off-time as well. I will try to work something out (with explanation), probably tomorrow;it will be a bit more advanced.

In post #21, you grouped related info for a led as shown below

You can now take that a step further and place the related info of a led in a class or a struct; I'm more of a C programmer than a C++ programmer and will use a struct. A struct is like an entry in a phone book with a name and a phone number and possibly some other information (like address).

struct BLINKER
{
  const uint8_t pin;
  const uint32_t interval;
  uint32_t nextTime;
  uint8_t ledState;
};

Note that you can use any name, BLINKER was just what came up in my mind.

And you can now define a BLINKER variable as shown below

BLINKER blinkerRed =
{
  2, 1000, 0, LOW
};

And repeat for blue and green. It however is better to use an array for those

BLINKER blinkers[] =
{
  {2, 1000, 0, LOW},  // red
  {3, 2500, 0, LOW},  // green
  {4, 5000, 0, LOW},  // blue
};

You can rename blinkers to e.g. commLeds. You can add a second BLINKER array for your other two leds or add them in the blinkers array.

In setup(), you can now loop through the array elements and make all pins output. The fields in a BLINKER element can be accessed with a dot as shown below.

  for (uint8_t cnt = 0; cnt < 3; cnt++)
  {
    pinMode(blinkers[cnt].pin, OUTPUT);
  }

This is primitive, if you ever add another element to or remove one from the array you will have to adjust the '3' to '4' or to '2' etc. You might forget that and hence we add a macro that can calculate this for you; see below which will show the omplete code till now.

// macro to calculate number of elements in (any type of) array
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

// struct with blinker info
struct BLINKER
{
  const uint8_t pin;
  const uint16_t interval;
  uint32_t nextTime;
  uint8_t ledState;
};

BLINKER blinkers[] =
{
  {2, 1000, 0, LOW},  // red
  {3, 2500, 0, LOW},  // green
  {4, 5000, 0, LOW},  // blue
};

void setup()
{
  // serial for debugging
  Serial.begin(57600);

  // loop through the blinker leds and set pin mode
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(blinkers); cnt++)
  {
    pinMode(blinkers[cnt].pin, OUTPUT);
    Serial.print("Pin ");
    Serial.print(blinkers[cnt].pin);
    Serial.println(" set to output");
  }
}

void loop()
{
}

In the next step, we write a function as you already did in post #28, but it will be more universal and takes a BLINKER as an argument.

/*
  blink a led
  In:
    led info
*/
void blinkLed(BLINKER &blinker)
{
  // the current time
  uint32_t currentTime = millis();

  // if it's time to update the blue
  if (currentTime >= blinker.nextTime)
  {
    // set the next time
    blinker.nextTime += blinker.interval;

    // toggle the led state
    if (blinker.ledState == LOW)
    {
      blinker.ledState = HIGH;
    }
    else
    {
      blinker.ledState = LOW;
    }
    // set the led
    digitalWrite(blinker.pin, blinker.ledState);

    Serial.print(currentTime);
    Serial.print("\tPin ");
    Serial.print(blinker.pin);
    Serial.print(" set to ");
    Serial.println(blinker.ledState);
  }
}

The & in front of blinker indicates that we pass a reference; this is needed so the nextState and ledState can be updated; I will leave the technical reasoning out as I don't think that you're ready for that (but you can ask if you want to know). The alternative is to use a pointer and the -> to access the field.

Note that for a second array, you don't need an additional function, you can call this function.

And in loop() you can iterate through the array.

void loop()
{
  // loop through the blinker leds and toggle if needed
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(blinkers); cnt++)
  {
    blinkLed(blinkers[cnt]);
  }
}

Now we have, from a functionality perspective, not gained anything; the program became smaller as there is no duplication of functions. To get to a less static pattern, you can modify the BLINKER struct to contain a minimum interval and a maximum interval.

struct BLINKER
{
  const uint8_t pin;
  const uint32_t minInterval;
  const uint32_t maxInterval;
  uint32_t nextTime;
  uint8_t ledState;
};

And the definition can be e.g.

BLINKER blinkers[] =
{
  {2, 500, 1000, 0, LOW},  // red
  {3, 250, 2500, 0, LOW},  // green
  {4, 100, 5000, 0, LOW},  // blue
};

And in blinkLed(), you can change blinker.nextTime += blinker.interval; to use a random number between minInterval and maxInterval.

    blinker.nextTime += random(blinker.minInterval, blinker.maxInterval + 1);

The + 1 is used to include the specified maxInterval

Note that the random intervals are not really random; e.g. every time you reset the Arduino, you will have the same sequence. You can improve the situation a little by using a call to randomSeed() and seed the random number generator. You will need to use an analog input for this that is not connected to anything; in the below full code A0 is used.

// macro to calculate number of elements in (any type of) array
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

// struct with info related to blinking a led
struct BLINKER
{
  const uint8_t pin;
  const uint16_t minInterval;
  const uint16_t maxInterval;
  uint32_t nextTime;
  uint8_t ledState;
};

// blinking leds
BLINKER blinkers[] =
{
  {2, 500, 1000, 0, LOW},  // red
  {3, 250, 2500, 0, LOW},  // green
  {4, 100, 5000, 0, LOW},  // blue
};


void setup()
{
  // serial for debugging
  Serial.begin(57600);

  // seed the random number generator
  randomSeed(analogRead(A0));

  // loop through the blinker leds and set pin mode
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(blinkers); cnt++)
  {
    pinMode(blinkers[cnt].pin, OUTPUT);
    Serial.print("Pin ");
    Serial.print(blinkers[cnt].pin);
    Serial.println(" set to output");
  }
}

void loop()
{
  // loop through the blinker leds and toggle if needed
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(blinkers); cnt++)
  {
    blinkLed(blinkers[cnt]);
  }
}

/*
  blink a led
  In:
    led info
*/
void blinkLed(BLINKER &blinker)
{
  // the current time
  uint32_t currentTime = millis();

  // if it's time to update the blue
  if (currentTime >= blinker.nextTime)
  {
    // set the next time
    blinker.nextTime += random(blinker.minInterval, blinker.maxInterval + 1);

    // toggle the led state
    if (blinker.ledState == LOW)
    {
      blinker.ledState = HIGH;
    }
    else
    {
      blinker.ledState = LOW;
    }
    digitalWrite(blinker.pin, blinker.ledState);

    Serial.print(currentTime);
    Serial.print("\tPin ");
    Serial.print(blinker.pin);
    Serial.print(" set to ");
    Serial.println(blinker.ledState);
  }
}

// Edit
changed second blinker from 13 to 3 in the final code

All your examples look like they are well explained. There is a lot of information to digest, I will need a couple of days to experiment with the examples you sent.

Thanks,