Go Down

Topic: Blink without delay Macros "Simplifying the New Arduino Programmers Life" (Read 2999 times) previous topic - next topic

zhomeslice

Very much appreciate your work.
Still think a new person benefits greatly when the light comes on when they grasp BWD.

On a different topic, here are a few debug macros I use, thought you might be interested.
Welcome and Your Debug code Is greatly appropriated! I've already added it to my code and added a macro
I had a macro created for Floats I Think you will love!!!
I works with other numbers also just convert them to floats

Modified code to match your format 
Code: [Select]
#define  DPRINTLNSF(...)    {char S[30]; Serial.println(dtostrf(__VA_ARGS__ , S));}   //Variable, Width, Percision
#define  DPRINTSF(...)      {char S[30]; Serial.print(dtostrf(__VA_ARGS__ , S));}     //Variable, Width, Percision


Test Example
Code: [Select]
#define runAfter(t)          for (static unsigned long _ATimer; (unsigned long)(millis() - _ATimer) >= (t); _ATimer = millis())
#define  DPRINTLNSF(...)    {char S[30]; Serial.println(dtostrf(__VA_ARGS__ , S));}  //Variable, Width, Percision
#define  DPRINTSF(...)      {char S[30]; Serial.print(dtostrf(__VA_ARGS__ , S));}    //Variable, Width, Percision
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(123);
}

void loop() {
  // put your main code here, to run repeatedly:
  runAfter(100) {
    DPRINTSF((float) micros()*-0.001, 13, 3); //Variable, Width, Percision
    DPRINTLNSF((float) micros()*0.1, 13, 1);  //Variable, Width, Percision
  }
}


Output:
Quote
-13525.001    1352521.3
   -13624.329    1362454.9
   -13724.681    1372490.0
   -13824.009    1382422.9
   -13924.360    1392457.6
   -14024.713    1402492.9
The DPRINTSF & DPRINTLNSF macros converts the double value passed in into an ASCII representation that will be printed to the serial output.
Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the possible '.' and the possible sign for negative values) is given in width, 
The precision determines the number of digits after the decimal sign. 
width is signed value, negative for left adjustment.


Z
HC

larryd

Nice.
If you add this to DebugMacros.h remember to add the second part in the 'else' section.

#else
#define  DPRINTLNSF(...)    //
#define  DPRINTSF(...)       //


.
No technical PMs.
If you are asked a question, please respond with an answer.
If you are asked for more information, please supply it.
If you need clarification, ask for help.

zhomeslice

Nice.
If you add this to DebugMacros.h remember to add the second part in the 'else' section.

#else
#define  DPRINTLNSF(...)    //
#define  DPRINTSF(...)       //
Yep I did that and it's working great :)
Thanks again
Z
HC

zhomeslice

LarryD, I want to thank you for showing me the code that helped create this incredible powerful timer It far surpasses what I was working on. 
Thanks,
Z
Code: [Select]
// Thank you LarryD. This has become a great way to manage multiple timers thanks to your code you shared with me.
struct S_TIMER {
  unsigned long waitTime;
  bool          everyTime;
  bool          micro;
  bool          restart;
  bool          enableFlag;
  unsigned long lastTime;
  unsigned long remainingTime;

  bool CheckTime() { //Delay time expired function "CheckTime()"
    unsigned long Now = S_TIMER::GetNow();
    if (enableFlag && (((unsigned long) Now - lastTime) >= (waitTime))) { // Test Timer
      if (restart) lastTime = (everyTime) ? (lastTime + waitTime) : Now; //get ready for the next iteration Every or (After) Has Different affects
      return true; // Timer Finished
    }
    return false; // Still Waiting
  } //END of CheckTime()

  void init(unsigned long wT, bool eT = false, bool m = false, bool r = true, bool eF = true) {
    waitTime = wT; // The Delay
    everyTime = eT;
    micro = m;
    restart = r;
    enableFlag = eF;
  }//END of init()

  unsigned long GetNow() {
    return ((micro) ? micros() : millis());
  }

  void stopTimer() {
    remainingTime = S_TIMER::GetNow() - lastTime;
    enableFlag = false;
  }

  void startTimer() {
    lastTime = S_TIMER::GetNow() + remainingTime;
    enableFlag = true;
  }

  void resetTimer(bool r = true) {
    lastTime = S_TIMER::GetNow();
    restart = r;
    enableFlag = true;
  }
}; //END of structure timer

#define Create_S_TIMER(ID)   S_TIMER STMR_##ID
#define Init_S_TIMER(ID,args...)     STMR_##ID.init(args)          // (waitMillis, everyTime, restart, enableFlag)  Sets the initial behavior of the timer
#define Check_S_TIME(ID)             STMR_##ID.CheckTime()         // Check Timer
#define SetTime_S_TIMER(ID,Time)     STMR_##ID.waitTime = Time     // Change the timers delay time
#define Time_S_TIMER(ID)             STMR_##ID.waitTime            // Access the timers delay time
#define SetLastTime_S_TIMER(ID,Time) STMR_##ID.lastTime  = Time    // Change the timers last time
#define LastTime_S_TIMER(ID)         STMR_##ID.lastTime            // Access the timers last time
#define Stop_S_TIME(ID)              STMR_##ID.stopTimer()         // Pauses Timer
#define Start_S_TIME(ID)             STMR_##ID.startTimer()        // Start Timer Where it left off << Rollover issue HELP
#define Pause_S_TIME(ID)             STMR_##ID.restart = false     // Pauses Timer at end of timing WARNING CheckTimer() returns true at end of timing event and wont reset to false
#define Reset_S_TIME(ID,args...)     STMR_##ID.resetTimer(args)    // Reset and args (restart bool default true) timer
#define Every_S_TIME(ID)             STMR_##ID.everyTime = true    // By adding waitMillis to lastMillis timing will always shift by (waitMillis)
#define After_S_TIME(ID)             STMR_##ID.everyTime = false   // By shifting to millis() the next time interval will always be (waitMillis) long
#define This_S_TIME(ID)              STMR_##ID                     // Get the name of the Structure for Direct Access This_S_TIME(ID).lastMillis for example

