Go Down

Topic: Yet ANOTHER millis() blink with different on/off durations (Read 216 times) previous topic - next topic

lastchancename

I was bored this evening - so here's the same old' millis() blink - but showing different on/off durations.
Indenting has been pushed - to help identify the separate blocks of code!
Also demonstrates conditional compilation with #define #ifdef and #endif

Code: [Select]
//----------------------------------------------
// BLINK ON-BOARD LED using millis()
// Demonstrating variable length on/off duration.
// Also illustrate using a function() without parameters
//----------------------------------------------
#define SERIAL_COMMENTS  115200 //comment-out, UNDEFine or delete if not required
//----------------------------------------------
#define LED_pin 13  // ths inbuilt UNO LED
//----------------------------------------------
unsigned long state_started_at;

// these /could/ be a smaller data type - sufficient to hold the durations
unsigned long blink_on_duration = 100;  // mSecs LED on
unsigned long blink_off_duration = 1000;  // mSecs LED off

bool LED_state = LOW;  // initial state will be toggled as part of setup()

//----------------------------------------------
// set the LED pin direction to OUTPUT, and enable Serial if it is needed
// then send the initial LED_state out to the LED
//----------------------------------------------
void setup() {
pinMode (LED_pin, OUTPUT);
#ifdef SERIAL_COMMENTS  // these lines can be deleted if you understand the code
// ensure serial is opened -before- calling toggle - so the LED_state can be displayed !
Serial.begin(SERIAL_COMMENTS);
#endif
toggle_LED(); // call a function to invert the LED_state
}

//----------------------------------------------
void loop() {
// depending on prevailing state and period - toggle LED to the 'other' state
if (LED_state) { // if the LED state is currently ON
// and the ON duration has elapsed
if (millis() - state_started_at >= blink_on_duration) {
#ifdef SERIAL_COMMENTS  // these lines can be deleted if you understand the code
Serial.print("ON duration elapsed...");
#endif
toggle_LED();
}
} else { // then, the LED state must be OFF
// and the OFF duration has elapsed
if (millis() - state_started_at >= blink_off_duration) {
#ifdef SERIAL_COMMENTS  // these lines can be deleted if you understand the code
Serial.print("OFF duration elapsed...");
#endif
toggle_LED();
}
}
}

//----------------------------------------------
// change the LED state from on->off and vice-versa with each call
//----------------------------------------------
void toggle_LED() {
LED_state = !LED_state;  // invert the LED_state variable
#ifdef SERIAL_COMMENTS  // these lines can be deleted if you understand the code
//------------------------
if (LED_state)
Serial.println ("TURN ON");
else
Serial.println ("TURN OFF");
#endif
//------------------------
// start a new duration for current LED_state
state_started_at = millis();
digitalWrite(LED_pin, LED_state);  // push it out to the LED
}
//----------------------------------------------
Q: How many searches did you make before posting this question?      A: none
At the very least, take a guess at the solution, then we can help move forward from what you know already.

UKHeliBob

Personally I would favour something like this
Code: [Select]

const byte ledPin = 13;
const unsigned long durations[] = {1000, 100};
byte indexToDurations = 0;
unsigned long startTime;

void setup()
{
  pinMode(ledPin, OUTPUT);
  startTime = millis();
}

void loop()
{
  if (millis() - startTime >= durations[indexToDurations])
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    startTime = startTime + durations[indexToDurations];
    indexToDurations = !indexToDurations;
  }
}
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

lastchancename

Yes, i agree if the purpose is solely to perform on/off blinking, but I feel it introduces too many skills inline for a beginner.  - Indexing, arrays etc.

(I did consider folding the conditional block into a single line, but figured leaving it open would help newbies see the logoc more easily)

Most are looking for an understanding of why/how mills() can replace delay()
Good shot though, everything helps beginners grasp a bit more.

Cheers.
Q: How many searches did you make before posting this question?      A: none
At the very least, take a guess at the solution, then we can help move forward from what you know already.

UKHeliBob

The inclusion of an array and an index index was deliberate as, I assume, was your use of a function and the scary looking #defines and #ifdefs, to say nothing of the truly nutty formatting.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

larryd

For serial comments consider something like this:
Code: [Select]
// DebugMacros.h

/* Example of use:
   #define DEBUG          // <-----<<<< this line must appear before the include line
   #include <DebugMacros.h>
*/

//If you comment the line:  #define DEBUG
//The Macro lines are defined as blank, thus would be ignored by the compiler.
//If the line is NOT commented, these macros will be included in the sketch.
// examples:
// This  converts to         >>>>----->         This OR a Blank Line.
//--------------------------------------------------------------------------------------------
// DPRINTLN("Testing123");   >>>>----->     Serial.println("Testing123");
// DPRINTLN(0xC0FFEEul,DEC); >>>>----->     Serial.println(0xC0FFEEul,DEC);
// DPRINTLN(12648430ul,HEX); >>>------>     Serial.println(12648430ul,HEX);
// DPRINTLNF("This text came from flash");  Serial.println(F("This text came from flash"));
// DPRINT(myVariable);       >>>>----->     Serial.print(myVariable);
// DELAY(100);               >>>>----->     delay(100);
// SERIALBEGIN(9600);        >>>>----->     Serial.begin(9600);
// PINMODE(13,OUTPUT);       >>>>----->     pinMode(13,OUTPUT);
// TOGGLEd13;                >>>>----->     PINB = 0x20;  // D13 Toggle,for UNO ONLY
 
#ifdef DEBUG
//#define DPRINT(args...)  Serial.print(args)             //OR use the following syntax:
#define SERIALBEGIN(...)   Serial.begin(__VA_ARGS__)
#define DPRINT(...)        Serial.print(__VA_ARGS__)
#define DPRINTLN(...)      Serial.println(__VA_ARGS__)
#define DRINTF(...)        Serial.print(F(__VA_ARGS__))
#define DPRINTLNF(...)     Serial.println(F(__VA_ARGS__)) //Printing text using the F macro
#define DELAY(...)         delay(__VA_ARGS__)
#define PINMODE(...)       pinMode(__VA_ARGS__)
#define TOGGLEd13          PINB = 0x20                    //For the UNO only
 
#else
#define SERIALBEGIN(...)   //blank line
#define DPRINT(...)        //blank line
#define DPRINTLN(...)      //blank line
#define DPRINTF(...)       //blank line
#define DPRINTLNF(...)     //blank line
#define DELAY(...)         //blank line
#define PINMODE(...)       //blank line
#define TOGGLEd13          //blank line
 
#endif
//***************************************************************
 
 



Consider this kind of format for updating a timing variable.
Code: [Select]
while ( currentMillis - millisOne >= delayTime )
    {
      millisOne = millisOne + delayTime;
    }


No technical PMs.
The last thing you did is where you should start looking.

Go Up