Scheduler and U8glib on DUE

Hy,

I try to program a multitasking system and fail on an early state.

I use the DUE with the MultipleBlinks Demo. All is fine.

I use the U8glib without multitaskin to control a KS108 LCD display. All is fine.

But if I include U8g and configure U8GLIB_KS0108_128 u8g(22, 23, 24, 25, 26, 27, 28, 29, 17, 14, 15, 16, 30); to the MultipleBlinks Demo the DUE seems to do nothing. No blink, no LCD output and no serial communication.

My code:

// 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);

  // Setup the 3 pins as OUTPUT
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);

  u8g.setFont(u8g_font_4x6);
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop();

  // Add "loop2" and "loop3" to scheduling.
  // "loop" is always started by default.
  Scheduler.startLoop(loop2);
  Scheduler.startLoop(loop3);
}

// Task no.1: blink LED with 1 second delay.
void loop() {
  digitalWrite(led1, HIGH);

  // IMPORTANT:
  // When multiple tasks are running 'delay' passes control to
  // other tasks while waiting and guarantees they get executed.
  delay(1000);

  digitalWrite(led1, LOW);
  delay(1000);
}

// Task no.2: blink LED with 0.1 second delay.
void loop2() {
  digitalWrite(led2, HIGH);
  delay(100);
  digitalWrite(led2, LOW);
  delay(100);
}

// Task no.3: accept commands from Serial port
// '0' turns off LED
// '1' turns on LED
void loop3() {
  static char c=0;
  if (Serial.available()) {
    c = Serial.read();
    if (c=='0') {
      digitalWrite(led3, LOW);
      Serial.println("Led turned off!");
    }
    if (c=='1') {
      digitalWrite(led3, HIGH);
      Serial.println("Led turned on!");
    }
  }
  
  u8g.firstPage();  
  do
  {
    u8g.drawStr(0,0, "LED");
  }
  while( u8g.nextPage() );


  // IMPORTANT:
  // We must call 'yield' at a regular basis to pass
  // control to other tasks.
  yield();
}

The same is also without the LCD output part

  u8g.setFont(u8g_font_4x6);
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop();

and

u8g.firstPage();  
  do
  {
    u8g.drawStr(0,0, "LED");
  }
  while( u8g.nextPage() );

Has anyone an idea what the problem is?

Thanx
lowsax

It helps us a lot helping you if you provide links to the libraries you used.

@pylon:

sorry, I thought it was an often used library 8)

I got it from
http://code.google.com/p/u8glib/
Version 1.11
I have to test the v1.12 :blush:

The Scheduler.h is the one, delivered with arduino 1.5.2

lowsax

I don't see the problematic part yet. The multitasking is only cooperative, so in every loopX() you have to either call yield() or delay() (which call yield() as often as possible during the wait). If you comment everything out which might call the LCD and still have a freeze, the problem must reside in the LCD object constructor. But this should have been called already when the new loops are created.

Can you insert some debugging code (Serial.println()s) to see how far the code is running (and post the result)?

@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