Scheduler and U8glib on DUE

@pylon:

yes, sure. The new code is reduced to the essential:

// Include Scheduler since we want to manage multiple tasks.
#include <Scheduler.h>

#define HDMM01_I2C_Addr 0x30

#include <U8glib.h>
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 17, 14, 15, 16, 30); 		// 8Bit Com: D0..D7: 22..29 en=17, cs1=14, cs2=15, di=17 (,rw=30)
//KS108:   1=Vss; 2=Vdd; 3=V0; 4=D/I; 5=R/W; 6=E; 7..14=D0..D7; 15=CS1; 16=CD2
//        17=RST; 18=Vee; 19=A; 20=K

int led1 = 13;
int led2 = 12;
int led3 = 11;

void setup() {
  Serial.begin(9600);

  Serial.println("Setup 01");
//  u8g.setFont(u8g_font_4x6);
//  u8g.setFontRefHeightExtendedText();
//  u8g.setDefaultForegroundColor();
//  u8g.setFontPosTop();
//  Serial.println("Setup 02");

  Scheduler.startLoop(loop2);
  Serial.println("Setup 03");
  Scheduler.startLoop(loop3);
  Serial.println("Setup 04");

}

void loop() {
  Serial.println("Loop 1");
  delay(1000);
}

void loop2() {
  Serial.println("Loop 2");
  delay(100);
}

void loop3() {
  Serial.println("Loop 3-1");
  
//  u8g.firstPage();  
//  do
//  {
//    u8g.drawStr(0,0, "LED");
//  }
//  while( u8g.nextPage() );
  
//  Serial.println("Loop 3-2");

  yield();
}

the serial Windows stays still empty.

After commenting line

//U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 17, 14, 15, 16, 30); 		// 8Bit Com: D0..D7: 22..29 en=17, cs1=14,

out, I got :
op 3-C!ë 3-1?êë 2
LoÿSetup 01
Setup 03
Setup 04
Loop 1
Loop 3-1
Loop 2
Loop 3-1
Loop 3-1
Loop 3-1
Loop 3-1
Loop 3-1
Loop 3-1
Loop 3-1
Loop 3-1
Loop 3-1

yield() or delay() is important and it is included.
It seems to be in the constructor of u8glib, but why/what?

I have also u8glib v1.12 tested - same result :frowning:

lowsax

Have you tried to track it from the other side? Start with the #include <Scheduler.h>, try if it still works, then add the first Scheduler.startLoop() call and so on? Where does it stop to work? To know that helps finding the relevant part in the U8lib.

OK, lets try:

#include <Scheduler.h>
#include <U8glib.h>
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 17, 14, 15, 16, 30);
->no output

#include <U8glib.h>
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 17, 14, 15, 16, 30);
#include <Scheduler.h>
->no output

#include <U8glib.h>
#include <Scheduler.h>
U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 17, 14, 15, 16, 30);
->no output

startLoop(..) at first in setup()
->no output

U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 17, 14, 15, 16, 30);
after setup()
->no output

Hopefully I havn't forget one possibility.

Because I dosn't get any serial output (also no flash of Tx-LED on Board), I think DUE stops before first println() or still dosn't start.

lowsax

Does it really give you output if you don't include the

#include <Scheduler.h>

?

Is it any different if you move the U8glib code into loop() and move the LED-flashing code into loop3()?

@pylon

no, if i haven't #include <Scheduler.h> I got a compilation error, that Scheduler is not defined.
I had #include <Scheduler.h> always in the code.
[if ment in 4) and 5), it was combined with 3)]

lowsax

@stimmer:

no, there is no difference,
also without LED, but println - it is also the same. The DUE seams not to run/start.
see:

yes, sure. The new code is reduced to the essential:
...
the serial Windows stays still empty.

lowsax

You have to remove the Scheduler.startLoop() (and yield()) calls if you remove the include line of course. But then you shouldn't get a compile error. Then (with remove startLoop()) try if you get an output without the include and if that's successful try it with the include.

Hi

I did some review on the both sides, the U8glib startup (which was really difficult on the DUE) and on the Scheduler.
For historical reasons, U8glib tries to setup the display inside the constructor. This means, procedure like digitalWrite() and delay() are already called at constructor time.

Indeed, the delay code from /arduino-1.5.2/hardware/arduino/sam/cores/arduino looks like this.

void delay( uint32_t ms )
{
    uint32_t end = GetTickCount() + ms;
    while (GetTickCount() < end)
    	yield();
}

So the yield procedure might be called without proper setup of the scheduler.
What could be done is to redefine the u8g delay procedure in u8g_delay.c:

void u8g_Delay(uint16_t val)
{
	delay(val);
}

replace ist by

void u8g_Delay(uint16_t val)
{
	delayMicroseconds((uint32_t)val*(uint32_t)1000);
}

maybe this works because delayMicroseconds does NOT call yield() ...

Oliver

@pylon:

that was one of my first tyies before I started the question.

It work as it should.

lowsax

@olikraus:

perfect, I have changed the code of u8g_delay.c as mentioned in your post.

It works :slight_smile:

Thanx for your support
lowsax

Thanks for your feedback. I have created an issue: Google Code Archive - Long-term storage for Google Code Project Hosting.

Oliver

It would be better if the initialization code is placed into a begin() function.
Many arduino libraries does it this way, you know exactly when the initialization is done,
and avoids you to hit the "C++ static initialization order fiasco".

http://www.parashift.com/c++-faq/static-init-order.html

Well, yes, and indeed the modification of u8g_Delay() is more a workaround (or hack) instead of a good solution. To excause the current situation a little bit: I never read in the Arduino documentation that some of the procedures are not valid to be called during constructor time. And on the ATMEGA it was never a problem to call digitalWrite() or delay() in the constructor.

For the port to the Arduino Due i also had to deal with this problem because of some other conflicts. U8glib already has a begin() procedure. But u8glib has not been completly redesigned for it. So to say, i am on the half way of a complete redesign of the internal architecture without changing much of the existing API.

So to conclude this:
I was not aware of this problem in the past, but now i do my very best to update U8glib.

My suggestion to the Arduino Project: Please clearly state that delay() and digitalWrite() must not be used in any construtor calls.

Oliver

olikraus:
Well, yes, and indeed the modification of u8g_Delay() is more a workaround (or hack) instead of a good solution. To excause the current situation a little bit: I never read in the Arduino documentation that some of the procedures are not valid to be called during constructor time. And on the ATMEGA it was never a problem to call digitalWrite() or delay() in the constructor.

olikraus,
you don't need to justify, initializations (with digitalWrite and delays) in the constructors should be legal.

The issue here is that delay() didn't work until the Arduino initialization is done in main() and C++ starts constructors of static objects before the main! I got some problems with the LiquidCrystal library because of that:

https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp#L27

and the solution was:

but for some reason the scheduler has still some interactions I didn't considered that should be looked into.

So, in the end, consider my previous post just a hint to workaround these troubles... :slight_smile:

Hi cmaglie

Regarding your link to the LiquidCrystal lib: I had a similar problem with init of the display within u8glib.
After constructor calls, the Arduino Due will reset all I/O pins. This problem still exists in 1.5.2.

Oliver

Hi.

I'm trying to implement the scheduler in my project, but the behaviour is not what I was expecting.

Due runs a lot of times the main loop, and sometimes the second loop.

But when it does, there isn't a consistent number of runs.

What I has expecting, was it to run main loop, then 2nd loop, then main loop, then 2nd loop, and so on.

What I get from the debug is this: ( number is the corresponding runtime in millis for the loop)

"
loop1 1
loop1 1
loop1 0
loop1 1
loop 135
loop 125
loop 125
loop 126
loop 125
loop 125
loop 126
loop 125
loop 125
loop 125
loop 125
loop 126
loop 125
loop 125
loop 126
loop 125
loop1 0
loop1 1
loop1 0
loop1 1
loop 130
loop 125
loop 125
loop 125
loop 125
loop 126
loop 125
loop 125
loop 126
loop 125
loop 125
loop 125
loop 125
loop 126
loop 125
loop 125
loop1 1
loop1 0
loop1 1
loop1 1
loop 135
loop 126
loop 125
loop 125
loop 167
loop 125
loop 125
loop 125
loop 126
loop 125
loop 125
loop 126
loop 125
loop 125
loop 125
loop 125
loop1 1
loop1 0
loop1 1
loop 130
loop 125
loop 125
loop 125
loop 125
loop 126
loop 125
loop 125
loop 126
loop 125
loop 126
loop 125
loop 125
loop 126
loop 125
loop 125
loop1 1
loop1 1
loop1 0
loop1 1
loop 135
loop 125
loop 125
loop 167
loop 125
loop 126
loop 125
loop 125
loop 125
loop 125
loop 126
loop 125
loop 125
loop 126
loop 125
loop 125
loop1 1
loop1 1
"

Am I missing something here?

Am I missing something here?

The Scheduler is used for cooperative multitasking and not a preemptive one as you was expecting. Read here about the differences: Computer multitasking - Wikipedia

Thank you Pylon for pointing me in right direction. I think its clear now, but I'll read it again.

To solve my problem, I've built a scheduler with a switch. With this I run only one time consuming function per loop.

I've dropped the loop time from 120millis to 10 millis average.

Regards

Joao