Geek's Valentine card with LED 8x8 pixel display
├── README.md
├── img
│ └── *.png
├── bitmap_img # files, that will be converted to bitmaps
│ ├── fonts # fonts directory
│ │ └── basic # "basic" font directory
│ │ ├── font_map.json # images and letters map
│ │ └── *.png # letters images
│ └── *.png, *.txt, *.h
├── bitmaps_generate.py # bitmaps generation script
└── firmware # microcontroller firmware (PlatformIO project)
├── Makefile
├── include
│ └── bitmaps.h # automatically generated bitmaps
├── lib
│ └── DisplayMax7219
│ └── DisplayMax7219.h
├── platformio.ini
└── src
└── main.cpp
| Name | Qty | Link | Description |
|---|---|---|---|
| Heart-shaped PCB | 1 | Gerber files | EasyEDA project |
| Attiny13A | 1 | Aliexpress | |
| MAX7219 | 1 | Aliexpress | LED matrix driver |
| 0805 white LED | 64 | Aliexpress | |
| CR2032 | 2 | Aliexpress | |
| CR2032 holder | 1 | Aliexpress | 2 batteries in one holder (3V isn't enough) |
| SMD button | 1 | Aliexpress | For mode switching |
| 10k R0805 | 1 | Aliexpress | |
| ~500k R0805 | 1 | Aliexpress | |
| 10uF C0805 | 1 | Aliexpress | |
| 2 positions switch | 1 | Aliexpress | Power switch |
You will need USBasp or something similar to upload the firmware.
Soldering 64 LEDs with soldering iron might be quite challenging, so I advise you to get hot air gun and soldering paste.
| PCB footprint | Nominal value |
|---|---|
R1 |
10k |
R2 |
~500k |
C1 |
10uF |
In my opinion, this soldering order is most convenient:
- LEDs and button on the face of PCB
- Attiny13
- MAX7219
- SMD components on the back side
- Power switch and batteries holder
Note
LED's triangle on its backside must be turned in agreement with footprint on PCB (45° right and up)
Attiny13 and MAX7219 also have polarity. You need to match keys with keys on the footprint.
PlatformIOPython 3GNU make
To build the firmware run this inside firmware directory:
make
I recommend not to solder ICSP pins (6 pins group at the top of the PCB). It is enough to hold pins manually to upload firmware.
Note
If your Attiny is new, write fuses firstly (this will set necessary internal oscillator frequency):
make fuses
Upload or reupload firmware:
make upload
Bitmaps are automatically generated from files in bitmap_img directory. Each file corresponds to one bitmap. You can add your own there or edit given files. Generated bitmaps are written to header file firmware/include/bitmaps.h. Each bitmap is a byte array and has name of source file in caps. For example, bitmap generated from file example_bmap.txt will be named EXAMPLE_BMAP.
Inside bitmap_img there is a font directory. Currently there is only one font, called basic. It supports English and Russian capital letters, numbers, punctuation marks and some additional symbols. Actually, you can create your custom font. I will give instructions below.
So, bitmaps can be generated from 3 types of files:
.png-- image will be converted to black and white. White regions are enabled LEDs. Height must be8pixels, widthN*8pixels.N- is number of frames. Multiple frames in one bitmap is used for slideshows or blinking animations..h-- text from these files will be simply pasted to header file..txt-- text for running line mode. File must contain 2 lines:- Font name, e.g.
basic - Text, e.g.
I love you♥. Allowed symbols are listed in font map file (bitmap_img/fonts/<font_name>/font_map.json.
- Font name, e.g.
You can create your font or add symbols to basic. In font directory must be a font_map.json file. It tells generator what .png file it must use for specific symbol.
E.g.
"♥": "heart.png",
"+": "plus.png",
"-": "minus.png",
Images height must be 8 pixels. Width can be any. Generator puts 1 empty column between symbols, so you don't need to add empty columns to images.
You can use bitmaps inside of C++ code. The main part is here:
firmware/src/main.cpp
=====
...
switch (mode) {
case 0: cycle_bitmap( 60, BITMAPS_AND_SIZE(HEART_BLINK)); break;
case 1: scroll_bitmap( 7, BITMAP_AND_WIDTH(FOR_SMBDY_WITH_LOVE)); break;
case 2: cycle_bitmap( 50, BITMAPS_AND_SIZE(HEART_MINI)); break;
case 3: cycle_bitmap( 30, BITMAPS_AND_SIZE(HEART_HALVES)); break;
case 4: cycle_bitmap( 30, BITMAPS_AND_SIZE(HEART_MESSAGES)); break;
default: mode = 0; break;
}
...
You can add new modes and bitmaps here. There are two types of animations:
cycle_bitmap-- used for slideshows and blink animations. It will sequentially switch bitmaps from array.scroll_bitmap-- scrolls bitmap column by column. Used for running line text.
First argument is number of frames (FPS is set in this file) for one animation step. Second and third arguments are bitmap array and its size. You can add macro BITMAPS_AND_SIZE for cycle_bitmap and BITMAP_AND_WIDTH for scroll_bitmap.

