Joined Sep 14, 2020
16
Scheduler_example00_Blink is ~300 lines. For just an Arduino Uno, what is a minimal example?

It's hard to know what belongs and what doesn't. This example has six different approaches, and I'm just trying to extract one of them.

This website allows compilation and run of the program: wokwi.com/playground/task-scheduler
(I tried deleting sections of the program to reduce it down to one method, but get different errors each time.)

Joined Sep 14, 2020
16
By method I mean "approach."

djsfantasi

Joined Apr 11, 2010
7,551
The Scheduler_example_blink is a lot of code to digest... Is there a member here who has used it?

Plus, if you “get different errors” each time, don’t you think it would be helpful if you told us what they were? My crystal ball is in the shop.

If we knew what you changed and the errors (in detail) that occurred, perhaps we’d have a chance to help.

Joined Sep 14, 2020
16
Plus, if you “get different errors” each time, don’t you think it would be helpful if you told us what they were?
Variables. It seems sections are somehow dependent on each other.
I'm not sure if each "approach" corresponds to "// === # ==========================================" for each number.

The link has the full program, so you can see errors or "Build failed!" when taking out sections 2-6 or just 6 and various combinations. I could list all the "Build failed!" and errors for each specific case, but I don't think that'd be useful.

Joined Sep 14, 2020
16
Here is one error. I took out approaches 2-6, and what I assume to be the corresponding sections below void loop, I took out 2-6:
Code:
'tBlink2' was not declared in this scope
suggested alternative: 'tBlink1'
This is a variable in approach 2. So I put that approach back in, and it says "Build failed!" I can run it through the real Arduino IDE, but I think I did that earlier today, and it's just a cascade of errors until most of the original program is back... which defeats the whole purpose of minimizing it. I just want to get one method, alone, to work. This way I can use one of the methods in a separate program.

Yaakov

Joined Jan 27, 2019
2,353
Here is one error. I took out approaches 2-6, and what I assume to be the corresponding sections below void loop, I took out 2-6:
Code:
'tBlink2' was not declared in this scope
suggested alternative: 'tBlink1'
This is a variable in approach 2. So I put that approach back in, and it says "Build failed!" I can run it through the real Arduino IDE, but I think I did that earlier today, and it's just a cascade of errors until most of the original program is back... which defeats the whole purpose of minimizing it. I just want to get one method, alone, to work. This way I can use one of the methods in a separate program.
“Cargo cult” programming is a very bad approach. Copy-pasting bits of code that “work” is sure to make the program you are writing unstable. Instead of blindly cutting away code, you really need to dig into it and understand how and why it works.

I can’t tell you how much unstable spaghetti code I’ve had to deal with, some of it written by me!

There is a principle when commenting code: don’t write comments about what code is doing, the code tells you that, comment on why you wrote the code that way. This is called being kind to the maintenance programmer, who, a very large percentage of the time, will be you!

In the same vein, cargo cult coding means that future you will be unable to untangle the progress that past you spent a considerable time sawing, filing, gluing, and taping together from parts you didn’t understand even then.

Work through the code example and when you can separately use one of the methods without (much) mystery, add it to your program, comment it, and enjoy the splendor of dong The Right Thing®.

[EDIT] For those not familiar with the "cargo cult" and how it relates to programming, Wikipedia has a pretty good write-up: https://en.wikipedia.org/wiki/Cargo_cult_programming

Last edited:

djsfantasi

Joined Apr 11, 2010
7,551
Here is one error. I took out approaches 2-6, and what I assume to be the corresponding sections below void loop, I took out 2-6:
Code:
'tBlink2' was not declared in this scope
suggested alternative: 'tBlink1'
This is a variable in approach 2. So I put that approach back in, and it says "Build failed!" I can run it through the real Arduino IDE, but I think I did that earlier today, and it's just a cascade of errors until most of the original program is back... which defeats the whole purpose of minimizing it. I just want to get one method, alone, to work. This way I can use one of the methods in a separate program.
Excellent article from @Yaakov I must admit I was gobsmacked by your response.

I don’t want to underestimate you. Can you describe your programming background?

I feel that you don’t understand what this example is doing. And that is leading you to incorrect assumptions.

You cannot just snip out a piece of code from a larger program without understanding each line of code and what all of the variables purpose, definition and scope. That leads to the kind of errors you’ve posted. And, without the details I requested and with a 300 line sketch, there is no way to address the issues in a meaningful way. That’s why I’ve been silent for so long.

So, the source of all your errors is an inability to understand what the code is, it’s structure and “Data, data, data”. The later is a personal quote based on my belief that “The data is the code”.

Joined Sep 14, 2020
16
It's nice that you're trying to help, but has anyone looked at the program? (It's much easier to say general things rather than get into the dirty details of the program itself.) Also, I'm not doing cargo cult programming. I'm trying to get a minimal example to work from the multi-example program. That way, I would understand how to integrate the Task Scheduler library into a different program (to replace delay).

It looks and the error messages suggest that each approach is linked together. However, if I comment out the linked part, undefined reference errors result:

C++:
// === 1 =======================================
bool LED_state = false;
_PP(millis());
_PL(": Blink1 - simple flag driven");
LED_state = false;
}

if ( LED_state ) {
LEDOff();
LED_state = false;
}
else {
LEDOn();
LED_state = true;
}
//  if ( tBlink1.isLastIteration() ) {
//    LEDOff();
//  }
}
Errors:

Code:
C:\Users\user\AppData\Local\Temp\cc39Gvct.ltrans0.ltrans.o: In function global constructors keyed to 65535_0_21_3_23_taskScheduler.ino.cpp.o.1918':
<artificial>:(.text.startup+0xc4): undefined reference to blink2CB_ON()'
<artificial>:(.text.startup+0xe4): undefined reference to blink3CB()'
<artificial>:(.text.startup+0x104): undefined reference to blink41OE()'
<artificial>:(.text.startup+0x10c): undefined reference to blink41()'
<artificial>:(.text.startup+0x12c): undefined reference to blink42OD()'
<artificial>:(.text.startup+0x138): undefined reference to blink42()'
<artificial>:(.text.startup+0x15c): undefined reference to blink51OE()'
<artificial>:(.text.startup+0x164): undefined reference to blink51()'
<artificial>:(.text.startup+0x184): undefined reference to blink52OD()'
<artificial>:(.text.startup+0x190): undefined reference to blink52()'
<artificial>:(.text.startup+0x1b0): undefined reference to blink6OD()'
<artificial>:(.text.startup+0x1b8): undefined reference to blink6OE()'
<artificial>:(.text.startup+0x1c0): undefined reference to blink6CB()'
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino Uno.

Joined Sep 14, 2020
16
"Work through the code example and when you can separately use one of the methods"--that's part of the problem. That's what I've been trying to do. Each approach is linked to the next. I don't know how to get just one method/approach to work. That is the question I'm asking.

Yaakov

Joined Jan 27, 2019
2,353
It's nice that you're trying to help, but has anyone looked at the program? (It's much easier to say general things rather than get into the dirty details of the program itself.) Also, I'm not doing cargo cult programming. I'm trying to get a minimal example to work from the multi-example program. That way, I would understand how to integrate the Task Scheduler library into a different program (to replace delay).

It looks and the error messages suggest that each approach is linked together. However, if I comment out the linked part, undefined reference errors result:

C++:
// === 1 =======================================
bool LED_state = false;
_PP(millis());
_PL(": Blink1 - simple flag driven");
LED_state = false;
}

if ( LED_state ) {
LEDOff();
LED_state = false;
}
else {
LEDOn();
LED_state = true;
}
//  if ( tBlink1.isLastIteration() ) {
//    LEDOff();
//  }
}
Errors:

Code:
C:\Users\user\AppData\Local\Temp\cc39Gvct.ltrans0.ltrans.o: In function global constructors keyed to 65535_0_21_3_23_taskScheduler.ino.cpp.o.1918':
<artificial>:(.text.startup+0xc0): undefined reference to blink2CB_ON()'
<artificial>:(.text.startup+0xe0): undefined reference to blink3CB()'
<artificial>:(.text.startup+0x100): undefined reference to blink41OE()'
<artificial>:(.text.startup+0x108): undefined reference to blink41()'
<artificial>:(.text.startup+0x128): undefined reference to blink42OD()'
<artificial>:(.text.startup+0x134): undefined reference to blink42()'
<artificial>:(.text.startup+0x158): undefined reference to blink51OE()'
<artificial>:(.text.startup+0x160): undefined reference to blink51()'
<artificial>:(.text.startup+0x180): undefined reference to blink52OD()'
<artificial>:(.text.startup+0x18c): undefined reference to blink52()'
<artificial>:(.text.startup+0x1ac): undefined reference to blink6OD()'
<artificial>:(.text.startup+0x1b4): undefined reference to blink6OE()'
<artificial>:(.text.startup+0x1bc): undefined reference to blink6CB()'
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino Uno.
Yes, I looked that the program.

Joined Sep 14, 2020
16
Ok, I figured it out. For some reason, errors resulted from using the program from the wokwi site. If the example program is used from the library, and all the other "approaches" are commented out--including the last if-statement in the approach you want to use--and the declarations, then it compiles.

Example for approach 1:

C++:
/*
Every example set must have a LED blink example
For this one the idea is to have as many ways to blink the LED
as I can think of. So, here we go.

Tested on:
- Arduino Nano
- ESP8266
- ESP32
- STM32 Maple Mini
*/

