by robie1373 on Wed Dec 23, 2009 10:51 am

I ordered a fine graphic LCD from the adafruit store and decided to write a little graphics Menorah to learn how it works. I am not a programmer, and am new to micro-controllers so I learned a lot in the following sketch.

Some of the topics I included are
- Creating functions
- drawing graphics with GLCD (I did it by hand for fun, but I assume the bitmap works as well or better)
- Text placement in GLCD
- debouncing (this doesn't actually work in the following sketch. If you know why, drop a comment :)
- abstraction (an array determines what order the flames are lit in so you can change it up)
- A non-blocking timer. Using delay(); made my button detection icky. I decided to try and find a different way. I'm actually pretty happy with how this part worked out. suggestions on improving efficiency will be appreciated. I found a library in called fuse I think. I could never get the page to load, though so I couldn't use it.

Lastly, I made this for my wife, and I know next to nothing about the Menorah. Please trust that it was done out of respect and that any mispellings, or cultural gaffes are based on my ignorance alone. Feel free to post corrections in this regard as well.

Without further ado, I present to you just in time to be much to late for this year,

The button handling code is copied straight out of the bounce script in the examples,
 so all credit goes there.  The GLCD stuff is heavily influenced if not straight copied
 from the GLCD library page in the playground.  The non-blocking timer code is based on
 the blink without delay example from Ladyada. Everything else you see has an even chance
 of having been copied from somewhere.  If I failed to attribute something, my apologies.
 Let me know and I'll get your name into the comments.  
 Truth is, I don't really write code, since all the good stories have already been told :)
#include <ks0108.h>
#include "SystemFont5x7.h" // proportional font
#include <Bounce.h>

const int buttonPin = 13; // the number of the pushbutton pin
int buttonCount; // the current count from the input pin
int reading;
int lastButtonState = 0; // the previous reading from the input pin
long previousMillis = 0; // will store time flames have been on or off
const int onInterval = 500; // How long the flames should be "on" for flickering
const int offInterval = 100; // How long the flames should be "off" for flickering
byte flickerState = 1; // used to check if flames are on or off in flicker code
byte oldflickerState = 0; //ditto

Bounce bouncer = Bounce(buttonPin, 75); // I've gotta be honest. The syntax of this
// library still confuses me. All I know is 
//it works.
byte flameNum = 0;
int flameOrder[] = { // this is the order the flames come on in.
  0, 1, 2, 3, 5, 6, 7, 8};              // to change the order, rearrange the numbers
// in this array.  #4 is the center flame 0 is left.

// This example draws things "by hand" instead of using GLCD.DrawBitmap(). No real reason
// really. I didn't have a bitmap to image to convert, and I felt like playing artist :)
void drawBase(){ // this draws the "candle holder" I'm not sure what the correct
  GLCD.ClearScreen(); // word is. it also draws the candles themselves.
  GLCD.FillRect(40,59,44,2, BLACK); //bottom
  GLCD.FillRect(44,57,36,2, BLACK); //second from bott
  GLCD.FillRect(50,55,24,2, BLACK); //3 from bott
  GLCD.FillRect(85,17,3,19, BLACK); // candle 8 Idea: base the height on a timer so
  GLCD.FillRect(79,17,3,19, BLACK); // candle 7 the candles burn down.
  GLCD.FillRect(73,17,3,19, BLACK); // candle 6 If you do that, you'll have to put
  GLCD.FillRect(67,17,3,19, BLACK); // candle 5 the candle drawing code in the loop
  GLCD.FillRect(61,13,3,42, BLACK); // candle 4 center Instead of setup()
  GLCD.FillRect(55,17,3,19, BLACK); // candle 3
  GLCD.FillRect(49,17,3,19, BLACK); // candle 2
  GLCD.FillRect(43,17,3,17, BLACK); // candle 1
  GLCD.FillRect(37,17,3,17, BLACK); // candle 0
  GLCD.FillRect(43,39,38,2, BLACK); //bottom arm
  GLCD.FillRect(40,37,44,2, BLACK); //second arm
  GLCD.FillRect(37,35,9,2, BLACK); //third arm L
  GLCD.FillRect(79,35,9,2, BLACK); //third arm R

void drawCenterFlame(){
  GLCD.FillRect(61,7,3,4, BLACK); // flame
  GLCD.FillRect(61,6,2,1, BLACK); // flame
  GLCD.SetDot(62,5,BLACK); //flame

void drawCandleFlame(int flameNum){
  GLCD.FillRect(37+6*flameNum, 11, 3, 4, BLACK); // flame
  GLCD.FillRect(37+6*flameNum, 10, 2, 1, BLACK); // flame
  GLCD.SetDot(38+6*flameNum, 9, BLACK); //flame

void flickerFlames(int flameNum){
  //flames should twinkle
  GLCD.FillRect(37+6*flameNum, 11, 3, 4, WHITE); // flame
  GLCD.FillRect(37+6*flameNum, 10, 2, 1, WHITE); // flame
  GLCD.SetDot(38+6*flameNum, 9, WHITE); //flame
  GLCD.FillRect(61,7,3,4, WHITE); // center flame
  GLCD.FillRect(61,6,2,1, WHITE); // center flame
  GLCD.SetDot(62,5,WHITE); // center flame

void drawGreeting(){ // prints some text in the space arround the menorrah. Manually position
  GLCD.GotoXY(2, 46);
  GLCD.Puts("To my");
  GLCD.GotoXY(85, 46);

void setup(){
  GLCD.Init(NON_INVERTED); // initialise the library, non inverted writes pixels onto a clear screen
  drawBase();        //draw the base once. no need to update it.
  drawGreeting();    // same with the greeting.
  pinMode(buttonPin, INPUT); //set up the button as input

void loop(){ // run over and over again

// Something feels off here in the debouncing.  It seems like I occasionally get bouncy readings.
  if (bouncer.update()) { // Needed to get the current state of the button
    reading =; // read the button to turn on
    if (reading == 0) {
      if (buttonCount < 8) // loop through the 8 flames as the button is pushed.
        buttonCount = 0;  // and reset the counter when all 8 are lit.
      lastButtonState = reading;

  // all this is for a non-blocking replacement for delay() because it makes it hard to read
  // button presses.
  if (flickerState == 1){ // check to see if the desired state is "on"
    if (millis() - previousMillis < onInterval) { // we want the flames on for about 1/2 a second
      if (oldflickerState != flickerState){ // check to see if the state has just changed.
        // without this step we redraw the flames every
        // time we go through the main loop. Wasteful,
        // and the lcd can't handle the framerate anyway.
        drawCenterFlame(); // Turn on the middle flame

          for (int i=0; i<buttonCount; i++){ // turn on the rest of the flames. based on
          drawCandleFlame(flameOrder[i]);    // a counter of button pushes.
          oldflickerState = flickerState;  // update the statechange checking variable so
          // we don't keep drawing flames.
    else { // once the onInterval is up,
      flickerState = 0; //we update the desired state of the flames to "off"
      previousMillis = millis(); // and reset the timer so they can spend the right amount
      // of time turned off.

  if (flickerState == 0) { //since we know we want the flames to turn off
    if (millis() - previousMillis < offInterval) { //check to see if they've been off long enough.
      if (oldflickerState != flickerState){ //check to see if state just changed
        for (int i=0; i<8; i++){ // turn the flames off
          oldflickerState = flickerState; //update the statechange detection.

    else { // once the flames have been out for the offInterval
      flickerState = 1; // change the desired state back to on
      previousMillis = millis(); // and update the timer.

Posts: 6
Joined: Wed Dec 23, 2009 10:32 am

by adafruit on Wed Dec 23, 2009 10:55 am

can you put up a photo of the finished project? we'll post it up :)
User avatar
Posts: 11502
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

by robie1373 on Wed Dec 23, 2009 1:35 pm

adafruit wrote:can you put up a photo of the finished project? we'll post it up :)

Why yes, I believe I can :)

And for bonus points a short video of it in action.
GLCDsketch.jpg (42.44 KiB) Viewed 3640 times
Posts: 6
Joined: Wed Dec 23, 2009 10:32 am

by adafruit on Wed Dec 23, 2009 1:36 pm

User avatar
Posts: 11502
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc