Arduino Forum

Community => Exhibition / Gallery => Topic started by: lastchancename on May 16, 2017, 10:07 am

Title: Yet ANOTHER millis() blink with different on/off durations
Post by: lastchancename on May 16, 2017, 10:07 am
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
}
//----------------------------------------------
Title: Re: Yet ANOTHER millis() blink with different on/off durations
Post by: UKHeliBob on May 16, 2017, 01:24 pm
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;
  }
}
Title: Re: Yet ANOTHER millis() blink with different on/off durations
Post by: lastchancename on May 16, 2017, 08:55 pm
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.
Title: Re: Yet ANOTHER millis() blink with different on/off durations
Post by: UKHeliBob on May 16, 2017, 09:08 pm
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.
Title: Re: Yet ANOTHER millis() blink with different on/off durations
Post by: larryd on May 16, 2017, 10:02 pm
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;
    }