// #define _TASK_TIMECRITICAL      // Enable monitoring scheduling overruns
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
#define _TASK_STATUS_REQUEST    // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
// #define _TASK_WDT_IDS           // Compile with support for wdt control points and task ids
// #define _TASK_LTS_POINTER       // Compile with support for local task storage pointer
// #define _TASK_PRIORITY          // Support for layered scheduling priority
// #define _TASK_MICRO_RES         // Support for microsecond resolution
// #define _TASK_STD_FUNCTION      // Support for std::function (ESP8266 and ESP32 ONLY)
// #define _TASK_DEBUG             // Make all methods and variables public for debug purposes
// #define _TASK_INLINE            // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
// #define _TASK_OO_CALLBACKS      // Support for dynamic callback method binding

// Debug and Test options
#define _DEBUG_
//#define _TEST_

#ifdef _DEBUG_
#define _PP(a) Serial.print(a);
#define _PL(a) Serial.println(a);
#else
#define _PP(a)
#define _PL(a)
#endif

// LED_BUILTIN  13
#if defined( ARDUINO_ARCH_ESP32 )
#define LED_BUILTIN  23 // esp32 dev2 kit does not have LED
#endif

// Scheduler
Scheduler ts;

/*
Approach 1: LED is driven by the boolean variable; false = OFF, true = ON
*/
#define PERIOD1 500
#define DURATION 10000

/*
Approac 2: two callback methods: one turns ON, another turns OFF
*/
//#define PERIOD2 400
//
///*
//   Approach 3: Use RunCounter
//*/
//#define PERIOD3 300
//
///*
//   Approach 4: Use status request objects to pass control from one task to the other
//*/
//#define PERIOD4 200
//
//
///*
//   Approach 5: Two interleaving tasks
//*/
//#define PERIOD5 600
//
//
///*
//   Approach 6: RunCounter-based with random intervals
//*/
//#define PERIOD6 300

void setup() {
// put your setup code here, to run once:
#if defined(_DEBUG_) || defined(_TEST_)
Serial.begin(115200);
_PL("Blinking for 10 seconds using various techniques\n");
#endif
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
ts.execute();
}

inline void LEDOn() {
digitalWrite( LED_BUILTIN, HIGH );
}

inline void LEDOff() {
digitalWrite( LED_BUILTIN, LOW );
}

// === 1 =======================================
bool LED_state = false;
_PP(millis());
_PL(": Blink1 - simple flag driven");
LED_state = false;
}

if ( LED_state ) {
LEDOff();
LED_state = false;
}
else {
LEDOn();
LED_state = true;
}

//  if ( tBlink1.isLastIteration() ) {
//    LEDOff();
//  }
}

//// === 2 ======================================
//  if ( tBlink2.isFirstIteration() ) {
//    _PP(millis());
//    _PL(": Blink2 - 2 callback methods");
//  }
//
//  LEDOn();
//
//  if ( tBlink2.isLastIteration() ) {
//    LEDOff();
//  }
//}
//
//
//
//  LEDOff();
//
//  if ( tBlink2.isLastIteration() ) {
//    LEDOff();
//  }
//}
//
//
//// === 3 =====================================
//  if ( tBlink3.isFirstIteration() ) {
//    _PP(millis());
//    _PL(": Blink3 - Run Counter driven");
//  }
//
//  if ( tBlink3.getRunCounter() & 1 ) {
//    LEDOn();
//  }
//  else {
//    LEDOff();
//  }
//
//  if ( tBlink3.isLastIteration() ) {
//    LEDOff();
//  }
//}
//
//
//// === 4 =============================================
//int counter = 0;
//  _PP(millis());
//  _PL(": Blink4 - Internal status request based");
//  counter = 0;
//  return true;
//}
//
//  //  _PP(millis());
//  LEDOn();
//  counter++;
//}
//
//  //  _PP(millis());
//  LEDOff();
//  counter++;
//}
//
//
//  if ( counter >= DURATION / PERIOD4 ) {
//
//    LEDOff();
//  }
//}
//
//
//// === 5 ==========================================
//  _PP(millis());
//  return true;
//}
//  //  _PP(millis());
//  LEDOn();
//}
//  //  _PP(millis());
//  LEDOff();
//}
//  LEDOff();
//}
//
//
//// === 6 ============================================
//long interval6 = 0;
//  _PP(millis());
//  _PP(": Blink6 - RunCounter + Random ON interval = ");
//  interval6 = random( 100, 901 );
//  _PL( interval6 );
//
//  return true;
//}
//
//  if ( tBlink6.getRunCounter() & 1 ) {
//    LEDOn();
//  }
//  else {
//    LEDOff();
//  }
//}
//
//  LEDOff();
//}
Thanks all for trying to help.

Last edited:

andrewmm

Joined Feb 25, 2011
1,128
well done for getting back and persevering,

djsfantasi

Joined Apr 11, 2010
7,551
It's nice that you're trying to help, but has anyone looked at the program? (It's much easier to say general things rather than get into the dirty details of the program itself.)
Yes, I have looked at the program. In detail.