[SOLVED] - Sleep mode & u8glib & ST7920

OK so I’m trying to display some graphics and text on a LCD (ST7920) which i’ve got working. But after the graphics are finished i want the Arduino to go sleepy to save battery. I’ve tested using the sleep demo and got it working with a switch on pin 2. But i can’t integrate the code into my graphics program.

This is the code i’m using for testing. It’s a mixture of U8Glib graphics test program and the Arduino playground sleep program.

#include "U8glib.h"

U8GLIB_ST7920_128X64_1X u8g(10);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16

#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>


int wakePin = 2;                 // pin used for waking up
int sleepStatus = 0;             // variable to store a request for sleep

void wakeUpNow()        // here the interrupt is handled after wakeup
{
// execute code here after wake-up before returning to the loop() function
// timers and code using timers (serial.print and more...) will not work here.
// we don't really need to execute any special functions here, since we
// just want the thing to wake up

}

void u8g_prepare(void) {
  u8g.setFont(u8g_font_6x10);
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop();
}

void u8g_box_frame(uint8_t a) {
  u8g.drawStr( 0, 0, "drawBox");
  u8g.drawBox(5,10,20,10);
  u8g.drawBox(10+a,15,30,7);
  u8g.drawStr( 0, 30, "drawFrame");
  u8g.drawFrame(5,10+30,20,10);
  u8g.drawFrame(10+a,15+30,30,7);
}

void u8g_disc_circle(uint8_t a) {
  u8g.drawStr( 0, 0, "drawDisc");
  u8g.drawDisc(10,18,9);
  u8g.drawDisc(24+a,16,7);
  u8g.drawStr( 0, 30, "drawCircle");
  u8g.drawCircle(10,18+30,9);
  u8g.drawCircle(24+a,16+30,7);
}

void u8g_r_frame(uint8_t a) {
  u8g.drawStr( 0, 0, "drawRFrame/Box");
  u8g.drawRFrame(5, 10,40,30, a+1);
  u8g.drawRBox(50, 10,25,40, a+1);
}

void u8g_string(uint8_t a) {
  u8g.drawStr(30+a,31, " 0");
  u8g.drawStr90(30,31+a, " 90");
  u8g.drawStr180(30-a,31, " 180");
  u8g.drawStr270(30,31-a, " 270");
}

void u8g_line(uint8_t a) {
  u8g.drawStr( 0, 0, "drawLine");
  u8g.drawLine(7+a, 10, 40, 55);
  u8g.drawLine(7+a*2, 10, 60, 55);
  u8g.drawLine(7+a*3, 10, 80, 55);
  u8g.drawLine(7+a*4, 10, 100, 55);
}

void u8g_ascii_1() {
  char s[2] = " ";
  uint8_t x, y;
  u8g.drawStr( 0, 0, "ASCII page 1");
  for( y = 0; y < 6; y++ ) {
    for( x = 0; x < 16; x++ ) {
      s[0] = y*16 + x + 32;
      u8g.drawStr(x*7, y*10+10, s);
    }
  }
}

void u8g_ascii_2() {
  char s[2] = " ";
  uint8_t x, y;
  u8g.drawStr( 0, 0, "ASCII page 2");
  for( y = 0; y < 6; y++ ) {
    for( x = 0; x < 16; x++ ) {
      s[0] = y*16 + x + 160;
      u8g.drawStr(x*7, y*10+10, s);
    }
  }
}

void u8g_extra_page(uint8_t a)
{
  if ( u8g.getMode() == U8G_MODE_HICOLOR || u8g.getMode() == U8G_MODE_R3G3B2) {
    /* draw background (area is 128x128) */
    u8g_uint_t r, g, b;
    b = a << 5;
    for( g = 0; g < 64; g++ )
    {
      for( r = 0; r < 64; r++ )
      {
	u8g.setRGB(r<<2, g<<2, b );
	u8g.drawPixel(g, r);
      }
    }
    u8g.setRGB(255,255,255);
    u8g.drawStr( 66, 0, "Color Page");
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )
  {
    u8g.drawStr( 66, 0, "Gray Level");
    u8g.setColorIndex(1);
    u8g.drawBox(0, 4, 64, 32);    
    u8g.drawBox(70, 20, 4, 12);
    u8g.setColorIndex(2);
    u8g.drawBox(0+1*a, 4+1*a, 64-2*a, 32-2*a);
    u8g.drawBox(74, 20, 4, 12);
    u8g.setColorIndex(3);
    u8g.drawBox(0+2*a, 4+2*a, 64-4*a, 32-4*a);
    u8g.drawBox(78, 20, 4, 12);
    
  }
  else
  {
    u8g.drawStr( 0, 12, "setScale2x2");
    u8g.setScale2x2();
    u8g.drawStr( 0, 6+a, "setScale2x2");
    u8g.undoScale();
  }
}

