Close

Displaying raster images

A project log for Word watch

There's not much that's more EDC than a watch. LED matrix-based word watch, inspired by Daniel Rojas's micro word clock recently on the blog

pointyointmentPointyOintment 12/03/2014 at 07:080 Comments

After much struggling, I managed to get it displaying hardcoded raster images chosen by sending a letter over the serial connection. Here it is displaying A, B, C, a smiley face, and the LEDs that are illuminated in my mockup image (taken from [Daniel]'s photo):

direct video link in case the embed doesn't work for you (YT: LED matrix: predefined raster images (0:20))

I first tried to use a switch case statement to load the chosen pixel array into the pixel array that refreshScreen() reads from, but apparently you can't set all elements of an array unless you're doing so when you're first defining it. Seems strange to me, but whatever. I changed those pixel arrays to constants, and then made a switch case statement inside refreshScreen() that chooses among them as it draws to the LED matrix. After that I had loads of syntax errors resulting from moving code around and trying different approaches, but they were all easily fixed. It's not particularly efficient (or maintainable), but it looks like it updates plenty fast—much faster than the x-y demo I did earlier, for some reason. It's good enough for a proof of concept, at least. The actual word clock function will use a more dynamic way of generating the pixel arrays. Here's the code:

char imageID;

// images:
const int pixelsA[8][8] = {
   {1,1,1,0,0,1,1,1},
   {1,1,0,0,0,0,1,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,0,0,0,0,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,1,1,0,0,1}
};
const int pixelsB[8][8] = {
   {1,0,0,0,0,0,1,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,0,0,0,1,1},
   {1,0,0,0,0,0,1,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,1,1,0,0,1},
   {1,0,0,0,0,0,1,1}
};
const int pixelsC[8][8] = {
   {1,1,0,0,0,0,1,1},
   {1,0,0,0,0,0,0,1},
   {0,0,1,1,1,1,0,0},
   {0,1,1,1,1,1,1,1},
   {0,1,1,1,1,1,1,1},
   {0,0,1,1,1,1,0,0},
   {1,0,0,0,0,0,0,1},
   {1,1,0,0,0,0,1,1}
};
const int pixelsSmile[8][8] = {
   {0,0,1,1,1,1,0,0},
   {0,1,1,1,1,1,1,0},
   {1,1,0,1,1,0,1,1},
   {1,1,1,1,1,1,1,1},
   {1,0,1,1,1,1,0,1},
   {1,1,0,0,0,0,1,1},
   {0,1,1,1,1,1,1,0},
   {0,0,1,1,1,1,0,0}
};
const int pixelsWords[8][8] = {
   {1,1,0,0,0,0,0,0},
   {0,0,1,0,1,0,1,1},
   {1,1,1,0,0,0,0,1},
   {1,1,1,1,1,1,1,1},
   {1,1,1,1,1,1,1,1},
   {1,1,0,0,0,0,0,0},
   {1,1,1,1,1,1,1,1},
   {1,1,1,1,1,1,1,1}
};

void readSerial() {
   // get value from serial:
   imageID = Serial.read();
}

void refreshScreen() {
   // iterate over the rows (anodes):
   for (int thisRow = 0; thisRow < 8; thisRow++) {
      // take the row pin (anode) high:
      digitalWrite(row[thisRow], HIGH);
      // iterate over the cols (cathodes):
      for (int thisCol = 0; thisCol < 8; thisCol++) {
         // get the state of the current pixel:
         //int thisPixel = pixels[thisRow][thisCol];
         int thisPixel;
         switch (imageID) {
            case 'a':
               thisPixel = pixelsA[thisRow][thisCol];
            break;
            case 'b':
               thisPixel = pixelsB[thisRow][thisCol];
            break;
            case 'c':
               thisPixel = pixelsC[thisRow][thisCol];
            break;
            case 's':
               thisPixel = pixelsSmile[thisRow][thisCol];
            break;
            case 'w':
               thisPixel = pixelsWords[thisRow][thisCol];
            break;
         }
         // when the row is HIGH and the col is LOW,
         // the LED where they meet turns on:
         digitalWrite(col[thisCol], thisPixel);
         // turn the pixel off:
         if (thisPixel == LOW) {
            digitalWrite(col[thisCol], HIGH);
         }
      }
      // take the row pin low to turn off the whole row:
      digitalWrite(row[thisRow], LOW);
   }
}

Discussions