Create_S_TIMER(Spam); // Create timer object

void setup() {
  Serial.begin(115200);
  Init_S_TIMER(Spam, 100, true); // Set the timer for 100 ms and it is additive triggere every 100 ms no matter how long the other code takes in between
  SetLastTime_S_TIMER(Spam, 0); // Sets the timer to start at zero miliseconds
}

void loop() {
  if (Check_S_TIME(Spam)) {
    Serial.println(millis());
    if (LastTime_S_TIMER(Spam) == 2000) {
      Stop_S_TIME(Spam);
      delay(500);
      Start_S_TIME(Spam);
    }
  }
}
HC

kowalski

@zhomeslice
I have implemented something similar but as a C++ class. This avoids many of the problems with macros. A class is much easier to use with arrays, etc.

Please see https://github.com/mikaelpatel/Arduino-Timemark and the example sketches.

Cheers!

jimLee

Maybe the inability to "get" BWoD is "survival of the fittest" in action. (Programming red in tooth and claw) :)

...R
This made me laugh.

You are spot on with that statement.

-jim lee
PNW Ardiuno & Maker club
1012 9Th Street, Anacortes, WA 98221 (Around the back of building)

zhomeslice

@zhomeslice
I have implemented something similar but as a C++ class. This avoids many of the problems with macros. A class is much easier to use with arrays, etc.

Please see https://github.com/mikaelpatel/Arduino-Timemark and the example sketches.

Cheers!
kowalski, Thanks for the link :)

I have shifted gears and reserved macros for Debug only code, Meanwhile I have generated a class also that similar functionality to yours with more features.
I have made dramatic changes to the direction I was going after finally determining how to handle callbacks you might be interested int seeing what has come about.
http://forum.arduino.cc/index.php?topic=437642.new;topicseen#new
I am always up for suggestions and ideas to continue to enhance the timer code.
Z


I have limited the for() macro timer to my Debug Macros, Here they are as of now:
The first macro is my timer to prevent spam during debug output
Code: [Select]
#define DEBUG
//#define DPRINT(args...)  Serial.print(args)             //OR use the following syntax:
#define DPRINTSTIMER(t)    for (static unsigned long SpamTimer; (unsigned long)(millis() - SpamTimer) >= (t); SpamTimer = millis())
#define SERIALBEGIN(...)   Serial.begin(__VA_ARGS__)
#define DPRINT(...)        Serial.print(__VA_ARGS__)
#define DPRINTLN(...)      Serial.println(__VA_ARGS__)
#define DPRINTF(...)       Serial.print(F(__VA_ARGS__))   //Printing text using the F macro
#define DPRINTLNF(...)     Serial.println(F(__VA_ARGS__)) //Printing text using the F macro
#define DPRINTSFN(StrSize,Name,...) {char S[StrSize];Serial.print("\t");Serial.print(Name);Serial.print(" "); Serial.print(dtostrf((float)__VA_ARGS__ ,S));}//StringSize,Name,Variable,Spaces,Percision
#define DPRINTSF(...)      {char S[30]; Serial.print(dtostrf((float)__VA_ARGS__ , S))}//Variable,Spaces,Percision
#define DPRINTLNSF(...)    {char S[30]; Serial.print(dtostrf((float)__VA_ARGS__ , S))}//Variable,Spaces,Percision
#define DELAY(...)         delay(__VA_ARGS__)
#define PINMODE(...)       pinMode(__VA_ARGS__)
#define TOGGLEd13          PINB = 0x20                    //For the UNO only

#else
#define DPRINTSTIMER(t)    if(false)
#define SERIALBEGIN(...)   //blank line
#define DPRINT(...)        //blank line
#define DPRINTLN(...)      //blank line
#define DPRINTF(...)       //blank line
#define DPRINTSFN(...)     //blank line
#define DPRINTSF(...)      //blank line
#define DPRINTLNSF(...)    //blank line
#define DPRINTLNF(...)     //blank line
#define DELAY(...)         //blank line
#define PINMODE(...)       //blank line
#define TOGGLEd13          //blank line

#endif
//***************************************************************


usage
Code: [Select]
#define DEBUG
//......
float N = 55.298;
float out = -96.2222;
int test = -1000;
DPRINTSTIMER(100){
  DPRINTSFN(10,"MyVar",N,6,2);  // String size, "Name" Var
  DPRINTSFN(15,"Output",Out,8,3);
  DPRINTSFN(10,"Test",test,7,0);
  DPRINTLN();
}
HC

Go Up