void sleepmsg(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr (0,20, "Going to Sleep");
}

uint8_t draw_state = 0;



void draw(void) {
  u8g_prepare();
  switch(draw_state >> 3) {
    case 0: u8g_box_frame(draw_state&7); break;
    case 1: u8g_disc_circle(draw_state&7); break;
    case 2: u8g_r_frame(draw_state&7); break;
    case 3: u8g_string(draw_state&7); break;
    case 4: u8g_line(draw_state&7); break;
    case 5: u8g_ascii_1(); break;
    case 6: u8g_ascii_2(); break;
    case 7: u8g_extra_page(draw_state&7); break;
    case 8: sleepmsg(); break;
    case 9: sleepNow(); break;
  }
}

void setup(void) {

  // flip screen, if required
  //u8g.setRot180();
  pinMode(13, OUTPUT);           
  digitalWrite(13, HIGH);  
}


void sleepNow()         // here we put the arduino to sleep
{

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
  sleep_enable();          // enables the sleep bit in the mcucr register
                          
 attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                    // wakeUpNow when pin 2 gets LOW 
 sleep_mode();            // here the device is actually put to sleep!!
                          // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
 sleep_disable();         // first thing after waking from sleep:
                          // disable sleep...
 detachInterrupt(0);      // disables interrupt 0 on pin 2 so the 
                          // wakeUpNow code will not be executed 
                          // during normal running time.
}


void loop(void) {
  
  // picture loop  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  // increase the state
  draw_state++;
  if ( draw_state >= 9*9 )
    draw_state = 0;
  
  // rebuild the picture after some delay
  delay(150);

}

What happens is the program runs and the graphics display as should, then the message “i’m going to sleep”
Then nothing the message stays which i’m thinking is the uno going to sleep (would prefer the screen to go blank but i don’t think there’s a CLEAR command with u8glib)

When you press the switch the screen clears and nothing else happens, the graphics don’t start.

Any help/ideas on getting it to work.

Hi

Calling the sleep procedure within the picture loop is a bad idea, because this procedure will be called several times (8x in your case, so you need to press the wake up key 8x). Do a call to the sleep procedure outside of the picture loop.

The screen can be cleared with an empty picture loop

  // clear lcd  
  u8g.firstPage();  
  do {
   // do nothing
  } while( u8g.nextPage() );

Oliver

Thanks for the tips Since i'm new to all this Arduino programing can you explain this line for me

if ( draw_state >= 9*9)

as i'm playing with the numbers and getting strange results on what is displayed.

Also where should i put the sleep command so it runs when the last case is displayed? (i.e. the sleep message)

Hi

The line if ( draw_state >= 9*9) has been modified by you. The original number was 8*8 which is the state value to restart the sequence again. The graphics test sequence has 8 pages with are divided into 8 sub steps. These 8 sub steps are extracted and used here:

  switch(draw_state >> 3) {
    case 0: u8g_box_frame(draw_state&7); break;
    case 1: u8g_disc_circle(draw_state&7); break;
    case 2: u8g_r_frame(draw_state&7); break;
    case 3: u8g_string(draw_state&7); break;
    case 4: u8g_line(draw_state&7); break;
    case 5: u8g_ascii_1(); break;
    case 6: u8g_ascii_2(); break;
    case 7: u8g_extra_page(draw_state&7); break;
  }

If you add a new page, then the values will be 9*8. If you add two new pages, then this will be 10*8.

My suggestion was to place the sleep command outside the picture loop. That means: Place it in the loop() procedure:

void loop(void) {  
  // picture loop  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  // increase the state
  draw_state++;
  if ( draw_state >= 9*8 )
  {
    draw_state = 0;
    sleepNow()         // here we put the arduino to sleep
  }
  
  // rebuild the picture after some delay
  delay(150);
}

Please note that i have never used the wake up procedures. I can not tell if these procedures are correct or not.

Oliver

Still not 100% on what that draw_state line is doing but i'll get it once i go through the program a few times lol.

Thanks for all the help oliver that sleep command worked. I tried it in there but it wasn't doing it, i must of missed something but it's worked great!

Thanks

now i see.

I wasn't putting the draw_state =0 and sleepnow inside of { }