Go Down

Topic: Scheduler and U8glib on DUE (Read 3618 times) previous topic - next topic

lowsax

Apr 02, 2013, 06:50 pm Last Edit: Apr 02, 2013, 06:57 pm by lowsax Reason: 1
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:
Code: [Select]
// 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
Code: [Select]
 u8g.setFont(u8g_font_4x6);
 u8g.setFontRefHeightExtendedText();
 u8g.setDefaultForegroundColor();
 u8g.setFontPosTop();

and
Code: [Select]
u8g.firstPage();  
 do
 {
   u8g.drawStr(0,0, "LED");
 }
 while( u8g.nextPage() );


Has anyone an idea what the problem is?

Thanx
lowsax

pylon

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

lowsax

#2
Apr 03, 2013, 03:20 pm Last Edit: Apr 03, 2013, 09:14 pm by lowsax Reason: 1
@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  :smiley-red:

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

lowsax

pylon

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)?

lowsax

#4
Apr 05, 2013, 08:46 am Last Edit: Apr 08, 2013, 10:40 am by lowsax Reason: 1
@pylon:

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

Code: [Select]
// 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
Code: [Select]
//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  :(

lowsax

pylon

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.

lowsax

OK, lets try:

1)
#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

2)
#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

3)
#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

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

5)
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

pylon

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

#include <Scheduler.h>

?

stimmer

Is it any different if you move the U8glib code into loop() and move the LED-flashing code into loop3()?
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

lowsax

#9
Apr 05, 2013, 08:06 pm Last Edit: Apr 08, 2013, 10:39 am by lowsax Reason: 1
@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

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:
Quote
yes, sure. The new code is reduced to the essential:
...
the serial Windows stays still empty.


lowsax


pylon

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.

olikraus

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.
Code: [Select]

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:

Code: [Select]
void u8g_Delay(uint16_t val)
{
delay(val);
}

replace ist by
Code: [Select]
void u8g_Delay(uint16_t val)
{
delayMicroseconds((uint32_t)val*(uint32_t)1000);
}


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

Oliver






lowsax

@pylon:

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

It work as it should.

lowsax

lowsax

@olikraus:

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

It works :)

Thanx for your support
lowsax

Go Up